From c10a7247d7f66f4801e4bef000344d953cb5f87c Mon Sep 17 00:00:00 2001 From: PP Date: Tue, 18 Jul 2023 15:31:46 +0800 Subject: [PATCH 001/184] add back WASM_FALLBACK constant (#15758) --- cc.config.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cc.config.json b/cc.config.json index add518b733d..f4d4da87658 100644 --- a/cc.config.json +++ b/cc.config.json @@ -663,6 +663,12 @@ "value": false, "internal": true }, + "WASM_FALLBACK": { + "comment": "An internal constant to indicate whether need a fallback of wasm.\nIf true, we build a wasm fallback module for the compatibility of wasm files compiled by different version of emscripten.\nThis is useful when we use wasm on different version of Safari browsers.", + "type": "boolean", + "value": "$HTML5", + "internal": true + }, "WASM_SUBPACKAGE": { "comment": "An internal constant to indicate whether we use wasm assets as minigame subpackage.\nThis is useful when we need to reduce code size.", "type": "boolean", From ec88dc516000cb1d932cd7fc09d717ba1c6e1986 Mon Sep 17 00:00:00 2001 From: troublemaker52025 Date: Tue, 18 Jul 2023 16:47:15 +0800 Subject: [PATCH 002/184] fix invalid punctual lights for custom pipeline (#15759) --- cocos/rendering/custom/define.ts | 8 ++++---- cocos/rendering/custom/executor.ts | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index a461e93f1eb..35a5832108c 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -75,7 +75,7 @@ export function validPunctualLightsCulling (pipeline: BasicPipeline, camera: Cam const { spotLights } = camera.scene!; for (let i = 0; i < spotLights.length; i++) { const light = spotLights[i]; - if (light.baked) { + if (light.baked && !camera.node.scene.globals.disableLightmap) { continue; } @@ -88,7 +88,7 @@ export function validPunctualLightsCulling (pipeline: BasicPipeline, camera: Cam const { sphereLights } = camera.scene!; for (let i = 0; i < sphereLights.length; i++) { const light = sphereLights[i]; - if (light.baked) { + if (light.baked && !camera.node.scene.globals.disableLightmap) { continue; } geometry.Sphere.set(_sphere, light.position.x, light.position.y, light.position.z, light.range); @@ -117,8 +117,8 @@ export function validPunctualLightsCulling (pipeline: BasicPipeline, camera: Cam validPunctualLights.push(light); } } - // array push not supported. - pipeline.pipelineSceneData.validPunctualLights = validPunctualLights; + // in jsb, std::vector is not synchronized, so we need to assign it manually + sceneData.validPunctualLights = validPunctualLights; } const _cameras: Camera[] = []; diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 285fc02d679..732f36b4f64 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -59,7 +59,7 @@ import { RenderShadowMapBatchedQueue } from '../render-shadow-map-batched-queue' import { PlanarShadowQueue } from '../planar-shadow-queue'; import { DefaultVisitor, depthFirstSearch, ReferenceGraphView } from './graph'; import { VectorGraphColorMap } from './effect'; -import { getDescBindingFromName, getDescriptorSetDataFromLayout, getDescriptorSetDataFromLayoutId, getRenderArea, mergeSrcToTargetDesc, updateGlobalDescBinding } from './define'; +import { getDescBindingFromName, getDescriptorSetDataFromLayout, getDescriptorSetDataFromLayoutId, getRenderArea, mergeSrcToTargetDesc, updateGlobalDescBinding, validPunctualLightsCulling } from './define'; import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; import { builtinResMgr } from '../../asset/asset-manager/builtin-res-mgr'; import { Texture2D } from '../../asset/assets/texture-2d'; @@ -1131,6 +1131,7 @@ class DevicePreSceneTask extends WebSceneTask { } if (sceneFlag & SceneFlags.DEFAULT_LIGHTING) { this._submitInfo.additiveLight = context.additiveLight; + validPunctualLightsCulling(context.pipeline, this.camera); this._submitInfo.additiveLight.gatherLightPasses(this.camera, this._cmdBuff, this._currentQueue.devicePass.layoutName); } if (sceneFlag & SceneFlags.PLANAR_SHADOW) { From 81ab04144658935286b9cbcc0d01d8bf95893c04 Mon Sep 17 00:00:00 2001 From: Canvas Date: Tue, 18 Jul 2023 23:55:23 +0800 Subject: [PATCH 003/184] fix spine opacity failure. (#15765) --- cocos/2d/components/ui-opacity.ts | 9 ++++++++- cocos/spine/assembler/simple.ts | 1 + cocos/spine/skeleton.ts | 8 ++++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/cocos/2d/components/ui-opacity.ts b/cocos/2d/components/ui-opacity.ts index 96a36be5a83..97c93687ab4 100644 --- a/cocos/2d/components/ui-opacity.ts +++ b/cocos/2d/components/ui-opacity.ts @@ -23,7 +23,7 @@ */ import { ccclass, disallowMultiple, editable, executeInEditMode, executionOrder, help, menu, serializable, tooltip } from 'cc.decorator'; -import { JSB } from 'internal:constants'; +import { EDITOR_NOT_IN_PREVIEW, JSB } from 'internal:constants'; import { Component } from '../../scene-graph/component'; import { misc } from '../../core'; import { UIRenderer } from '../framework/ui-renderer'; @@ -67,6 +67,13 @@ export class UIOpacity extends Component { this.node._uiProps.localOpacity = value / 255; this.setEntityLocalOpacityDirtyRecursively(true); + + if(EDITOR_NOT_IN_PREVIEW) { + setTimeout(()=>{ + EditorExtends.Node.emit('change', this.node.uuid, this.node); + }, 200); + } + } private setEntityLocalOpacityDirtyRecursively (dirty: boolean) { diff --git a/cocos/spine/assembler/simple.ts b/cocos/spine/assembler/simple.ts index 6175ad53dd0..e62fe5935a5 100644 --- a/cocos/spine/assembler/simple.ts +++ b/cocos/spine/assembler/simple.ts @@ -130,6 +130,7 @@ export const simple: IAssembler = { function updateComponentRenderData (comp: Skeleton, batcher: Batcher2D) { comp.drawList.reset(); if (comp.color.a === 0) return; + comp._updateColor(); _premultipliedAlpha = comp.premultipliedAlpha; _useTint = comp.useTint || comp.isAnimationCached(); if (comp.isAnimationCached()) { diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index 1509d19341d..c64122bc5b1 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -1490,12 +1490,16 @@ export class Skeleton extends UIRenderer { } } - protected _updateColor () { + /** + * @engineInternal + */ + public _updateColor (): void { + //if(EDITOR_NOT_IN_PREVIEW) cce.Node.emit('change-node', this.node); this.node._uiProps.colorDirty = true; const r = this._color.r / 255.0; const g = this._color.g / 255.0; const b = this._color.b / 255.0; - const a = this._color.a / 255.0; + const a = this.node._uiProps.opacity; this._instance.setColor(r, g, b, a); } From 0b910aa7c4ebdab7998e7e7bb106cd9cef66545e Mon Sep 17 00:00:00 2001 From: Canvas Date: Wed, 19 Jul 2023 12:38:12 +0800 Subject: [PATCH 004/184] fix setDebugMode on JSB mode. (#15769) --- cocos/spine/skeleton.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index c64122bc5b1..190beae246a 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -1467,7 +1467,7 @@ export class Skeleton extends UIRenderer { this._debugRenderer.node.destroy(); this._debugRenderer = null; if (!this.isAnimationCached()) { - this._instance.setDebugMode(false); + if (!JSB) this._instance.setDebugMode(false); } } } @@ -1494,7 +1494,6 @@ export class Skeleton extends UIRenderer { * @engineInternal */ public _updateColor (): void { - //if(EDITOR_NOT_IN_PREVIEW) cce.Node.emit('change-node', this.node); this.node._uiProps.colorDirty = true; const r = this._color.r / 255.0; const g = this._color.g / 255.0; From 41304cfbd13cf65b49adc2d0ea838eff4c0f64f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=88=98?= <40414978+PatriceJiang@users.noreply.github.com> Date: Wed, 19 Jul 2023 17:46:17 +0800 Subject: [PATCH 005/184] fix setter for node.siblingIndex (#15776) --- cocos/scene-graph/node.jsb.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos/scene-graph/node.jsb.ts b/cocos/scene-graph/node.jsb.ts index db1a53c5b5c..15f31c4beee 100644 --- a/cocos/scene-graph/node.jsb.ts +++ b/cocos/scene-graph/node.jsb.ts @@ -1012,7 +1012,7 @@ Object.defineProperty(nodeProto, '_siblingIndex', { return this._sharedInt32Arr[0]; // Int32, 0: siblingIndex }, set(v) { - this.setSiblingIndex(v); + this._sharedInt32Arr[0] = v; }, }); @@ -1024,10 +1024,11 @@ Object.defineProperty(nodeProto, 'siblingIndex', { return this._sharedInt32Arr[0]; // Int32, 0: siblingIndex }, set(v) { - this.setSiblingIndex(v); + this._sharedInt32Arr[0] = v; }, }); +// note: setSiblingIndex is a JSB function, DO NOT override it nodeProto.getSiblingIndex = function getSiblingIndex() { return this._sharedInt32Arr[0]; // Int32, 0: siblingIndex }; From 6aba5f85d9806dd72a8c22774fe6449e006aa39f Mon Sep 17 00:00:00 2001 From: Ling Zhan Date: Wed, 19 Jul 2023 18:48:43 +0800 Subject: [PATCH 006/184] [fix] physics3d native cct api error (#15779) --- platforms/native/engine/jsb-physics.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platforms/native/engine/jsb-physics.js b/platforms/native/engine/jsb-physics.js index 31310609783..7f137116dfa 100644 --- a/platforms/native/engine/jsb-physics.js +++ b/platforms/native/engine/jsb-physics.js @@ -44,8 +44,8 @@ const CollisionEventObject = { const CCTShapeEventObject = { type: 'onControllerColliderHit', - selfController: null, - otherCollider: null, + controller: null, + collider: null, worldPosition: null, worldNormal: null, motionDirection: null, @@ -146,8 +146,8 @@ function emitCCTShapeEvent (t, cct, collider, b) { CCTShapeEventObject.worldNormal = new cc.Vec3(b[3], b[4], b[5]); CCTShapeEventObject.motionDirection = new cc.Vec3(b[6], b[7], b[8]); CCTShapeEventObject.motionLength = b[9]; - CCTShapeEventObject.selfController = cct; - CCTShapeEventObject.otherCollider = collider; + CCTShapeEventObject.controller = cct; + CCTShapeEventObject.collider = collider; cct.emit(t, CCTShapeEventObject); } @@ -914,7 +914,7 @@ class CharacterController { this.setCenter(this._com.center); this.setStepOffset(this._com.stepOffset); this.setSlopeLimit(this._com.slopeLimit); - this.setContactOffset(this._com.contactOffset); + this.setContactOffset(this._com.skinWidth); this.setDetectCollisions(true);//this._com.detectCollisions); this.setOverlapRecovery(true);//this._com.enableOverlapRecovery); } From 9ce02b54aa6bf54016c5fc4ccbb4f47004e4696a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=88=98?= <40414978+PatriceJiang@users.noreply.github.com> Date: Thu, 20 Jul 2023 10:21:41 +0800 Subject: [PATCH 007/184] use boost-bcp to reduce external size (#15770) --- native/utils/clear-platform.js | 293 ++++++++++- package-lock.json | 905 +++++++++++++++++++-------------- package.json | 4 + 3 files changed, 806 insertions(+), 396 deletions(-) diff --git a/native/utils/clear-platform.js b/native/utils/clear-platform.js index b034dd2113a..0cba7d8934e 100644 --- a/native/utils/clear-platform.js +++ b/native/utils/clear-platform.js @@ -1,8 +1,17 @@ 'use strict'; +// @ts-check + const chalk = require('chalk'); const path = require("path"); const fs = require('fs-extra'); +const tar = require('tar'); +const zlib = require('zlib'); +const axios = require('axios'); +const ProgressBar = require('progress'); +const os = require('os'); +const child_process = require('child_process'); +const fetch = require('node-fetch'); // usage: npm run clear-platform let externalDir = path.join(__dirname, "../external"); @@ -13,13 +22,22 @@ let winUsefulDirs = ['android', 'cmake', 'emscripten', 'ohos', 'sources', 'win64 let linuxUsefulDirs = ['android', 'cmake', 'emscripten', 'linux', 'ohos', 'sources']; let allDirs = []; +['log', 'warn', 'error', 'info'].forEach(field => { + const oldFn = console[field]; + console[field] = function (...args) { + oldFn.apply(this, [`[clear-platform.js:${field}] `, ...args]); + }; +}); + + main(); -function main() { +async function main() { readDirectory(externalDir, allDirs); console.log(chalk.green(`==== current exists 3rd-libs directories ====`)); console.log(allDirs); cleanPlatform(process.platform); + await minimizeBoost(); } function readDirectory(path, filesList) { @@ -52,7 +70,7 @@ function cleanPlatform(platform) { if (winUselessDirs.length > 0) { console.log(chalk.magenta(`==== Remove win32 useless 3rd-libs ====`)); console.log(winUselessDirs); - for (let i = 0; i < winUselessDirs.length; i++) { + for (let i = 0; i < winUselessDirs.length; i++) { let clearDirectory = path.join(externalDir, winUselessDirs[i]); console.log(` ${chalk.green('Remove directory: ')} ${clearDirectory}`); ensureRemove(clearDirectory); @@ -63,7 +81,7 @@ function cleanPlatform(platform) { } else if (platform === 'linux') { // linux let linuxUselessDirs = getArrDiff(allDirs, linuxUsefulDirs); - if (linuxUselessDirs.length > 0) { + if (linuxUselessDirs.length > 0) { console.log(chalk.magenta(`==== Remove linux useless 3rd-libs ====`)); console.log(linuxUselessDirs); for (let i = 0; i < linuxUselessDirs.length; i++) { @@ -99,7 +117,272 @@ function ensureRemove(clearDirectory) { } function getArrDiff(arr1, arr2) { - return arr1.concat(arr2).filter(function(v, i, arr) { - return arr.indexOf(v) === arr.lastIndexOf(v); + return arr1.concat(arr2).filter(function (v, i, arr) { + return arr.indexOf(v) === arr.lastIndexOf(v); + }); +} + +function execName(fn, winPostFix = '.exe', linuxPosFix = '') { + return os.platform() === 'win32' ? fn + winPostFix : fn + linuxPosFix; +} + +async function runCommand(dir, cmd, ...args) { + console.log(`Exec ${cmd} with [${args.join(', ')}]`); + return new Promise((resolve, reject) => { + const child = child_process.spawn(cmd, args, { + cwd: dir, + shell: true, + }); + child.stdout.on('data', (data) => { + console.log(data.toString('utf8')); + }); + child.stderr.on('data', (data) => { + console.error(data.toString('utf8')); + }); + child.on('error', (data) => { + console.log(`Error:`); + console.error(data.toString('utf8')); + }); + child.on('close', (code) => { + if (code == 0) { + return resolve(); + } + console.error(`Command ${cmd} exited with code ${code}`) + reject(new Error(`Command ${cmd} exited with code ${code}`)); + }) }); } + +async function filterFiles(root, tstFn) { + const all = []; + const walk = async (dir) => { + const st = fs.statSync(dir); + if (st.isDirectory()) { + const files = await fs.readdir(dir); + const sub = []; + for (let f of files) { + if (f.startsWith('.')) continue; + const p = path.join(dir, f); + if (tstFn(p, true)) sub.push(walk(p)); + } + await Promise.all(sub); + } else { + if (tstFn(dir, false)) all.push(dir); + } + } + await walk(root); + return all; +} + +async function batcher(array, batchSize, fn) { + for (let i = 0, l = array.length; i < l; i += batchSize) { + await Promise.all(array.slice(i, i + batchSize).map(fn)) + } +} + +async function minimizeBoost() { + const BOOST_VERSION = [1, 78, 0] + const BOOST_VERSION_DOTTED = BOOST_VERSION.join('.'); + const BOOST_VERSION_UNDERSCORE = BOOST_VERSION.join('_'); + const BOOST_ZIP_FILE = `boost_${BOOST_VERSION_UNDERSCORE}.tar.gz`; + const EXTERNAL_SOURCE_DIR = path.join(__dirname, '..', 'external', 'sources'); + const BOOST_DOWNLOAD = path.join(EXTERNAL_SOURCE_DIR, 'boost-download'); + const BOOST_ORIG_PATH = path.join(EXTERNAL_SOURCE_DIR, 'boost'); + const BOOST_DEST = path.join(EXTERNAL_SOURCE_DIR, 'boost-minimized'); + const BOOST_DECOMPRESSED_PATH = path.join(BOOST_DOWNLOAD, `boost_${BOOST_VERSION_UNDERSCORE}`); + const BOOST_FILE_PATH = path.join(BOOST_DOWNLOAD, BOOST_ZIP_FILE); + const BOOST_URL_REMOTE = `https://jaist.dl.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOTTED}/boost_${BOOST_VERSION_UNDERSCORE}.tar.gz` + const BOOST_URL_LOCAL = `http://ftp.cocos.org/TestBuilds/Editor-3d/tools/boost_${BOOST_VERSION_UNDERSCORE}.tar.gz` + + const BCP_PATH = path.join(BOOST_DECOMPRESSED_PATH, 'dist', 'bin', execName('bcp')); + const ENGINE_ROOT = path.normalize(path.join(__dirname, '../../')); + + let headersUsedByEngine = []; + + const fnCheckDirectories = async () => { + if (!await fs.pathExists(BOOST_DOWNLOAD)) { + await fs.mkdir(BOOST_DOWNLOAD); + } + if (!await fs.pathExists(BOOST_DEST)) { + await fs.mkdir(BOOST_DEST); + } + } + + const fnDownloadWithAxios = async (url, dstUrl) => { + let bar = null; + const dstFile = fs.createWriteStream(dstUrl); + return new Promise((resolve, reject) => { + axios.get(url, { responseType: 'stream' }) + .then((res) => { + // console.log(res.headers); + const total = res.headers['Content-Length'] || res.headers['content-length']; + bar = new ProgressBar('Downloading [:bar] :percent :etas', { + complete: '=', + incomplete: ' ', + width: 40, + total: parseInt(total) + }); + res.data.pipe(dstFile); + res.data.on('data', (chunk) => { bar.tick(chunk.length); }); + res.data.on('end', () => { + console.log(` Download Finished`); + resolve(); + }); + }).catch(err => reject(err)); + }); + }; + + const fnDownloadWithCurl = async (url, dstUrl) => { + await runCommand(BOOST_DOWNLOAD, 'curl', url, '-o', `"${dstUrl}"`) + } + + const rm = async (file) => { + const st = fs.statSync(file); + if (st.isDirectory()) { + const files = (await fs.readdir(file)).filter(x => x !== '.' && x !== '..').map(x => path.join(file, x)); + await Promise.all(files.map(x => rm(x))); + await fs.rmdir(file) + } else { + await fs.unlink(file); + } + }; + + const fnDownloadBoost = async () => { + const targetExist = await fs.pathExists(BOOST_FILE_PATH); + if (!targetExist) { + let boostURL; + console.log(`Testing local url: ${BOOST_URL_LOCAL}`); + try { + const FETCH_TIMEOUTOUT = 3000; + const testLocal = await Promise.race( [fetch(BOOST_URL_LOCAL), new Promise((_, r)=> { + setTimeout(()=> r(new Error('Request timed out')), FETCH_TIMEOUTOUT); + })]); + if (testLocal.ok) { + console.log(` Use ${BOOST_URL_LOCAL}!`); + boostURL = BOOST_URL_LOCAL; + } else { + console.log(` Failed on error code, use ${BOOST_URL_REMOTE}!`); + boostURL = BOOST_URL_REMOTE; + } + } catch (e) { + console.error(e); + console.log(` Failed on exception, use ${BOOST_URL_REMOTE}!`); + boostURL = BOOST_URL_REMOTE; + } + console.log(` downloading ${boostURL}\n to ${BOOST_FILE_PATH}`); + + await fnDownloadWithAxios(boostURL, BOOST_FILE_PATH); + // await fnDownloadWithCurl(BOOST_URL, BOOST_FILE_PATH); + } else { + console.log(`Skip downloading, file ${BOOST_FILE_PATH} exists.`); + } + }; + + const fnDecompressBoost = async () => { + if (await fs.pathExists(BOOST_DECOMPRESSED_PATH)) { + console.log(` Folder ${BOOST_DECOMPRESSED_PATH} exists, skip decompressing...`); + return; + } + console.log(`Decompressing file ${BOOST_FILE_PATH}`); + const srcStream = fs.createReadStream(BOOST_FILE_PATH); + const st = fs.statSync(BOOST_FILE_PATH); + let bar; + return new Promise((resolve, reject) => { + bar = new ProgressBar(' Extracting [:bar] :percent :etas', { + complete: '=', + incomplete: ' ', + width: 40, + total: st.size + }); + srcStream.on('data', chunk => bar.tick(chunk.length)) + .pipe(zlib.createGunzip()) + .pipe(tar.extract({ cwd: BOOST_DOWNLOAD })) + .on('entry', (entry) => { + // console.log(` processing ${entry.path}`); + }) + .on('error', err => { + console.error(` decompressing error!`); + reject(err); + }) + .on('end', () => { + console.log(` decompressing done!`); + resolve(); + }); + }); + }; + + const fnCompileBoost = async () => { + if (await fs.pathExists(BCP_PATH)) { + console.log(` File ${BCP_PATH} already exists, skip compilation`); + return; + } + const bootstrap = path.join(BOOST_DECOMPRESSED_PATH, execName('bootstrap', '.bat', '.sh')); + const b2 = path.join(BOOST_DECOMPRESSED_PATH, execName('b2')); + await runCommand(BOOST_DECOMPRESSED_PATH, bootstrap); + await runCommand(BOOST_DECOMPRESSED_PATH, b2, 'headers'); + await runCommand(BOOST_DECOMPRESSED_PATH, b2, 'tools/bcp'); + + if (await fs.pathExists(BCP_PATH)) { + console.log(` Compile bcp.exe successed!`); + } else { + console.error(` Failed to compile bcp.exe, file not found!`) + } + }; + + const fnCollectBoostHeaders = async () => { + console.log(` Analyzing source files...`); + const allSource = await filterFiles(ENGINE_ROOT, (path, isdir) => { + return isdir ? !/native(\\|\/)+external/.test(path) : ['.h', '.hpp', '.cpp', '.mm'].filter(e => path.endsWith(e)).length > 0; + }); + console.log(`${allSource.length} files found!`); + const R = /#include\s+[<"]boost\/([^">]+)/ + const boostHeaders = {}; + await batcher(allSource, 20, async (file) => { + const data = await fs.readFile(file, 'utf8') + const includes = data.split(`\n`).filter(x => x.trim().startsWith("#include")).map(x => x.trim()).filter(x => R.test(x)); + includes.forEach(x => { + const m = x.match(R); + if (m) { + boostHeaders[m[1]] = true; + } + }) + }) + headersUsedByEngine = Object.keys(boostHeaders).sort(); + console.log(` headers: ${headersUsedByEngine.join(', ')}`); + }; + + const fnRunBCP = async () => { + await runCommand(BOOST_DECOMPRESSED_PATH, BCP_PATH, + `--boost="${BOOST_DECOMPRESSED_PATH}"`, + 'graph', /* manually add components here */ + ...headersUsedByEngine, + BOOST_DEST + ); + + if (await fs.pathExists(BOOST_ORIG_PATH)) { + console.log(`Remove old folder ${BOOST_ORIG_PATH}`); + await rm(BOOST_ORIG_PATH); + } + console.log(`Link to minimized boost folder ${BOOST_DEST}`); + await fs.rename(path.join(BOOST_DEST, 'boost'), BOOST_ORIG_PATH); + if (await fs.pathExists(BOOST_DEST)) { + console.log(`Remove folder ${BOOST_DEST}`); + await rm(BOOST_DEST); + } + }; + + const fnCleanUp = async () => { + if (await fs.pathExists(BOOST_DOWNLOAD)) { + await rm(BOOST_DOWNLOAD); + } + } + + + await fnCheckDirectories(); + await fnDownloadBoost(); + await fnDecompressBoost(); + await fnCompileBoost(); + await fnCollectBoostHeaders(); + await fnRunBCP(); + await fnCleanUp(); // skip this step when debugging +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0fa7f37bda9..b276c5e8771 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1122,7 +1122,7 @@ }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", - "resolved": "https://registry.nlark.com/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-async-generators/download/@babel/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha1-qYP7Gusuw/btBCohD2QOkOeG/g0=", "dev": true, "requires": { @@ -1174,7 +1174,7 @@ }, "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", - "resolved": "https://registry.nlark.com/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz?cache=0&sync_timestamp=1618847125283&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-syntax-dynamic-import%2Fdownload%2F%40babel%2Fplugin-syntax-dynamic-import-7.8.3.tgz", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha1-Yr+Ysto80h1iYVT8lu5bPLaOrLM=", "dev": true, "requires": { @@ -1217,7 +1217,7 @@ }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", - "resolved": "https://registry.nlark.com/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-json-strings/download/@babel/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha1-AcohtmjNghjJ5kDLbdiMVBKyyWo=", "dev": true, "requires": { @@ -1226,7 +1226,7 @@ }, "@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", - "resolved": "https://registry.nlark.com/@babel/plugin-syntax-logical-assignment-operators/download/@babel/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-logical-assignment-operators/download/@babel/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha1-ypHvRjA1MESLkGZSusLp/plB9pk=", "dev": true, "requires": { @@ -1269,7 +1269,7 @@ }, "@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", - "resolved": "https://registry.nlark.com/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-object-rest-spread/download/@babel/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha1-YOIl7cvZimQDMqLnLdPmbxr1WHE=", "dev": true, "requires": { @@ -1287,7 +1287,7 @@ }, "@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", - "resolved": "https://registry.nlark.com/@babel/plugin-syntax-optional-chaining/download/@babel/plugin-syntax-optional-chaining-7.8.3.tgz", + "resolved": "https://registry.npm.taobao.org/@babel/plugin-syntax-optional-chaining/download/@babel/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha1-T2nCq5UWfgGAzVM2YT+MV4j31Io=", "dev": true, "requires": { @@ -1647,7 +1647,7 @@ }, "@babel/preset-env": { "version": "7.8.7", - "resolved": "https://registry.npmmirror.com/@babel/preset-env/download/@babel/preset-env-7.8.7.tgz?cache=0&sync_timestamp=1637103615805&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40babel%2Fpreset-env%2Fdownload%2F%40babel%2Fpreset-env-7.8.7.tgz", + "resolved": "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.8.7.tgz?cache=0&sync_timestamp=1593522855920&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fpreset-env%2Fdownload%2F%40babel%2Fpreset-env-7.8.7.tgz", "integrity": "sha1-H8fYnH910tcMK2do3mwuBJs8uds=", "dev": true, "requires": { @@ -1823,7 +1823,7 @@ }, "@cocos/box2d": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/@cocos/box2d/download/@cocos/box2d-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/@cocos/box2d/download/@cocos/box2d-1.0.1.tgz", "integrity": "sha1-Fc2lzPxRCCt91tNoo+S55IXS5To=", "requires": { "@types/systemjs": "^0.20.6" @@ -1863,13 +1863,13 @@ "dependencies": { "ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { @@ -1878,7 +1878,7 @@ }, "cliui": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "requires": { @@ -1889,7 +1889,7 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { @@ -1898,13 +1898,13 @@ }, "color-name": { "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "find-up": { "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { @@ -1914,7 +1914,7 @@ }, "fs-extra": { "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-8.1.0.tgz", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { @@ -1925,7 +1925,7 @@ }, "get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, @@ -1940,13 +1940,13 @@ }, "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { @@ -1955,7 +1955,7 @@ }, "p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { @@ -1964,13 +1964,13 @@ }, "path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, @@ -1996,7 +1996,7 @@ }, "string-width": { "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { @@ -2007,7 +2007,7 @@ }, "strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { @@ -2022,7 +2022,7 @@ }, "wrap-ansi": { "version": "6.2.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { @@ -2033,13 +2033,13 @@ }, "y18n": { "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "yargs": { "version": "15.4.1", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { @@ -2058,7 +2058,7 @@ }, "yargs-parser": { "version": "18.1.3", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { @@ -3585,7 +3585,7 @@ }, "type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true } @@ -5845,7 +5845,7 @@ }, "@jest/types": { "version": "24.9.0", - "resolved": "https://registry.npmmirror.com/@jest/types/download/@jest/types-24.9.0.tgz", + "resolved": "https://registry.npm.taobao.org/@jest/types/download/@jest/types-24.9.0.tgz", "integrity": "sha1-Y8smy3UA0Gnlo4lEGnxqtekJ/Fk=", "dev": true, "requires": { @@ -5876,7 +5876,7 @@ }, "@jridgewell/resolve-uri": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==" }, "@jridgewell/set-array": { @@ -5909,12 +5909,12 @@ }, "@jridgewell/sourcemap-codec": { "version": "1.4.13", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==" }, "@jridgewell/trace-mapping": { "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", "requires": { "@jridgewell/resolve-uri": "^3.0.3", @@ -6172,7 +6172,7 @@ }, "@types/fs-extra": { "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/@types/fs-extra/download/@types/fs-extra-5.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/@types/fs-extra/download/@types/fs-extra-5.1.0.tgz", "integrity": "sha1-KjJe+XkBUEo4KHGMOQ00uEJqEKE=", "dev": true, "requires": { @@ -6205,7 +6205,7 @@ }, "@types/istanbul-reports": { "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/@types/istanbul-reports/download/@types/istanbul-reports-1.1.2.tgz?cache=0&sync_timestamp=1637266160892&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40types%2Fistanbul-reports%2Fdownload%2F%40types%2Fistanbul-reports-1.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/@types/istanbul-reports/download/@types/istanbul-reports-1.1.2.tgz?cache=0&sync_timestamp=1613379043554&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fistanbul-reports%2Fdownload%2F%40types%2Fistanbul-reports-1.1.2.tgz", "integrity": "sha1-6HXMaJ5HvOVJ7IHz315vbxHPrrI=", "dev": true, "requires": { @@ -6215,7 +6215,7 @@ }, "@types/jest": { "version": "24.9.1", - "resolved": "https://registry.npmmirror.com/@types/jest/download/@types/jest-24.9.1.tgz", + "resolved": "https://registry.npm.taobao.org/@types/jest/download/@types/jest-24.9.1.tgz?cache=0&sync_timestamp=1616695463771&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fjest%2Fdownload%2F%40types%2Fjest-24.9.1.tgz", "integrity": "sha1-Arr5Vzx48bmXSl82d4s2aqd71TQ=", "dev": true, "requires": { @@ -6892,7 +6892,7 @@ }, "abab": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "resolved": "https://registry.npmmirror.com/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "dev": true }, @@ -6904,7 +6904,7 @@ }, "acorn-globals": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "resolved": "https://registry.npmmirror.com/acorn-globals/-/acorn-globals-6.0.0.tgz", "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", "dev": true, "requires": { @@ -6930,13 +6930,13 @@ }, "acorn-walk": { "version": "7.2.0", - "resolved": "https://registry.nlark.com/acorn-walk/download/acorn-walk-7.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Facorn-walk%2Fdownload%2Facorn-walk-7.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/acorn-walk/download/acorn-walk-7.2.0.tgz", "integrity": "sha1-DeiJpgEgOQmw++B7iTjcIdLpZ7w=", "dev": true }, "agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "requires": { @@ -6999,7 +6999,7 @@ }, "ansi-styles": { "version": "3.2.1", - "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-3.2.1.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-3.2.1.tgz", "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", "requires": { "color-convert": "^1.9.0" @@ -7007,13 +7007,13 @@ }, "ansi-wrap": { "version": "0.1.0", - "resolved": "https://registry.nlark.com/ansi-wrap/download/ansi-wrap-0.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-wrap/download/ansi-wrap-0.1.0.tgz", "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, "anymatch": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/anymatch/download/anymatch-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/anymatch/download/anymatch-2.0.0.tgz", "integrity": "sha1-vLJLTzeTTZqnrBe0ra+J58du8us=", "dev": true, "requires": { @@ -7032,7 +7032,7 @@ }, "archy": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/archy/download/archy-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/archy/download/archy-1.0.0.tgz", "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, @@ -7047,7 +7047,7 @@ }, "arr-diff": { "version": "4.0.0", - "resolved": "https://registry.nlark.com/arr-diff/download/arr-diff-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/arr-diff/download/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", "dev": true }, @@ -7062,13 +7062,13 @@ }, "arr-flatten": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/arr-flatten/download/arr-flatten-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz", "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", "dev": true }, "arr-map": { "version": "2.0.2", - "resolved": "https://registry.nlark.com/arr-map/download/arr-map-2.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/arr-map/download/arr-map-2.0.2.tgz", "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", "dev": true, "requires": { @@ -7077,7 +7077,7 @@ }, "arr-union": { "version": "3.1.0", - "resolved": "https://registry.nlark.com/arr-union/download/arr-union-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/arr-union/download/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, @@ -7142,7 +7142,7 @@ "dependencies": { "call-bind": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { @@ -7242,12 +7242,12 @@ }, "array-union": { "version": "2.1.0", - "resolved": "https://registry.npm.taobao.org/array-union/download/array-union-2.1.0.tgz?cache=0&sync_timestamp=1614624262896&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Farray-union%2Fdownload%2Farray-union-2.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/array-union/download/array-union-2.1.0.tgz", "integrity": "sha1-t5hCCtvrHego2ErNii4j0+/oXo0=" }, "array-unique": { "version": "0.3.2", - "resolved": "https://registry.nlark.com/array-unique/download/array-unique-0.3.2.tgz", + "resolved": "https://registry.npm.taobao.org/array-unique/download/array-unique-0.3.2.tgz", "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, @@ -7431,13 +7431,13 @@ }, "async-each": { "version": "1.0.3", - "resolved": "https://registry.nlark.com/async-each/download/async-each-1.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/async-each/download/async-each-1.0.3.tgz", "integrity": "sha1-tyfb+H12UWAvBvTUrDh/R9kbDL8=", "dev": true }, "async-settle": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/async-settle/download/async-settle-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/async-settle/download/async-settle-1.0.0.tgz", "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", "dev": true, "requires": { @@ -7446,13 +7446,13 @@ }, "asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, "atob": { "version": "2.1.2", - "resolved": "https://registry.nlark.com/atob/download/atob-2.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/atob/download/atob-2.1.2.tgz", "integrity": "sha1-bZUX654DDSQ2ZmZR6GvZ9vE1M8k=", "dev": true }, @@ -7462,6 +7462,25 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true }, + "axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dev": true, + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + }, + "dependencies": { + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "dev": true + } + } + }, "babel-jest": { "version": "28.1.2", "resolved": "https://registry.npmmirror.com/babel-jest/-/babel-jest-28.1.2.tgz", @@ -7616,7 +7635,7 @@ }, "bach": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/bach/download/bach-1.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/bach/download/bach-1.2.0.tgz", "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", "dev": true, "requires": { @@ -7662,7 +7681,7 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { @@ -7671,7 +7690,7 @@ }, "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { @@ -7699,13 +7718,13 @@ }, "basic-auth": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/basic-auth/download/basic-auth-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/basic-auth/download/basic-auth-1.1.0.tgz", "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=", "dev": true }, "binary-extensions": { "version": "1.13.1", - "resolved": "https://registry.nlark.com/binary-extensions/download/binary-extensions-1.13.1.tgz", + "resolved": "https://registry.npm.taobao.org/binary-extensions/download/binary-extensions-1.13.1.tgz", "integrity": "sha1-WYr+VHVbKGilMw0q/51Ou1Mgm2U=", "dev": true }, @@ -7727,7 +7746,7 @@ }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.nlark.com/brace-expansion/download/brace-expansion-1.1.11.tgz", + "resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz", "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "requires": { "balanced-match": "^1.0.0", @@ -7785,7 +7804,7 @@ }, "browser-process-hrtime": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "resolved": "https://registry.npmmirror.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, @@ -8049,7 +8068,7 @@ }, "bs-logger": { "version": "0.2.6", - "resolved": "https://registry.nlark.com/bs-logger/download/bs-logger-0.2.6.tgz", + "resolved": "https://registry.npm.taobao.org/bs-logger/download/bs-logger-0.2.6.tgz", "integrity": "sha1-6302UwenLPl0zGzadraDVK0za9g=", "dev": true, "requires": { @@ -8113,7 +8132,7 @@ }, "cache-base": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/cache-base/download/cache-base-1.0.1.tgz?cache=0&sync_timestamp=1636237266442&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fcache-base%2Fdownload%2Fcache-base-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/cache-base/download/cache-base-1.0.1.tgz", "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { @@ -8146,12 +8165,12 @@ }, "callsites": { "version": "3.1.0", - "resolved": "https://registry.nlark.com/callsites/download/callsites-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/callsites/download/callsites-3.1.0.tgz", "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=" }, "camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmmirror.com/camelcase/download/camelcase-5.3.1.tgz?cache=0&sync_timestamp=1636945130104&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fcamelcase%2Fdownload%2Fcamelcase-5.3.1.tgz", + "resolved": "https://registry.npm.taobao.org/camelcase/download/camelcase-5.3.1.tgz", "integrity": "sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA=", "dev": true }, @@ -8163,7 +8182,7 @@ }, "chalk": { "version": "2.4.2", - "resolved": "https://registry.npmmirror.com/chalk/download/chalk-2.4.2.tgz", + "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-2.4.2.tgz?cache=0&sync_timestamp=1573282918610&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-2.4.2.tgz", "integrity": "sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ=", "requires": { "ansi-styles": "^3.2.1", @@ -8180,12 +8199,12 @@ "child_process": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", - "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==", + "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o=", "dev": true }, "chokidar": { "version": "2.1.8", - "resolved": "https://registry.npmmirror.com/chokidar/download/chokidar-2.1.8.tgz", + "resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-2.1.8.tgz", "integrity": "sha1-gEs6e2qZNYw8XGHnHYco8EHP+Rc=", "dev": true, "requires": { @@ -8205,7 +8224,7 @@ "dependencies": { "glob-parent": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/glob-parent/download/glob-parent-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1569108917227&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { @@ -8215,7 +8234,7 @@ "dependencies": { "is-glob": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/is-glob/download/is-glob-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { @@ -8241,9 +8260,15 @@ } } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, "ci-info": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ci-info/download/ci-info-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/ci-info/download/ci-info-2.0.0.tgz", "integrity": "sha1-Z6npZL4xpR4V5QENWObxKDQAL0Y=", "dev": true }, @@ -8265,7 +8290,7 @@ }, "class-utils": { "version": "0.3.6", - "resolved": "https://registry.nlark.com/class-utils/download/class-utils-0.3.6.tgz", + "resolved": "https://registry.npm.taobao.org/class-utils/download/class-utils-0.3.6.tgz", "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { @@ -8305,7 +8330,7 @@ }, "clone": { "version": "2.1.2", - "resolved": "https://registry.nlark.com/clone/download/clone-2.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/clone/download/clone-2.1.2.tgz", "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", "dev": true }, @@ -8340,7 +8365,7 @@ }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/code-point-at/download/code-point-at-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/code-point-at/download/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, @@ -8352,7 +8377,7 @@ }, "collection-map": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/collection-map/download/collection-map-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/collection-map/download/collection-map-1.0.0.tgz", "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", "dev": true, "requires": { @@ -8373,7 +8398,7 @@ }, "color-convert": { "version": "1.9.3", - "resolved": "https://registry.nlark.com/color-convert/download/color-convert-1.9.3.tgz", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-1.9.3.tgz", "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=", "requires": { "color-name": "1.1.3" @@ -8424,7 +8449,7 @@ }, "combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "requires": { @@ -8433,19 +8458,19 @@ }, "commander": { "version": "2.20.3", - "resolved": "https://registry.npmmirror.com/commander/download/commander-2.20.3.tgz?cache=0&sync_timestamp=1634886357672&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fcommander%2Fdownload%2Fcommander-2.20.3.tgz", + "resolved": "https://registry.npm.taobao.org/commander/download/commander-2.20.3.tgz", "integrity": "sha1-/UhehMA+tIgcIHIrpIA16FMa6zM=", "dev": true }, "commondir": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/commondir/-/commondir-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, "component-emitter": { "version": "1.3.0", - "resolved": "https://registry.nlark.com/component-emitter/download/component-emitter-1.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz", "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=", "dev": true }, @@ -8456,7 +8481,7 @@ }, "concat-stream": { "version": "1.6.2", - "resolved": "https://registry.nlark.com/concat-stream/download/concat-stream-1.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/concat-stream/download/concat-stream-1.6.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fconcat-stream%2Fdownload%2Fconcat-stream-1.6.2.tgz", "integrity": "sha1-kEvfGUzTEi/Gdcd/xKw9T/D9GjQ=", "dev": true, "requires": { @@ -8494,7 +8519,7 @@ }, "copy-descriptor": { "version": "0.1.1", - "resolved": "https://registry.nlark.com/copy-descriptor/download/copy-descriptor-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/copy-descriptor/download/copy-descriptor-0.1.1.tgz", "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, @@ -8528,7 +8553,7 @@ "dependencies": { "semver": { "version": "7.0.0", - "resolved": "https://registry.nlark.com/semver/download/semver-7.0.0.tgz?cache=0&sync_timestamp=1618846864940&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-7.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.0.0.tgz?cache=0&sync_timestamp=1581458063470&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.0.0.tgz", "integrity": "sha1-XzyjV2HkfgWyBsba/yz4FPAxa44=", "dev": true } @@ -8536,13 +8561,13 @@ }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "corser": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/corser/download/corser-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/corser/download/corser-2.0.1.tgz", "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=", "dev": true }, @@ -8636,7 +8661,7 @@ }, "cssstyle": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "resolved": "https://registry.npmmirror.com/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", "dev": true, "requires": { @@ -8645,7 +8670,7 @@ "dependencies": { "cssom": { "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.3.8.tgz", "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true } @@ -8683,13 +8708,13 @@ }, "decamelize": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/decamelize/download/decamelize-1.2.0.tgz?cache=0&sync_timestamp=1633055760479&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fdecamelize%2Fdownload%2Fdecamelize-1.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, "decimal.js": { "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.3.1.tgz", "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", "dev": true }, @@ -8702,7 +8727,7 @@ "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" }, "deep-is": { "version": "0.1.3", @@ -8740,7 +8765,7 @@ }, "define-properties": { "version": "1.1.3", - "resolved": "https://registry.nlark.com/define-properties/download/define-properties-1.1.3.tgz?cache=0&sync_timestamp=1618847174317&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdefine-properties%2Fdownload%2Fdefine-properties-1.1.3.tgz", + "resolved": "https://registry.npm.taobao.org/define-properties/download/define-properties-1.1.3.tgz", "integrity": "sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE=", "dev": true, "requires": { @@ -8759,7 +8784,7 @@ "dependencies": { "is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { @@ -8768,7 +8793,7 @@ }, "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { @@ -8820,7 +8845,7 @@ }, "delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true }, @@ -8879,7 +8904,7 @@ }, "diff-sequences": { "version": "24.9.0", - "resolved": "https://registry.npmmirror.com/diff-sequences/download/diff-sequences-24.9.0.tgz", + "resolved": "https://registry.npm.taobao.org/diff-sequences/download/diff-sequences-24.9.0.tgz?cache=0&sync_timestamp=1579655107286&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdiff-sequences%2Fdownload%2Fdiff-sequences-24.9.0.tgz", "integrity": "sha1-VxXWJE4qpl9Iu6C8ly2wsLEelbU=", "dev": true }, @@ -8964,7 +8989,7 @@ }, "ecstatic": { "version": "3.3.2", - "resolved": "https://registry.npmmirror.com/ecstatic/download/ecstatic-3.3.2.tgz", + "resolved": "https://registry.npm.taobao.org/ecstatic/download/ecstatic-3.3.2.tgz", "integrity": "sha1-bR3UmBTQBZRoLGUq22YHamnUbEg=", "dev": true, "requires": { @@ -9025,7 +9050,7 @@ }, "error-ex": { "version": "1.3.2", - "resolved": "https://registry.nlark.com/error-ex/download/error-ex-1.3.2.tgz", + "resolved": "https://registry.npm.taobao.org/error-ex/download/error-ex-1.3.2.tgz", "integrity": "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=", "dev": true, "requires": { @@ -9077,7 +9102,7 @@ "dependencies": { "call-bind": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { @@ -9252,7 +9277,7 @@ }, "es6-iterator": { "version": "2.0.3", - "resolved": "https://registry.nlark.com/es6-iterator/download/es6-iterator-2.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/es6-iterator/download/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { @@ -9285,17 +9310,17 @@ }, "escalade": { "version": "3.1.1", - "resolved": "https://registry.npm.taobao.org/escalade/download/escalade-3.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/escalade/download/escalade-3.1.1.tgz?cache=0&sync_timestamp=1602567343144&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fescalade%2Fdownload%2Fescalade-3.1.1.tgz", "integrity": "sha1-2M/ccACWXFoBdLSoLqpcBVJ0LkA=" }, "escape-string-regexp": { "version": "1.0.5", - "resolved": "https://registry.nlark.com/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", + "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "resolved": "https://registry.npmmirror.com/escodegen/-/escodegen-2.0.0.tgz", "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", "dev": true, "requires": { @@ -9308,13 +9333,13 @@ "dependencies": { "estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, "source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true @@ -9423,7 +9448,7 @@ }, "chalk": { "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { @@ -9433,7 +9458,7 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { @@ -9442,13 +9467,13 @@ }, "color-name": { "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "cross-spawn": { "version": "7.0.3", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { @@ -9468,7 +9493,7 @@ }, "escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, @@ -9529,7 +9554,7 @@ }, "has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, @@ -9544,7 +9569,7 @@ }, "levn": { "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { @@ -9601,19 +9626,19 @@ }, "path-key": { "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, "shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { @@ -9622,7 +9647,7 @@ }, "shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, @@ -9646,7 +9671,7 @@ }, "type-check": { "version": "0.4.0", - "resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { @@ -9655,7 +9680,7 @@ }, "type-fest": { "version": "0.20.2", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true } @@ -9744,7 +9769,7 @@ "dependencies": { "debug": { "version": "3.2.7", - "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { @@ -9775,7 +9800,7 @@ "dependencies": { "debug": { "version": "3.2.7", - "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { @@ -9818,7 +9843,7 @@ }, "doctrine": { "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/doctrine/-/doctrine-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { @@ -9978,7 +10003,7 @@ }, "execa": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/execa/download/execa-1.0.0.tgz?cache=0&sync_timestamp=1637147207309&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fexeca%2Fdownload%2Fexeca-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/execa/download/execa-1.0.0.tgz?cache=0&sync_timestamp=1576749091315&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexeca%2Fdownload%2Fexeca-1.0.0.tgz", "integrity": "sha1-xiNqW7TfbW8V6I5/AXeYIWdJ3dg=", "dev": true, "requires": { @@ -10014,7 +10039,7 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/download/debug-2.6.9.tgz", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { @@ -10032,7 +10057,7 @@ }, "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -10041,7 +10066,7 @@ }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/download/ms-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } @@ -10049,7 +10074,7 @@ }, "expand-tilde": { "version": "2.0.2", - "resolved": "https://registry.nlark.com/expand-tilde/download/expand-tilde-2.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/expand-tilde/download/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { @@ -10058,7 +10083,7 @@ }, "expect": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/expect/download/expect-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/expect/download/expect-26.6.2.tgz?cache=0&sync_timestamp=1616701586390&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fexpect%2Fdownload%2Fexpect-26.6.2.tgz", "integrity": "sha1-xrmWvya/P+GLZ7LQ9R/JgbqTRBc=", "dev": true, "requires": { @@ -10072,7 +10097,7 @@ "dependencies": { "@jest/types": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/@jest/types/download/@jest/types-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/@jest/types/download/@jest/types-26.6.2.tgz", "integrity": "sha1-vvWlMgMOHYii9abZM/hOlyJu1I4=", "dev": true, "requires": { @@ -10103,7 +10128,7 @@ }, "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1611327117754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz", "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", "dev": true, "requires": { @@ -10122,7 +10147,7 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/color-convert/download/color-convert-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", "dev": true, "requires": { @@ -10137,19 +10162,19 @@ }, "has-flag": { "version": "4.0.0", - "resolved": "https://registry.nlark.com/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1626715907927&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", "dev": true }, "jest-get-type": { "version": "26.3.0", - "resolved": "https://registry.npmmirror.com/jest-get-type/download/jest-get-type-26.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/jest-get-type/download/jest-get-type-26.3.0.tgz", "integrity": "sha1-6X3Dw/U8K0Bsp6+u1Ek7HQmRmeA=", "dev": true }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/download/supports-color-7.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1611394043517&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz", "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", "dev": true, "requires": { @@ -10183,7 +10208,7 @@ }, "extend-shallow": { "version": "3.0.2", - "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-3.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { @@ -10193,7 +10218,7 @@ "dependencies": { "is-extendable": { "version": "1.0.1", - "resolved": "https://registry.nlark.com/is-extendable/download/is-extendable-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { @@ -10204,7 +10229,7 @@ }, "extglob": { "version": "2.0.4", - "resolved": "https://registry.nlark.com/extglob/download/extglob-2.0.4.tgz", + "resolved": "https://registry.npm.taobao.org/extglob/download/extglob-2.0.4.tgz", "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { @@ -10229,7 +10254,7 @@ }, "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -10238,7 +10263,7 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { @@ -10247,7 +10272,7 @@ }, "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { @@ -10269,7 +10294,7 @@ }, "fancy-log": { "version": "1.3.3", - "resolved": "https://registry.nlark.com/fancy-log/download/fancy-log-1.3.3.tgz", + "resolved": "https://registry.npm.taobao.org/fancy-log/download/fancy-log-1.3.3.tgz", "integrity": "sha1-28GRVPVYaQFQojlToK29A1vkX8c=", "dev": true, "requires": { @@ -10350,7 +10375,7 @@ }, "fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.nlark.com/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz", + "resolved": "https://registry.npm.taobao.org/fast-levenshtein/download/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fast-safe-stringify": { @@ -10505,16 +10530,27 @@ }, "for-own": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/for-own/download/for-own-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/for-own/download/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { "for-in": "^1.0.1" } }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fragment-cache": { "version": "0.2.1", - "resolved": "https://registry.nlark.com/fragment-cache/download/fragment-cache-0.2.1.tgz", + "resolved": "https://registry.npm.taobao.org/fragment-cache/download/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { @@ -10524,12 +10560,12 @@ "fs": { "version": "0.0.1-security", "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", - "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==", + "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=", "dev": true }, "fs-extra": { "version": "7.0.1", - "resolved": "https://registry.nlark.com/fs-extra/download/fs-extra-7.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-7.0.1.tgz", "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=", "dev": true, "requires": { @@ -10538,9 +10574,29 @@ "universalify": "^0.1.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "fs-mkdirp-stream": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/fs-mkdirp-stream/download/fs-mkdirp-stream-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/fs-mkdirp-stream/download/fs-mkdirp-stream-1.0.0.tgz", "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", "dev": true, "requires": { @@ -10550,7 +10606,7 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/fs.realpath/download/fs.realpath-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { @@ -11183,7 +11239,7 @@ }, "function-bind": { "version": "1.1.1", - "resolved": "https://registry.nlark.com/function-bind/download/function-bind-1.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz", "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" }, "function.prototype.name": { @@ -11364,7 +11420,7 @@ }, "gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.nlark.com/gensync/download/gensync-1.0.0-beta.2.tgz", + "resolved": "https://registry.npm.taobao.org/gensync/download/gensync-1.0.0-beta.2.tgz", "integrity": "sha1-MqbudsPX9S1GsrGuXZP+qFgKJeA=" }, "get-assigned-identifiers": { @@ -11398,7 +11454,7 @@ }, "get-stream": { "version": "4.1.0", - "resolved": "https://registry.nlark.com/get-stream/download/get-stream-4.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/get-stream/download/get-stream-4.1.0.tgz", "integrity": "sha1-wbJVV189wh1Zv8ec09K0axw6VLU=", "dev": true, "requires": { @@ -11440,7 +11496,7 @@ }, "get-value": { "version": "2.0.6", - "resolved": "https://registry.nlark.com/get-value/download/get-value-2.0.6.tgz", + "resolved": "https://registry.npm.taobao.org/get-value/download/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, @@ -11479,7 +11535,7 @@ }, "glob-stream": { "version": "6.1.0", - "resolved": "https://registry.nlark.com/glob-stream/download/glob-stream-6.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/glob-stream/download/glob-stream-6.1.0.tgz", "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", "dev": true, "requires": { @@ -11497,7 +11553,7 @@ "dependencies": { "glob-parent": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/glob-parent/download/glob-parent-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz?cache=0&sync_timestamp=1569108917227&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglob-parent%2Fdownload%2Fglob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { @@ -11507,7 +11563,7 @@ }, "is-glob": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/is-glob/download/is-glob-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { @@ -11532,7 +11588,7 @@ }, "global-modules": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/global-modules/download/global-modules-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/global-modules/download/global-modules-1.0.0.tgz?cache=0&sync_timestamp=1571657602039&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fglobal-modules%2Fdownload%2Fglobal-modules-1.0.0.tgz", "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { @@ -11567,7 +11623,7 @@ }, "globals": { "version": "11.12.0", - "resolved": "https://registry.npmmirror.com/globals/download/globals-11.12.0.tgz", + "resolved": "https://registry.npm.taobao.org/globals/download/globals-11.12.0.tgz", "integrity": "sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4=" }, "globalthis": { @@ -11603,7 +11659,7 @@ }, "glogg": { "version": "1.0.2", - "resolved": "https://registry.nlark.com/glogg/download/glogg-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/glogg/download/glogg-1.0.2.tgz", "integrity": "sha1-LX3XAr7aIus7/634gGltpthGMT8=", "dev": true, "requires": { @@ -11670,7 +11726,7 @@ "camelcase": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, "gulp-cli": { @@ -11701,7 +11757,7 @@ }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-fullwidth-code-point/download/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { @@ -11710,7 +11766,7 @@ }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/string-width/download/string-width-1.0.2.tgz?cache=0&sync_timestamp=1632421309919&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fstring-width%2Fdownload%2Fstring-width-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-1.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { @@ -11826,7 +11882,7 @@ }, "gulplog": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/gulplog/download/gulplog-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/gulplog/download/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { @@ -11835,7 +11891,7 @@ }, "has": { "version": "1.0.3", - "resolved": "https://registry.nlark.com/has/download/has-1.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz", "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", "requires": { "function-bind": "^1.1.1" @@ -11849,7 +11905,7 @@ }, "has-flag": { "version": "3.0.0", - "resolved": "https://registry.nlark.com/has-flag/download/has-flag-3.0.0.tgz?cache=0&sync_timestamp=1626715907927&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhas-flag%2Fdownload%2Fhas-flag-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-gulplog": { @@ -11914,7 +11970,7 @@ }, "has-value": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/has-value/download/has-value-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { @@ -11925,7 +11981,7 @@ }, "has-values": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/has-values/download/has-values-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { @@ -12039,7 +12095,7 @@ }, "http-proxy": { "version": "1.18.1", - "resolved": "https://registry.nlark.com/http-proxy/download/http-proxy-1.18.1.tgz?cache=0&sync_timestamp=1618847045732&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhttp-proxy%2Fdownload%2Fhttp-proxy-1.18.1.tgz", + "resolved": "https://registry.npm.taobao.org/http-proxy/download/http-proxy-1.18.1.tgz", "integrity": "sha1-QBVB8FNIhLv5UmAzTnL4juOXZUk=", "dev": true, "requires": { @@ -12050,7 +12106,7 @@ }, "http-server": { "version": "0.12.3", - "resolved": "https://registry.npmmirror.com/http-server/download/http-server-0.12.3.tgz?cache=0&sync_timestamp=1634685922991&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhttp-server%2Fdownload%2Fhttp-server-0.12.3.tgz", + "resolved": "https://registry.npm.taobao.org/http-server/download/http-server-0.12.3.tgz", "integrity": "sha1-ugRx0OzEJYhmFss1xPryeRQKDTc=", "dev": true, "requires": { @@ -12074,7 +12130,7 @@ }, "https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "requires": { @@ -12121,7 +12177,7 @@ }, "imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.nlark.com/imurmurhash/download/imurmurhash-0.1.4.tgz", + "resolved": "https://registry.npm.taobao.org/imurmurhash/download/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { @@ -12141,7 +12197,7 @@ }, "inherits": { "version": "2.0.4", - "resolved": "https://registry.nlark.com/inherits/download/inherits-2.0.4.tgz", + "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" }, "ini": { @@ -12209,7 +12265,7 @@ }, "invariant": { "version": "2.2.4", - "resolved": "https://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz?cache=0&sync_timestamp=1615984365242&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Finvariant%2Fdownload%2Finvariant-2.2.4.tgz", + "resolved": "https://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz", "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", "dev": true, "requires": { @@ -12218,7 +12274,7 @@ }, "invert-kv": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/invert-kv/download/invert-kv-1.0.0.tgz?cache=0&sync_timestamp=1630996809231&other_urls=https%3A%2F%2Fregistry.nlark.com%2Finvert-kv%2Fdownload%2Finvert-kv-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/invert-kv/download/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, @@ -12234,7 +12290,7 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { @@ -12356,7 +12412,7 @@ }, "is-binary-path": { "version": "1.0.1", - "resolved": "https://registry.nlark.com/is-binary-path/download/is-binary-path-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/is-binary-path/download/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { @@ -12398,7 +12454,7 @@ }, "is-buffer": { "version": "1.1.6", - "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz?cache=0&sync_timestamp=1604432327227&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-buffer%2Fdownload%2Fis-buffer-1.1.6.tgz", + "resolved": "https://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz", "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=", "dev": true }, @@ -12410,7 +12466,7 @@ }, "is-ci": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/is-ci/download/is-ci-2.0.0.tgz?cache=0&sync_timestamp=1635261061017&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fis-ci%2Fdownload%2Fis-ci-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-ci/download/is-ci-2.0.0.tgz", "integrity": "sha1-a8YzQYGBDgS1wis9WJ/cpVAmQEw=", "dev": true, "requires": { @@ -12428,7 +12484,7 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { @@ -12483,7 +12539,7 @@ }, "is-extendable": { "version": "0.1.1", - "resolved": "https://registry.nlark.com/is-extendable/download/is-extendable-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz", "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, @@ -12524,13 +12580,13 @@ }, "is-module": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-module/-/is-module-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", "dev": true }, "is-negated-glob": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-negated-glob/download/is-negated-glob-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-negated-glob/download/is-negated-glob-1.0.0.tgz", "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", "dev": true }, @@ -12591,7 +12647,7 @@ }, "is-potential-custom-element-name": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "resolved": "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true }, @@ -12680,7 +12736,7 @@ }, "is-stream": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/is-stream/download/is-stream-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, @@ -12936,7 +12992,7 @@ }, "is-windows": { "version": "1.0.2", - "resolved": "https://registry.nlark.com/is-windows/download/is-windows-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/is-windows/download/is-windows-1.0.2.tgz", "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", "dev": true }, @@ -12952,13 +13008,13 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz?cache=0&sync_timestamp=1562592096220&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fisarray%2Fdownload%2Fisarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isexe": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/isexe/download/isexe-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/isexe/download/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isobject": { @@ -13961,7 +14017,7 @@ }, "jest-diff": { "version": "24.9.0", - "resolved": "https://registry.npmmirror.com/jest-diff/download/jest-diff-24.9.0.tgz", + "resolved": "https://registry.npm.taobao.org/jest-diff/download/jest-diff-24.9.0.tgz", "integrity": "sha1-kxt9DVd4obr3RSy4FuMl43JAVdo=", "dev": true, "requires": { @@ -14433,7 +14489,7 @@ }, "@types/istanbul-reports": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@types/istanbul-reports/download/@types/istanbul-reports-3.0.1.tgz?cache=0&sync_timestamp=1637266160892&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40types%2Fistanbul-reports%2Fdownload%2F%40types%2Fistanbul-reports-3.0.1.tgz", + "resolved": "https://registry.npmmirror.com/@types/istanbul-reports/download/@types/istanbul-reports-3.0.1.tgz", "integrity": "sha1-kVP+mLuivVZaY63ZQ21vDX+EaP8=", "dev": true, "requires": { @@ -14442,7 +14498,7 @@ }, "@types/yargs": { "version": "16.0.4", - "resolved": "https://registry.npmmirror.com/@types/yargs/download/@types/yargs-16.0.4.tgz?cache=0&sync_timestamp=1637271118840&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40types%2Fyargs%2Fdownload%2F%40types%2Fyargs-16.0.4.tgz", + "resolved": "https://registry.npmmirror.com/@types/yargs/download/@types/yargs-16.0.4.tgz", "integrity": "sha1-JqrZjdLCo45CEIbqmtQrnlFkKXc=", "dev": true, "requires": { @@ -14457,7 +14513,7 @@ }, "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz", + "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1618995588464&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz", "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", "dev": true, "requires": { @@ -14466,7 +14522,7 @@ }, "chalk": { "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/download/chalk-4.1.2.tgz", + "resolved": "https://registry.nlark.com/chalk/download/chalk-4.1.2.tgz?cache=0&sync_timestamp=1627646655305&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-4.1.2.tgz", "integrity": "sha1-qsTit3NKdAhnrrFr8CqtVWoeegE=", "dev": true, "requires": { @@ -14545,7 +14601,7 @@ "dependencies": { "ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-5.2.0.tgz", + "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-5.2.0.tgz?cache=0&sync_timestamp=1618995588464&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fansi-styles%2Fdownload%2Fansi-styles-5.2.0.tgz", "integrity": "sha1-B0SWkK1Fd30ZJKwquy/IiV26g2s=", "dev": true } @@ -14553,7 +14609,7 @@ }, "react-is": { "version": "17.0.2", - "resolved": "https://registry.npmmirror.com/react-is/download/react-is-17.0.2.tgz", + "resolved": "https://registry.npmmirror.com/react-is/download/react-is-17.0.2.tgz?cache=0&sync_timestamp=1637338596901&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Freact-is%2Fdownload%2Freact-is-17.0.2.tgz", "integrity": "sha1-5pHUqOnHiTZWVVOas3J2Kw77VPA=", "dev": true }, @@ -14570,7 +14626,7 @@ }, "jest-get-type": { "version": "24.9.0", - "resolved": "https://registry.npmmirror.com/jest-get-type/download/jest-get-type-24.9.0.tgz", + "resolved": "https://registry.npm.taobao.org/jest-get-type/download/jest-get-type-24.9.0.tgz?cache=0&sync_timestamp=1579655144842&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-get-type%2Fdownload%2Fjest-get-type-24.9.0.tgz", "integrity": "sha1-FoSgyKUPLkkBtmRK6GH1ee7S7w4=", "dev": true }, @@ -14863,7 +14919,7 @@ }, "jest-matcher-deep-close-to": { "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/jest-matcher-deep-close-to/download/jest-matcher-deep-close-to-2.0.1.tgz", + "resolved": "https://registry.nlark.com/jest-matcher-deep-close-to/download/jest-matcher-deep-close-to-2.0.1.tgz", "integrity": "sha1-L50NpE94oWo5BNGJguOV6Y43XFo=", "dev": true, "requires": { @@ -14872,7 +14928,7 @@ "dependencies": { "@jest/types": { "version": "25.5.0", - "resolved": "https://registry.npmmirror.com/@jest/types/download/@jest/types-25.5.0.tgz", + "resolved": "https://registry.nlark.com/@jest/types/download/@jest/types-25.5.0.tgz?cache=0&sync_timestamp=1624900057884&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40jest%2Ftypes%2Fdownload%2F%40jest%2Ftypes-25.5.0.tgz", "integrity": "sha1-TWpHk/e5WZ/DaAh3uFapfbzPKp0=", "dev": true, "requires": { @@ -14884,7 +14940,7 @@ }, "@types/yargs": { "version": "15.0.14", - "resolved": "https://registry.npmmirror.com/@types/yargs/download/@types/yargs-15.0.14.tgz?cache=0&sync_timestamp=1637271118840&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40types%2Fyargs%2Fdownload%2F%40types%2Fyargs-15.0.14.tgz", + "resolved": "https://registry.nlark.com/@types/yargs/download/@types/yargs-15.0.14.tgz", "integrity": "sha1-Jtgh3biecEkhYLZtEKDrbfj2+wY=", "dev": true, "requires": { @@ -14908,7 +14964,7 @@ }, "chalk": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/chalk/download/chalk-3.0.0.tgz", + "resolved": "https://registry.nlark.com/chalk/download/chalk-3.0.0.tgz?cache=0&sync_timestamp=1618995367379&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-3.0.0.tgz", "integrity": "sha1-P3PCv1JlkfV0zEksUeJFY0n4ROQ=", "dev": true, "requires": { @@ -14918,7 +14974,7 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/color-convert/download/color-convert-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", "dev": true, "requires": { @@ -14933,7 +14989,7 @@ }, "diff-sequences": { "version": "25.2.6", - "resolved": "https://registry.npmmirror.com/diff-sequences/download/diff-sequences-25.2.6.tgz", + "resolved": "https://registry.nlark.com/diff-sequences/download/diff-sequences-25.2.6.tgz?cache=0&sync_timestamp=1624900057366&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdiff-sequences%2Fdownload%2Fdiff-sequences-25.2.6.tgz", "integrity": "sha1-X0Z8AO3TU1K3vKRteSfWDmh6dt0=", "dev": true }, @@ -14945,7 +15001,7 @@ }, "jest-diff": { "version": "25.5.0", - "resolved": "https://registry.npmmirror.com/jest-diff/download/jest-diff-25.5.0.tgz", + "resolved": "https://registry.nlark.com/jest-diff/download/jest-diff-25.5.0.tgz", "integrity": "sha1-HdJu1k+WZnwGjO8Ca2d9+gGvz6k=", "dev": true, "requires": { @@ -14957,13 +15013,13 @@ }, "jest-get-type": { "version": "25.2.6", - "resolved": "https://registry.npmmirror.com/jest-get-type/download/jest-get-type-25.2.6.tgz", + "resolved": "https://registry.nlark.com/jest-get-type/download/jest-get-type-25.2.6.tgz?cache=0&sync_timestamp=1624900056951&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fjest-get-type%2Fdownload%2Fjest-get-type-25.2.6.tgz", "integrity": "sha1-Cwoy+riQi0TVCL6BaBSH26u42Hc=", "dev": true }, "jest-matcher-utils": { "version": "25.4.0", - "resolved": "https://registry.npmmirror.com/jest-matcher-utils/download/jest-matcher-utils-25.4.0.tgz", + "resolved": "https://registry.nlark.com/jest-matcher-utils/download/jest-matcher-utils-25.4.0.tgz", "integrity": "sha1-3D567EAqHlZ+2AtXK5rShYeIleY=", "dev": true, "requires": { @@ -14975,7 +15031,7 @@ }, "pretty-format": { "version": "25.5.0", - "resolved": "https://registry.npmmirror.com/pretty-format/download/pretty-format-25.5.0.tgz", + "resolved": "https://registry.nlark.com/pretty-format/download/pretty-format-25.5.0.tgz", "integrity": "sha1-eHPB13T2gsNLjUi2dDor8qxVeRo=", "dev": true, "requires": { @@ -14987,7 +15043,7 @@ }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/download/supports-color-7.2.0.tgz", + "resolved": "https://registry.nlark.com/supports-color/download/supports-color-7.2.0.tgz", "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", "dev": true, "requires": { @@ -14998,7 +15054,7 @@ }, "jest-matcher-utils": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/jest-matcher-utils/download/jest-matcher-utils-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/jest-matcher-utils/download/jest-matcher-utils-26.6.2.tgz?cache=0&sync_timestamp=1616701585427&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-matcher-utils%2Fdownload%2Fjest-matcher-utils-26.6.2.tgz", "integrity": "sha1-jm/W6GPIstMaxkcu6yN7xZXlPno=", "dev": true, "requires": { @@ -15010,7 +15066,7 @@ "dependencies": { "@jest/types": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/@jest/types/download/@jest/types-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/@jest/types/download/@jest/types-26.6.2.tgz", "integrity": "sha1-vvWlMgMOHYii9abZM/hOlyJu1I4=", "dev": true, "requires": { @@ -15047,7 +15103,7 @@ }, "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1611327117754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz", "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", "dev": true, "requires": { @@ -15066,7 +15122,7 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/color-convert/download/color-convert-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", "dev": true, "requires": { @@ -15081,19 +15137,19 @@ }, "diff-sequences": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/diff-sequences/download/diff-sequences-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/diff-sequences/download/diff-sequences-26.6.2.tgz", "integrity": "sha1-SLqZFX3hkjQS7tQdtrbUqpynwLE=", "dev": true }, "has-flag": { "version": "4.0.0", - "resolved": "https://registry.nlark.com/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1626715907927&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", "dev": true }, "jest-diff": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/jest-diff/download/jest-diff-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/jest-diff/download/jest-diff-26.6.2.tgz?cache=0&sync_timestamp=1616701585219&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-diff%2Fdownload%2Fjest-diff-26.6.2.tgz", "integrity": "sha1-GqdGi1LDpo19XF/c381eSb0WQ5Q=", "dev": true, "requires": { @@ -15105,13 +15161,13 @@ }, "jest-get-type": { "version": "26.3.0", - "resolved": "https://registry.npmmirror.com/jest-get-type/download/jest-get-type-26.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/jest-get-type/download/jest-get-type-26.3.0.tgz", "integrity": "sha1-6X3Dw/U8K0Bsp6+u1Ek7HQmRmeA=", "dev": true }, "pretty-format": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/pretty-format/download/pretty-format-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/pretty-format/download/pretty-format-26.6.2.tgz?cache=0&sync_timestamp=1616701219088&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-format%2Fdownload%2Fpretty-format-26.6.2.tgz", "integrity": "sha1-41wnBfFMt/4v6U+geDRbREEg/JM=", "dev": true, "requires": { @@ -15123,13 +15179,13 @@ }, "react-is": { "version": "17.0.2", - "resolved": "https://registry.npmmirror.com/react-is/download/react-is-17.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/react-is/download/react-is-17.0.2.tgz", "integrity": "sha1-5pHUqOnHiTZWVVOas3J2Kw77VPA=", "dev": true }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/download/supports-color-7.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1611394043517&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz", "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", "dev": true, "requires": { @@ -15140,7 +15196,7 @@ }, "jest-message-util": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/jest-message-util/download/jest-message-util-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/jest-message-util/download/jest-message-util-26.6.2.tgz?cache=0&sync_timestamp=1616701584149&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-message-util%2Fdownload%2Fjest-message-util-26.6.2.tgz", "integrity": "sha1-WBc3RK1vwFBrXSEVC5vlbvABygc=", "dev": true, "requires": { @@ -15157,7 +15213,7 @@ "dependencies": { "@jest/types": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/@jest/types/download/@jest/types-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/@jest/types/download/@jest/types-26.6.2.tgz", "integrity": "sha1-vvWlMgMOHYii9abZM/hOlyJu1I4=", "dev": true, "requires": { @@ -15194,7 +15250,7 @@ }, "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1611327117754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz", "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", "dev": true, "requires": { @@ -15222,7 +15278,7 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/color-convert/download/color-convert-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", "dev": true, "requires": { @@ -15252,7 +15308,7 @@ }, "has-flag": { "version": "4.0.0", - "resolved": "https://registry.nlark.com/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1626715907927&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", "dev": true }, @@ -15274,7 +15330,7 @@ }, "pretty-format": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/pretty-format/download/pretty-format-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/pretty-format/download/pretty-format-26.6.2.tgz?cache=0&sync_timestamp=1616701219088&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpretty-format%2Fdownload%2Fpretty-format-26.6.2.tgz", "integrity": "sha1-41wnBfFMt/4v6U+geDRbREEg/JM=", "dev": true, "requires": { @@ -15286,13 +15342,13 @@ }, "react-is": { "version": "17.0.2", - "resolved": "https://registry.npmmirror.com/react-is/download/react-is-17.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/react-is/download/react-is-17.0.2.tgz", "integrity": "sha1-5pHUqOnHiTZWVVOas3J2Kw77VPA=", "dev": true }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/download/supports-color-7.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1611394043517&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz", "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", "dev": true, "requires": { @@ -15411,7 +15467,7 @@ }, "jest-regex-util": { "version": "26.0.0", - "resolved": "https://registry.npmmirror.com/jest-regex-util/download/jest-regex-util-26.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/jest-regex-util/download/jest-regex-util-26.0.0.tgz?cache=0&sync_timestamp=1607352728942&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-regex-util%2Fdownload%2Fjest-regex-util-26.0.0.tgz", "integrity": "sha1-0l5xhLNuOf1GbDvEG+CXHoIf7ig=", "dev": true }, @@ -16700,7 +16756,7 @@ }, "jest-util": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/jest-util/download/jest-util-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/jest-util/download/jest-util-26.6.2.tgz?cache=0&sync_timestamp=1616701582882&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjest-util%2Fdownload%2Fjest-util-26.6.2.tgz", "integrity": "sha1-kHU12+TVpstMR6ybkm9q8pV2y8E=", "dev": true, "requires": { @@ -16714,7 +16770,7 @@ "dependencies": { "@jest/types": { "version": "26.6.2", - "resolved": "https://registry.npmmirror.com/@jest/types/download/@jest/types-26.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/@jest/types/download/@jest/types-26.6.2.tgz", "integrity": "sha1-vvWlMgMOHYii9abZM/hOlyJu1I4=", "dev": true, "requires": { @@ -16745,7 +16801,7 @@ }, "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.nlark.com/ansi-styles/download/ansi-styles-4.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-4.3.0.tgz?cache=0&sync_timestamp=1611327117754&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-styles%2Fdownload%2Fansi-styles-4.3.0.tgz", "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", "dev": true, "requires": { @@ -16773,7 +16829,7 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/color-convert/download/color-convert-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/color-convert/download/color-convert-2.0.1.tgz", "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", "dev": true, "requires": { @@ -16803,7 +16859,7 @@ }, "has-flag": { "version": "4.0.0", - "resolved": "https://registry.nlark.com/has-flag/download/has-flag-4.0.0.tgz?cache=0&sync_timestamp=1626715907927&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fhas-flag%2Fdownload%2Fhas-flag-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/has-flag/download/has-flag-4.0.0.tgz", "integrity": "sha1-lEdx/ZyByBJlxNaUGGDaBrtZR5s=", "dev": true }, @@ -16825,7 +16881,7 @@ }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/download/supports-color-7.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1611394043517&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz", "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=", "dev": true, "requires": { @@ -17150,7 +17206,7 @@ }, "js-tokens": { "version": "4.0.0", - "resolved": "https://registry.nlark.com/js-tokens/download/js-tokens-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz", "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=" }, "js-yaml": { @@ -17165,7 +17221,7 @@ }, "jsdom": { "version": "19.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", + "resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-19.0.0.tgz", "integrity": "sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==", "dev": true, "requires": { @@ -17206,7 +17262,7 @@ }, "acorn": { "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.7.1.tgz", "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", "dev": true }, @@ -17353,7 +17409,7 @@ }, "jsesc": { "version": "2.5.2", - "resolved": "https://registry.nlark.com/jsesc/download/jsesc-2.5.2.tgz", + "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-2.5.2.tgz", "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q=" }, "json-parse-even-better-errors": { @@ -17364,12 +17420,12 @@ }, "json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.nlark.com/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz", + "resolved": "https://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.4.1.tgz", "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=" }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.nlark.com/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/json-stable-stringify-without-jsonify/download/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "json5": { @@ -17385,7 +17441,7 @@ }, "jsonfile": { "version": "4.0.0", - "resolved": "https://registry.nlark.com/jsonfile/download/jsonfile-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { @@ -17428,7 +17484,7 @@ }, "last-run": { "version": "1.1.1", - "resolved": "https://registry.nlark.com/last-run/download/last-run-1.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/last-run/download/last-run-1.1.1.tgz", "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", "dev": true, "requires": { @@ -17447,7 +17503,7 @@ }, "lcid": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/lcid/download/lcid-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/lcid/download/lcid-1.0.0.tgz", "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { @@ -17465,7 +17521,7 @@ }, "leven": { "version": "3.1.0", - "resolved": "https://registry.nlark.com/leven/download/leven-3.1.0.tgz?cache=0&sync_timestamp=1628597922950&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fleven%2Fdownload%2Fleven-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/leven/download/leven-3.1.0.tgz", "integrity": "sha1-d4kd6DQGTMy6gq54QrtrFKE+1/I=", "dev": true }, @@ -17480,7 +17536,7 @@ }, "levn": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "resolved": "https://registry.npmmirror.com/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, "requires": { @@ -17512,7 +17568,7 @@ }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/load-json-file/download/load-json-file-1.1.0.tgz?cache=0&sync_timestamp=1631508607226&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fload-json-file%2Fdownload%2Fload-json-file-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/load-json-file/download/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { @@ -17552,7 +17608,7 @@ }, "loose-envify": { "version": "1.4.0", - "resolved": "https://registry.nlark.com/loose-envify/download/loose-envify-1.4.0.tgz", + "resolved": "https://registry.npm.taobao.org/loose-envify/download/loose-envify-1.4.0.tgz", "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=", "dev": true, "requires": { @@ -17561,7 +17617,7 @@ }, "lru-cache": { "version": "6.0.0", - "resolved": "https://registry.nlark.com/lru-cache/download/lru-cache-6.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/lru-cache/download/lru-cache-6.0.0.tgz", "integrity": "sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=", "requires": { "yallist": "^4.0.0" @@ -17595,7 +17651,7 @@ }, "make-error": { "version": "1.3.6", - "resolved": "https://registry.nlark.com/make-error/download/make-error-1.3.6.tgz", + "resolved": "https://registry.npm.taobao.org/make-error/download/make-error-1.3.6.tgz?cache=0&sync_timestamp=1582105630664&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-error%2Fdownload%2Fmake-error-1.3.6.tgz", "integrity": "sha1-LrLjfqm2fEiR9oShOUeZr0hM96I=", "dev": true }, @@ -17628,7 +17684,7 @@ }, "map-age-cleaner": { "version": "0.1.3", - "resolved": "https://registry.nlark.com/map-age-cleaner/download/map-age-cleaner-0.1.3.tgz?cache=0&sync_timestamp=1629750856019&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmap-age-cleaner%2Fdownload%2Fmap-age-cleaner-0.1.3.tgz", + "resolved": "https://registry.npm.taobao.org/map-age-cleaner/download/map-age-cleaner-0.1.3.tgz", "integrity": "sha1-fVg6cwZDTAVf5HSw9FB45uG0uSo=", "dev": true, "requires": { @@ -17637,13 +17693,13 @@ }, "map-cache": { "version": "0.2.2", - "resolved": "https://registry.nlark.com/map-cache/download/map-cache-0.2.2.tgz", + "resolved": "https://registry.npm.taobao.org/map-cache/download/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, "map-visit": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/map-visit/download/map-visit-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/map-visit/download/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { @@ -17664,7 +17720,7 @@ "dependencies": { "findup-sync": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/findup-sync/download/findup-sync-2.0.0.tgz?cache=0&sync_timestamp=1635766114067&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Ffindup-sync%2Fdownload%2Ffindup-sync-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/findup-sync/download/findup-sync-2.0.0.tgz", "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { @@ -17676,7 +17732,7 @@ }, "is-glob": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/is-glob/download/is-glob-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { @@ -17698,7 +17754,7 @@ }, "mem": { "version": "4.3.0", - "resolved": "https://registry.nlark.com/mem/download/mem-4.3.0.tgz?cache=0&sync_timestamp=1626534487701&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmem%2Fdownload%2Fmem-4.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/mem/download/mem-4.3.0.tgz", "integrity": "sha1-Rhr0l7xK4JYIzbLmDu+2m/90QXg=", "dev": true, "requires": { @@ -17717,7 +17773,7 @@ }, "merge-stream": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/merge-stream/download/merge-stream-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/merge-stream/download/merge-stream-2.0.0.tgz", "integrity": "sha1-UoI2KaFN0AyXcPtq1H3GMQ8sH2A=", "dev": true }, @@ -17767,19 +17823,19 @@ }, "mime": { "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/mime/download/mime-1.6.0.tgz", + "resolved": "https://registry.npm.taobao.org/mime/download/mime-1.6.0.tgz?cache=0&sync_timestamp=1560034758817&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime%2Fdownload%2Fmime-1.6.0.tgz", "integrity": "sha1-Ms2eXGRVO9WNGaVor0Uqz/BJgbE=", "dev": true }, "mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true }, "mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "requires": { @@ -17788,7 +17844,7 @@ }, "mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, @@ -17814,7 +17870,7 @@ }, "minimist": { "version": "1.2.5", - "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz", + "resolved": "https://registry.npm.taobao.org/minimist/download/minimist-1.2.5.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fminimist%2Fdownload%2Fminimist-1.2.5.tgz", "integrity": "sha1-Z9ZgFLZqaoqqDAg8X9WN9OTpdgI=", "dev": true }, @@ -17823,9 +17879,30 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==" }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "mixin-deep": { "version": "1.3.2", - "resolved": "https://registry.nlark.com/mixin-deep/download/mixin-deep-1.3.2.tgz", + "resolved": "https://registry.npm.taobao.org/mixin-deep/download/mixin-deep-1.3.2.tgz", "integrity": "sha1-ESC0PcNZp4Xc5ltVuC4lfM9HlWY=", "dev": true, "requires": { @@ -17835,7 +17912,7 @@ "dependencies": { "is-extendable": { "version": "1.0.1", - "resolved": "https://registry.nlark.com/is-extendable/download/is-extendable-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/is-extendable/download/is-extendable-1.0.1.tgz", "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { @@ -17844,6 +17921,12 @@ } } }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, "mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -17875,7 +17958,7 @@ }, "ms": { "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/ms/download/ms-2.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz", "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=" }, "mute-stdout": { @@ -17900,7 +17983,7 @@ }, "nanomatch": { "version": "1.2.13", - "resolved": "https://registry.nlark.com/nanomatch/download/nanomatch-1.2.13.tgz", + "resolved": "https://registry.npm.taobao.org/nanomatch/download/nanomatch-1.2.13.tgz", "integrity": "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=", "dev": true, "requires": { @@ -17919,7 +18002,7 @@ }, "natural-compare": { "version": "1.4.0", - "resolved": "https://registry.nlark.com/natural-compare/download/natural-compare-1.4.0.tgz", + "resolved": "https://registry.npm.taobao.org/natural-compare/download/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "natural-compare-lite": { @@ -17929,16 +18012,22 @@ }, "next-tick": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/next-tick/download/next-tick-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/next-tick/download/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "nice-try": { "version": "1.0.5", - "resolved": "https://registry.nlark.com/nice-try/download/nice-try-1.0.5.tgz", + "resolved": "https://registry.npm.taobao.org/nice-try/download/nice-try-1.0.5.tgz", "integrity": "sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y=", "dev": true }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmmirror.com/node-int64/-/node-int64-0.4.0.tgz", @@ -17953,7 +18042,7 @@ }, "normalize-package-data": { "version": "2.5.0", - "resolved": "https://registry.nlark.com/normalize-package-data/download/normalize-package-data-2.5.0.tgz?cache=0&sync_timestamp=1629301872905&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnormalize-package-data%2Fdownload%2Fnormalize-package-data-2.5.0.tgz", + "resolved": "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz", "integrity": "sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg=", "dev": true, "requires": { @@ -17983,7 +18072,7 @@ }, "npm-run-path": { "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/npm-run-path/download/npm-run-path-2.0.2.tgz?cache=0&sync_timestamp=1633420566316&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fnpm-run-path%2Fdownload%2Fnpm-run-path-2.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/npm-run-path/download/npm-run-path-2.0.2.tgz?cache=0&sync_timestamp=1577053500910&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnpm-run-path%2Fdownload%2Fnpm-run-path-2.0.2.tgz", "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { @@ -17992,13 +18081,13 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/number-is-nan/download/number-is-nan-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/number-is-nan/download/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "nwsapi": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "resolved": "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.0.tgz", "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", "dev": true }, @@ -18047,13 +18136,13 @@ }, "object-keys": { "version": "1.1.1", - "resolved": "https://registry.nlark.com/object-keys/download/object-keys-1.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/object-keys/download/object-keys-1.1.1.tgz", "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", "dev": true }, "object-visit": { "version": "1.0.1", - "resolved": "https://registry.nlark.com/object-visit/download/object-visit-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/object-visit/download/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { @@ -18097,7 +18186,7 @@ "dependencies": { "call-bind": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { @@ -18177,7 +18266,7 @@ "dependencies": { "call-bind": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { @@ -18217,7 +18306,7 @@ }, "once": { "version": "1.4.0", - "resolved": "https://registry.nlark.com/once/download/once-1.4.0.tgz", + "resolved": "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" @@ -18225,7 +18314,7 @@ }, "onetime": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { @@ -18245,13 +18334,13 @@ }, "opener": { "version": "1.5.2", - "resolved": "https://registry.nlark.com/opener/download/opener-1.5.2.tgz?cache=0&sync_timestamp=1618847055043&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fopener%2Fdownload%2Fopener-1.5.2.tgz", + "resolved": "https://registry.npm.taobao.org/opener/download/opener-1.5.2.tgz", "integrity": "sha1-XTfh81B3udysQwE3InGv3rKhNZg=", "dev": true }, "optionator": { "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "resolved": "https://registry.npmmirror.com/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { @@ -18280,7 +18369,7 @@ }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/os-locale/download/os-locale-1.4.0.tgz?cache=0&sync_timestamp=1633618260196&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fos-locale%2Fdownload%2Fos-locale-1.4.0.tgz", + "resolved": "https://registry.npm.taobao.org/os-locale/download/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { @@ -18295,7 +18384,7 @@ }, "p-finally": { "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-finally%2Fdownload%2Fp-finally-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/p-finally/download/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, @@ -18334,7 +18423,7 @@ }, "p-try": { "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/p-try/download/p-try-2.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz", "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=", "dev": true }, @@ -18387,7 +18476,7 @@ }, "parse-json": { "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/parse-json/download/parse-json-2.2.0.tgz?cache=0&sync_timestamp=1637475717072&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fparse-json%2Fdownload%2Fparse-json-2.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/parse-json/download/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { @@ -18396,7 +18485,7 @@ }, "parse-node-version": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/parse-node-version/download/parse-node-version-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/parse-node-version/download/parse-node-version-1.0.1.tgz", "integrity": "sha1-4rXb7eAOf6m8NjYH9TMn6LBzGJs=", "dev": true }, @@ -18408,20 +18497,20 @@ }, "parse5": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "resolved": "https://registry.npmmirror.com/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, "pascalcase": { "version": "0.1.1", - "resolved": "https://registry.nlark.com/pascalcase/download/pascalcase-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/pascalcase/download/pascalcase-0.1.1.tgz", "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, "path": { "version": "0.12.7", "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", "dev": true, "requires": { "process": "^0.11.1", @@ -18436,13 +18525,13 @@ }, "path-dirname": { "version": "1.0.2", - "resolved": "https://registry.nlark.com/path-dirname/download/path-dirname-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, "path-exists": { "version": "3.0.0", - "resolved": "https://registry.nlark.com/path-exists/download/path-exists-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/path-exists/download/path-exists-3.0.0.tgz", "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true }, @@ -18470,7 +18559,7 @@ }, "path-root": { "version": "0.1.1", - "resolved": "https://registry.nlark.com/path-root/download/path-root-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/path-root/download/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { @@ -18479,7 +18568,7 @@ }, "path-root-regex": { "version": "0.1.2", - "resolved": "https://registry.nlark.com/path-root-regex/download/path-root-regex-0.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/path-root-regex/download/path-root-regex-0.1.2.tgz", "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true }, @@ -18536,19 +18625,19 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/pify/download/pify-2.3.0.tgz?cache=0&sync_timestamp=1581697613983&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpify%2Fdownload%2Fpify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, "pinkie": { "version": "2.0.4", - "resolved": "https://registry.nlark.com/pinkie/download/pinkie-2.0.4.tgz", + "resolved": "https://registry.npm.taobao.org/pinkie/download/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, "pinkie-promise": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/pinkie-promise/download/pinkie-promise-2.0.1.tgz?cache=0&sync_timestamp=1618847023792&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpinkie-promise%2Fdownload%2Fpinkie-promise-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/pinkie-promise/download/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { @@ -18626,7 +18715,7 @@ }, "portfinder": { "version": "1.0.28", - "resolved": "https://registry.nlark.com/portfinder/download/portfinder-1.0.28.tgz", + "resolved": "https://registry.npm.taobao.org/portfinder/download/portfinder-1.0.28.tgz", "integrity": "sha1-Z8RiKFK9U3TdHdkA93n1NGL6x3g=", "dev": true, "requires": { @@ -18637,7 +18726,7 @@ "dependencies": { "debug": { "version": "3.2.7", - "resolved": "https://registry.npmmirror.com/debug/download/debug-3.2.7.tgz", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.7.tgz?cache=0&sync_timestamp=1607566580543&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.2.7.tgz", "integrity": "sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o=", "dev": true, "requires": { @@ -18657,19 +18746,19 @@ }, "posix-character-classes": { "version": "0.1.1", - "resolved": "https://registry.nlark.com/posix-character-classes/download/posix-character-classes-0.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/posix-character-classes/download/posix-character-classes-0.1.1.tgz", "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, "prelude-ls": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true }, "pretty-format": { "version": "24.9.0", - "resolved": "https://registry.npmmirror.com/pretty-format/download/pretty-format-24.9.0.tgz", + "resolved": "https://registry.npm.taobao.org/pretty-format/download/pretty-format-24.9.0.tgz", "integrity": "sha1-EvrDGzcBmk7qPBGqmpWet2KKp8k=", "dev": true, "requires": { @@ -18681,7 +18770,7 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-4.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-4.1.0.tgz", "integrity": "sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc=", "dev": true } @@ -18702,7 +18791,7 @@ "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true }, "process-nextick-args": { @@ -18711,6 +18800,12 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/prompts/-/prompts-2.4.2.tgz", @@ -18721,9 +18816,15 @@ "sisteransi": "^1.0.5" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, "psl": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "resolved": "https://registry.npmmirror.com/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, @@ -18795,7 +18896,7 @@ }, "punycode": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true }, @@ -18841,7 +18942,7 @@ }, "react-is": { "version": "16.13.1", - "resolved": "https://registry.npmmirror.com/react-is/download/react-is-16.13.1.tgz", + "resolved": "https://registry.npm.taobao.org/react-is/download/react-is-16.13.1.tgz", "integrity": "sha1-eJcppNw23imZ3BVt1sHZwYzqVqQ=", "dev": true }, @@ -18856,7 +18957,7 @@ }, "read-pkg": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/read-pkg/download/read-pkg-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/read-pkg/download/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { @@ -18867,7 +18968,7 @@ }, "read-pkg-up": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/read-pkg-up/download/read-pkg-up-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/read-pkg-up/download/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { @@ -18877,7 +18978,7 @@ "dependencies": { "find-up": { "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/find-up/download/find-up-1.1.2.tgz?cache=0&sync_timestamp=1633620747957&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Ffind-up%2Fdownload%2Ffind-up-1.1.2.tgz", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { @@ -18887,7 +18988,7 @@ }, "path-exists": { "version": "2.1.0", - "resolved": "https://registry.nlark.com/path-exists/download/path-exists-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { @@ -18924,7 +19025,7 @@ }, "readdirp": { "version": "2.2.1", - "resolved": "https://registry.nlark.com/readdirp/download/readdirp-2.2.1.tgz", + "resolved": "https://registry.npm.taobao.org/readdirp/download/readdirp-2.2.1.tgz?cache=0&sync_timestamp=1575629866543&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freaddirp%2Fdownload%2Freaddirp-2.2.1.tgz", "integrity": "sha1-DodiKjMlqjPokihcr4tOhGUppSU=", "dev": true, "requires": { @@ -18935,7 +19036,7 @@ }, "rechoir": { "version": "0.6.2", - "resolved": "https://registry.nlark.com/rechoir/download/rechoir-0.6.2.tgz?cache=0&sync_timestamp=1627101677944&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frechoir%2Fdownload%2Frechoir-0.6.2.tgz", + "resolved": "https://registry.npm.taobao.org/rechoir/download/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { @@ -18975,7 +19076,7 @@ }, "regex-not": { "version": "1.0.2", - "resolved": "https://registry.nlark.com/regex-not/download/regex-not-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/regex-not/download/regex-not-1.0.2.tgz", "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { @@ -19048,7 +19149,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "https://registry.nlark.com/jsesc/download/jsesc-0.5.0.tgz", + "resolved": "https://registry.npm.taobao.org/jsesc/download/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -19077,7 +19178,7 @@ }, "remove-trailing-separator": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz", "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, @@ -19112,7 +19213,7 @@ }, "require-directory": { "version": "2.1.1", - "resolved": "https://registry.nlark.com/require-directory/download/require-directory-2.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/require-directory/download/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, @@ -19124,7 +19225,7 @@ }, "requires-port": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/requires-port/download/requires-port-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, @@ -19180,7 +19281,7 @@ }, "resolve-url": { "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/resolve-url/download/resolve-url-0.2.1.tgz", + "resolved": "https://registry.npm.taobao.org/resolve-url/download/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, @@ -19192,7 +19293,7 @@ }, "ret": { "version": "0.1.15", - "resolved": "https://registry.nlark.com/ret/download/ret-0.1.15.tgz", + "resolved": "https://registry.npm.taobao.org/ret/download/ret-0.1.15.tgz", "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=", "dev": true }, @@ -19275,7 +19376,7 @@ }, "@babel/highlight": { "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.18.6.tgz", "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { @@ -19432,7 +19533,7 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.nlark.com/safe-buffer/download/safe-buffer-5.1.2.tgz?cache=0&sync_timestamp=1618847044058&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsafe-buffer%2Fdownload%2Fsafe-buffer-5.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" }, "safe-regex": { @@ -19487,13 +19588,13 @@ }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.nlark.com/safer-buffer/download/safer-buffer-2.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsafer-buffer%2Fdownload%2Fsafer-buffer-2.1.2.tgz", "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo=", "dev": true }, "saxes": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "resolved": "https://registry.npmmirror.com/saxes/-/saxes-5.0.1.tgz", "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", "dev": true, "requires": { @@ -19514,7 +19615,7 @@ }, "semver-greatest-satisfied-range": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/semver-greatest-satisfied-range/download/semver-greatest-satisfied-range-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/semver-greatest-satisfied-range/download/semver-greatest-satisfied-range-1.1.0.tgz", "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", "dev": true, "requires": { @@ -19532,13 +19633,13 @@ }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/set-blocking/download/set-blocking-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/set-blocking/download/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "set-value": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/set-value/download/set-value-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/set-value/download/set-value-2.0.1.tgz", "integrity": "sha1-oY1AUw5vB95CKMfe/kInr4ytAFs=", "dev": true, "requires": { @@ -19550,7 +19651,7 @@ "dependencies": { "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -19612,7 +19713,7 @@ }, "side-channel": { "version": "1.0.4", - "resolved": "https://registry.nlark.com/side-channel/download/side-channel-1.0.4.tgz", + "resolved": "https://registry.npm.taobao.org/side-channel/download/side-channel-1.0.4.tgz", "integrity": "sha1-785cj9wQTudRslxY1CkAEfpeos8=", "dev": true, "requires": { @@ -19654,12 +19755,12 @@ }, "slash": { "version": "3.0.0", - "resolved": "https://registry.nlark.com/slash/download/slash-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/slash/download/slash-3.0.0.tgz", "integrity": "sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ=" }, "snapdragon": { "version": "0.8.2", - "resolved": "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz?cache=0&sync_timestamp=1617971785350&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsnapdragon%2Fdownload%2Fsnapdragon-0.8.2.tgz", + "resolved": "https://registry.npm.taobao.org/snapdragon/download/snapdragon-0.8.2.tgz", "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "requires": { @@ -19675,7 +19776,7 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/download/debug-2.6.9.tgz", + "resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz", "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", "dev": true, "requires": { @@ -19693,7 +19794,7 @@ }, "extend-shallow": { "version": "2.0.1", - "resolved": "https://registry.nlark.com/extend-shallow/download/extend-shallow-2.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { @@ -19702,7 +19803,7 @@ }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/download/ms-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true } @@ -19730,7 +19831,7 @@ }, "is-accessor-descriptor": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { @@ -19739,7 +19840,7 @@ }, "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz", "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { @@ -19761,7 +19862,7 @@ }, "snapdragon-util": { "version": "3.0.1", - "resolved": "https://registry.nlark.com/snapdragon-util/download/snapdragon-util-3.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/snapdragon-util/download/snapdragon-util-3.0.1.tgz", "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { @@ -19830,7 +19931,7 @@ }, "sparkles": { "version": "1.0.1", - "resolved": "https://registry.nlark.com/sparkles/download/sparkles-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/sparkles/download/sparkles-1.0.1.tgz", "integrity": "sha1-AI22XtzmxQ7sDF4ijhlFBh3QQ3w=", "dev": true }, @@ -19874,7 +19975,7 @@ }, "split-string": { "version": "3.1.0", - "resolved": "https://registry.nlark.com/split-string/download/split-string-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz", "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { @@ -19883,13 +19984,13 @@ }, "sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.nlark.com/sprintf-js/download/sprintf-js-1.0.3.tgz?cache=0&sync_timestamp=1618847174560&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsprintf-js%2Fdownload%2Fsprintf-js-1.0.3.tgz", + "resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "stack-trace": { "version": "0.0.10", - "resolved": "https://registry.nlark.com/stack-trace/download/stack-trace-0.0.10.tgz?cache=0&sync_timestamp=1620387179562&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fstack-trace%2Fdownload%2Fstack-trace-0.0.10.tgz", + "resolved": "https://registry.npm.taobao.org/stack-trace/download/stack-trace-0.0.10.tgz", "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", "dev": true }, @@ -19904,7 +20005,7 @@ "dependencies": { "escape-string-regexp": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/escape-string-regexp/download/escape-string-regexp-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-2.0.0.tgz", "integrity": "sha1-owME6Z2qMuI7L9IPUbq9B8/8o0Q=", "dev": true } @@ -20160,7 +20261,7 @@ "dependencies": { "call-bind": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { @@ -20211,7 +20312,7 @@ "dependencies": { "call-bind": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { @@ -20275,7 +20376,7 @@ }, "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/strip-eof/download/strip-eof-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/strip-eof/download/strip-eof-1.0.0.tgz", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, @@ -20301,7 +20402,7 @@ }, "supports-color": { "version": "5.5.0", - "resolved": "https://registry.npmmirror.com/supports-color/download/supports-color-5.5.0.tgz", + "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-5.5.0.tgz", "integrity": "sha1-4uaaRKyHcveKHsCzW2id9lMO/I8=", "requires": { "has-flag": "^3.0.0" @@ -20336,7 +20437,7 @@ }, "supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "sver-compat": { @@ -20351,7 +20452,7 @@ }, "symbol-tree": { "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, @@ -20364,6 +20465,28 @@ "acorn-node": "^1.2.0" } }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + } + } + }, "terminal-link": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/terminal-link/-/terminal-link-2.1.1.tgz", @@ -20400,7 +20523,7 @@ }, "source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "resolved": "https://registry.npmmirror.com/source-map-support/download/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { @@ -20423,7 +20546,7 @@ }, "text-table": { "version": "0.2.0", - "resolved": "https://registry.nlark.com/text-table/download/text-table-0.2.0.tgz?cache=0&sync_timestamp=1618847142316&other_urls=https%3A%2F%2Fregistry.nlark.com%2Ftext-table%2Fdownload%2Ftext-table-0.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/text-table/download/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "tfig": { @@ -20439,13 +20562,13 @@ "dependencies": { "ansi-regex": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-4.1.1.tgz", "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", "dev": true }, "cliui": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "resolved": "https://registry.npmmirror.com/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { @@ -20456,25 +20579,25 @@ }, "emoji-regex": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-7.0.3.tgz", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "string-width": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { @@ -20485,7 +20608,7 @@ }, "strip-ansi": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { @@ -20500,7 +20623,7 @@ }, "wrap-ansi": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { @@ -20511,13 +20634,13 @@ }, "y18n": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "yargs": { "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "resolved": "https://registry.npmmirror.com/yargs/-/yargs-13.3.2.tgz", "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { @@ -20535,7 +20658,7 @@ }, "yargs-parser": { "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-13.1.2.tgz", "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { @@ -20585,7 +20708,7 @@ }, "time-stamp": { "version": "1.1.0", - "resolved": "https://registry.nlark.com/time-stamp/download/time-stamp-1.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/time-stamp/download/time-stamp-1.1.0.tgz", "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, @@ -20609,13 +20732,13 @@ }, "tmpl": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "resolved": "https://registry.npmmirror.com/tmpl/-/tmpl-1.0.5.tgz", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "to-absolute-glob": { "version": "2.0.2", - "resolved": "https://registry.nlark.com/to-absolute-glob/download/to-absolute-glob-2.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/to-absolute-glob/download/to-absolute-glob-2.0.2.tgz", "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", "dev": true, "requires": { @@ -20625,12 +20748,12 @@ }, "to-fast-properties": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/to-fast-properties/download/to-fast-properties-2.0.0.tgz?cache=0&sync_timestamp=1628418893613&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fto-fast-properties%2Fdownload%2Fto-fast-properties-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/to-fast-properties/download/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "to-object-path": { "version": "0.3.0", - "resolved": "https://registry.nlark.com/to-object-path/download/to-object-path-0.3.0.tgz", + "resolved": "https://registry.npm.taobao.org/to-object-path/download/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { @@ -20650,7 +20773,7 @@ }, "to-regex": { "version": "3.0.2", - "resolved": "https://registry.nlark.com/to-regex/download/to-regex-3.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/to-regex/download/to-regex-3.0.2.tgz", "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { @@ -20681,7 +20804,7 @@ }, "tough-cookie": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-4.0.0.tgz", "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", "dev": true, "requires": { @@ -20722,13 +20845,13 @@ "dependencies": { "mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/download/mkdirp-1.0.4.tgz", + "resolved": "https://registry.npm.taobao.org/mkdirp/download/mkdirp-1.0.4.tgz?cache=0&sync_timestamp=1587535418745&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-1.0.4.tgz", "integrity": "sha1-PrXtYmInVteaXw4qIh3+utdcL34=", "dev": true }, "semver": { "version": "7.3.5", - "resolved": "https://registry.nlark.com/semver/download/semver-7.3.5.tgz?cache=0&sync_timestamp=1618846864940&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fsemver%2Fdownload%2Fsemver-7.3.5.tgz", + "resolved": "https://registry.npm.taobao.org/semver/download/semver-7.3.5.tgz?cache=0&sync_timestamp=1616463603361&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsemver%2Fdownload%2Fsemver-7.3.5.tgz", "integrity": "sha1-C2Ich5NI2JmOSw5L6Us/EuYBjvc=", "dev": true, "requires": { @@ -21120,7 +21243,7 @@ }, "unc-path-regex": { "version": "0.1.2", - "resolved": "https://registry.nlark.com/unc-path-regex/download/unc-path-regex-0.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/unc-path-regex/download/unc-path-regex-0.1.2.tgz", "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, @@ -21190,7 +21313,7 @@ }, "union": { "version": "0.5.0", - "resolved": "https://registry.nlark.com/union/download/union-0.5.0.tgz", + "resolved": "https://registry.npm.taobao.org/union/download/union-0.5.0.tgz", "integrity": "sha1-ssEb6E9gU4U3uEbtuboma6AJAHU=", "dev": true, "requires": { @@ -21199,7 +21322,7 @@ }, "union-value": { "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/union-value/download/union-value-1.0.1.tgz", + "resolved": "https://registry.npm.taobao.org/union-value/download/union-value-1.0.1.tgz", "integrity": "sha1-C2/nuDWuzaYcbqTU8CwUIh4QmEc=", "dev": true, "requires": { @@ -21221,13 +21344,13 @@ }, "universalify": { "version": "0.1.2", - "resolved": "https://registry.nlark.com/universalify/download/universalify-0.1.2.tgz", + "resolved": "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz", "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", "dev": true }, "unset-value": { "version": "1.0.0", - "resolved": "https://registry.nlark.com/unset-value/download/unset-value-1.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/unset-value/download/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { @@ -21237,7 +21360,7 @@ "dependencies": { "has-value": { "version": "0.3.1", - "resolved": "https://registry.nlark.com/has-value/download/has-value-0.3.1.tgz", + "resolved": "https://registry.npm.taobao.org/has-value/download/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { @@ -21259,7 +21382,7 @@ }, "has-values": { "version": "0.1.4", - "resolved": "https://registry.nlark.com/has-values/download/has-values-0.1.4.tgz", + "resolved": "https://registry.npm.taobao.org/has-values/download/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true }, @@ -21273,7 +21396,7 @@ }, "upath": { "version": "1.2.0", - "resolved": "https://registry.npm.taobao.org/upath/download/upath-1.2.0.tgz", + "resolved": "https://registry.npm.taobao.org/upath/download/upath-1.2.0.tgz?cache=0&sync_timestamp=1567457281208&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fupath%2Fdownload%2Fupath-1.2.0.tgz", "integrity": "sha1-j2bbzVWog6za5ECK+LA1pQRMGJQ=", "dev": true }, @@ -21303,7 +21426,7 @@ }, "urix": { "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/urix/download/urix-0.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/urix/download/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, @@ -21327,13 +21450,13 @@ }, "url-join": { "version": "2.0.5", - "resolved": "https://registry.nlark.com/url-join/download/url-join-2.0.5.tgz", + "resolved": "https://registry.npm.taobao.org/url-join/download/url-join-2.0.5.tgz", "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", "dev": true }, "use": { "version": "3.1.1", - "resolved": "https://registry.nlark.com/use/download/use-3.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/use/download/use-3.1.1.tgz", "integrity": "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=", "dev": true }, @@ -21348,7 +21471,7 @@ "dependencies": { "inherits": { "version": "2.0.3", - "resolved": "https://registry.nlark.com/inherits/download/inherits-2.0.3.tgz", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true } @@ -21356,7 +21479,7 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.nlark.com/util-deprecate/download/util-deprecate-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, @@ -21382,7 +21505,7 @@ }, "validate-npm-package-license": { "version": "3.0.4", - "resolved": "https://registry.nlark.com/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz", + "resolved": "https://registry.npm.taobao.org/validate-npm-package-license/download/validate-npm-package-license-3.0.4.tgz", "integrity": "sha1-/JH2uce6FchX9MssXe/uw51PQQo=", "dev": true, "requires": { @@ -21392,7 +21515,7 @@ }, "value-or-function": { "version": "3.0.0", - "resolved": "https://registry.nlark.com/value-or-function/download/value-or-function-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/value-or-function/download/value-or-function-3.0.0.tgz", "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, @@ -21537,7 +21660,7 @@ }, "w3c-hr-time": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "resolved": "https://registry.npmmirror.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", "dev": true, "requires": { @@ -21769,7 +21892,7 @@ }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.nlark.com/wrappy/download/wrappy-1.0.2.tgz?cache=0&sync_timestamp=1619133505879&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwrappy%2Fdownload%2Fwrappy-1.0.2.tgz", + "resolved": "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { @@ -21792,7 +21915,7 @@ }, "xmlchars": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, @@ -21816,12 +21939,12 @@ }, "yallist": { "version": "4.0.0", - "resolved": "https://registry.nlark.com/yallist/download/yallist-4.0.0.tgz?cache=0&sync_timestamp=1622604530774&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fyallist%2Fdownload%2Fyallist-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/yallist/download/yallist-4.0.0.tgz", "integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=" }, "yargs": { "version": "12.0.5", - "resolved": "https://registry.npmmirror.com/yargs/download/yargs-12.0.5.tgz?cache=0&sync_timestamp=1632605487521&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fyargs%2Fdownload%2Fyargs-12.0.5.tgz", + "resolved": "https://registry.npm.taobao.org/yargs/download/yargs-12.0.5.tgz?cache=0&sync_timestamp=1583129847322&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs%2Fdownload%2Fyargs-12.0.5.tgz", "integrity": "sha1-BfWZe2CWR7ZPZrgeO0sQo2jnrRM=", "dev": true, "requires": { @@ -21841,13 +21964,13 @@ "dependencies": { "ansi-regex": { "version": "3.0.0", - "resolved": "https://registry.nlark.com/ansi-regex/download/ansi-regex-3.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-3.0.0.tgz?cache=0&sync_timestamp=1570188663907&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fansi-regex%2Fdownload%2Fansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "cliui": { "version": "4.1.0", - "resolved": "https://registry.nlark.com/cliui/download/cliui-4.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/cliui/download/cliui-4.1.0.tgz?cache=0&sync_timestamp=1573943292170&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcliui%2Fdownload%2Fcliui-4.1.0.tgz", "integrity": "sha1-NIQi2+gtgAswIu709qwQvy5NG0k=", "dev": true, "requires": { @@ -21867,13 +21990,13 @@ }, "invert-kv": { "version": "2.0.0", - "resolved": "https://registry.nlark.com/invert-kv/download/invert-kv-2.0.0.tgz?cache=0&sync_timestamp=1630996809231&other_urls=https%3A%2F%2Fregistry.nlark.com%2Finvert-kv%2Fdownload%2Finvert-kv-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/invert-kv/download/invert-kv-2.0.0.tgz", "integrity": "sha1-c5P1r6Weyf9fZ6J2INEcIm4+7AI=", "dev": true }, "lcid": { "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/lcid/download/lcid-2.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/lcid/download/lcid-2.0.0.tgz", "integrity": "sha1-bvXS32DlL4LrIopMNz6NHzlyU88=", "dev": true, "requires": { @@ -21892,7 +22015,7 @@ }, "os-locale": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/os-locale/download/os-locale-3.1.0.tgz?cache=0&sync_timestamp=1633618260196&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fos-locale%2Fdownload%2Fos-locale-3.1.0.tgz", + "resolved": "https://registry.npm.taobao.org/os-locale/download/os-locale-3.1.0.tgz", "integrity": "sha1-qAKm7hfyTBBIOrmTVxnO9O0Wvxo=", "dev": true, "requires": { @@ -21918,7 +22041,7 @@ }, "string-width": { "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/string-width/download/string-width-2.1.1.tgz?cache=0&sync_timestamp=1632421309919&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fstring-width%2Fdownload%2Fstring-width-2.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-2.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstring-width%2Fdownload%2Fstring-width-2.1.1.tgz", "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { @@ -21928,7 +22051,7 @@ }, "strip-ansi": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/download/strip-ansi-4.0.0.tgz", + "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-4.0.0.tgz?cache=0&sync_timestamp=1573280518303&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-ansi%2Fdownload%2Fstrip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { @@ -21949,7 +22072,7 @@ }, "yargs-parser": { "version": "11.1.1", - "resolved": "https://registry.npmmirror.com/yargs-parser/download/yargs-parser-11.1.1.tgz?cache=0&sync_timestamp=1637031045984&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fyargs-parser%2Fdownload%2Fyargs-parser-11.1.1.tgz", + "resolved": "https://registry.npm.taobao.org/yargs-parser/download/yargs-parser-11.1.1.tgz?cache=0&sync_timestamp=1583130314354&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyargs-parser%2Fdownload%2Fyargs-parser-11.1.1.tgz", "integrity": "sha1-h5oIZZc7yp9rq1y987HGfsfTvPQ=", "dev": true, "requires": { diff --git a/package.json b/package.json index 2a7ceb35714..6276d27946c 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "async": "^2.6.4", + "axios": "^1.4.0", "babelify": "^10.0.0", "browserify": "^17.0.0", "chalk": "^2.4.1", @@ -69,10 +70,13 @@ "jest-extended": "^1.1.0", "jest-matcher-deep-close-to": "^2.0.1", "jsdom": "^19.0.0", + "node-fetch": "^2.6.1", "path": "^0.12.7", "pngjs": "^6.0.0", + "progress": "^2.0.3", "spectorjs": "^0.9.15", "stats.js": "^0.17.0", + "tar": "^6.1.15", "tmp": "^0.2.1", "tree-kill": "^1.2.0", "ts-jest": "^26.5.4", From ebbba606ca3d5b2c35d8cb2d7d59d2aad1955dd7 Mon Sep 17 00:00:00 2001 From: mmyduckx <308303735@qq.com> Date: Thu, 20 Jul 2023 16:33:16 +0800 Subject: [PATCH 008/184] Fix videoplayer status after pause&finish (#15782) * fix videoplayer.isplaying status after pause * fix isPlaying status when play video finish --- cocos/video/video-player-impl.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos/video/video-player-impl.ts b/cocos/video/video-player-impl.ts index ac921c4828f..cc9a4ba7d64 100644 --- a/cocos/video/video-player-impl.ts +++ b/cocos/video/video-player-impl.ts @@ -163,11 +163,11 @@ export abstract class VideoPlayerImpl { } public onPause (e: Event): void { + this._playing = false; if (this._ignorePause) { this._ignorePause = false; return; } - this._playing = false; this.dispatchEvent(EventType.PAUSED); } @@ -178,6 +178,7 @@ export abstract class VideoPlayerImpl { } public onEnded (e: Event): void { + this._playing = false; this.dispatchEvent(EventType.COMPLETED); } @@ -193,7 +194,6 @@ export abstract class VideoPlayerImpl { } } - // public play (): void { if (this._loadedMeta || this._loaded) { this.canPlay(); From 6d666d2f1dfda58a354efb16892ec0898d7480f4 Mon Sep 17 00:00:00 2001 From: qiuguohua Date: Thu, 20 Jul 2023 17:32:12 +0800 Subject: [PATCH 009/184] Fix the problem of incorrect screen resolution after resize. (#15785) --- native/cocos/engine/Engine.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/native/cocos/engine/Engine.cpp b/native/cocos/engine/Engine.cpp index f376d142c1d..50d34212923 100644 --- a/native/cocos/engine/Engine.cpp +++ b/native/cocos/engine/Engine.cpp @@ -323,10 +323,12 @@ bool Engine::redirectWindowEvent(const WindowEvent &ev) { isHandled = true; } else if (ev.type == WindowEvent::Type::SIZE_CHANGED || ev.type == WindowEvent::Type::RESIZED) { - events::Resize::broadcast(ev.width, ev.height, ev.windowId); auto *w = CC_GET_SYSTEM_WINDOW(ev.windowId); CC_ASSERT(w); w->setViewSize(ev.width, ev.height); + // Because the ts layer calls the getviewsize interface in response to resize. + // So we need to set the view size when sending the message. + events::Resize::broadcast(ev.width, ev.height, ev.windowId); isHandled = true; } else if (ev.type == WindowEvent::Type::HIDDEN || ev.type == WindowEvent::Type::MINIMIZED) { From 9cffcaa84cc21b0470432b76f54d6adc0c40ab92 Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Thu, 20 Jul 2023 19:08:32 +0800 Subject: [PATCH 010/184] add multi-layers lighting model and fix direct specular (#15778) --- .../assets/chunks/common/lighting/brdf.chunk | 27 +- .../assets/chunks/common/lighting/bxdf.chunk | 49 ++- .../lighting-intermediate-data.chunk | 11 +- .../data-structures/lighting-result.chunk | 28 +- .../lighting-flow/common-flow.chunk | 57 ++- .../model-functions/standard.chunk | 105 ++++- .../model-functions/toon.chunk | 18 + .../surfaces/data-structures/standard.chunk | 7 +- .../default-functions/standard-fs.chunk | 45 +- .../effect-macros/common-macros.chunk | 11 +- .../module-functions/debug-view.chunk | 31 +- .../module-functions/standard-fs.chunk | 115 ++++-- .../surfaces/module-functions/toon-fs.chunk | 11 +- .../surfaces/module-functions/unlit-fs.chunk | 6 +- .../assets/effects/advanced/car-paint.effect | 383 ++++++++++++++++++ .../effects/advanced/car-paint.effect.meta | 11 + editor/assets/effects/advanced/glass.effect | 354 ++++++++++++++++ .../assets/effects/advanced/glass.effect.meta | 11 + editor/assets/effects/advanced/hair.effect | 2 +- .../dcc/vat/houdini-fluid-v3-liquid.effect | 2 +- .../util/dcc/vat/zeno-fluid-liquid.effect | 2 +- 21 files changed, 1186 insertions(+), 100 deletions(-) create mode 100644 editor/assets/effects/advanced/car-paint.effect create mode 100644 editor/assets/effects/advanced/car-paint.effect.meta create mode 100644 editor/assets/effects/advanced/glass.effect create mode 100644 editor/assets/effects/advanced/glass.effect.meta diff --git a/editor/assets/chunks/common/lighting/brdf.chunk b/editor/assets/chunks/common/lighting/brdf.chunk index 976a93914bc..ef4fea792a1 100644 --- a/editor/assets/chunks/common/lighting/brdf.chunk +++ b/editor/assets/chunks/common/lighting/brdf.chunk @@ -1,5 +1,6 @@ #include +// for dielectric(non-metal) surfaces float F0ToIor(float F0) { return 2.0f / (1.0f - sqrt(F0)) - 1.0f; @@ -11,9 +12,15 @@ float IorToF0(float ior) return F0_sqrt * F0_sqrt; } -float V_Kelemen(float LoH) +float square(float a) { return a * a;} +vec2 square(vec2 a) { return a * a;} +vec3 square(vec3 a) { return a * a;} +float G_Schlick( float roughness, float NoV, float NoL ) { - return 0.25 / (LoH * LoH); + float k = square( 0.5 + 0.5*roughness ); + float G_SchlickV = NoV * (1.0 - k) + k; + float G_SchlickL = NoL * (1.0 - k) + k; + return 0.25 / ( G_SchlickV * G_SchlickL ); } vec3 F_Schlick( vec3 specularColor, float VoH ) @@ -22,6 +29,12 @@ vec3 F_Schlick( vec3 specularColor, float VoH ) float selfShadowTerm = saturate(50.0 * specularColor.g); return specularColor * (1.0 - Fc) + vec3(selfShadowTerm * Fc); } +vec3 F_SchlickMultiplier( vec3 specularColor, float VoH ) +{ + float Fc = exp2( (-5.55473 * VoH - 6.98316) * VoH ); + float selfShadowTerm = saturate(50.0 * specularColor.g); + return vec3(1.0 - Fc) + vec3(selfShadowTerm * Fc) / (specularColor + vec3(EPSILON)); +} float D_GGX(float roughness, float NoH) { @@ -92,6 +105,16 @@ vec3 IntegratedGFApprox (vec3 specular, float roughness, float NoV) { AB.y *= clamp(50.0 * specular.g, 0.0, 1.0); return max(vec3(0.0), specular * AB.x + AB.y); } +void IntegratedGFMultiplier (out vec3 integratedGF, out vec3 integratedF, vec3 specular, float roughness, float NoV) { + const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); + const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); + vec4 r = roughness * c0 + c1; + float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y; + vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw; + AB.y *= clamp(50.0 * specular.g, 0.0, 1.0); + integratedF = vec3(max(0.0, AB.x)); + integratedGF = max(vec3(0.0), vec3(AB.x) + vec3(AB.y) / (specular + EPSILON_LOWP)); +} //Diffuse_Lambert #define DiffuseCoefficient_EnergyConservation INV_PI diff --git a/editor/assets/chunks/common/lighting/bxdf.chunk b/editor/assets/chunks/common/lighting/bxdf.chunk index b3fd91dfbc7..ba06af07417 100644 --- a/editor/assets/chunks/common/lighting/bxdf.chunk +++ b/editor/assets/chunks/common/lighting/bxdf.chunk @@ -1,5 +1,6 @@ // saturated N dot V +// for env reflection with dielectric(non-metal) and smooth surfaces float CalculateFresnelCoefficient(float ior, float NoVSat) { float g, c, n, prev, next; @@ -13,11 +14,49 @@ float CalculateFresnelCoefficient(float ior, float NoVSat) return 0.5 * prev * (1.0 + next); } +// for arbitary smooth surfaces +float CalculateFresnelCoefficient(float F0, float F90, float NoVSat) +{ + return mix(F90, F0, NoVSat); +} + vec3 CalculateScattering(vec3 unscatteredColor, float distance, float outScatterExtinctCoef, float inScatterExtinctCoef, float inScatterCoef, vec3 inScatterColor, vec3 outScatterColor) { - vec2 e = vec2(outScatterExtinctCoef, inScatterExtinctCoef * inScatterCoef); - vec2 extinction = exp(-e * distance); - vec3 inScattered = (1.0 - extinction.y) * inScatterColor; - vec3 outScattered = unscatteredColor * extinction.x * outScatterColor; - return outScattered + inScattered; + vec2 e = vec2(outScatterExtinctCoef, inScatterExtinctCoef * inScatterCoef); + vec2 extinction = exp(-e * distance); + vec3 inScattered = (1.0 - extinction.y) * inScatterColor; + vec3 outScattered = unscatteredColor * extinction.x * outScatterColor; + return outScattered + inScattered; +} + + +// LastLayerF for temporary use +// S is spec without GF +void InitializeLayerBlending(out vec3 blendedBaseLayerD, out vec3 blendedBaseLayerS, + out vec3 blendedSubLayerD, out vec3 blendedSubLayerS, + out vec3 lastLayerF, + in vec3 baseD, in vec3 baseS + ) +{ + blendedBaseLayerD = baseD; + blendedBaseLayerS = baseS; + blendedSubLayerD = blendedSubLayerS = vec3(0.0); + lastLayerF = vec3(1.0); +} + +// use subLayerF instead of subLayerGF for ior-dependent 0-1 range +void CalculateLayerBlending(inout vec3 blendedBaseLayerD, inout vec3 blendedBaseLayerS, + inout vec3 blendedSubLayerD, inout vec3 blendedSubLayerS, + inout vec3 lastLayerF, + in vec3 subLayerD, in vec3 subLayerDiffuseColor, + in vec3 subLayerS, in vec3 subLayerSpecularColor, + in float subLayerOpacity, inout vec3 subLayerF + ) +{ + subLayerF = saturate(subLayerF * subLayerOpacity); + blendedSubLayerD = blendedSubLayerD * (vec3(1.0) - lastLayerF) + subLayerD * subLayerDiffuseColor * subLayerF; + blendedSubLayerS = blendedSubLayerS *(vec3(1.0) - lastLayerF) + subLayerS * subLayerSpecularColor * subLayerF; + blendedBaseLayerD *= vec3(1.0) - subLayerF; + blendedBaseLayerS *= vec3(1.0) - subLayerF; + lastLayerF = subLayerF; } diff --git a/editor/assets/chunks/lighting-models/data-structures/lighting-intermediate-data.chunk b/editor/assets/chunks/lighting-models/data-structures/lighting-intermediate-data.chunk index 7a4b39bd1a9..54e54b14bbf 100644 --- a/editor/assets/chunks/lighting-models/data-structures/lighting-intermediate-data.chunk +++ b/editor/assets/chunks/lighting-models/data-structures/lighting-intermediate-data.chunk @@ -5,9 +5,9 @@ struct LightingIntermediateData float distToCamera, distToCameraSqr; // pos->camera float angleAttenuation, distAttenuation; - float NoL, NoV, NoH;//, VoH; + float NoL, NoV, NoH, VoH; float NoLSat, NoVSat, NoHSat;//, VoHSat; // clamped to 0-1 - float NoVAbsSat; // abs and clamped to 1 + float NoVAbsSat, VoHAbsSat; // abs and clamped to 1 HIGHP_VALUE_STRUCT_DEFINE(vec3, worldPosition); @@ -16,7 +16,8 @@ struct LightingIntermediateData // material data float specularParam; // roughness or specular power - float ior; + // todo: add F0 & F90 + float ior, layerOpacity; #if CC_SURFACES_LIGHTING_ANISOTROPIC float anisotropyShape; @@ -92,9 +93,11 @@ void CCSurfacesLightingGetIntermediateData_PerLight(inout LightingIntermediateDa // dot data.NoL = dot(data.N, data.L); data.NoH = dot(data.N, data.H); - // data.VoH = dot(data.V, data.H); + data.VoH = dot(data.V, data.H); data.NoLSat = max(data.NoL, 0.0); data.NoHSat = max(data.NoH, 0.0); // data.VoHSat = max(data.VoH, 0.0); + + data.VoHAbsSat = max(abs(data.VoH), 0.0); } diff --git a/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk b/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk index 6ab96c09d35..d6310b378a2 100644 --- a/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk +++ b/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk @@ -1,18 +1,21 @@ struct LightingResult { // material-dependent lighting data - vec3 diffuseColorWithLighting, specularColorWithLighting, specularColorWithEnvLighting; + vec3 diffuseColorWithLighting, specularColorWithLighting; // pure lighting - vec3 directDiffuse, directSpecular; - vec3 environmentDiffuse, environmentSpecular; + vec3 directDiffuse, directSpecular, directGF; + vec3 environmentDiffuse, environmentSpecular, environmentGF; float shadow, ao; vec3 lightmapColor; vec3 emissive; // advanced -#if CC_SURFACES_LIGHTING_USE_FRESNEL - float fresnel; + vec3 fresnel; // for transmit materials , rim or special effects + +#if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + vec3 directDiffuseSubLayers, directSpecularSubLayers; + vec3 environmentDiffuseSubLayers, environmentSpecularSubLayers; #endif #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR @@ -20,10 +23,12 @@ struct LightingResult #endif #if CC_SURFACES_LIGHTING_TRANSMIT_DIFFUSE vec3 directTransmitDiffuse, environmentTransmitDiffuse; -#endif +#endif #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR vec3 direct2ndSpecular, environment2ndSpecular; - vec3 specularColorWithLighting2ndSpecular, specularColorWithEnvLighting2ndSpecular; + vec3 specularColorWithLighting2ndSpecular; + vec3 directGF2ndSpecular, environmentGF2ndSpecular; + vec3 directSubLayerF, environmentSubLayerF; #endif #if CC_SURFACES_LIGHTING_TT vec3 directTT; @@ -31,3 +36,12 @@ struct LightingResult #endif //vec3 scattered; }; + + +/* for multi-layer materials, should define: +struct LightingResultPerLayer +{ + vec3 diffuseColorWithLighting, specularColorWithLighting; + vec3 directDiffuse, directSpecular, directGF; + vec3 environmentDiffuse, environmentSpecular, environmentGF; +}*/ diff --git a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk index a9a6316003a..d21d83c428d 100644 --- a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk +++ b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk @@ -11,16 +11,15 @@ CCSurfacesInitializeLightingIntermediateData(lightingData, surfaceData); LightingResult lightingResult; - CCSurfacesLightingInitializeColorWithLighting(lightingResult.diffuseColorWithLighting, lightingResult.specularColorWithLighting, lightingResult.specularColorWithEnvLighting, surfaceData, lightingData); + CCSurfacesLightingInitializeColorWithLighting(lightingResult.diffuseColorWithLighting, lightingResult.specularColorWithLighting, surfaceData, lightingData); lightingResultAccumulated.diffuseColorWithLighting = lightingResult.diffuseColorWithLighting; lightingResultAccumulated.specularColorWithLighting = lightingResult.specularColorWithLighting; - lightingResultAccumulated.specularColorWithEnvLighting = lightingResult.specularColorWithEnvLighting; #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR vec3 diff; SurfacesMaterialData surfaceData2ndSpecular; CCSurfacesGetSurfacesMaterialData2ndSpecular(surfaceData2ndSpecular, surfaceData); - CCSurfacesLightingInitializeColorWithLighting(diff, lightingResultAccumulated.specularColorWithLighting2ndSpecular, lightingResultAccumulated.specularColorWithEnvLighting2ndSpecular, surfaceData2ndSpecular, lightingData); + CCSurfacesLightingInitializeColorWithLighting(diff, lightingResultAccumulated.specularColorWithLighting2ndSpecular, surfaceData2ndSpecular, lightingData); #endif int numLights = CC_PIPELINE_TYPE == CC_PIPELINE_TYPE_FORWARD ? LIGHTS_PER_PASS : int(cc_lightDir[0].w); @@ -29,15 +28,18 @@ vec3 lightDirWithLength = IS_RANGED_DIRECTIONAL_LIGHT(cc_lightPos[i].w) ? -normalize(cc_lightDir[i].xyz) : cc_lightPos[i].xyz - worldPos; CCSurfacesLightingCalculateIntermediateData_PerLight(lightingData, surfaceData, lightDirWithLength); - CCSurfacesLightingCalculateColorWithLighting(lightingResult.diffuseColorWithLighting, lightingResult.specularColorWithLighting, lightingResult.specularColorWithEnvLighting, surfaceData, lightingData); + CCSurfacesLightingCalculateColorWithLighting(lightingResult.diffuseColorWithLighting, lightingResult.specularColorWithLighting, surfaceData, lightingData); vec3 diffuseLighting, specularLighting; CCSurfacesLightingCalculateDirect(diffuseLighting, specularLighting, lightingData, cc_lightColor[i]); - float fresnel = 1.0; #if CC_SURFACES_LIGHTING_USE_FRESNEL - fresnel = lightingResult.fresnel = CCSurfaceLightingCalculateFresnel(lightingData); + vec3 fresnel = CCSurfaceLightingCalculateExtraFresnel(lightingData); + #else + vec3 fresnel = vec3(1.0); #endif + lightingResult.fresnel = fresnel; + float shadow = 1.0; #if CC_RECEIVE_SHADOW && CC_SHADOW_TYPE == CC_SHADOW_MAP @@ -84,7 +86,8 @@ lightingData.angleAttenuation = angleAtt; lightingData.distAttenuation = distAtt; lightingResult.directDiffuse = diffuseLighting * multiplier; - lightingResult.directSpecular = specularLighting * multiplier * fresnel; + lightingResult.directSpecular = specularLighting * multiplier; + CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF, lightingData, lightingResult.specularColorWithLighting, vec3(1.0)); vec4 attenuatedLightColorAndIntensity = vec4(cc_lightColor[i].xyz, cc_lightColor[i].w * multiplier); @@ -106,13 +109,18 @@ CCSurfacesInitializeLightingIntermediateData(lightingData2ndSpecular, surfaceData2ndSpecular); CCSurfacesLightingCalculateIntermediateData_PerLight(lightingData2ndSpecular, surfaceData, lightDirWithLength); CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, attenuatedLightColorAndIntensity, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); - lightingResult.direct2ndSpecular *= multiplier * fresnel; + CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF2ndSpecular, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, vec3(1.0)); + + lightingResult.direct2ndSpecular *= multiplier; #endif #if CC_SURFACES_LIGHTING_TT CCSurfacesLightingCalculateDirectTT(lightingResult, lightingData, attenuatedLightColorAndIntensity); #endif + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + CCSurfacesLightingCalculateDirectMultiLayerBlending(lightingResult, lightingData2ndSpecular); + #endif // user-defined lighting model #ifdef CC_SURFACES_LIGHTING_MODIFY_FINAL_RESULT @@ -139,7 +147,7 @@ CCSurfacesInitializeLightingIntermediateData(lightingData, surfaceData); CCSurfacesInitializeLightingResult(lightingResult, surfaceData); - CCSurfacesLightingInitializeColorWithLighting(lightingResult.diffuseColorWithLighting, lightingResult.specularColorWithLighting, lightingResult.specularColorWithEnvLighting, surfaceData, lightingData); + CCSurfacesLightingInitializeColorWithLighting(lightingResult.diffuseColorWithLighting, lightingResult.specularColorWithLighting, surfaceData, lightingData); CCSurfacesLightingCalculateIntermediateData_PerLight(lightingData, surfaceData, -cc_mainLitDir.xyz); @@ -200,20 +208,24 @@ #endif + // apply SSR, local probe & global probe + vec3 unused; + CCSurfacesLightingCalculateEnvironment(lightingResult.environmentDiffuse, lightingResult.environmentSpecular, lightingData, cc_ambientSky.w); + CCSurfaceLightingCalculateEnvironmentFresnel(lightingResult.environmentGF, unused, lightingData, lightingResult.specularColorWithLighting); + // dynamic & stationary dir light lightingResult.directDiffuse = lightingResult.directSpecular = vec3(0.0); #if !CC_DISABLE_DIRECTIONAL_LIGHT && !CC_FORWARD_ADD - CCSurfacesLightingCalculateColorWithLighting(lightingResult.diffuseColorWithLighting, lightingResult.specularColorWithLighting, lightingResult.specularColorWithEnvLighting, surfaceData, lightingData); + CCSurfacesLightingCalculateColorWithLighting(lightingResult.diffuseColorWithLighting, lightingResult.specularColorWithLighting, surfaceData, lightingData); CCSurfacesLightingCalculateDirect(lightingResult.directDiffuse, lightingResult.directSpecular, lightingData, cc_mainLitColor); + CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF, lightingData, lightingResult.specularColorWithLighting, lightingResult.environmentGF); #endif - // apply SSR, local probe & global probe - CCSurfacesLightingCalculateEnvironment(lightingResult.environmentDiffuse, lightingResult.environmentSpecular, lightingData, cc_ambientSky.w); - - #if CC_SURFACES_LIGHTING_USE_FRESNEL - lightingResult.fresnel = CCSurfaceLightingCalculateFresnel(lightingData); + lightingResult.fresnel = CCSurfaceLightingCalculateExtraFresnel(lightingData); + #else + lightingResult.fresnel = vec3(1.0); #endif #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR @@ -236,17 +248,26 @@ LightingIntermediateData lightingData2ndSpecular; CCSurfacesInitializeLightingIntermediateData(lightingData2ndSpecular, surfaceData2ndSpecular); CCSurfacesLightingCalculateIntermediateData_PerLight(lightingData2ndSpecular, surfaceData2ndSpecular, -cc_mainLitDir.xyz); - CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, cc_mainLitColor, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); - CCSurfacesLightingCalculateEnvironment2ndSpecular(lightingResult.environment2ndSpecular, lightingData2ndSpecular, cc_ambientSky.w, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.environmentSpecular); vec3 diff; - CCSurfacesLightingInitializeColorWithLighting(diff, lightingResult.specularColorWithLighting2ndSpecular, lightingResult.specularColorWithEnvLighting2ndSpecular, surfaceData2ndSpecular, lightingData2ndSpecular); + CCSurfacesLightingInitializeColorWithLighting(diff, lightingResult.specularColorWithLighting2ndSpecular, surfaceData2ndSpecular, lightingData2ndSpecular); + + CCSurfacesLightingCalculateEnvironment2ndSpecular(lightingResult.environment2ndSpecular, lightingData2ndSpecular, cc_ambientSky.w, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.environmentSpecular); + CCSurfaceLightingCalculateEnvironmentFresnel(lightingResult.environmentGF2ndSpecular, lightingResult.environmentSubLayerF, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular); + + CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, cc_mainLitColor, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); + CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF2ndSpecular, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, lightingResult.environmentGF2ndSpecular); #endif #if CC_SURFACES_LIGHTING_TT CCSurfacesLightingCalculateDirectTT(lightingResult, lightingData, cc_mainLitColor); #endif + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + CCSurfacesLightingCalculateDirectMultiLayerBlending(lightingResult, lightingData2ndSpecular); + CCSurfacesLightingCalculateEnvironmentMultiLayerBlending(lightingResult, lightingData2ndSpecular); + #endif + // user-defined lighting model #ifdef CC_SURFACES_LIGHTING_MODIFY_FINAL_RESULT LightingMiscData miscData; diff --git a/editor/assets/chunks/lighting-models/model-functions/standard.chunk b/editor/assets/chunks/lighting-models/model-functions/standard.chunk index 922bc513a21..accd9389b63 100644 --- a/editor/assets/chunks/lighting-models/model-functions/standard.chunk +++ b/editor/assets/chunks/lighting-models/model-functions/standard.chunk @@ -59,9 +59,43 @@ void CCSurfacesLightingCalculateEnvironment(out vec3 lightingDiffuse, out vec3 l } #if CC_SURFACES_LIGHTING_USE_FRESNEL - float CCSurfaceLightingCalculateFresnel(in LightingIntermediateData lightingData) +vec3 CCSurfaceLightingCalculateExtraFresnel(in LightingIntermediateData lightingData) +{ + float fresnel = CalculateFresnelCoefficient(lightingData.ior, lightingData.NoVAbsSat); //NoVSat for single side, and NoVAbsSat for two sided + return vec3(fresnel); +} +#endif + +void CCSurfaceLightingCalculateDirectFresnel(out vec3 directGF, in LightingIntermediateData lightingData, vec3 specularColor, in vec3 environmentGF) +{ + #if CC_SURFACES_USE_LEGACY_COMPATIBLE_LIGHTING + // local lighting also use EnvIntegratedFresnel for estimated GF terms, calculate accurate GF instead in the future, CCSurfacesDebugViewLightingResult also needs modified + directGF = environmentGF; + #else + float roughness = lightingData.specularParam; + directGF = F_SchlickMultiplier(specularColor, lightingData.VoHAbsSat) * G_Schlick(roughness, lightingData.NoVSat, lightingData.NoLSat); + #endif +} + +void CCSurfaceLightingCalculateEnvironmentFresnel(out vec3 integratedGF, vec3 integratedF, in LightingIntermediateData lightingData, vec3 specularColor) +{ + float roughness = lightingData.specularParam; + IntegratedGFMultiplier(integratedGF, integratedF, specularColor, roughness, lightingData.NoVAbsSat); +} + +#if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + void CCSurfaceLightingCalculateDirectSubLayerFresnel(out vec3 subLayerF, in LightingIntermediateData lightingData, vec3 specularColor) + { + float VoH = lightingData.VoHAbsSat; + subLayerF = vec3(exp2( (-5.55473 * VoH - 6.98316) * VoH )); + } + void CCSurfaceLightingCalculateEnvironmentSubLayerFresnel(out vec3 subLayerF, in LightingIntermediateData lightingData, vec3 specularColor) { - return CalculateFresnelCoefficient(lightingData.ior, abs(lightingData.NoV)); //NoVSat for single side, and NoVAbs for two sided + // ior related: + subLayerF = vec3(CalculateFresnelCoefficient(lightingData.ior, lightingData.NoVSat)); + // F0 F90 related: + // if (equalf(lightingData.ior, 0.0)) + // subLayerF = vec3(CalculateFresnelCoefficient(lightingData.F0, lightingData.F90, lightingData.NoVSat)); } #endif @@ -218,3 +252,70 @@ void CCSurfacesLightingCalculateEnvironment(out vec3 lightingDiffuse, out vec3 l lightingResult.directTT = ttLighting * DiffuseCoefficient_EnergyConservation * lightSourceColorAndIntensity.xyz* lightSourceColorAndIntensity.w; } #endif + +#if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + // todo: layer result in LightingResult separate to single structure like LightingResultPerLayer + void CCSurfacesLightingCalculateDirectMultiLayerBlending(inout LightingResult lightingResult + , in LightingIntermediateData lightingData2ndLayer + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND > 1 + // add more layers... + #endif + ) + { + vec3 lastLayerF, zeroDiffuse = vec3(0.0); + vec3 blendedBaseD = lightingResult.directDiffuse, blendedBaseS = lightingResult.directSpecular; + InitializeLayerBlending(blendedBaseD, blendedBaseS, + lightingResult.directDiffuseSubLayers, lightingResult.directSpecularSubLayers, + lastLayerF, + lightingResult.directDiffuse, lightingResult.directSpecular + ); + + CCSurfaceLightingCalculateDirectSubLayerFresnel(lightingResult.directSubLayerF, lightingData2ndLayer, lightingResult.specularColorWithLighting2ndSpecular); + CalculateLayerBlending (blendedBaseD, blendedBaseS, + lightingResult.directDiffuseSubLayers, lightingResult.directSpecularSubLayers, + lastLayerF, + zeroDiffuse, zeroDiffuse, + lightingResult.direct2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, + lightingData2ndLayer.layerOpacity, lightingResult.directSubLayerF + ); + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND > 1 + // add more layers... + #endif + + // output + lightingResult.directDiffuse = blendedBaseD; + lightingResult.directSpecular = blendedBaseS; + } + + void CCSurfacesLightingCalculateEnvironmentMultiLayerBlending(inout LightingResult lightingResult + , in LightingIntermediateData lightingData2ndLayer + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND > 1 + // add more layers... + #endif + ) + { + vec3 lastLayerF, zeroDiffuse = vec3(0.0); + vec3 blendedBaseD = lightingResult.environmentDiffuse, blendedBaseS = lightingResult.environmentSpecular; + InitializeLayerBlending(blendedBaseD, blendedBaseS, + lightingResult.environmentDiffuseSubLayers, lightingResult.environmentSpecularSubLayers, + lastLayerF, + lightingResult.environmentDiffuse, lightingResult.environmentSpecular + ); + + CCSurfaceLightingCalculateEnvironmentSubLayerFresnel(lightingResult.environmentSubLayerF, lightingData2ndLayer, lightingResult.specularColorWithLighting2ndSpecular); + CalculateLayerBlending (blendedBaseD, blendedBaseS, + lightingResult.environmentDiffuseSubLayers, lightingResult.environmentSpecularSubLayers, + lastLayerF, + zeroDiffuse, zeroDiffuse, + lightingResult.environment2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, + lightingData2ndLayer.layerOpacity, lightingResult.environmentSubLayerF + ); + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND > 1 + // add more layers... + #endif + + // output + lightingResult.environmentDiffuse = blendedBaseD; + lightingResult.environmentSpecular = blendedBaseS; + } +#endif diff --git a/editor/assets/chunks/lighting-models/model-functions/toon.chunk b/editor/assets/chunks/lighting-models/model-functions/toon.chunk index cdea2dff79a..1e4088faae4 100644 --- a/editor/assets/chunks/lighting-models/model-functions/toon.chunk +++ b/editor/assets/chunks/lighting-models/model-functions/toon.chunk @@ -40,3 +40,21 @@ void CCSurfacesLightingCalculateEnvironment(out vec3 lightingDiffuse, out vec3 l lightingDiffuse = vec3(0.0); lightingSpecular = vec3(0.0); } + + +#if CC_SURFACES_LIGHTING_USE_FRESNEL +vec3 CCSurfaceLightingCalculateExtraFresnel(in LightingIntermediateData lightingData) +{ + return vec3(1.0); +} +#endif + +void CCSurfaceLightingCalculateDirectFresnel(out vec3 fresnel, in LightingIntermediateData lightingData, vec3 specularColor, in vec3 environmentGF) +{ + fresnel = vec3(1.0); +} + +void CCSurfaceLightingCalculateEnvironmentFresnel(out vec3 integratedGF, out vec3 integratedF, in LightingIntermediateData lightingData, vec3 specularColor) +{ + integratedF = integratedGF = vec3(1.0); +} diff --git a/editor/assets/chunks/surfaces/data-structures/standard.chunk b/editor/assets/chunks/surfaces/data-structures/standard.chunk index 52cbfb976b9..fd8f052538a 100644 --- a/editor/assets/chunks/surfaces/data-structures/standard.chunk +++ b/editor/assets/chunks/surfaces/data-structures/standard.chunk @@ -27,9 +27,14 @@ struct SurfacesMaterialData vec4 transmitDiffuseParams; #endif #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR + // for storage only, copied with CCSurfacesGetSurfacesMaterialData2ndSpecular vec3 baseColor2ndSpecular, color2ndSpecular; - float intensity2ndSpecular, roughness2ndSpecular; + float intensity2ndSpecular, roughness2ndSpecular, metallic2ndSpecular; vec3 worldNormal2ndSpecular, worldTangent2ndSpecular, worldBinormal2ndSpecular; + #if CC_SURFACES_LIGHTING_ANISOTROPIC + float anisotropyShape2ndSpecular; + #endif + float ior2ndSpecular, opacity2ndSpecular; // for multi-layer #endif #if CC_SURFACES_LIGHTING_TT vec3 baseColorTT; diff --git a/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk b/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk index e7f3446aacd..230cbf6f2bb 100644 --- a/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk +++ b/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk @@ -164,6 +164,18 @@ vec3 SurfacesFragmentModifyTTColor(in vec3 baseColor) } #endif +#ifndef CC_SURFACES_FRAGMENT_MODIFY_SSS_PARAMS +// depends on CC_SURFACES_FRAGMENT_MODIFY_SSS_PARAMS +vec4 SurfacesFragmentModifySSSParams() +{ + // x: sssIntensity, moisture + // y: sssCurvature, for preintegrated sss + // z: sssColoration, for sss transmitted light color with dark area + // w: unused + return vec4(1.0, 0.1, 1.0, 0.0); +} +#endif + #ifndef CC_SURFACES_FRAGMENT_MODIFY_DUAL_LOBE_SPECULAR_PARAMS // depends on CC_SURFACES_FRAGMENT_MODIFY_DUAL_LOBE_SPECULAR_PARAMS vec4 SurfacesFragmentModifyDualLobeSpecularParams(float roughness) @@ -174,15 +186,32 @@ vec4 SurfacesFragmentModifyDualLobeSpecularParams(float roughness) } #endif -#ifndef CC_SURFACES_FRAGMENT_MODIFY_SSS_PARAMS -// depends on CC_SURFACES_FRAGMENT_MODIFY_SSS_PARAMS -vec4 SurfacesFragmentModifySSSParams() +#ifndef CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_PARAMS +// depends on CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_PARAMS +vec4 SurfacesFragmentModifyClearCoatParams() { - // x: sssIntensity, moisture - // y: sssCurvature, for preintegrated sss - // z: sssColoration, for sss transmitted light color with dark area - // w: unused - return vec4(1.0, 0.1, 1.0, 0.0); + //x: coat roughness + //y: coat ior + //z: coat opacity + //w: coat intensity + return vec4(0.2, 1.5, 1.0, 1.0); +} +#endif + +#ifndef CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_COLOR +// depends on CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_COLOR +vec3 SurfacesFragmentModifyClearCoatColor() +{ + // for iridescense color variation + return vec3(1.0, 1.0, 1.0); +} +#endif + +#ifndef CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_WORLD_NORMAL +// depends on CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_WORLD_NORMAL +vec3 SurfacesFragmentModifyClearCoatWorldNormal() +{ + return normalize(FSInput_worldNormal); } #endif diff --git a/editor/assets/chunks/surfaces/effect-macros/common-macros.chunk b/editor/assets/chunks/surfaces/effect-macros/common-macros.chunk index ec593297817..6c8caca0b8d 100644 --- a/editor/assets/chunks/surfaces/effect-macros/common-macros.chunk +++ b/editor/assets/chunks/surfaces/effect-macros/common-macros.chunk @@ -87,11 +87,20 @@ #define CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR 1 #endif #endif - #ifndef CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR #define CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR 0 #endif +// this value should be sub-layers count +#ifndef CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + #if CC_SURFACES_LIGHTING_CLEAR_COAT + #define CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND 1 + #endif +#endif +#ifndef CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + #define CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND 0 +#endif + // render-to-color-map can disable functionality to avoid error data map #ifndef CC_SURFACES_ENABLE_DEBUG_VIEW diff --git a/editor/assets/chunks/surfaces/module-functions/debug-view.chunk b/editor/assets/chunks/surfaces/module-functions/debug-view.chunk index 2ea1d14f81e..5f380b79db6 100644 --- a/editor/assets/chunks/surfaces/module-functions/debug-view.chunk +++ b/editor/assets/chunks/surfaces/module-functions/debug-view.chunk @@ -110,13 +110,13 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_DIRECT_SPECULAR)) { - color.rgb = lightingResult.directSpecular * lightingResult.specularColorWithEnvLighting; + color.rgb = lightingResult.directSpecular * lightingResult.specularColorWithLighting * lightingResult.directGF; isSRGBColor = true; } if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_DIRECT_ALL)) { - color.rgb = lightingResult.directDiffuse * lightingResult.diffuseColorWithLighting + lightingResult.directSpecular * lightingResult.specularColorWithLighting; + color.rgb = lightingResult.directDiffuse * lightingResult.diffuseColorWithLighting + lightingResult.directSpecular * lightingResult.specularColorWithLighting * lightingResult.directGF; isSRGBColor = true; } @@ -128,13 +128,13 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_ENV_SPECULAR)) { - color.rgb = lightingResult.environmentSpecular * lightingResult.specularColorWithEnvLighting; + color.rgb = lightingResult.environmentSpecular * lightingResult.specularColorWithLighting * lightingResult.environmentGF; isSRGBColor = true; } if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_ENV_ALL)) { - color.rgb = lightingResult.environmentDiffuse * lightingResult.diffuseColorWithLighting + lightingResult.environmentSpecular * lightingResult.specularColorWithLighting; + color.rgb = lightingResult.environmentDiffuse * lightingResult.diffuseColorWithLighting + lightingResult.environmentSpecular * lightingResult.specularColorWithLighting * lightingResult.environmentGF; isSRGBColor = true; } @@ -162,14 +162,11 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) isSRGBColor = false; } - float fresnel = 0.0; + vec3 fresnel = lightingResult.fresnel; vec3 directTransmitSpecular = vec3(0.0), environmentTransmitSpecular = vec3(0.0); vec3 directTransmitDiffuse = vec3(0.0), environmentTransmitDiffuse = vec3(0.0); vec3 diffuseColorWithLightingTT = vec3(0.0), specularColorWithLighting2ndSpecular = vec3(0.0); vec3 direct2ndSpecular = vec3(0.0), environment2ndSpecular = vec3(0.0); - #if CC_SURFACES_LIGHTING_USE_FRESNEL - fresnel = lightingResult.fresnel; - #endif #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR directTransmitSpecular = lightingResult.directTransmitSpecular; environmentTransmitSpecular = lightingResult.environmentTransmitSpecular; @@ -179,11 +176,19 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) environmentTransmitDiffuse = lightingResult.environmentTransmitDiffuse; #endif #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR - direct2ndSpecular = lightingResult.direct2ndSpecular; - environment2ndSpecular = lightingResult.environment2ndSpecular; - specularColorWithLighting2ndSpecular = lightingResult.specularColorWithEnvLighting2ndSpecular; + direct2ndSpecular = lightingResult.direct2ndSpecular * lightingResult.directGF2ndSpecular; + environment2ndSpecular = lightingResult.environment2ndSpecular * lightingResult.environmentGF2ndSpecular; + specularColorWithLighting2ndSpecular = lightingResult.specularColorWithLighting2ndSpecular; + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + fresnel = lightingResult.environmentSubLayerF; + #endif + #endif + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + direct2ndSpecular = lightingResult.directSpecularSubLayers; + environment2ndSpecular = lightingResult.environmentSpecularSubLayers; #endif + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_FRESNEL)) { color.rgb = vec3(fresnel); @@ -287,9 +292,7 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) if (!IS_DEBUG_VIEW_COMPOSITE_ENABLE_AO) lightingResult.ao = 1.0; - #if CC_SURFACES_LIGHTING_USE_FRESNEL if (!IS_DEBUG_VIEW_COMPOSITE_ENABLE_FRESNEL) - lightingResult.fresnel = 1.0; - #endif + lightingResult.fresnel = vec3(1.0); } #endif diff --git a/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk b/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk index ce3c9a81b59..6399cee8adc 100644 --- a/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk @@ -47,12 +47,18 @@ void CCSurfacesFragmentGetMaterialData(inout SurfacesMaterialData surfaceData) // skip in shader graph, need extra code vec4 trtParams = SurfacesFragmentModifyTRTParams(); surfaceData.roughness2ndSpecular = saturate(surfaceData.roughness + trtParams.x); + surfaceData.metallic2ndSpecular = surfaceData.metallic; surfaceData.intensity2ndSpecular = trtParams.w; surfaceData.baseColor2ndSpecular = vec3(1.0); // specular color use specified trt color only surfaceData.color2ndSpecular = SurfacesFragmentModifyTRTColor(); surfaceData.worldNormal2ndSpecular = surfaceData.worldNormal; surfaceData.worldTangent2ndSpecular = surfaceData.worldTangent; surfaceData.worldBinormal2ndSpecular = surfaceData.worldBinormal; + surfaceData.ior2ndSpecular = surfaceData.ior; //unused + surfaceData.opacity2ndSpecular = 1.0; // unused + #if CC_SURFACES_LIGHTING_ANISOTROPIC + surfaceData.anisotropyShape2ndSpecular = surfaceData.anisotropyShape; + #endif RotateNormalAndBinormal(surfaceData.worldBinormal2ndSpecular, surfaceData.worldNormal2ndSpecular, surfaceData.worldTangent2ndSpecular, trtParams.y, FSInput_mirrorNormal); #endif @@ -67,12 +73,37 @@ void CCSurfacesFragmentGetMaterialData(inout SurfacesMaterialData surfaceData) // skip in shader graph, need extra code vec4 dualLobeParams = SurfacesFragmentModifyDualLobeSpecularParams(surfaceData.roughness); surfaceData.roughness2ndSpecular = saturate(dualLobeParams.x); + surfaceData.metallic2ndSpecular = surfaceData.metallic; surfaceData.intensity2ndSpecular = dualLobeParams.w; surfaceData.baseColor2ndSpecular = surfaceData.baseColor.rgb; surfaceData.color2ndSpecular = vec3(1.0); // no extra coloration surfaceData.worldNormal2ndSpecular = surfaceData.worldNormal; surfaceData.worldTangent2ndSpecular = surfaceData.worldTangent; surfaceData.worldBinormal2ndSpecular = surfaceData.worldBinormal; + surfaceData.ior2ndSpecular = surfaceData.ior; + surfaceData.opacity2ndSpecular = 1.0; // unused + #if CC_SURFACES_LIGHTING_ANISOTROPIC + surfaceData.anisotropyShape2ndSpecular = surfaceData.anisotropyShape; + #endif +#endif + +#if CC_SURFACES_LIGHTING_CLEAR_COAT + // skip in shader graph, need extra code + vec4 clearCoatParams = SurfacesFragmentModifyClearCoatParams(); + surfaceData.roughness2ndSpecular = clearCoatParams.x; + surfaceData.metallic2ndSpecular = 0.0; + surfaceData.ior2ndSpecular = clearCoatParams.y; + surfaceData.opacity2ndSpecular = clearCoatParams.z; + surfaceData.intensity2ndSpecular = clearCoatParams.w; + surfaceData.baseColor2ndSpecular = vec3(1.0); // specular color use specified coat color only + surfaceData.color2ndSpecular = SurfacesFragmentModifyClearCoatColor(); + surfaceData.worldNormal2ndSpecular = SurfacesFragmentModifyClearCoatWorldNormal(); + surfaceData.worldBinormal2ndSpecular = surfaceData.worldBinormal; + surfaceData.worldTangent2ndSpecular = CalculateTangent(surfaceData.worldNormal2ndSpecular, surfaceData.worldBinormal2ndSpecular); + #if CC_SURFACES_LIGHTING_ANISOTROPIC + surfaceData.anisotropyShape2ndSpecular = surfaceData.anisotropyShape; + // float anisoRotation = xxx; RotateNormalAndBinormal(surfaceData.worldBinormal2ndSpecular, surfaceData.worldNormal2ndSpecular, surfaceData.worldTangent2ndSpecular, anisoRotation, FSInput_mirrorNormal); + #endif #endif #if CC_SURFACES_LIGHTING_SSS @@ -114,19 +145,20 @@ vec3 CCSurfacesGetSpecularColor(in SurfacesMaterialData surfaceData) } // Diffuse/Specular Color with BRDF lighting preparation -void CCSurfacesLightingInitializeColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, inout vec3 specularColorWithEnvLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) +void CCSurfacesLightingInitializeColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) { diffuseColorWithLighting = CCSurfacesGetDiffuseColor(surfaceData); specularColorWithLighting = CCSurfacesGetSpecularColor(surfaceData).xyz; // (Intergrated) GF/4Pi use approximate value for both direct lighting and environment lighting // accuracy value can be calculated in LightingCalculateDirect/Environment instead of IntegratedGFApprox - specularColorWithEnvLighting = IntegratedGFApprox(specularColorWithLighting, surfaceData.roughness, lightingData.NoVAbsSat); + // specularColorWithEnvLighting = IntegratedGFApprox(specularColorWithLighting, surfaceData.roughness, lightingData.NoVAbsSat); } // Update two colors with BRDF which depend on lights (optional) -void CCSurfacesLightingCalculateColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, inout vec3 specularColorWithEnvLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) +void CCSurfacesLightingCalculateColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) { } + // Copy material data to lighting data // such as tangent data for anisotropic materials void CCSurfacesInitializeLightingIntermediateData(inout LightingIntermediateData lightingData, in SurfacesMaterialData surfaceData) @@ -140,6 +172,7 @@ void CCSurfacesInitializeLightingIntermediateData(inout LightingIntermediateData ); lightingData.specularParam = surfaceData.roughness; lightingData.ior = surfaceData.ior; + lightingData.layerOpacity = surfaceData.baseColor.a; #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR || CC_SURFACES_LIGHTING_TRANSMIT_DIFFUSE lightingData.transmitScatteringParams = surfaceData.transmitScatteringParams; lightingData.inScatteringColor = surfaceData.inScatteringColor; @@ -178,11 +211,16 @@ void CCSurfacesGetLightingIntermediateDataTransmitDiffuse(inout LightingIntermed void CCSurfacesGetSurfacesMaterialData2ndSpecular(inout SurfacesMaterialData surfaceData2ndSpecular, in SurfacesMaterialData surfaceData) { surfaceData2ndSpecular = surfaceData; - surfaceData2ndSpecular.baseColor = vec4(surfaceData.baseColor2ndSpecular, 1.0); + surfaceData2ndSpecular.baseColor = vec4(surfaceData.baseColor2ndSpecular, surfaceData.opacity2ndSpecular); surfaceData2ndSpecular.roughness = surfaceData.roughness2ndSpecular; + surfaceData2ndSpecular.metallic = surfaceData.metallic2ndSpecular; surfaceData2ndSpecular.worldNormal = surfaceData.worldNormal2ndSpecular; surfaceData2ndSpecular.worldTangent = surfaceData.worldTangent2ndSpecular; surfaceData2ndSpecular.worldBinormal = surfaceData.worldBinormal2ndSpecular; + surfaceData2ndSpecular.ior = surfaceData.ior2ndSpecular; + #if CC_SURFACES_LIGHTING_ANISOTROPIC + surfaceData2ndSpecular.anisotropyShape = surfaceData.anisotropyShape2ndSpecular; + #endif } #endif @@ -191,12 +229,21 @@ void CCSurfacesInitializeLightingResult(inout LightingResult lightingResult, in { lightingResult.ao = surfaceData.ao; lightingResult.emissive = surfaceData.emissive; + lightingResult.directGF = vec3(1.0); +#if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + lightingResult.directDiffuseSubLayers = lightingResult.directSpecularSubLayers = vec3(0.0); + lightingResult.environmentDiffuseSubLayers = lightingResult.environmentSpecularSubLayers = vec3(0.0); +#endif } // Init accumulated lighting results for additive pass void CCSurfacesInitializeLightingResult(inout LightingResult lightingResult) { lightingResult.directDiffuse = lightingResult.directSpecular = vec3(0.0); + lightingResult.directGF = vec3(1.0); +#if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + lightingResult.directDiffuseSubLayers = lightingResult.directSpecularSubLayers = vec3(0.0); +#endif #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR lightingResult.directTransmitSpecular = vec3(0.0); @@ -212,20 +259,25 @@ void CCSurfacesInitializeLightingResult(inout LightingResult lightingResult) #endif } -// Accumulated lighting results for additive pass +// Accumulated lighting results for additive pass only void CCSurfacesAccumulateLightingResult(inout LightingResult lightingResultAccumulated, in LightingResult lightingResult) { lightingResultAccumulated.directDiffuse += lightingResult.directDiffuse * lightingResult.shadow; - lightingResultAccumulated.directSpecular += lightingResult.directSpecular * lightingResult.shadow; + lightingResultAccumulated.directSpecular += lightingResult.directSpecular * lightingResult.shadow * lightingResult.directGF * lightingResult.fresnel; + + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + lightingResultAccumulated.directDiffuseSubLayers += lightingResult.directDiffuseSubLayers * lightingResult.shadow; + lightingResultAccumulated.directSpecularSubLayers += lightingResult.directSpecularSubLayers * lightingResult.shadow; + #endif #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR - lightingResultAccumulated.directTransmitSpecular += lightingResult.directTransmitSpecular; + lightingResultAccumulated.directTransmitSpecular += lightingResult.directTransmitSpecular * (vec3(1.0) - lightingResult.fresnel); #endif #if CC_SURFACES_LIGHTING_TRANSMIT_DIFFUSE lightingResultAccumulated.directTransmitDiffuse += lightingResult.directTransmitDiffuse; #endif #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR - lightingResultAccumulated.direct2ndSpecular += lightingResult.direct2ndSpecular * lightingResult.shadow; + lightingResultAccumulated.direct2ndSpecular += lightingResult.direct2ndSpecular * lightingResult.shadow * lightingResult.directGF2ndSpecular * lightingResult.fresnel; #endif #if CC_SURFACES_LIGHTING_TT lightingResultAccumulated.directTT += lightingResult.directTT * lightingResult.shadow; @@ -256,16 +308,20 @@ vec4 CCSurfacesShading(in SurfacesMaterialData surfaceData, in LightingResult li { vec4 color = vec4(0.0, 0.0, 0.0, surfaceData.baseColor.a); - // todo: local lighting also use EnvLightingSpecularColor for estimated GF terms, calculate accurate GF instead in the future, CCSurfacesDebugViewLightingResult also needs modified #if CC_FORWARD_ADD // shadow and fresnel has already been applied with common flow color.xyz += lightingResult.directDiffuse * lightingResult.diffuseColorWithLighting - + lightingResult.directSpecular * lightingResult.specularColorWithEnvLighting + + lightingResult.directSpecular * lightingResult.specularColorWithLighting * lightingResult.directGF #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR - + lightingResult.directTransmitSpecular * lightingResult.specularColorWithEnvLighting + + lightingResult.directTransmitSpecular * lightingResult.specularColorWithLighting * lightingResult.directGF #endif - #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR - + lightingResult.direct2ndSpecular * lightingResult.specularColorWithEnvLighting2ndSpecular * surfaceData.color2ndSpecular + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + + lightingResult.directDiffuseSubLayers + + lightingResult.directSpecularSubLayers + #else + #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR + + lightingResult.direct2ndSpecular * lightingResult.specularColorWithLighting2ndSpecular * surfaceData.color2ndSpecular * lightingResult.directGF2ndSpecular + #endif #endif #if CC_SURFACES_LIGHTING_TT + lightingResult.directTT * lightingResult.diffuseColorWithLightingTT @@ -276,20 +332,22 @@ vec4 CCSurfacesShading(in SurfacesMaterialData surfaceData, in LightingResult li ; #else - float fresnel = 1.0; - #if CC_SURFACES_LIGHTING_USE_FRESNEL - fresnel = lightingResult.fresnel; - #endif - float invFresnel = 1.0 - fresnel; + vec3 fresnel = lightingResult.fresnel; + vec3 invFresnel = vec3(1.0) - fresnel; color.xyz += ( lightingResult.directDiffuse * lightingResult.diffuseColorWithLighting - + lightingResult.directSpecular * lightingResult.specularColorWithEnvLighting * fresnel + + lightingResult.directSpecular * lightingResult.specularColorWithLighting * lightingResult.directGF * fresnel #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR - + lightingResult.directTransmitSpecular * lightingResult.specularColorWithEnvLighting * invFresnel + + lightingResult.directTransmitSpecular * lightingResult.specularColorWithLighting * lightingResult.directGF * invFresnel #endif - #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR - + lightingResult.direct2ndSpecular * lightingResult.specularColorWithEnvLighting2ndSpecular * surfaceData.color2ndSpecular + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + + lightingResult.directDiffuseSubLayers + + lightingResult.directSpecularSubLayers + #else + #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR + + lightingResult.direct2ndSpecular * lightingResult.specularColorWithLighting2ndSpecular * surfaceData.color2ndSpecular * lightingResult.directGF2ndSpecular + #endif #endif #if CC_SURFACES_LIGHTING_TT + lightingResult.directTT * lightingResult.diffuseColorWithLightingTT @@ -309,12 +367,17 @@ vec4 CCSurfacesShading(in SurfacesMaterialData surfaceData, in LightingResult li color.xyz += ( lightingResult.environmentDiffuse * lightingResult.diffuseColorWithLighting - + lightingResult.environmentSpecular * lightingResult.specularColorWithEnvLighting * fresnel + + lightingResult.environmentSpecular * lightingResult.specularColorWithLighting * lightingResult.environmentGF * fresnel #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR - + lightingResult.environmentTransmitSpecular * lightingResult.specularColorWithEnvLighting * invFresnel + + lightingResult.environmentTransmitSpecular * lightingResult.specularColorWithLighting * lightingResult.environmentGF * invFresnel #endif - #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR - + lightingResult.environment2ndSpecular * lightingResult.specularColorWithEnvLighting2ndSpecular * surfaceData.color2ndSpecular + #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + + lightingResult.environmentDiffuseSubLayers + + lightingResult.environmentSpecularSubLayers + #else + #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR + + lightingResult.environment2ndSpecular * lightingResult.specularColorWithLighting2ndSpecular * surfaceData.color2ndSpecular * lightingResult.environmentGF2ndSpecular + #endif #endif ) * lightingResult.ao diff --git a/editor/assets/chunks/surfaces/module-functions/toon-fs.chunk b/editor/assets/chunks/surfaces/module-functions/toon-fs.chunk index 5afc2f508e4..f2019bc22e3 100644 --- a/editor/assets/chunks/surfaces/module-functions/toon-fs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/toon-fs.chunk @@ -50,12 +50,12 @@ vec3 CCSurfacesGetSpecularColor(in SurfacesMaterialData surfaceData) { return surfaceData.specular.xyz; } -void CCSurfacesLightingInitializeColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, inout vec3 specularColorWithEnvLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) +void CCSurfacesLightingInitializeColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) { diffuseColorWithLighting = vec3(0.0); - specularColorWithEnvLighting = specularColorWithLighting = surfaceData.specular.xyz * surfaceData.baseStep; + specularColorWithLighting = surfaceData.specular.xyz * surfaceData.baseStep; } -void CCSurfacesLightingCalculateColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, inout vec3 specularColorWithEnvLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) +void CCSurfacesLightingCalculateColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) { float NL = 0.5 * lightingData.NoL + 0.5; @@ -68,7 +68,6 @@ void CCSurfacesLightingCalculateColorWithLighting(inout vec3 diffuseColorWithLig diffuseColorWithLighting = diffuse * surfaceData.baseStep; } - // Copy material data to lighting data // such as tangent data for anisotropic materials void CCSurfacesInitializeLightingIntermediateData(inout LightingIntermediateData lightingData, in SurfacesMaterialData surfaceData) @@ -140,8 +139,8 @@ vec4 CCSurfacesShading(in SurfacesMaterialData surfaceData, in LightingResult li LightingIntermediateData lightingData; lightingData.NoL = -1.0; vec3 backLightingDiffuse, backLightingSpecular; - CCSurfacesLightingInitializeColorWithLighting(backLightingDiffuse, backLightingSpecular, backLightingSpecular, surfaceData, lightingData); - CCSurfacesLightingCalculateColorWithLighting(backLightingDiffuse, backLightingSpecular, backLightingSpecular, surfaceData, lightingData); + CCSurfacesLightingInitializeColorWithLighting(backLightingDiffuse, backLightingSpecular, surfaceData, lightingData); + CCSurfacesLightingCalculateColorWithLighting(backLightingDiffuse, backLightingSpecular, surfaceData, lightingData); color.xyz += mix(lightingResult.directDiffuse, lightingResult.lightmapColor, lightmapCoef) * mix(backLightingDiffuse, lightingResult.diffuseColorWithLighting, lightingResult.shadow) diff --git a/editor/assets/chunks/surfaces/module-functions/unlit-fs.chunk b/editor/assets/chunks/surfaces/module-functions/unlit-fs.chunk index edc14d1b03f..ed8a5ce578c 100644 --- a/editor/assets/chunks/surfaces/module-functions/unlit-fs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/unlit-fs.chunk @@ -27,13 +27,13 @@ vec3 CCSurfacesGetSpecularColor(in SurfacesMaterialData surfaceData) } // Diffuse/Specular Color with BRDF lighting preparation -void CCSurfacesLightingInitializeColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, inout vec3 specularColorWithEnvLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) +void CCSurfacesLightingInitializeColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) { diffuseColorWithLighting = CCSurfacesGetDiffuseColor(surfaceData); - specularColorWithEnvLighting = specularColorWithLighting = CCSurfacesGetSpecularColor(surfaceData).xyz; + specularColorWithLighting = CCSurfacesGetSpecularColor(surfaceData).xyz; } // Update two colors with BRDF which depend on lights (optional) -void CCSurfacesLightingCalculateColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, inout vec3 specularColorWithEnvLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) +void CCSurfacesLightingCalculateColorWithLighting(inout vec3 diffuseColorWithLighting, inout vec3 specularColorWithLighting, in SurfacesMaterialData surfaceData, in LightingIntermediateData lightingData) { } diff --git a/editor/assets/effects/advanced/car-paint.effect b/editor/assets/effects/advanced/car-paint.effect new file mode 100644 index 00000000000..6e5aede6071 --- /dev/null +++ b/editor/assets/effects/advanced/car-paint.effect @@ -0,0 +1,383 @@ +// Copyright (c) 2017-2022 Xiamen Yaji Software Co., Ltd. + +CCEffect %{ + techniques: + - name: opaque + passes: + - vert: standard-vs + frag: standard-fs + properties: &props + tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } + mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, linear: true, editor: { displayName: Albedo, type: color } } + albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } + alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST, slide: true, range: [0, 1.0], step: 0.001 } } + occlusion: { value: 0.0, target: pbrParams.x, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + roughness: { value: 0.5, target: pbrParams.y, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + metallic: { value: 0.0, target: pbrParams.z, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + specularIntensity: { value: 0.5, target: pbrParams.w, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + normalStrength: { value: 1.0, target: emissiveScaleParam.w, editor: { parent: USE_NORMAL_MAP, slide: true, range: [0, 5.0], step: 0.001 } } + addOnShadowBias: { value: 0.0, target: emissiveScaleParam.z } + coatRoughness: { value: 0.05, target: coatParam.x, editor: { slide : true, range : [0, 1.0] , step : 0.0001 } } + coatIOR: { value: 1.0, target: coatParam.y, editor: { slide : true, range : [1.0, 1.5] , step : 0.0001 } } + coatOpacity: { value: 1.0, target: coatParam.z, editor: { slide : true, range : [0.0, 1.0] , step : 0.0001 } } + coatIntensity: { value: 1.0, target: coatParam.w, editor: { slide : true, range : [0.0, 3.0] , step : 0.0001 } } + coatColor: { value: [1.0, 1.0, 1.0, 1.0], linear: true, editor: { displayName: CoatColor, type: color } } + flakeDensity: { value: 0.5, target: flakeParam.x, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } + flakeColorIntensity: { value: 0.2, target: flakeParam.y, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } + flakeTiling: { value: 10.0, target: flakeParam.z, editor: { parent: USE_FLAKE, slide: true, range: [1.0, 40.0], step: 0.001 } } + coatNormalStrength: { value: 0.1, target: flakeParam.w, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } + gradientColor: { value: [1.0, 1.0, 1.0, 1.0], linear: true, editor: { parent: USE_GRADIENT_COLOR, type: color } } + gradientIntensity: { value: 0.5, target: emissiveScaleParam.y, editor: { parent: USE_GRADIENT_COLOR, slide: true, range: [0, 1.0], step: 0.001 } } + mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } + normalMap: { value: normal } + coatNormalMap: { value: normal, editor: { parent: USE_FLAKE } } + flakeDataMap: { value: white, editor: { parent: USE_FLAKE } } + pbrMap: { value: grey } + occlusionMap: { value: white } + - &forward-add + vert: standard-vs + frag: standard-fs + phase: forward-add + propertyIndex: 0 + embeddedMacros: { CC_FORWARD_ADD: true } + depthStencilState: + depthFunc: equal + depthTest: true + depthWrite: false + blendState: + targets: + - blend: true + blendSrc: one + blendDst: one + blendSrcAlpha: zero + blendDstAlpha: one + - &shadow-caster + vert: shadow-caster-vs + frag: shadow-caster-fs + phase: shadow-caster + propertyIndex: 0 + rasterizerState: + cullMode: front + properties: + tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } + mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, editor: { displayName: Albedo, type: color } } + albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } + alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } } + mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } + - &reflect-map + vert: standard-vs + frag: reflect-map-fs + phase: reflect-map + propertyIndex: 0 + - &planar-shadow + vert: planar-shadow-vs + frag: planar-shadow-fs + phase: planar-shadow + propertyIndex: 0 + depthStencilState: + depthTest: true + depthWrite: false + stencilTestFront: true + stencilFuncFront: not_equal + stencilPassOpFront: replace + stencilRef: 0x80 # only use the leftmost bit + stencilReadMask: 0x80 + stencilWriteMask: 0x80 + blendState: + targets: + - blend: true + blendSrc: src_alpha + blendDst: one_minus_src_alpha + blendDstAlpha: one_minus_src_alpha + - &deferred + vert: standard-vs + frag: standard-fs + pass: gbuffer + phase: gbuffer + embeddedMacros: { CC_PIPELINE_TYPE: 1 } + propertyIndex: 0 + - name: transparent + passes: + - vert: standard-vs + frag: standard-fs + embeddedMacros: { CC_FORCE_FORWARD_SHADING: true } + depthStencilState: &d1 + depthTest: true + depthWrite: false + blendState: &b1 + targets: + - blend: true + blendSrc: src_alpha + blendDst: one_minus_src_alpha + blendDstAlpha: one_minus_src_alpha + properties: *props + - *forward-add + - *shadow-caster + - *planar-shadow + - &deferred-forward + vert: standard-vs + frag: standard-fs + phase: deferred-forward + embeddedMacros: { CC_PIPELINE_TYPE: 0 } + propertyIndex: 0 + depthStencilState: *d1 + blendState: *b1 +}% + +CCProgram shared-ubos %{ + uniform Constants { + vec4 tilingOffset; + vec4 albedo; + vec4 albedoScaleAndCutoff; + vec4 pbrParams; + vec4 emissiveScaleParam; + vec4 coatParam; + vec4 coatColor; + vec4 flakeParam; + vec4 gradientColor; + }; +}% + +CCProgram macro-remapping %{ + // ui displayed macros + #pragma define-meta HAS_SECOND_UV + #pragma define-meta USE_TWOSIDE + #pragma define-meta USE_VERTEX_COLOR + #pragma define-meta USE_FLAKE + + #define CC_SURFACES_USE_SECOND_UV HAS_SECOND_UV + #define CC_SURFACES_USE_TWO_SIDED USE_TWOSIDE + #define CC_SURFACES_USE_VERTEX_COLOR USE_VERTEX_COLOR + #define CC_SURFACES_LIGHTING_CLEAR_COAT 1 + + // depend on UI macros +#if USE_NORMAL_MAP || USE_FLAKE + #define CC_SURFACES_USE_TANGENT_SPACE 1 +#endif +}% + +CCProgram surface-vertex %{ + #define CC_SURFACES_VERTEX_MODIFY_SHADOW_BIAS + vec2 SurfacesVertexModifyShadowBias(in SurfacesStandardVertexIntermediate In, vec2 originShadowBias) + { + return originShadowBias + vec2(emissiveScaleParam.z, 0.0); + } + + #define CC_SURFACES_VERTEX_MODIFY_UV + void SurfacesVertexModifyUV(inout SurfacesStandardVertexIntermediate In) + { + In.texCoord = In.texCoord * tilingOffset.xy + tilingOffset.zw; + #if CC_SURFACES_USE_SECOND_UV + In.texCoord1 = In.texCoord1 * tilingOffset.xy + tilingOffset.zw; + #endif + } +}% + +CCProgram surface-fragment %{ + #if USE_ALBEDO_MAP + uniform sampler2D albedoMap; + #pragma define-meta ALBEDO_UV options([v_uv, v_uv1]) + #endif + #if USE_NORMAL_MAP + uniform sampler2D normalMap; + #pragma define-meta NORMAL_UV options([v_uv, v_uv1]) + #endif + #pragma define-meta DEFAULT_UV options([v_uv, v_uv1]) + #if USE_PBR_MAP + uniform sampler2D pbrMap; + #endif + #if USE_OCCLUSION_MAP + uniform sampler2D occlusionMap; + #endif + #if USE_FLAKE + uniform sampler2D coatNormalMap; + uniform sampler2D flakeDataMap; + #endif + + #pragma define OCCLUSION_CHANNEL r + #pragma define ROUGHNESS_CHANNEL g + #pragma define METALLIC_CHANNEL b + #pragma define SPECULAR_INTENSITY_CHANNEL a + + #if USE_ALPHA_TEST + #pragma define-meta ALPHA_TEST_CHANNEL options([a, r]) + #endif + + #define CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_PARAMS + vec4 SurfacesFragmentModifyClearCoatParams() + { + return vec4(coatParam.x, coatParam.y - 0.99, coatParam.z, coatParam.w * 2.0); + } + + #define CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_COLOR + vec3 SurfacesFragmentModifyClearCoatColor() + { + return coatColor.xyz; + } + + vec4 sampleFlake(sampler2D tex, vec2 uv) + { + vec4 blurred = texture(tex, uv); + vec4 detailed = fragTextureLod(tex, uv, 1.0); + return lerp(blurred, detailed, 0.3); + } + + #define CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_WORLD_NORMAL + vec3 SurfacesFragmentModifyClearCoatWorldNormal() + { + vec3 normal = FSInput_worldNormal; + #if USE_FLAKE + float density = flakeParam.x, densityMin = 0.25, flakeTiling = flakeParam.z; + vec2 uv = FSInput_texcoord * flakeTiling; + vec4 data = sampleFlake(flakeDataMap, uv); + vec3 nmmp = (sampleFlake(coatNormalMap, uv).xyz - vec3(0.5)) * 2.0; + float C = (data.a - 1.0) / density + 1.0; + float bumpIntensity = saturate(max(densityMin, C)); + nmmp = lerp(vec3(0.0, 0.0, 1.0), nmmp, bumpIntensity); + normal = CalculateNormalFromTangentSpace(nmmp, flakeParam.w, normalize(normal.xyz), normalize(FSInput_worldTangent), FSInput_mirrorNormal); + #endif + + return normalize(normal); + } + + #include + + + #include + #define CC_SURFACES_FRAGMENT_MODIFY_SHARED_DATA + void SurfacesFragmentModifySharedData(inout SurfacesMaterialData surfaceData) + { + #if USE_GRADIENT_COLOR + vec3 viewDir = normalize(cc_cameraPos.xyz - surfaceData.worldPos); + float NoVSat = saturate(dot(surfaceData.worldNormal, viewDir)); + surfaceData.baseColor.rgb = lerp(gradientColor, surfaceData.baseColor, pow(NoVSat, emissiveScaleParam.y)).rgb; + #endif + + #if USE_FLAKE + float density = flakeParam.x, flakeColorIntensity = flakeParam.y, flakeTiling = flakeParam.z; + vec2 uv = FSInput_texcoord * flakeTiling; + + vec4 data = sampleFlake(flakeDataMap, uv); + float C = (data.a - 1.0) / density + 1.0; + float flakeTintWeight = 1.0; + float flakeWeight = saturate(C) * flakeTintWeight * flakeColorIntensity; + + // color + vec4 flakeA = vec4(0.972,0.96,0.915,1); + vec4 flakeB = vec4(1.0,0.78,0.344,1); + vec4 flakeColor = lerp(flakeA, flakeB, data.r); + + vec4 color = surfaceData.baseColor; + color = lerp(color, flakeColor, flakeWeight); + color = lerp(surfaceData.baseColor, color, surfaceData.metallic); + surfaceData.baseColor = color; + surfaceData.roughness *= lerp(1.0, 0.5, flakeWeight); + #endif + } +}% + +CCProgram standard-vs %{ + precision highp float; + + // 1. surface internal macros, for technique usage or remapping some user (material) macros to surface internal macros + #include + #include + + // 2. common include with corresponding shader stage, include before surface functions + #include + + // 3. user surface functions that can use user (effect) parameters (ubo Constants) + // see surfaces/default-functions/xxx.chunk + #include + #include + + // 4. surface include with corresponding shader stage and shading-model (optional) + #include + + // 5. shader entry with corresponding shader stage and technique usage/type + #include +}% + + +CCProgram shadow-caster-vs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram planar-shadow-vs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + + +CCProgram standard-fs %{ + // shading-model : standard + // lighting-model : standard (isotropy / anisotropy pbr) + // shader stage : fs + // technique usage/type : render-to-scene + + precision highp float; + // 1. surface internal macros, for technique usage or remapping some user (material) macros to surface internal macros + #include + #include + + // 2. common include with corresponding shader stage, include before surface functions + #include + + // 3. user surface functions that can use user (effect) parameters (ubo Constants) + // see surfaces/default-functions/xxx.chunk + #include + #include + + // 4. lighting-model (optional) + #include + + // 5. surface include with corresponding shader stage and shading-model (optional) + #include + + // 6. shader entry with corresponding shader stage and technique usage/type + #include +}% + +CCProgram shadow-caster-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram planar-shadow-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram reflect-map-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include + #include + #include +}% + diff --git a/editor/assets/effects/advanced/car-paint.effect.meta b/editor/assets/effects/advanced/car-paint.effect.meta new file mode 100644 index 00000000000..ab9bcd058f7 --- /dev/null +++ b/editor/assets/effects/advanced/car-paint.effect.meta @@ -0,0 +1,11 @@ +{ + "ver": "1.7.0", + "importer": "effect", + "imported": true, + "uuid": "304a12db-3955-46e4-b712-e5e26f45258b", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} diff --git a/editor/assets/effects/advanced/glass.effect b/editor/assets/effects/advanced/glass.effect new file mode 100644 index 00000000000..f8c76e0ce2e --- /dev/null +++ b/editor/assets/effects/advanced/glass.effect @@ -0,0 +1,354 @@ +// Copyright (c) 2017-2022 Xiamen Yaji Software Co., Ltd. + +CCEffect %{ + techniques: + - name: opaque + passes: + - vert: standard-vs + frag: standard-fs + properties: &props + tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } + mainColor: { value: [0.05, 0.05, 0.05, 1.0], target: albedo, linear: true, editor: { displayName: Albedo, type: color } } + albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } + roughness: { value: 0.0, target: pbrParams.y, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + metallic: { value: 0.0, target: pbrParams.z, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + specularIntensity: { value: 0.2, target: pbrParams.w, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + F0: { value: 0.7, target: emissiveScaleParam.x, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + F90: { value: 0.9, target: emissiveScaleParam.y, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + gradientColor: { value: [0.0, 0.05, 0.0, 1.0], linear: true, editor: { parent: USE_GRADIENT_COLOR, type: color } } + gradientIntensity: { value: 0.2, target: emissiveScaleParam.z, editor: { parent: USE_GRADIENT_COLOR, slide: true, range: [0, 1.0], step: 0.001 } } + normalStrength: { value: 1.0, target: emissiveScaleParam.w, editor: { parent: USE_NORMAL_MAP, slide: true, range: [0, 5.0], step: 0.001 } } + mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } + normalMap: { value: normal } + pbrMap: { value: grey } + - &forward-add + vert: standard-vs + frag: standard-fs + phase: forward-add + propertyIndex: 0 + embeddedMacros: { CC_FORWARD_ADD: true } + depthStencilState: + depthFunc: equal + depthTest: true + depthWrite: false + blendState: + targets: + - blend: true + blendSrc: one + blendDst: one + blendSrcAlpha: zero + blendDstAlpha: one + - &shadow-caster + vert: shadow-caster-vs + frag: shadow-caster-fs + phase: shadow-caster + propertyIndex: 0 + rasterizerState: + cullMode: front + properties: + tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } + mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, editor: { displayName: Albedo, type: color } } + albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } + mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } + - &reflect-map + vert: standard-vs + frag: reflect-map-fs + phase: reflect-map + propertyIndex: 0 + - &planar-shadow + vert: planar-shadow-vs + frag: planar-shadow-fs + phase: planar-shadow + propertyIndex: 0 + depthStencilState: + depthTest: true + depthWrite: false + stencilTestFront: true + stencilFuncFront: not_equal + stencilPassOpFront: replace + stencilRef: 0x80 # only use the leftmost bit + stencilReadMask: 0x80 + stencilWriteMask: 0x80 + blendState: + targets: + - blend: true + blendSrc: src_alpha + blendDst: one_minus_src_alpha + blendDstAlpha: one_minus_src_alpha + - &deferred + vert: standard-vs + frag: standard-fs + pass: gbuffer + phase: gbuffer + embeddedMacros: { CC_PIPELINE_TYPE: 1 } + propertyIndex: 0 + - name: transparent + passes: + - vert: standard-vs + frag: standard-fs + embeddedMacros: { CC_FORCE_FORWARD_SHADING: true } + depthStencilState: &d1 + depthTest: true + depthWrite: false + blendState: &b1 + targets: + - blend: true + blendSrc: src_alpha + blendDst: one_minus_src_alpha + blendDstAlpha: one_minus_src_alpha + properties: *props + - *forward-add + - *shadow-caster + - *planar-shadow + - &deferred-forward + vert: standard-vs + frag: standard-fs + phase: deferred-forward + embeddedMacros: { CC_PIPELINE_TYPE: 0 } + propertyIndex: 0 + depthStencilState: *d1 + blendState: *b1 +}% + +CCProgram shared-ubos %{ + uniform Constants { + vec4 tilingOffset; + vec4 albedo; + vec4 albedoScaleAndCutoff; + vec4 pbrParams; + vec4 emissiveScaleParam; + vec4 gradientColor; + }; +}% + +CCProgram macro-remapping %{ + // ui displayed macros + #pragma define-meta USE_TWOSIDE + #pragma define-meta USE_VERTEX_COLOR + #pragma define-meta USE_PROBE_REFRACTION editor({ tooltip: 'Use transparency technique when disabled, otherwise use opaque technique' }) + + #define CC_SURFACES_USE_TWO_SIDED USE_TWOSIDE + #define CC_SURFACES_USE_VERTEX_COLOR USE_VERTEX_COLOR + #define CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR USE_PROBE_REFRACTION + #define CC_SURFACES_LIGHTING_USE_FRESNEL USE_PROBE_REFRACTION + + // depend on UI macros +#if USE_NORMAL_MAP + #define CC_SURFACES_USE_TANGENT_SPACE 1 +#endif +}% + +CCProgram surface-vertex %{ + #define CC_SURFACES_VERTEX_MODIFY_UV + void SurfacesVertexModifyUV(inout SurfacesStandardVertexIntermediate In) + { + In.texCoord = In.texCoord * tilingOffset.xy + tilingOffset.zw; + #if CC_SURFACES_USE_SECOND_UV + In.texCoord1 = In.texCoord1 * tilingOffset.xy + tilingOffset.zw; + #endif + } +}% + +CCProgram surface-fragment %{ + #if USE_ALBEDO_MAP + uniform sampler2D albedoMap; + #pragma define-meta ALBEDO_UV options([v_uv, v_uv1]) + #endif + #if USE_NORMAL_MAP + uniform sampler2D normalMap; + #pragma define-meta NORMAL_UV options([v_uv, v_uv1]) + #endif + #if USE_PBR_MAP + uniform sampler2D pbrMap; + #endif + #pragma define-meta DEFAULT_UV options([v_uv, v_uv1]) + + #define CC_SURFACES_FRAGMENT_MODIFY_BASECOLOR_AND_TRANSPARENCY + vec4 SurfacesFragmentModifyBaseColorAndTransparency() + { + vec4 baseColor = albedo; + + #if USE_VERTEX_COLOR + baseColor.rgb *= SRGBToLinear(FSInput_vertexColor.rgb); // use linear + baseColor.a *= FSInput_vertexColor.a; + #endif + + #if USE_ALBEDO_MAP + vec4 texColor = texture(albedoMap, ALBEDO_UV); + texColor.rgb = SRGBToLinear(texColor.rgb); + baseColor *= texColor; + #endif + + baseColor.rgb *= albedoScaleAndCutoff.xyz; + return baseColor; + } + + #define CC_SURFACES_FRAGMENT_MODIFY_WORLD_NORMAL + vec3 SurfacesFragmentModifyWorldNormal() + { + vec3 normal = FSInput_worldNormal; + #if USE_NORMAL_MAP + vec3 nmmp = texture(normalMap, NORMAL_UV).xyz - vec3(0.5); + normal = CalculateNormalFromTangentSpace(nmmp, emissiveScaleParam.w, normalize(normal.xyz), normalize(FSInput_worldTangent), FSInput_mirrorNormal); + #endif + + return normalize(normal); + } + + #define CC_SURFACES_FRAGMENT_MODIFY_PBRPARAMS + vec4 SurfacesFragmentModifyPBRParams() + { + vec4 pbr = pbrParams; + pbr.x = 1.0; + #if USE_PBR_MAP + vec4 res = texture(pbrMap, DEFAULT_UV); + pbr.yzw *= res.yzw; + #endif + + return pbr; + } + + #include + #include + #define CC_SURFACES_FRAGMENT_MODIFY_SHARED_DATA + void SurfacesFragmentModifySharedData(inout SurfacesMaterialData surfaceData) + { + vec3 viewDir = normalize(cc_cameraPos.xyz - surfaceData.worldPos); + float NoVSat = saturate(dot(surfaceData.worldNormal, viewDir)); + + #if !USE_PROBE_REFRACTION + // fresnel for alpha blend + float F0 = emissiveScaleParam.x, F90 = emissiveScaleParam.y; + surfaceData.baseColor.a = CalculateFresnelCoefficient(min(F0, F90), F90, NoVSat); + #endif + + #if USE_GRADIENT_COLOR + surfaceData.baseColor.rgb = lerp(gradientColor * albedoScaleAndCutoff, surfaceData.baseColor, pow(NoVSat, emissiveScaleParam.z)).rgb; + #endif + } + + #include + #define CC_SURFACES_LIGHTING_MODIFY_FINAL_RESULT + void SurfacesLightingModifyFinalResult(inout LightingResult result, in LightingIntermediateData lightingData, in SurfacesMaterialData surfaceData, in LightingMiscData miscData) + { + #if USE_PROBE_REFRACTION + // fresnel for refraction + vec3 viewDir = normalize(cc_cameraPos.xyz - surfaceData.worldPos); + float NoVSat = saturate(dot(surfaceData.worldNormal, viewDir)); + float F0 = emissiveScaleParam.x, F90 = emissiveScaleParam.y; + float fresnel = CalculateFresnelCoefficient(min(F0, F90), F90, NoVSat); + result.fresnel = vec3(fresnel); + #else + // simply fix oit depth issue for bright color alpha blending + float threshold = 0.5, bright = dot(result.environmentSpecular, vec3(0.33333)); + if (bright > threshold) + result.environmentSpecular = result.environmentSpecular / bright * threshold; + #endif + } +}% + +CCProgram standard-vs %{ + precision highp float; + + // 1. surface internal macros, for technique usage or remapping some user (material) macros to surface internal macros + #include + #include + + // 2. common include with corresponding shader stage, include before surface functions + #include + + // 3. user surface functions that can use user (effect) parameters (ubo Constants) + // see surfaces/default-functions/xxx.chunk + #include + #include + + // 4. surface include with corresponding shader stage and shading-model (optional) + #include + + // 5. shader entry with corresponding shader stage and technique usage/type + #include +}% + + +CCProgram shadow-caster-vs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram planar-shadow-vs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + + +CCProgram standard-fs %{ + // shading-model : standard + // lighting-model : standard (isotropy / anisotropy pbr) + // shader stage : fs + // technique usage/type : render-to-scene + + precision highp float; + // 1. surface internal macros, for technique usage or remapping some user (material) macros to surface internal macros + #include + #include + + // 2. common include with corresponding shader stage, include before surface functions + #include + + // 3. user surface functions that can use user (effect) parameters (ubo Constants) + // see surfaces/default-functions/xxx.chunk + #include + #include + + // 4. lighting-model (optional) + #include + + // 5. surface include with corresponding shader stage and shading-model (optional) + #include + + // 6. shader entry with corresponding shader stage and technique usage/type + #include +}% + +CCProgram shadow-caster-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram planar-shadow-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram reflect-map-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include + #include + #include +}% + diff --git a/editor/assets/effects/advanced/glass.effect.meta b/editor/assets/effects/advanced/glass.effect.meta new file mode 100644 index 00000000000..ff18657e4e4 --- /dev/null +++ b/editor/assets/effects/advanced/glass.effect.meta @@ -0,0 +1,11 @@ +{ + "ver": "1.7.0", + "importer": "effect", + "imported": true, + "uuid": "f288f946-150b-443d-b4b3-0227c5117c93", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} diff --git a/editor/assets/effects/advanced/hair.effect b/editor/assets/effects/advanced/hair.effect index 3a2d18e2b2e..9c500f38a29 100644 --- a/editor/assets/effects/advanced/hair.effect +++ b/editor/assets/effects/advanced/hair.effect @@ -26,7 +26,7 @@ CCEffect %{ anisotropyMap: { value: black } roughnessTRT: { value: 0.2, target: trtParams.x, editor: { displayName: TRT Roughness Offset, slide: true, range: [0, 1.0], step: 0.001, tooltip: 'The extend range of internal reflection lighting around the direct specular' } } offsetTRT: { value: 0.0, target: trtParams.y, editor: { displayName: TRT Lighting Offset, slide: true, range: [-0.5, 0.5], step: 0.001, tooltip: 'The position offset of internal reflection lighting compared to direct specular' } } - IntensityTRT: { value: 1.0, target: trtParams.w, editor: { displayName: TRT Intensity, slide: true, range: [0, 5.0], step: 0.01 } } + IntensityTRT: { value: 2.0, target: trtParams.w, editor: { displayName: TRT Intensity, slide: true, range: [0, 10.0], step: 0.01 } } baseColorTRT: { value: [0.5, 0.33, 0.18, 1.0], target: trtColor, linear: true, editor: { displayName: TRT Albedo, type: color, tooltip: 'The color of internal reflection lighting' } } ScatterCoefTT: { value: 0.0, target: ttParams.x, editor: { displayName: TT Scatter Coef, slide: true, range: [0, 1.0], step: 0.01, tooltip: 'The saturation of internal transmit lighting color' } } IntensityTT: { value: 1.0, target: ttParams.w, editor: { displayName: TT Intensity, slide: true, range: [0, 1.0], step: 0.01 } } diff --git a/editor/assets/effects/util/dcc/vat/houdini-fluid-v3-liquid.effect b/editor/assets/effects/util/dcc/vat/houdini-fluid-v3-liquid.effect index 25d9e5c09f8..2a4d39a1e9a 100644 --- a/editor/assets/effects/util/dcc/vat/houdini-fluid-v3-liquid.effect +++ b/editor/assets/effects/util/dcc/vat/houdini-fluid-v3-liquid.effect @@ -301,7 +301,7 @@ CCProgram surface-fragment %{ return normalize(CalculateNormalFromTangentSpace(nmmp, normalIntensity, N, T, FSInput_mirrorNormal)); } - float GetFresnel(float fresnel) + vec3 GetFresnel(vec3 fresnel) { return saturate(fresnel * 1.5); } diff --git a/editor/assets/effects/util/dcc/vat/zeno-fluid-liquid.effect b/editor/assets/effects/util/dcc/vat/zeno-fluid-liquid.effect index fb1af249d9d..e553d178eda 100644 --- a/editor/assets/effects/util/dcc/vat/zeno-fluid-liquid.effect +++ b/editor/assets/effects/util/dcc/vat/zeno-fluid-liquid.effect @@ -226,7 +226,7 @@ CCProgram surface-fragment %{ return normalize(CalculateNormalFromTangentSpace(nmmp, normalIntensity, N, T, FSInput_mirrorNormal)); } - float GetFresnel(float fresnel) + vec3 GetFresnel(vec3 fresnel) { return saturate(fresnel * 1.5); } From d83d2ac3f11eeb5e81e91562d405c3574d19406c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Thu, 20 Jul 2023 22:03:11 +0800 Subject: [PATCH 011/184] fix reflection probe type for skin and instancing (#15789) --- cocos/3d/framework/mesh-renderer.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cocos/3d/framework/mesh-renderer.ts b/cocos/3d/framework/mesh-renderer.ts index 00d82bb0e8d..2132c568b88 100644 --- a/cocos/3d/framework/mesh-renderer.ts +++ b/cocos/3d/framework/mesh-renderer.ts @@ -901,10 +901,11 @@ export class MeshRenderer extends ModelRenderer { // because the lighting map will influence the model's shader this._model.initLightingmap(this.bakeSettings.texture, this.bakeSettings.uvParam); this._updateUseLightProbe(); - this._updateUseReflectionProbe(); + this._updateUseReflectionProbeType(); this._updateModelParams(); this._onUpdateLightingmap(); this._onUpdateLocalShadowBiasAndProbeId(); + this._updateUseReflectionProbe(); this._updateReceiveDirLight(); this._onUpdateReflectionProbeDataMap(); this._onUpdateLocalReflectionProbeData(); @@ -1185,6 +1186,11 @@ export class MeshRenderer extends ModelRenderer { this._updateReflectionProbeTexture(); } + protected _updateUseReflectionProbeType () { + if (!this._model) return; + this._model.reflectionProbeType = this.bakeSettings.reflectionProbe; + } + protected _updateBakeToReflectionProbe () { if (!this._model) { return; } this._model.bakeToReflectionProbe = this.bakeSettings.bakeToReflectionProbe; From aacc0d7261ba3fc9b6c0018e4205ef7290aff592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Fri, 21 Jul 2023 11:48:57 +0800 Subject: [PATCH 012/184] add help for reflection probe and rename Fxaa (#15790) --- cocos/3d/reflection-probe/reflection-probe-component.ts | 3 ++- cocos/rendering/post-process/components/fxaa.ts | 8 ++++---- cocos/rendering/post-process/passes/fxaa-pass.ts | 4 ++-- editor/i18n/en/localization.js | 3 ++- editor/i18n/zh/localization.js | 3 ++- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/cocos/3d/reflection-probe/reflection-probe-component.ts b/cocos/3d/reflection-probe/reflection-probe-component.ts index eb24ff03c03..3a125488251 100644 --- a/cocos/3d/reflection-probe/reflection-probe-component.ts +++ b/cocos/3d/reflection-probe/reflection-probe-component.ts @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { ccclass, executeInEditMode, menu, playOnFocus, serializable, tooltip, type, visible } from 'cc.decorator'; +import { ccclass, executeInEditMode, help, menu, playOnFocus, serializable, tooltip, type, visible } from 'cc.decorator'; import { EDITOR, EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; import { CCBoolean, CCObject, Color, Enum, Vec3 } from '../../core'; @@ -62,6 +62,7 @@ export enum ProbeResolution { @menu('Rendering/ReflectionProbe') @executeInEditMode @playOnFocus +@help('i18n:cc.ReflectionProbe') export class ReflectionProbe extends Component { protected static readonly DEFAULT_CUBE_SIZE: Readonly = new Vec3(1, 1, 1); protected static readonly DEFAULT_PLANER_SIZE: Readonly = new Vec3(5, 0.5, 5); diff --git a/cocos/rendering/post-process/components/fxaa.ts b/cocos/rendering/post-process/components/fxaa.ts index 8f1c8a23d86..41fb51f05cc 100644 --- a/cocos/rendering/post-process/components/fxaa.ts +++ b/cocos/rendering/post-process/components/fxaa.ts @@ -1,10 +1,10 @@ import { ccclass, disallowMultiple, executeInEditMode, help, menu } from '../../../core/data/decorators'; import { PostProcessSetting } from './post-process-setting'; -@ccclass('cc.Fxaa') -@help('cc.Fxaa') -@menu('PostProcess/Fxaa') +@ccclass('cc.FXAA') +@help('cc.FXAA') +@menu('PostProcess/FXAA') @disallowMultiple @executeInEditMode -export class Fxaa extends PostProcessSetting { +export class FXAA extends PostProcessSetting { } diff --git a/cocos/rendering/post-process/passes/fxaa-pass.ts b/cocos/rendering/post-process/passes/fxaa-pass.ts index 64419cad668..80a774571a9 100644 --- a/cocos/rendering/post-process/passes/fxaa-pass.ts +++ b/cocos/rendering/post-process/passes/fxaa-pass.ts @@ -6,10 +6,10 @@ import { getCameraUniqueID } from '../../custom/define'; import { passContext } from '../utils/pass-context'; import { getSetting, SettingPass } from './setting-pass'; -import { Fxaa } from '../components/fxaa'; +import { FXAA } from '../components/fxaa'; export class FxaaPass extends SettingPass { - get setting () { return getSetting(Fxaa); } + get setting () { return getSetting(FXAA); } name = 'FxaaPass' effectName = 'pipeline/post-process/fxaa-hq'; diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 1ba99832758..7b238392b84 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -137,12 +137,13 @@ module.exports = link(mixin({ BlitScreen: `${url}/${version}/manual/en/render-pipeline/post-process/blit-screen.html`, TAA: `${url}/${version}/manual/en/render-pipeline/post-process/index.html`, FSR: `${url}/${version}/manual/en/render-pipeline/post-process/index.html`, - Fxaa: `${url}/${version}/manual/en/render-pipeline/post-process/index.html`, + FXAA: `${url}/${version}/manual/en/render-pipeline/post-process/index.html`, Bloom: `${url}/${version}/manual/en/render-pipeline/post-process/index.html`, HBAO: `${url}/${version}/manual/en/render-pipeline/post-process/index.html`, ColorGrading: `${url}/${version}/manual/en/render-pipeline/post-process/index.html`, Skin: `${url}/${version}/manual/en/shader/advanced-shader/skin.html`, RenderRoot2D: `${url}/${version}/manual/en/ui-system/components/editor/renderroot2d.html`, + ReflectionProbe: `${url}/${version}/manual/en/concepts/scene/light/probe/reflection-art-workflow.html`, }, assets: { javascript: `${url}/${version}/manual/en/concepts/scene/node-component.html`, diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 2e51cd91d3d..9e562d57c3d 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -137,12 +137,13 @@ module.exports = link(mixin({ BlitScreen: `${url}/${version}/manual/zh/render-pipeline/post-process/blit-screen.html`, TAA: `${url}/${version}/manual/zh/render-pipeline/post-process/index.html`, FSR: `${url}/${version}/manual/zh/render-pipeline/post-process/index.html`, - Fxaa: `${url}/${version}/manual/zh/render-pipeline/post-process/index.html`, + FXAA: `${url}/${version}/manual/zh/render-pipeline/post-process/index.html`, Bloom: `${url}/${version}/manual/zh/render-pipeline/post-process/index.html`, HBAO: `${url}/${version}/manual/zh/render-pipeline/post-process/index.html`, ColorGrading: `${url}/${version}/manual/zh/render-pipeline/post-process/index.html`, Skin: `${url}/${version}/manual/zh/shader/advanced-shader/skin.html`, RenderRoot2D: `${url}/${version}/manual/zh/ui-system/components/editor/renderroot2d.html`, + ReflectionProbe: `${url}/${version}/manual/zh/concepts/scene/light/probe/reflection-art-workflow.html`, }, assets: { javascript: `${url}/${version}/manual/zh/concepts/scene/node-component.html`, From 775b794aa9f079da75a16b3836bd0f07804cce8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Fri, 21 Jul 2023 11:54:54 +0800 Subject: [PATCH 013/184] Fix clip visiting in animation controller; fix typo (#15791) --- editor/src/marionette/preview.ts | 1 - editor/src/marionette/visit.ts | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/editor/src/marionette/preview.ts b/editor/src/marionette/preview.ts index 42566e88fc7..c7b8d2f16ce 100644 --- a/editor/src/marionette/preview.ts +++ b/editor/src/marionette/preview.ts @@ -88,7 +88,6 @@ class AnimationGraphPartialPreviewer { const bindingContext = new AnimationGraphBindingContext( this._root, this._poseLayoutMaintainer, this._varInstances, this._dummyAnimationController, - new EventTarget(), ); poseLayoutMaintainer.startBind(); diff --git a/editor/src/marionette/visit.ts b/editor/src/marionette/visit.ts index a6e4e8dc512..12bf082ece7 100644 --- a/editor/src/marionette/visit.ts +++ b/editor/src/marionette/visit.ts @@ -15,6 +15,7 @@ import { PoseNodeStateMachine } from '../../../cocos/animation/marionette/pose-g import { PoseNodePlayMotion } from "../../../cocos/animation/marionette/pose-graph/pose-nodes/play-motion"; import { PoseNodeSampleMotion } from "../../../cocos/animation/marionette/pose-graph/pose-nodes/sample-motion"; import { PoseGraph } from "../../../cocos/animation/marionette/pose-graph/pose-graph"; +import { AnimationGraphVariant } from "../../../cocos/animation/marionette/animation-graph-variant"; export function* visitAnimationGraphEditorExtras(animationGraph: AnimationGraph): Generator { for (const layer of animationGraph.layers) { @@ -112,7 +113,17 @@ export function* visitAnimationClipsInController(animationController: AnimationC const { graph, } = animationController; - if (graph) { - yield* visitAnimationClips(graph as AnimationGraph); + if (graph instanceof AnimationGraph) { + yield* visitAnimationClips(graph); + } else if (graph instanceof AnimationGraphVariant) { + const { + original, + clipOverrides, + } = graph; + if (original) { + for (const clip of visitAnimationClips(original)) { + yield clipOverrides.get(clip) ?? clip; + } + } } } From 3ca7d08db3694437a93e97f65aca6266435312e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Fri, 21 Jul 2023 14:32:12 +0800 Subject: [PATCH 014/184] Animation components localization (#15701) Fix --- .../skeletal-animation/skeletal-animation.ts | 6 +-- cocos/animation/animation-component.ts | 6 +-- editor/i18n/en/animation.js | 40 +++++++++++++++++++ editor/i18n/zh/animation.js | 37 +++++++++++++++++ editor/i18n/zh/localization.js | 7 ---- 5 files changed, 82 insertions(+), 14 deletions(-) diff --git a/cocos/3d/skeletal-animation/skeletal-animation.ts b/cocos/3d/skeletal-animation/skeletal-animation.ts index 62f980eb51c..a53df4e3ffc 100644 --- a/cocos/3d/skeletal-animation/skeletal-animation.ts +++ b/cocos/3d/skeletal-animation/skeletal-animation.ts @@ -23,7 +23,7 @@ */ import { - ccclass, executeInEditMode, executionOrder, help, menu, tooltip, type, serializable, editable, + ccclass, executeInEditMode, executionOrder, help, menu, type, serializable, editable, } from 'cc.decorator'; import { SkinnedMeshRenderer } from '../skinned-mesh-renderer'; import { Mat4, cclegacy, js, assertIsTrue } from '../../core'; @@ -107,7 +107,7 @@ export class SkeletalAnimation extends Animation { * 当前动画组件维护的挂点数组。要挂载自定义节点到受动画驱动的骨骼上,必须先在此注册挂点。 */ @type([Socket]) - @tooltip('i18n:animation.sockets') + @editable get sockets (): Socket[] { return this._sockets; } @@ -131,7 +131,7 @@ export class SkeletalAnimation extends Animation { * 是否使用预烘焙动画,默认启用,可以大幅提高运行效时率,但所有动画效果会被彻底固定,不支持任何形式的编辑和混合。
* 运行时动态修改此选项会在播放下一条动画片段时生效。 */ - @tooltip('i18n:animation.use_baked_animation') + @editable get useBakedAnimation (): boolean { return this._useBakedAnimation; } diff --git a/cocos/animation/animation-component.ts b/cocos/animation/animation-component.ts index 0c1045fc680..ced9b78886e 100644 --- a/cocos/animation/animation-component.ts +++ b/cocos/animation/animation-component.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { ccclass, executeInEditMode, executionOrder, help, menu, tooltip, type, serializable } from 'cc.decorator'; +import { ccclass, executeInEditMode, executionOrder, help, menu, type, serializable, editable } from 'cc.decorator'; import { EDITOR_NOT_IN_PREVIEW, TEST } from 'internal:constants'; import { Component } from '../scene-graph/component'; import { Eventify, warnID, js, cclegacy } from '../core'; @@ -60,7 +60,6 @@ export class Animation extends Eventify(Component) { * 设置时,已有剪辑关联的动画状态将被停止;若默认剪辑不在新的动画剪辑中,将被重置为空。 */ @type([AnimationClip]) - @tooltip('i18n:animation.clips') get clips (): (AnimationClip | null)[] { return this._clips; } @@ -103,7 +102,6 @@ export class Animation extends Eventify(Component) { * @see [[playOnLoad]] */ @type(AnimationClip) - @tooltip('i18n:animation.default_clip') get defaultClip (): AnimationClip | null { return this._defaultClip; } @@ -131,7 +129,7 @@ export class Animation extends Eventify(Component) { * 注意,若在组件开始运行前调用了 `crossFade` 或 `play()`,此字段将不会生效。 */ @serializable - @tooltip('i18n:animation.play_on_load') + @editable public playOnLoad = false; /** diff --git a/editor/i18n/en/animation.js b/editor/i18n/en/animation.js index 7d5f7e45433..055ec951478 100644 --- a/editor/i18n/en/animation.js +++ b/editor/i18n/en/animation.js @@ -18,7 +18,47 @@ module.exports = { classes: { 'cc': { + 'Animation': { + 'properties': { + 'clips': { + displayName: 'Clips', + tooltip: 'All clips this component governs.', + }, + 'defaultClip': { + displayName: 'Default Clip', + tooltip: 'The default clip to play.', + }, + 'playOnLoad': { + displayName: 'Play On Load', + tooltip: 'Whether automatically play the default clip after component loaded.', + }, + }, + }, + 'SkeletalAnimation': { + 'properties': { + __extends__: 'classes.cc.Animation.properties', + 'sockets': { + displayName: 'Sockets', + tooltip: 'The joint sockets this animation component maintains. ' + + 'Sockets have to be registered here before attaching custom nodes to animated joints.', + }, + 'useBakedAnimation': { + displayName: 'Use Baked Animation', + tooltip: `Whether to bake animations. Default to true, ` + + `which substantially increases performance while making all animations completely fixed.` + + `Dynamically changing this property will take effect when playing the next animation clip.`, + }, + }, + }, 'animation': { + 'AnimationController': { + properties: { + 'graph': { + displayName: 'Graph', + tooltip: 'The animation graph or animation graph variant associated with this animation controller.', + }, + }, + }, 'PoseGraphOutputNode': { displayName: 'Output Pose', }, diff --git a/editor/i18n/zh/animation.js b/editor/i18n/zh/animation.js index 08fe6073151..a164ef8588a 100644 --- a/editor/i18n/zh/animation.js +++ b/editor/i18n/zh/animation.js @@ -18,7 +18,44 @@ module.exports = { classes: { 'cc': { + 'Animation': { + 'properties': { + 'clips': { + displayName: '剪辑列表', + tooltip: '此组件管理的所有剪辑。', + }, + 'defaultClip': { + displayName: '默认剪辑', + tooltip: '默认播放的剪辑。', + }, + 'playOnLoad': { + displayName: '加载后播放', + tooltip: '是否在组件加载完成后自动播放默认剪辑。', + }, + }, + }, + 'SkeletalAnimation': { + 'properties': { + __extends__: 'classes.cc.Animation.properties', + 'sockets': { + displayName: '挂点列表', + tooltip: '当前动画组件维护的挂点列表。要挂载自定义节点到受动画驱动的骨骼上,必须先在此注册挂点。', + }, + 'useBakedAnimation': { + displayName: '预烘培动画', + tooltip: '是否预烘焙动画,默认启用,可以大幅提高运行效时率,但所有动画效果会被彻底固定,不支持任何形式的编辑和混合。', + }, + }, + }, 'animation': { + 'AnimationController': { + properties: { + 'graph': { + displayName: '图', + tooltip: '此动画控制器所关联的动画图或动画图变体。', + }, + }, + }, 'PoseGraphOutputNode': { displayName: '输出姿态', }, diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 2e51cd91d3d..ae59472f96f 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -225,13 +225,6 @@ module.exports = link(mixin({ shadowMapSize: '阴影贴图分辨率,目前支持 Low_256x256、Medium_512x512、High_1024x1024、Ultra_2048x2048 四种精度的纹理', maxReceived: '产生阴影的有效光源数量', }, - animation: { - default_clip: '在勾选自动播放或调用 play() 时默认播放的动画 clip。', - clips: '通过脚本可以访问并播放的 AnimationClip 列表', - play_on_load: '是否在运行游戏后自动播放默认动画 clip。', - use_baked_animation: '是否使用预烘焙动画,默认启用,可以大幅提高运行效时率,
但所有动画效果会被彻底固定,不支持任何形式的编辑', - sockets: '当前动画组件维护的挂点数组。要挂载自定义节点到受动画驱动的骨骼上,必须先在此注册挂点', - }, audio: { clip: '通过该组件播放的默认 AudioClip 引用', volume: '音频的音量', From 72db3322bdfed3af3f5cee355b64d3dea057bac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=90=89=E6=9E=97?= <798080536@qq.com> Date: Fri, 21 Jul 2023 15:19:24 +0800 Subject: [PATCH 015/184] add light probe group help (#15797) --- cocos/core/math/vec2.ts | 8 +------- cocos/gi/light-probe/light-probe-group.ts | 2 ++ editor/i18n/en/localization.js | 1 + editor/i18n/zh/localization.js | 1 + native/cocos/math/Vec2.h | 1 - 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cocos/core/math/vec2.ts b/cocos/core/math/vec2.ts index b3d9aa33150..4513d732f6c 100644 --- a/cocos/core/math/vec2.ts +++ b/cocos/core/math/vec2.ts @@ -297,13 +297,10 @@ export class Vec2 extends ValueType { * @override (a:Vec2, b:Vec2) => number * @override [deprecated] (out:Vec3, a:Vec2, b:Vec2) => Vec3 */ - /** - * @deprecated since v3.8.0, There is no physical meaning. - */ public static cross (a: IVec2Like, b: IVec2Like): number; /** - * @deprecated since v3.8.0, There is no physical meaning. + * @deprecated Consider use another overrides please. */ public static cross (out: Vec3, a: Out, b: Out): Vec3; @@ -719,9 +716,6 @@ export class Vec2 extends ValueType { * @param other specified vector * @return `out` */ - /** - * @deprecated since v3.8.0, There is no physical meaning. - */ public cross (other: Vec2): number { return this.x * other.y - this.y * other.x; } diff --git a/cocos/gi/light-probe/light-probe-group.ts b/cocos/gi/light-probe/light-probe-group.ts index 4da0e6bbad3..1e993cdb9d0 100644 --- a/cocos/gi/light-probe/light-probe-group.ts +++ b/cocos/gi/light-probe/light-probe-group.ts @@ -28,6 +28,7 @@ import { displayName, editable, executeInEditMode, + help, menu, range, serializable, @@ -46,6 +47,7 @@ import { AutoPlacement, PlaceMethod } from './auto-placement'; * @zh 光照探针组组件。 */ @ccclass('cc.LightProbeGroup') +@help('i18n:cc.LightProbeGroup') @menu('Rendering/LightProbeGroup') @disallowMultiple @executeInEditMode diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 1ba99832758..922eb971dae 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -71,6 +71,7 @@ module.exports = link(mixin({ DirectionalLight: `${url}/${version}/manual/en/concepts/scene/light/lightType/dir-light.html`, SphereLight: `${url}/${version}/manual/en/concepts/scene/light/lightType/sphere-light.html`, SpotLight: `${url}/${version}/manual/en/concepts/scene/light/lightType/spot-light.html`, + LightProbeGroup: `${url}/${version}/manual/en/concepts/scene/light/probe/light-probe.html`, UICoordinateTracker: `${url}/${version}/manual/en/ui-system/components/editor/ui-coordinate-tracker.html`, Animation: `${url}/${version}/manual/en/animation/animation-component.html`, SkeletalAnimation: `${url}/${version}/manual/en/animation/skeletal-animation.html`, diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index ae59472f96f..7e0569856a5 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -71,6 +71,7 @@ module.exports = link(mixin({ DirectionalLight: `${url}/${version}/manual/zh/concepts/scene/light/lightType/dir-light.html`, SphereLight: `${url}/${version}/manual/zh/concepts/scene/light/lightType/sphere-light.html`, SpotLight: `${url}/${version}/manual/zh/concepts/scene/light/lightType/spot-light.html`, + LightProbeGroup: `${url}/${version}/manual/zh/concepts/scene/light/probe/light-probe.html`, UICoordinateTracker: `${url}/${version}/manual/zh/ui-system/components/editor/ui-coordinate-tracker.html`, Animation: `${url}/${version}/manual/zh/animation/animation-component.html`, SkeletalAnimation: `${url}/${version}/manual/zh/animation/skeletal-animation.html`, diff --git a/native/cocos/math/Vec2.h b/native/cocos/math/Vec2.h index 163c3350c67..dcf5abaac9c 100644 --- a/native/cocos/math/Vec2.h +++ b/native/cocos/math/Vec2.h @@ -510,7 +510,6 @@ class CC_DLL Vec2 { /** Calculates cross product of two points. @return float @since v2.1.4 - @deprecated since v3.8.0, There is no physical meaning. */ inline float cross(const Vec2 &other) const { return x * other.y - y * other.x; From acab20f3482fb82f1770e99c2acffe497aff1f11 Mon Sep 17 00:00:00 2001 From: bofeng-song Date: Mon, 24 Jul 2023 10:21:39 +0800 Subject: [PATCH 016/184] fix multi touch cause crash on Android platform (#15796) --- .../cocos/platform/android/AndroidPlatform.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/native/cocos/platform/android/AndroidPlatform.cpp b/native/cocos/platform/android/AndroidPlatform.cpp index d39df1f0d16..fc8d213420a 100644 --- a/native/cocos/platform/android/AndroidPlatform.cpp +++ b/native/cocos/platform/android/AndroidPlatform.cpp @@ -422,7 +422,8 @@ class GameInputProxy { if (actionMasked == AMOTION_EVENT_ACTION_DOWN || actionMasked == AMOTION_EVENT_ACTION_POINTER_DOWN) { if (actionMasked == AMOTION_EVENT_ACTION_POINTER_DOWN) { - eventChangedIndex = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + eventChangedIndex = ((action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) + >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); } else { eventChangedIndex = 0; } @@ -431,7 +432,8 @@ class GameInputProxy { actionMasked == AMOTION_EVENT_ACTION_POINTER_UP) { touchEvent.type = cc::TouchEvent::Type::ENDED; if (actionMasked == AMOTION_EVENT_ACTION_POINTER_UP) { - eventChangedIndex = action >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + eventChangedIndex = ((action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) + >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); } else { eventChangedIndex = 0; } @@ -443,8 +445,9 @@ class GameInputProxy { return false; } + bool touchHandled = true; if (eventChangedIndex >= 0) { - addTouchEvent(touchEvent, eventChangedIndex, motionEvent); + touchHandled = addTouchEvent(touchEvent, eventChangedIndex, motionEvent); } else { for (int i = 0; i < motionEvent->pointerCount; i++) { addTouchEvent(touchEvent, i, motionEvent); @@ -452,7 +455,7 @@ class GameInputProxy { } events::Touch::broadcast(touchEvent); touchEvent.touches.clear(); - return true; + return touchHandled; } return false; } @@ -670,14 +673,15 @@ class GameInputProxy { } private: - static void addTouchEvent(cc::TouchEvent &touchEvent, int index, GameActivityMotionEvent *motionEvent) { + static bool addTouchEvent(cc::TouchEvent &touchEvent, int index, GameActivityMotionEvent *motionEvent) { if (index < 0 || index >= motionEvent->pointerCount) { - ABORT_IF(false); + return false; } int id = motionEvent->pointers[index].id; float x = GameActivityPointerAxes_getX(&motionEvent->pointers[index]); float y = GameActivityPointerAxes_getY(&motionEvent->pointers[index]); touchEvent.touches.emplace_back(x, y, id); + return true; } static void setMousePosition(cc::MouseEvent &mouseEvent, GameActivityMotionEvent *motionEvent) { From 069557388ac9994193c20fcd0c0052d7634ebca7 Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Tue, 25 Jul 2023 10:01:24 +0800 Subject: [PATCH 017/184] sky effect support blend and fog (#15801) --- .../lighting-flow/common-flow.chunk | 2 ++ .../model-functions/standard.chunk | 2 +- .../main-functions/misc/sky-fs.chunk | 9 ++++- .../assets/effects/advanced/car-paint.effect | 2 +- editor/assets/effects/advanced/glass.effect | 2 +- editor/assets/effects/advanced/sky.effect | 35 +++++++++++++++---- 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk index d21d83c428d..ad2dc2efcae 100644 --- a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk +++ b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk @@ -119,6 +119,7 @@ #endif #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + lightingResult.specularColorWithLighting2ndSpecular *= surfaceData.color2ndSpecular; //temporary coloration CCSurfacesLightingCalculateDirectMultiLayerBlending(lightingResult, lightingData2ndSpecular); #endif @@ -264,6 +265,7 @@ #endif #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND + lightingResult.specularColorWithLighting2ndSpecular *= surfaceData.color2ndSpecular; //temporary coloration CCSurfacesLightingCalculateDirectMultiLayerBlending(lightingResult, lightingData2ndSpecular); CCSurfacesLightingCalculateEnvironmentMultiLayerBlending(lightingResult, lightingData2ndSpecular); #endif diff --git a/editor/assets/chunks/lighting-models/model-functions/standard.chunk b/editor/assets/chunks/lighting-models/model-functions/standard.chunk index accd9389b63..74d1afe399f 100644 --- a/editor/assets/chunks/lighting-models/model-functions/standard.chunk +++ b/editor/assets/chunks/lighting-models/model-functions/standard.chunk @@ -123,7 +123,7 @@ void CCSurfaceLightingCalculateEnvironmentFresnel(out vec3 integratedGF, vec3 in #if CC_USE_REFLECTION_PROBE == REFLECTION_PROBE_TYPE_CUBE envSpec = EnvReflection(cc_reflectionProbeCubemap, R, roughness, cc_ambientGround.w); #endif - //todo: planar refraction from scene color + // todo: planar refraction from scene color when use planar probe or no probe #endif #if CC_USE_IBL && CC_USE_REFLECTION_PROBE != REFLECTION_PROBE_TYPE_CUBE diff --git a/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk b/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk index 74e5b4de8ea..ec31cee9515 100644 --- a/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk @@ -22,5 +22,12 @@ void main() { color.rgb = LinearToSRGB(color.rgb); #endif - fragColorX = color; + //todo: LDR fogging in gamma space, HDR fogging should move before tone mapping + #if CC_USE_FOG != CC_FOG_NONE + float fogFactor = 1.0; + CC_TRANSFER_FOG_BASE(vec4(FSInput_worldPos, 1.0), fogFactor); + CC_APPLY_FOG_BASE(color, fogFactor); + #endif + + fragColorX = color; } diff --git a/editor/assets/effects/advanced/car-paint.effect b/editor/assets/effects/advanced/car-paint.effect index 6e5aede6071..186e6b5276f 100644 --- a/editor/assets/effects/advanced/car-paint.effect +++ b/editor/assets/effects/advanced/car-paint.effect @@ -24,7 +24,7 @@ CCEffect %{ coatColor: { value: [1.0, 1.0, 1.0, 1.0], linear: true, editor: { displayName: CoatColor, type: color } } flakeDensity: { value: 0.5, target: flakeParam.x, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } flakeColorIntensity: { value: 0.2, target: flakeParam.y, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } - flakeTiling: { value: 10.0, target: flakeParam.z, editor: { parent: USE_FLAKE, slide: true, range: [1.0, 40.0], step: 0.001 } } + flakeTiling: { value: 10.0, target: flakeParam.z, editor: { parent: USE_FLAKE, slide: true, range: [1.0, 50.0], step: 0.001 } } coatNormalStrength: { value: 0.1, target: flakeParam.w, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } gradientColor: { value: [1.0, 1.0, 1.0, 1.0], linear: true, editor: { parent: USE_GRADIENT_COLOR, type: color } } gradientIntensity: { value: 0.5, target: emissiveScaleParam.y, editor: { parent: USE_GRADIENT_COLOR, slide: true, range: [0, 1.0], step: 0.001 } } diff --git a/editor/assets/effects/advanced/glass.effect b/editor/assets/effects/advanced/glass.effect index f8c76e0ce2e..8fd1228902a 100644 --- a/editor/assets/effects/advanced/glass.effect +++ b/editor/assets/effects/advanced/glass.effect @@ -239,7 +239,7 @@ CCProgram surface-fragment %{ float fresnel = CalculateFresnelCoefficient(min(F0, F90), F90, NoVSat); result.fresnel = vec3(fresnel); #else - // simply fix oit depth issue for bright color alpha blending + // simply fix single blend source issue for bright color alpha blending float threshold = 0.5, bright = dot(result.environmentSpecular, vec3(0.33333)); if (bright > threshold) result.environmentSpecular = result.environmentSpecular / bright * threshold; diff --git a/editor/assets/effects/advanced/sky.effect b/editor/assets/effects/advanced/sky.effect index d8c9f59d29d..b7e2e59ff2f 100644 --- a/editor/assets/effects/advanced/sky.effect +++ b/editor/assets/effects/advanced/sky.effect @@ -7,7 +7,10 @@ CCEffect %{ - vert: sky-vs frag: sky-fs properties: &props - environmentMap: { value: grey } + environmentMap: { value: grey } + positionScaling: { value: 1.0, target: params.w, editor: { tooltip: 'Set a smaller value (such as less than 1.0) to remove the effects of fog' } } + blendEnvironmentMap: { value: grey, editor: { parent: BLEND_ENV_MAP } } + blendWeight: { value: 0.0, target: params.x, editor: { parent: BLEND_ENV_MAP } } priority : max - 10 rasterizerState : &r1 cullMode : none @@ -24,30 +27,46 @@ CCEffect %{ depthStencilState: *d1 }% +CCProgram shared-ubos %{ + uniform Constants { + vec4 params; + }; +}% CCProgram surface-vertex %{ #define CC_SURFACES_VERTEX_MODIFY_WORLD_POS vec3 SurfacesVertexModifyWorldPos(in SurfacesStandardVertexIntermediate In) { // Apply uniform scaling for atmosphere effects - return In.worldPos; + return In.worldPos * params.w; } }% CCProgram surface-fragment %{ - uniform samplerCube environmentMap; + #if BLEND_ENV_MAP + uniform samplerCube blendEnvironmentMap; + #endif #define CC_SURFACES_FRAGMENT_MODIFY_BASECOLOR_AND_TRANSPARENCY + vec3 sampleEnvMap(samplerCube tex, vec3 R) + { + vec3 c = vec3(1.0); + #if USE_RGBE_CUBEMAP + c *= unpackRGBE(fragTextureLod(tex, R, 0.0)); + #else + c *= SRGBToLinear(fragTextureLod(tex, R, 0.0).rgb); + #endif + return c; + } vec4 SurfacesFragmentModifyBaseColorAndTransparency() { vec3 c = vec3(1.0); #if CC_USE_IBL vec3 normal = normalize(FSInput_worldNormal); vec3 rotationDir = RotationVecFromAxisY(normal.xyz, cc_surfaceTransform.z, cc_surfaceTransform.w); - #if USE_RGBE_CUBEMAP - c *= unpackRGBE(fragTextureLod(environmentMap, rotationDir.xyz, 0.0)); - #else - c *= SRGBToLinear(fragTextureLod(environmentMap, rotationDir.xyz, 0.0).rgb); + c = sampleEnvMap(environmentMap, rotationDir); + #if BLEND_ENV_MAP + c = mix(c, sampleEnvMap(blendEnvironmentMap, rotationDir), params.x); #endif #endif return vec4(c * cc_ambientSky.w, 1.0); @@ -59,6 +78,7 @@ CCProgram sky-vs %{ #include #include + #include #include #include }% @@ -69,6 +89,7 @@ CCProgram sky-fs %{ #include #include + #include #include #include }% From d97d3c655a28cdaec52882921a3a60f5eb2f343f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Tue, 25 Jul 2023 15:40:55 +0800 Subject: [PATCH 018/184] add global post settings (#15558) --- cocos/native-binding/decorators.ts | 20 ++++- cocos/render-scene/scene/index.jsb.ts | 10 +++ cocos/render-scene/scene/index.ts | 1 + cocos/render-scene/scene/post-settings.ts | 37 +++++++++ cocos/rendering/pipeline-scene-data.ts | 11 ++- cocos/scene-graph/scene-globals.jsb.ts | 24 +++++- cocos/scene-graph/scene-globals.ts | 46 +++++++++++- editor/i18n/en/localization.js | 3 + editor/i18n/zh/localization.js | 3 + editor/inspector/contributions/node.js | 7 ++ native/CMakeLists.txt | 2 + .../cocos/core/scene-graph/SceneGlobals.cpp | 10 +++ native/cocos/core/scene-graph/SceneGlobals.h | 4 + .../renderer/pipeline/PipelineSceneData.cpp | 4 + .../renderer/pipeline/PipelineSceneData.h | 4 + native/cocos/scene/PostSettings.cpp | 75 +++++++++++++++++++ native/cocos/scene/PostSettings.h | 67 +++++++++++++++++ native/tools/swig-config/pipeline.i | 1 + native/tools/swig-config/scene.i | 6 ++ 19 files changed, 328 insertions(+), 7 deletions(-) create mode 100644 cocos/render-scene/scene/post-settings.ts create mode 100644 native/cocos/scene/PostSettings.cpp create mode 100644 native/cocos/scene/PostSettings.h diff --git a/cocos/native-binding/decorators.ts b/cocos/native-binding/decorators.ts index fb4dc49c7c9..cfdfc74d5c9 100644 --- a/cocos/native-binding/decorators.ts +++ b/cocos/native-binding/decorators.ts @@ -792,6 +792,21 @@ export function patch_cc_PointLight(ctx: cc_PointLight_Context_Args, apply = def apply(() => { $.ccclass('cc.PointLight')(PointLight); }, 'ccclass', null); } // end of patch_cc_PointLight +//---- class cc_PostSettingsInfo +interface cc_PostSettingsInfo_Context_Args { + PostSettingsInfo: any; + ToneMappingType: any; +} +export function patch_cc_PostSettingsInfo(ctx: cc_PostSettingsInfo_Context_Args, apply = defaultExec) { + const { PostSettingsInfo, ToneMappingType } = { ...ctx }; + const toneMappingTypeDescriptor = Object.getOwnPropertyDescriptor(PostSettingsInfo.prototype, 'toneMappingType'); + apply(() => { $.tooltip('i18n:tone_mapping.toneMappingType')(PostSettingsInfo.prototype, 'toneMappingType', toneMappingTypeDescriptor); }, 'tooltip', 'toneMappingType'); + apply(() => { $.type(ToneMappingType)(PostSettingsInfo.prototype, 'toneMappingType', toneMappingTypeDescriptor); }, 'type', 'toneMappingType'); + apply(() => { $.editable(PostSettingsInfo.prototype, 'toneMappingType', toneMappingTypeDescriptor); }, 'editable', 'toneMappingType'); + apply(() => { $.serializable(PostSettingsInfo.prototype, '_toneMappingType', () => { return ToneMappingType.DEFAULT; }); }, 'serializable', '_toneMappingType'); + apply(() => { $.ccclass('cc.PostSettingsInfo')(PostSettingsInfo); }, 'ccclass', null); +} // end of patch_cc_PostSettingsInfo + //---- class cc_RangedDirectionalLight interface cc_RangedDirectionalLight_Context_Args { RangedDirectionalLight: any; @@ -874,9 +889,10 @@ interface cc_SceneGlobals_Context_Args { OctreeInfo: any; SkinInfo: any; LightProbeInfo: any; + PostSettingsInfo: any; } export function patch_cc_SceneGlobals(ctx: cc_SceneGlobals_Context_Args, apply = defaultExec) { - const { SceneGlobals, AmbientInfo, ShadowsInfo, SkyboxInfo, FogInfo, OctreeInfo, SkinInfo, LightProbeInfo } = { ...ctx }; + const { SceneGlobals, AmbientInfo, ShadowsInfo, SkyboxInfo, FogInfo, OctreeInfo, SkinInfo, LightProbeInfo, PostSettingsInfo } = { ...ctx }; const skyboxDescriptor = Object.getOwnPropertyDescriptor(SceneGlobals.prototype, 'skybox'); apply(() => { $.editable(SceneGlobals.prototype, 'ambient', () => { return new AmbientInfo(); }); }, 'editable', 'ambient'); apply(() => { $.serializable(SceneGlobals.prototype, 'ambient', () => { return new AmbientInfo(); }); }, 'serializable', 'ambient'); @@ -893,6 +909,8 @@ export function patch_cc_SceneGlobals(ctx: cc_SceneGlobals_Context_Args, apply = apply(() => { $.editable(SceneGlobals.prototype, 'skin', () => { return new SkinInfo(); }); }, 'editable', 'skin'); apply(() => { $.serializable(SceneGlobals.prototype, 'lightProbeInfo', () => { return new LightProbeInfo(); }); }, 'serializable', 'lightProbeInfo'); apply(() => { $.editable(SceneGlobals.prototype, 'lightProbeInfo', () => { return new LightProbeInfo(); }); }, 'editable', 'lightProbeInfo'); + apply(() => { $.serializable(SceneGlobals.prototype, 'postSettings', () => { return new PostSettingsInfo(); }); }, 'serializable', 'postSettings'); + apply(() => { $.editable(SceneGlobals.prototype, 'postSettings', () => { return new PostSettingsInfo(); }); }, 'editable', 'postSettings'); apply(() => { $.serializable(SceneGlobals.prototype, 'bakedWithStationaryMainLight', () => { return false; }); }, 'serializable', 'bakedWithStationaryMainLight'); apply(() => { $.editable(SceneGlobals.prototype, 'bakedWithStationaryMainLight', () => { return false; }); }, 'editable', 'bakedWithStationaryMainLight'); apply(() => { $.serializable(SceneGlobals.prototype, 'bakedWithHighpLightmap', () => { return false; }); }, 'serializable', 'bakedWithHighpLightmap'); diff --git a/cocos/render-scene/scene/index.jsb.ts b/cocos/render-scene/scene/index.jsb.ts index 87d7cff567e..9cdfcdbacc9 100644 --- a/cocos/render-scene/scene/index.jsb.ts +++ b/cocos/render-scene/scene/index.jsb.ts @@ -40,6 +40,7 @@ import type { Fog as JsbFog, Shadows as JsbShadows, Skybox as JsbSkybox, + PostSettings as JsbPostSettings } from './index'; // NOTE: why don't we export FogInfo and ShadowInfo from 'index.ts' @@ -339,6 +340,11 @@ export const EnvironmentLightingType = Enum({ DIFFUSEMAP_WITH_REFLECTION: 2, }); +export const ToneMappingType = Enum({ + DEFAULT: 0, + LINEAR: 1, +}); + export const ShadowsInfo: typeof JsbShadowsInfo = jsb.ShadowsInfo; export type ShadowsInfo = JsbShadowsInfo; export const Shadows: typeof JsbShadows = jsb.Shadows; @@ -377,6 +383,10 @@ export const Skybox: typeof JsbSkybox = jsb.Skybox; export type Skybox = JsbSkybox; cclegacy.Skybox = Skybox; +export const PostSettings: typeof JsbPostSettings = jsb.PostSettings; +export type PostSettings = JsbPostSettings; +cclegacy.PostSettings = PostSettings; + export * from './model'; export * from './submodel'; export * from './camera'; diff --git a/cocos/render-scene/scene/index.ts b/cocos/render-scene/scene/index.ts index f16cab46bd9..51843260cb6 100644 --- a/cocos/render-scene/scene/index.ts +++ b/cocos/render-scene/scene/index.ts @@ -39,3 +39,4 @@ export * from './point-light'; export * from './ranged-directional-light'; export * from './reflection-probe'; export * from './lod-group'; +export * from './post-settings'; diff --git a/cocos/render-scene/scene/post-settings.ts b/cocos/render-scene/scene/post-settings.ts new file mode 100644 index 00000000000..9d124385770 --- /dev/null +++ b/cocos/render-scene/scene/post-settings.ts @@ -0,0 +1,37 @@ +import { Enum, cclegacy } from '../../core'; +import { PostSettingsInfo } from '../../scene-graph/scene-globals'; + +export const ToneMappingType = Enum({ + DEFAULT: 0, + LINEAR: 1, +}); + +export class PostSettings { + protected _toneMappingType = ToneMappingType.DEFAULT; + protected _activated = false; + + set toneMappingType (val) { + this._toneMappingType = val; + this._updatePipeline(); + } + get toneMappingType (): number { + return this._toneMappingType; + } + public initialize (postSettingsInfo: PostSettingsInfo): void { + this._toneMappingType = postSettingsInfo.toneMappingType; + } + + public activate (): void { + this._updatePipeline(); + this._activated = true; + } + + protected _updatePipeline (): void { + const root = cclegacy.director.root; + const pipeline = root.pipeline; + pipeline.macros.CC_TONE_MAPPING_TYPE = this._toneMappingType; + if (this._activated) { + root.onGlobalPipelineStateChanged(); + } + } +} diff --git a/cocos/rendering/pipeline-scene-data.ts b/cocos/rendering/pipeline-scene-data.ts index ccee5477714..529d6c44cb9 100644 --- a/cocos/rendering/pipeline-scene-data.ts +++ b/cocos/rendering/pipeline-scene-data.ts @@ -34,7 +34,7 @@ import { Pass } from '../render-scene/core/pass'; import { CSMLayers } from './shadow/csm-layers'; import { cclegacy } from '../core'; import { Skin } from '../render-scene/scene/skin'; -import { Model } from '../render-scene/scene'; +import { Model, PostSettings } from '../render-scene/scene'; import { MeshRenderer } from '../3d/framework/mesh-renderer'; const GEOMETRY_RENDERER_TECHNIQUE_COUNT = 6; @@ -108,6 +108,7 @@ export class PipelineSceneData { public csmLayers: CSMLayers = new CSMLayers(); public octree: Octree = new Octree(); public skin: Skin = new Skin(); + public postSettings: PostSettings = new PostSettings(); public lightProbes = cclegacy.internal.LightProbes ? new cclegacy.internal.LightProbes() : null; /** @@ -224,7 +225,9 @@ export class PipelineSceneData { const vbSize = vbStride * 8; this._occlusionQueryVertexBuffer = device.createBuffer(new BufferInfo( BufferUsageBit.VERTEX | BufferUsageBit.TRANSFER_DST, - MemoryUsageBit.DEVICE, vbSize, vbStride, + MemoryUsageBit.DEVICE, + vbSize, + vbStride, )); this._occlusionQueryVertexBuffer.update(vertices); @@ -234,7 +237,9 @@ export class PipelineSceneData { const ibSize = ibStride * 36; this._occlusionQueryIndicesBuffer = device.createBuffer(new BufferInfo( BufferUsageBit.INDEX | BufferUsageBit.TRANSFER_DST, - MemoryUsageBit.DEVICE, ibSize, ibStride, + MemoryUsageBit.DEVICE, + ibSize, + ibStride, )); this._occlusionQueryIndicesBuffer.update(indices); diff --git a/cocos/scene-graph/scene-globals.jsb.ts b/cocos/scene-graph/scene-globals.jsb.ts index 36421dd2515..fc00e60db45 100644 --- a/cocos/scene-graph/scene-globals.jsb.ts +++ b/cocos/scene-graph/scene-globals.jsb.ts @@ -24,7 +24,7 @@ import { legacyCC } from '../core/global-exports'; import { CCFloat, CCInteger } from '../core/data'; import { TextureCube } from '../asset/assets/texture-cube'; import { Enum } from '../core/value-types'; -import { Ambient, EnvironmentLightingType } from '../render-scene/scene'; +import { Ambient, EnvironmentLightingType, ToneMappingType } from '../render-scene/scene'; import { Material } from '../asset/assets/material'; import { Vec2, Vec3, Color, Vec4 } from '../core/math'; import * as decros from '../native-binding/decorators'; @@ -37,6 +37,7 @@ import type { SceneGlobals as JsbSceneGlobals, LightProbeInfo as JsbLightProbeInfo, SkinInfo as JsbSkinInfo, + PostSettingsInfo as JsbPostSettingsInfo, } from './scene-globals'; declare const jsb: any; @@ -181,6 +182,10 @@ export const SkinInfo: typeof JsbSkinInfo = jsb.SkinInfo; export type SkinInfo = JsbSkinInfo; legacyCC.SkinInfo = SkinInfo; +export const PostSettingsInfo: typeof JsbPostSettingsInfo = jsb.PostSettingsInfo; +export type PostSettingsInfo = JsbPostSettingsInfo; +legacyCC.PostSettingsInfo = PostSettingsInfo; + (function () { const sceneGlobalsProto: any = SceneGlobals.prototype; @@ -192,6 +197,7 @@ legacyCC.SkinInfo = SkinInfo; this._octreeRef = this.getOctreeInfo(); this._lightProbeRef = this.getLightProbeInfo(); this._skinRef = this.getSkinInfo(); + this._postSettingsRef = this.getPostSettingsInfo(); }; Object.defineProperty(sceneGlobalsProto, 'ambient', { @@ -290,13 +296,25 @@ legacyCC.SkinInfo = SkinInfo; }, }); + Object.defineProperty(sceneGlobalsProto, 'postSettings', { + enumerable: true, + configurable: true, + get() { + return this._postSettingsRef; + }, + set(v) { + this._postSettingsRef = v; + this.setPostSettingsInfo(v); + }, + }); + })(); // handle meta data, it is generated automatically -decros.patch_cc_SceneGlobals({SceneGlobals, AmbientInfo, SkyboxInfo, FogInfo, ShadowsInfo, LightProbeInfo, OctreeInfo, SkinInfo}); +decros.patch_cc_SceneGlobals({SceneGlobals, AmbientInfo, SkyboxInfo, FogInfo, ShadowsInfo, LightProbeInfo, OctreeInfo, SkinInfo, PostSettingsInfo}); decros.patch_cc_OctreeInfo({OctreeInfo, CCInteger, Vec3, DEFAULT_WORLD_MAX_POS, DEFAULT_WORLD_MIN_POS, DEFAULT_OCTREE_DEPTH}); @@ -311,3 +329,5 @@ decros.patch_cc_AmbientInfo({AmbientInfo, Vec4, Ambient, CCFloat, legacyCC}); decros.patch_cc_LightProbeInfo({LightProbeInfo, CCFloat, CCInteger}); decros.patch_cc_SkinInfo({SkinInfo, CCFloat}); + +decros.patch_cc_PostSettingsInfo({PostSettingsInfo, ToneMappingType}); diff --git a/cocos/scene-graph/scene-globals.ts b/cocos/scene-graph/scene-globals.ts index 158b717febe..f3d97b259d5 100644 --- a/cocos/scene-graph/scene-globals.ts +++ b/cocos/scene-graph/scene-globals.ts @@ -45,6 +45,7 @@ import { cclegacy, macro } from '../core'; import { Scene } from './scene'; import { NodeEventType } from './node-event'; import { property } from '../core/data/class-decorator'; +import { PostSettings, ToneMappingType } from '../render-scene/scene/post-settings'; const _up = new Vec3(0, 1, 0); const _v3 = new Vec3(); @@ -1183,6 +1184,40 @@ export class SkinInfo { } legacyCC.SkinInfo = SkinInfo; +@ccclass('cc.PostSettingsInfo') +export class PostSettingsInfo { + /** + * @zh 色调映射类型 + * @en Tone mapping type + */ + @editable + @type(ToneMappingType) + @tooltip('i18n:tone_mapping.toneMappingType') + set toneMappingType (val) { + this._toneMappingType = val; + if (this._resource) { + this._resource.toneMappingType = val; + } + } + + get toneMappingType (): number { + return this._toneMappingType; + } + + @serializable + protected _toneMappingType = ToneMappingType.DEFAULT; + + protected _resource: PostSettings | null = null; + + public activate (resource: PostSettings): void { + this._resource = resource; + this._resource.initialize(this); + this._resource.activate(); + } +} + +legacyCC.PostSettingsInfo = PostSettingsInfo; + export interface ILightProbeNode { node: Node; probes: Vec3[] | null; @@ -1613,6 +1648,14 @@ export class SceneGlobals { @serializable public lightProbeInfo = new LightProbeInfo(); + /** + * @en Tone mapping related configuration + * @zh 色调映射相关配置 + */ + @editable + @serializable + public postSettings = new PostSettingsInfo(); + /** * @en bake with stationary main light * @zh 主光源是否以静止状态烘培 @@ -1648,8 +1691,9 @@ export class SceneGlobals { this.fog.activate(sceneData.fog); this.octree.activate(sceneData.octree); this.skin.activate(sceneData.skin); + this.postSettings.activate(sceneData.postSettings); if (this.lightProbeInfo && sceneData.lightProbes) { - this.lightProbeInfo.activate(scene, sceneData.lightProbes); + this.lightProbeInfo.activate(scene, sceneData.lightProbes as LightProbes); } const root = legacyCC.director.root as Root; diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 922eb971dae..4afe3536027 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -1318,6 +1318,9 @@ module.exports = link(mixin({ shadingScale: 'Rendering resolution.', enableShadingScaleInEditor: 'Enable Shading Scale In Editor', }, + tone_mapping: { + toneMappingType: 'Tone mapping type,valid only when HDR is enabled.', + }, }, require('./animation'), diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 7e0569856a5..9a3d870375a 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -1292,6 +1292,9 @@ module.exports = link(mixin({ shadingScale: '渲染分辨率', enableShadingScaleInEditor: '是否在编辑器中缩放渲染分辨率', }, + tone_mapping: { + toneMappingType: '色调映射方式,只在启用HDR时生效。', + }, }, require('./animation'), diff --git a/editor/inspector/contributions/node.js b/editor/inspector/contributions/node.js index fb0dbce8e80..bf17bebb444 100644 --- a/editor/inspector/contributions/node.js +++ b/editor/inspector/contributions/node.js @@ -381,6 +381,7 @@ exports.template = /* html*/` + @@ -453,6 +454,7 @@ exports.$ = { sceneSkyboxAfter: '.container > .body > .scene > .skybox > .after', sceneOctree: '.container > .body > .scene > .octree', sceneSkin: '.container > .body > .scene > .skin', + scenePostSettings: '.scene > .postSettings', node: '.container > .body > .node', nodeHeader: '.container > .body > .node > .component-header', @@ -953,6 +955,9 @@ const Elements = { panel.dump._globals.skin.help = panel.getHelpUrl({ help: 'i18n:cc.Skin' }); panel.$.sceneSkin.render(panel.dump._globals.skin); + panel.dump._globals.postSettings.displayName = 'PostSettings'; + panel.$.scenePostSettings.render(panel.dump._globals.postSettings); + const $skyProps = panel.$.sceneSkybox.querySelectorAll('ui-prop[type="dump"]'); $skyProps.forEach(($prop) => { if ($prop.dump.name === 'envLightingType') { @@ -1089,6 +1094,8 @@ const Elements = { const $prop = useHDR ? panel.$.sceneSkyboxEnvmapHDR : panel.$.sceneSkyboxEnvmapLDR; const uuid = $prop.dump.value.uuid; Elements.scene.setEnvMapAndConvolutionMap.call(panel, uuid); + + panel.$.scenePostSettings.style.display = useHDR ? 'inline-flex' : 'none'; }, skyboxEnvmapChange(useHDR, event) { const panel = this; diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index bf1218beb9c..a1c3dacce9b 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -1536,6 +1536,8 @@ cocos_source_files( cocos/scene/ReflectionProbeManager.h cocos/scene/Skin.h cocos/scene/Skin.cpp + cocos/scene/PostSettings.h + cocos/scene/PostSettings.cpp ) ##### primitive diff --git a/native/cocos/core/scene-graph/SceneGlobals.cpp b/native/cocos/core/scene-graph/SceneGlobals.cpp index d198e627d6c..6947fcbb5b6 100644 --- a/native/cocos/core/scene-graph/SceneGlobals.cpp +++ b/native/cocos/core/scene-graph/SceneGlobals.cpp @@ -33,6 +33,7 @@ #include "scene/Shadow.h" #include "scene/Skin.h" #include "scene/Skybox.h" +#include "scene/PostSettings.h" namespace cc { @@ -46,6 +47,7 @@ SceneGlobals::SceneGlobals() { _bakedWithStationaryMainLight = false; _bakedWithHighpLightmap = false; _skinInfo = ccnew scene::SkinInfo(); + _postSettingsInfo = ccnew scene::PostSettingsInfo(); } void SceneGlobals::activate(Scene *scene) { @@ -78,6 +80,10 @@ void SceneGlobals::activate(Scene *scene) { _skinInfo->activate(sceneData->getSkin()); } + if (_postSettingsInfo != nullptr && sceneData->getPostSettings()) { + _postSettingsInfo->activate(sceneData->getPostSettings()); + } + Root::getInstance()->onGlobalPipelineStateChanged(); } @@ -117,4 +123,8 @@ void SceneGlobals::setSkinInfo(scene::SkinInfo *info) { _skinInfo = info; } +void SceneGlobals::setPostSettingsInfo(scene::PostSettingsInfo *info) { + _postSettingsInfo = info; +} + } // namespace cc diff --git a/native/cocos/core/scene-graph/SceneGlobals.h b/native/cocos/core/scene-graph/SceneGlobals.h index 802151fbc65..b16f688cf02 100644 --- a/native/cocos/core/scene-graph/SceneGlobals.h +++ b/native/cocos/core/scene-graph/SceneGlobals.h @@ -36,6 +36,7 @@ class SkyboxInfo; class FogInfo; class OctreeInfo; class SkinInfo; +class PostSettingsInfo; } // namespace scene namespace gi { @@ -58,6 +59,7 @@ class SceneGlobals : public RefCounted { inline bool getBakedWithStationaryMainLight() const { return _bakedWithStationaryMainLight; } inline bool getBakedWithHighpLightmap() const { return _bakedWithHighpLightmap; } inline scene::SkinInfo *getSkinInfo() const { return _skinInfo.get(); } + inline scene::PostSettingsInfo *getPostSettingsInfo() const { return _postSettingsInfo.get(); } void setAmbientInfo(scene::AmbientInfo *info); void setShadowsInfo(scene::ShadowsInfo *info); @@ -68,6 +70,7 @@ class SceneGlobals : public RefCounted { void setBakedWithStationaryMainLight(bool value); void setBakedWithHighpLightmap(bool value); void setSkinInfo(scene::SkinInfo *info); + void setPostSettingsInfo(scene::PostSettingsInfo *info); private: IntrusivePtr _ambientInfo; @@ -77,6 +80,7 @@ class SceneGlobals : public RefCounted { IntrusivePtr _octreeInfo; IntrusivePtr _lightProbeInfo; IntrusivePtr _skinInfo; + IntrusivePtr _postSettingsInfo; bool _bakedWithStationaryMainLight; bool _bakedWithHighpLightmap; }; diff --git a/native/cocos/renderer/pipeline/PipelineSceneData.cpp b/native/cocos/renderer/pipeline/PipelineSceneData.cpp index 6383ee2032a..3a0db2f82ec 100644 --- a/native/cocos/renderer/pipeline/PipelineSceneData.cpp +++ b/native/cocos/renderer/pipeline/PipelineSceneData.cpp @@ -38,6 +38,8 @@ #include "scene/Shadow.h" #include "scene/Skin.h" #include "scene/Skybox.h" +#include "scene/Model.h" +#include "scene/PostSettings.h" namespace cc { namespace pipeline { @@ -51,6 +53,7 @@ PipelineSceneData::PipelineSceneData() { _octree = ccnew scene::Octree(); _lightProbes = ccnew gi::LightProbes(); _skin = ccnew scene::Skin(); + _postSettings = ccnew scene ::PostSettings(); } PipelineSceneData::~PipelineSceneData() { @@ -62,6 +65,7 @@ PipelineSceneData::~PipelineSceneData() { CC_SAFE_DELETE(_csmLayers); CC_SAFE_DELETE(_lightProbes); CC_SAFE_DELETE(_skin); + CC_SAFE_DELETE(_postSettings); } void PipelineSceneData::activate(gfx::Device *device) { diff --git a/native/cocos/renderer/pipeline/PipelineSceneData.h b/native/cocos/renderer/pipeline/PipelineSceneData.h index cb9e9eeab0a..1b2867a0b49 100644 --- a/native/cocos/renderer/pipeline/PipelineSceneData.h +++ b/native/cocos/renderer/pipeline/PipelineSceneData.h @@ -44,6 +44,7 @@ class Fog; class Octree; class Light; class Skin; +class PostSettings; } // namespace scene namespace gi { class LightProbes; @@ -76,6 +77,7 @@ class CC_DLL PipelineSceneData : public RefCounted { inline scene::Octree *getOctree() const { return _octree; } inline gi::LightProbes *getLightProbes() const { return _lightProbes; } inline scene::Skin *getSkin() const { return _skin; } + inline scene::PostSettings *getPostSettings() const { return _postSettings; } inline gfx::InputAssembler *getOcclusionQueryInputAssembler() const { return _occlusionQueryInputAssembler; } inline scene::Pass *getOcclusionQueryPass() const { return _occlusionQueryPass; } inline gfx::Shader *getOcclusionQueryShader() const { return _occlusionQueryShader; } @@ -134,6 +136,8 @@ class CC_DLL PipelineSceneData : public RefCounted { scene::Skin *_skin{nullptr}; // manage memory manually CSMLayers *_csmLayers{nullptr}; + // manage memory manually + scene::PostSettings *_postSettings{nullptr}; bool _isHDR{true}; bool _csmSupported{true}; diff --git a/native/cocos/scene/PostSettings.cpp b/native/cocos/scene/PostSettings.cpp new file mode 100644 index 00000000000..b83bb044a50 --- /dev/null +++ b/native/cocos/scene/PostSettings.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** + Copyright (c) 2023 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 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 "scene/PostSettings.h" +#include "core/Root.h" +#include "renderer/pipeline/custom/RenderInterfaceTypes.h" +namespace cc { +namespace scene { + +void PostSettingsInfo::activate(PostSettings *resource) { + _resource = resource; + if (_resource != nullptr) { + _resource->initialize(*this); + _resource->activate(); + } +} +void PostSettingsInfo::setToneMappingType(ToneMappingType toneMappingType) { + _toneMappingType = toneMappingType; + + if (_resource != nullptr) { + _resource->setToneMappingType(toneMappingType); + } +} + +void PostSettings::activate() { + _activated = true; + updatePipeline(); +} + +void PostSettings::initialize(const PostSettingsInfo &postSettingsInfo) { + _activated = false; + _toneMappingType = postSettingsInfo.getToneMappingType(); +} + +void PostSettings::setToneMappingType(ToneMappingType toneMappingType) { + _toneMappingType = toneMappingType; + updatePipeline(); +} + +void PostSettings::updatePipeline() const { + + Root *root = Root::getInstance(); + auto *pipeline = root->getPipeline(); + + pipeline->setValue("CC_TONE_MAPPING_TYPE", static_cast(_toneMappingType)); + + if (_activated) + { + root->onGlobalPipelineStateChanged(); + } +} + +} // namespace scene +} // namespace cc diff --git a/native/cocos/scene/PostSettings.h b/native/cocos/scene/PostSettings.h new file mode 100644 index 00000000000..f81d4106a29 --- /dev/null +++ b/native/cocos/scene/PostSettings.h @@ -0,0 +1,67 @@ +/**************************************************************************** + Copyright (c) 2023 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 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 "base/RefCounted.h" + +namespace cc { + namespace scene { + enum class ToneMappingType { + DEFAULT = 0, + LINEAR = 1, + }; + + class PostSettings; + class PostSettingsInfo : public RefCounted { + public: + PostSettingsInfo() = default; + ~PostSettingsInfo() override = default; + + inline ToneMappingType getToneMappingType() const { return _toneMappingType; } + void setToneMappingType(ToneMappingType toneMappingType); + + void activate(PostSettings *resource); + PostSettings *_resource{nullptr}; + ToneMappingType _toneMappingType{ ToneMappingType::DEFAULT }; + }; + + class PostSettings final { + public: + PostSettings() = default; + ~PostSettings() = default; + void activate(); + + void initialize(const PostSettingsInfo &postSettingsInfo); + inline ToneMappingType getToneMappingType() const { return _toneMappingType; } + void setToneMappingType(ToneMappingType toneMappingType); + private: + void updatePipeline() const; + bool _activated{ false }; + ToneMappingType _toneMappingType{ ToneMappingType::DEFAULT }; + }; + + + }// namespace scene +} // namespace cc diff --git a/native/tools/swig-config/pipeline.i b/native/tools/swig-config/pipeline.i index 9df3b14f6a9..130145affda 100644 --- a/native/tools/swig-config/pipeline.i +++ b/native/tools/swig-config/pipeline.i @@ -169,6 +169,7 @@ using namespace cc; %attribute(cc::pipeline::PipelineSceneData, cc::scene::Skybox*, skybox, getSkybox); %attribute(cc::pipeline::PipelineSceneData, cc::scene::Shadows*, shadows, getShadows); %attribute(cc::pipeline::PipelineSceneData, cc::scene::Skin*, skin, getSkin); +%attribute(cc::pipeline::PipelineSceneData, cc::scene::PostSettings*, postSettings, getPostSettings); %attribute(cc::pipeline::PipelineSceneData, cc::gi::LightProbes*, lightProbes, getLightProbes); %attribute(cc::pipeline::PipelineSceneData, ccstd::vector, validPunctualLights, getValidPunctualLights, setValidPunctualLights); %attribute(cc::pipeline::PipelineSceneData, bool, csmSupported, getCSMSupported); diff --git a/native/tools/swig-config/scene.i b/native/tools/swig-config/scene.i index 946c8fab6df..73b03f4ddd3 100644 --- a/native/tools/swig-config/scene.i +++ b/native/tools/swig-config/scene.i @@ -23,6 +23,7 @@ #include "scene/Shadow.h" #include "scene/Skybox.h" #include "scene/Skin.h" +#include "scene/PostSettings.h" #include "scene/DirectionalLight.h" #include "scene/SpotLight.h" #include "scene/SphereLight.h" @@ -478,6 +479,8 @@ using namespace cc; %attribute(cc::scene::Skin, float, blurRadius, getBlurRadius, setBlurRadius); %attribute(cc::scene::Skin, float, sssIntensity, getSSSIntensity, setSSSIntensity); +%attribute(cc::scene::PostSettings, cc::scene::ToneMappingType, toneMappingType, getToneMappingType, setToneMappingType); + %attribute(cc::scene::Model, cc::scene::RenderScene*, scene, getScene, setScene); %attribute(cc::scene::Model, ccstd::vector> &, _subModels, getSubModels); %attribute(cc::scene::Model, ccstd::vector> &, subModels, getSubModels); @@ -578,6 +581,8 @@ using namespace cc; %attribute(cc::scene::OctreeInfo, cc::Vec3&, maxPos, getMaxPos, setMaxPos); %attribute(cc::scene::OctreeInfo, uint32_t, depth, getDepth, setDepth); +%attribute(cc::scene::PostSettingsInfo, cc::scene::ToneMappingType, toneMappingType, getToneMappingType, setToneMappingType); + %attribute(cc::Scene, bool, autoReleaseAssets, isAutoReleaseAssets, setAutoReleaseAssets); %attribute(cc::scene::ReflectionProbe, cc::scene::ReflectionProbe::ProbeType, probeType, getProbeType, setProbeType); @@ -678,6 +683,7 @@ using namespace cc; %include "scene/Shadow.h" %include "scene/Skybox.h" %include "scene/Skin.h" +%include "scene/PostSettings.h" %include "scene/DirectionalLight.h" %include "scene/SpotLight.h" %include "scene/SphereLight.h" From 32245a2e20ec4e6c5a6573c0c811796483930d1b Mon Sep 17 00:00:00 2001 From: dogeFu <609075410@qq.com> Date: Tue, 25 Jul 2023 18:17:28 +0800 Subject: [PATCH 019/184] fix : node._instantiate has different behavior in native scene (#15816) --- cocos/scene-graph/node.jsb.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/cocos/scene-graph/node.jsb.ts b/cocos/scene-graph/node.jsb.ts index 15f31c4beee..3f4308293ce 100644 --- a/cocos/scene-graph/node.jsb.ts +++ b/cocos/scene-graph/node.jsb.ts @@ -1304,20 +1304,13 @@ nodeProto._instantiate = function (cloned: Node, isSyncedNode: boolean) { const newPrefabInfo = (cloned as any)._prefab; if (EDITOR && newPrefabInfo) { if (cloned === newPrefabInfo.root) { + EditorExtends.PrefabUtils.addPrefabInstance?.(cloned); // newPrefabInfo.fileId = ''; } else { // var PrefabUtils = Editor.require('scene://utils/prefab'); // PrefabUtils.unlinkPrefab(cloned); } } - if (EDITOR_NOT_IN_PREVIEW) { - // TODO: Property 'sync' does not exist on type 'PrefabInfo'. - // issue: https://github.com/cocos/cocos-engine/issues/14643 - const syncing = newPrefabInfo && cloned === newPrefabInfo.root && (newPrefabInfo as any).sync; - if (!syncing) { - cloned.name += ' (Clone)'; - } - } // reset and init // NOTE: access protected property From b6bcc12b7ecbece9712a0d045d4e0df2520143ad Mon Sep 17 00:00:00 2001 From: qiuguohua Date: Wed, 26 Jul 2023 10:15:45 +0800 Subject: [PATCH 020/184] Solve unchecked websocket link failure issue (#15799) --- native/external-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/external-config.json b/native/external-config.json index 143079286e8..082f542393f 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-6" + "checkout": "v3.8.1-8" } } From 31342c46334ec7380c72b3ee4bc8580324022a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Wed, 26 Jul 2023 11:09:38 +0800 Subject: [PATCH 021/184] Update editable.ts (#15820) --- cocos/core/data/decorators/editable.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cocos/core/data/decorators/editable.ts b/cocos/core/data/decorators/editable.ts index 75ab976b2f0..bf8d59df181 100644 --- a/cocos/core/data/decorators/editable.ts +++ b/cocos/core/data/decorators/editable.ts @@ -289,11 +289,7 @@ export const displayOrder: (order: number) => LegacyPropertyDecorator = !DEV * 设置该属性在编辑器中的计量单位。 * @param name 计量单位的名称。 */ -export const unit: (name: -| 'lm' -| 'lx' -| 'cd/m²' -) => LegacyPropertyDecorator = !DEV +export const unit: (name: string) => LegacyPropertyDecorator = !DEV ? emptyDecoratorFn : setPropertyStashVar1WithImplicitVisible('unit'); From b9c259eb2aa5a1c0b466c36d31e9c186ef82b3a3 Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Wed, 26 Jul 2023 11:11:41 +0800 Subject: [PATCH 022/184] add shader functions (#15814) --- .../chunks/common/math/coordinates.chunk | 10 +++++++ editor/assets/chunks/common/math/number.chunk | 11 ++++++++ .../assets/effects/advanced/car-paint.effect | 28 ++++++++++++------- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/editor/assets/chunks/common/math/coordinates.chunk b/editor/assets/chunks/common/math/coordinates.chunk index 08c05a227c9..c994cfc699d 100644 --- a/editor/assets/chunks/common/math/coordinates.chunk +++ b/editor/assets/chunks/common/math/coordinates.chunk @@ -101,6 +101,16 @@ vec3 RotationVecFromAxisY(vec3 v, float rotateAngleArc) return RotationVecFromAxisY(v, cos(rotateAngleArc), sin(rotateAngleArc)); } +vec3 RotationVecFromAxis(vec3 v, vec3 axis, float rotateAngleArc) +{ + float cosAngle = cos(rotateAngleArc); + float sinAngle = sin(rotateAngleArc); + vec3 crossProd = cross(axis, v); + float dotProd = dot(axis, v); + vec3 axisScaled = axis * dotProd * (1.0 - cosAngle); + return v * cosAngle + crossProd * sinAngle + axisScaled; +} + // rotationAngle: radians, 0-2Pi void RotateTangentAndBinormal(inout vec3 tangent, inout vec3 binormal, vec3 normal, float rotationAngle) { diff --git a/editor/assets/chunks/common/math/number.chunk b/editor/assets/chunks/common/math/number.chunk index cec08efffa7..843fa2ba750 100644 --- a/editor/assets/chunks/common/math/number.chunk +++ b/editor/assets/chunks/common/math/number.chunk @@ -51,3 +51,14 @@ vec4 rsqrt(vec4 value) { return vec4(1.0) / sqrt(value); } float rand(vec2 seeds_zero_to_one) { return fract(sin(dot(seeds_zero_to_one.xy, vec2(12.9898, 78.233))) * 43758.5453); } + +#if __VERSION__ <= 100 + mat4 transpose(mat4 v) { + mat4 tmp; + tmp[0] = vec4(v[0].x, v[1].x, v[2].x, v[3].x); + tmp[1] = vec4(v[0].y, v[1].y, v[2].y, v[3].y); + tmp[2] = vec4(v[0].z, v[1].z, v[2].z, v[3].z); + tmp[3] = vec4(v[0].w, v[1].w, v[2].w, v[3].w); + return tmp; + } +#endif diff --git a/editor/assets/effects/advanced/car-paint.effect b/editor/assets/effects/advanced/car-paint.effect index 186e6b5276f..457fd1d97c5 100644 --- a/editor/assets/effects/advanced/car-paint.effect +++ b/editor/assets/effects/advanced/car-paint.effect @@ -24,7 +24,7 @@ CCEffect %{ coatColor: { value: [1.0, 1.0, 1.0, 1.0], linear: true, editor: { displayName: CoatColor, type: color } } flakeDensity: { value: 0.5, target: flakeParam.x, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } flakeColorIntensity: { value: 0.2, target: flakeParam.y, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } - flakeTiling: { value: 10.0, target: flakeParam.z, editor: { parent: USE_FLAKE, slide: true, range: [1.0, 50.0], step: 0.001 } } + flakeTiling: { value: 10.0, target: flakeParam.z, editor: { parent: USE_FLAKE, slide: true, range: [1.0, 100.0], step: 0.001 } } coatNormalStrength: { value: 0.1, target: flakeParam.w, editor: { parent: USE_FLAKE, slide: true, range: [0, 1.0], step: 0.001 } } gradientColor: { value: [1.0, 1.0, 1.0, 1.0], linear: true, editor: { parent: USE_GRADIENT_COLOR, type: color } } gradientIntensity: { value: 0.5, target: emissiveScaleParam.y, editor: { parent: USE_GRADIENT_COLOR, slide: true, range: [0, 1.0], step: 0.001 } } @@ -215,12 +215,20 @@ CCProgram surface-fragment %{ return coatColor.xyz; } - vec4 sampleFlake(sampler2D tex, vec2 uv) - { - vec4 blurred = texture(tex, uv); - vec4 detailed = fragTextureLod(tex, uv, 1.0); - return lerp(blurred, detailed, 0.3); - } + #if USE_FLAKE + vec4 sampleFlakeData(vec2 uv) + { + vec4 blurred = texture(flakeDataMap, uv); + vec4 detailed = fragTextureLod(flakeDataMap, uv, 1.0); + return lerp(blurred, detailed, 0.3); + } + vec4 sampleFlakeNormal(vec2 uv) + { + vec4 blurred = texture(coatNormalMap, uv); + vec4 detailed = fragTextureLod(coatNormalMap, uv, 1.0); + return lerp(blurred, detailed, 0.3); + } + #endif #define CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_WORLD_NORMAL vec3 SurfacesFragmentModifyClearCoatWorldNormal() @@ -229,8 +237,8 @@ CCProgram surface-fragment %{ #if USE_FLAKE float density = flakeParam.x, densityMin = 0.25, flakeTiling = flakeParam.z; vec2 uv = FSInput_texcoord * flakeTiling; - vec4 data = sampleFlake(flakeDataMap, uv); - vec3 nmmp = (sampleFlake(coatNormalMap, uv).xyz - vec3(0.5)) * 2.0; + vec4 data = sampleFlakeData(uv); + vec3 nmmp = (sampleFlakeNormal(uv).xyz - vec3(0.5)) * 2.0; float C = (data.a - 1.0) / density + 1.0; float bumpIntensity = saturate(max(densityMin, C)); nmmp = lerp(vec3(0.0, 0.0, 1.0), nmmp, bumpIntensity); @@ -257,7 +265,7 @@ CCProgram surface-fragment %{ float density = flakeParam.x, flakeColorIntensity = flakeParam.y, flakeTiling = flakeParam.z; vec2 uv = FSInput_texcoord * flakeTiling; - vec4 data = sampleFlake(flakeDataMap, uv); + vec4 data = sampleFlakeData(uv); float C = (data.a - 1.0) / density + 1.0; float flakeTintWeight = 1.0; float flakeWeight = saturate(C) * flakeTintWeight * flakeColorIntensity; From 2e2b7ec03206f5b187bd5949c5c95e1fa5462c84 Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 26 Jul 2023 11:12:42 +0800 Subject: [PATCH 023/184] fixed fsr input/output size (#15798) --- .../rendering/post-process/passes/fsr-pass.ts | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/cocos/rendering/post-process/passes/fsr-pass.ts b/cocos/rendering/post-process/passes/fsr-pass.ts index eedfed677df..1231470b58e 100644 --- a/cocos/rendering/post-process/passes/fsr-pass.ts +++ b/cocos/rendering/post-process/passes/fsr-pass.ts @@ -10,12 +10,14 @@ import { FSR } from '../components/fsr'; import { getSetting, SettingPass } from './setting-pass'; import { game } from '../../../game'; +const tempVec4 = new Vec4(); + export class FSRPass extends SettingPass { get setting (): FSR { return getSetting(FSR); } - name = 'FSRPass' + name = 'FSRPass'; effectName = 'pipeline/post-process/fsr'; - outputNames = ['FSRColor'] + outputNames = ['FSRColor']; checkEnable (camera: Camera): boolean { let enable = super.checkEnable(camera); @@ -31,20 +33,16 @@ export class FSRPass extends SettingPass { passContext.material = this.material; passContext.clearBlack(); - passContext.updatePassViewPort(1 / passContext.shadingScale); + passContext.updatePassViewPort(1 / passContext.shadingScale, 0); - const inputWidth = Math.floor(game.canvas!.width * passContext.shadingScale); - const inputHeight = Math.floor(game.canvas!.height * passContext.shadingScale); - const outWidth = Math.floor(game.canvas!.width); - const outHeight = Math.floor(game.canvas!.height); + const inputWidth = Math.floor(passContext.passViewport.width * passContext.shadingScale); + const inputHeight = Math.floor(passContext.passViewport.height * passContext.shadingScale); + const outWidth = Math.floor(passContext.passViewport.width); + const outHeight = Math.floor(passContext.passViewport.height); const setting = this.setting; - this.material.setProperty('fsrParams', new Vec4(clamp(1.0 - setting.sharpness, 0.02, 0.98), 0, 0, 0)); - this.material.setProperty('texSize', - new Vec4( - inputWidth, inputHeight, - outWidth, outHeight, - )); + this.material.setProperty('fsrParams', tempVec4.set(clamp(1.0 - setting.sharpness, 0.02, 0.98), 0, 0, 0)); + this.material.setProperty('texSize', tempVec4.set(inputWidth, inputHeight, outWidth, outHeight)); const input0 = this.lastPass!.slotName(camera, 0); const easu = `FSR_EASU${cameraID}`; From e8e704cf184e87848b2a94845bedc96689b186cd Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Wed, 26 Jul 2023 11:13:14 +0800 Subject: [PATCH 024/184] fixed fsr/fxaa alpha (#15800) --- editor/assets/effects/pipeline/post-process/fsr.effect | 6 ++++-- editor/assets/effects/pipeline/post-process/fxaa-hq.effect | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/editor/assets/effects/pipeline/post-process/fsr.effect b/editor/assets/effects/pipeline/post-process/fsr.effect index 90728255e88..d7afb9fcc6a 100644 --- a/editor/assets/effects/pipeline/post-process/fsr.effect +++ b/editor/assets/effects/pipeline/post-process/fsr.effect @@ -80,7 +80,8 @@ CCProgram fs-easu %{ rendersize, rendersize, texSize.zw ); FsrEasuF(c, gl_FragCoord.xy, con0, con1, con2, con3); - fragColor = vec4(c.xyz, 1.); + float alpha = texture(outputResultMap, v_uv).a; + fragColor = vec4(c.xyz, alpha); } }% @@ -115,6 +116,7 @@ CCProgram fs-rcas %{ // Perform RCAS pass vec3 col = FsrRcasF(gl_FragCoord.xy, con); - fragColor = vec4(col, 1.); + float alpha = texture(outputResultMap, v_uv).a; + fragColor = vec4(col, alpha); } }% diff --git a/editor/assets/effects/pipeline/post-process/fxaa-hq.effect b/editor/assets/effects/pipeline/post-process/fxaa-hq.effect index 3f894f98fc2..1312f6e0508 100644 --- a/editor/assets/effects/pipeline/post-process/fxaa-hq.effect +++ b/editor/assets/effects/pipeline/post-process/fxaa-hq.effect @@ -35,7 +35,8 @@ CCProgram fxaa-edge-fs %{ vec4 frag () { vec3 color = FxaaPixelShader(v_uv, sceneColorMap, texSize.zw); - return vec4(color, 1.0); + float alpha = texture(sceneColorMap, v_uv).a; + return vec4(color, alpha); } }% From 41a16d73224e1e8f5ad52dfe690a4f78b09a11b2 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 26 Jul 2023 12:07:22 +0800 Subject: [PATCH 025/184] Fix ci --- cocos/2d/components/ui-opacity.ts | 5 +- cocos/render-scene/scene/reflection-probe.ts | 9 +- cocos/rendering/custom/define.ts | 472 +++++++++++++----- .../post-process/passes/fxaa-pass.ts | 4 +- cocos/spine/assembler/simple.ts | 28 +- cocos/spine/skeleton.ts | 21 +- 6 files changed, 381 insertions(+), 158 deletions(-) diff --git a/cocos/2d/components/ui-opacity.ts b/cocos/2d/components/ui-opacity.ts index 68d2052b247..2990cf854c9 100644 --- a/cocos/2d/components/ui-opacity.ts +++ b/cocos/2d/components/ui-opacity.ts @@ -68,12 +68,11 @@ export class UIOpacity extends Component { this.setEntityLocalOpacityDirtyRecursively(true); - if(EDITOR_NOT_IN_PREVIEW) { - setTimeout(()=>{ + if (EDITOR_NOT_IN_PREVIEW) { + setTimeout(() => { EditorExtends.Node.emit('change', this.node.uuid, this.node); }, 200); } - } private setEntityLocalOpacityDirtyRecursively (dirty: boolean): void { diff --git a/cocos/render-scene/scene/reflection-probe.ts b/cocos/render-scene/scene/reflection-probe.ts index ea7a32e481c..43bc0526fe0 100644 --- a/cocos/render-scene/scene/reflection-probe.ts +++ b/cocos/render-scene/scene/reflection-probe.ts @@ -29,6 +29,7 @@ import { CAMERA_DEFAULT_MASK } from '../../rendering/define'; import { ClearFlagBit, Framebuffer } from '../../gfx'; import { TextureCube } from '../../asset/assets/texture-cube'; import { RenderTexture } from '../../asset/assets/render-texture'; +import { view } from '../../ui/view'; export enum ProbeClearFlag { SKYBOX = SKYBOX_FLAG | ClearFlagBit.DEPTH_STENCIL, @@ -125,10 +126,10 @@ export class ReflectionProbe { * @en Set probe type,cube or planar. * @zh 设置探针类型,cube或者planar */ - set probeType (value: number) { + set probeType (value: ProbeType) { this._probeType = value; } - get probeType (): number { + get probeType (): ProbeType { return this._probeType; } @@ -308,7 +309,7 @@ export class ReflectionProbe { public renderPlanarReflection (sourceCamera: Camera): void { if (!sourceCamera) return; if (!this.realtimePlanarTexture) { - const canvasSize = cclegacy.view.getDesignResolutionSize(); + const canvasSize = view.getDesignResolutionSize(); this.realtimePlanarTexture = this._createTargetTexture(canvasSize.width, canvasSize.height); cclegacy.internal.reflectionProbeManager.updatePlanarMap(this, this.realtimePlanarTexture.getGFXTexture()); } @@ -317,7 +318,7 @@ export class ReflectionProbe { this._needRender = true; } - public switchProbeType (type: number, sourceCamera: Camera | null): void { + public switchProbeType (type: ProbeType, sourceCamera: Camera | null): void { if (type === ProbeType.CUBE) { this._needRender = false; } else if (sourceCamera !== null) { diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index 83cebdd8e45..21769f3a145 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -44,6 +44,8 @@ import { WebPipeline } from './web-pipeline'; import { DescriptorSetData } from './layout-graph'; import { AABB } from '../../core/geometry'; import { DebugViewCompositeType, DebugViewSingleType } from '../debug-view'; +import { ReflectionProbeManager } from '../../3d/reflection-probe/reflection-probe-manager'; +import { director } from '../../game/director'; const _rangedDirLightBoundingBox = new AABB(0.0, 0.0, 0.0, 0.5, 0.5, 0.5); const _tmpBoundingBox = new AABB(); @@ -148,7 +150,14 @@ export function getLoadOpOfClearFlag (clearFlag: ClearFlagBit, attachment: Attac return loadOp; } -export function getRenderArea (camera: Camera, width: number, height: number, light: Light | null = null, level = 0, out?: Rect): Rect { +export function getRenderArea ( + camera: Camera, + width: number, + height: number, + light: Light | null = null, + level = 0, + out: Rect | undefined = undefined, +): Rect { out = out || new Rect(); const vp = camera ? camera.viewport : new Rect(0, 0, 1, 1); const w = width; @@ -222,10 +231,12 @@ export function buildCopyPass (ppl: BasicPipeline, inOuts: CopyPair[]): void { } let fxaaData: FxaaData | null = null; -export function buildFxaaPass (camera: Camera, +export function buildFxaaPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): { rtName: string; dsName: string; } { + inputDS: string, +): { rtName: string; dsName: string; } { if (!fxaaData) { fxaaData = new FxaaData(); } @@ -262,7 +273,9 @@ export function buildFxaaPass (camera: Camera, fxaaPass.addRenderTarget(fxaaPassRTName, LoadOp.CLEAR, StoreOp.STORE, clearColor); fxaaData.fxaaMaterial.setProperty('texSize', new Vec4(width, height, 1.0 / width, 1.0 / height), fxaaPassIdx); fxaaPass.addQueue(QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, fxaaData.fxaaMaterial, fxaaPassIdx, + camera, + fxaaData.fxaaMaterial, + fxaaPassIdx, SceneFlags.NONE, ); return { rtName: fxaaPassRTName, dsName: inputDS }; @@ -318,12 +331,14 @@ class BloomData { } } let bloomData: BloomData | null = null; -export function buildBloomPass (camera: Camera, +export function buildBloomPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, threshold = 0.6, iterations = 2, - intensity = 2.0): { rtName: string; dsName: string; } { + intensity = 2.0, +): { rtName: string; dsName: string; } { if (!bloomData) { bloomData = new BloomData(); } @@ -366,7 +381,9 @@ export function buildBloomPass (camera: Camera, bloomPrefilterPass.addRenderTarget(bloomPassPrefilterRTName, LoadOp.CLEAR, StoreOp.STORE, bloomClearColor); bloomData.bloomMaterial.setProperty('texSize', new Vec4(0, 0, bloomData.threshold, 0), 0); bloomPrefilterPass.addQueue(QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, bloomData.bloomMaterial, 0, + camera, + bloomData.bloomMaterial, + 0, SceneFlags.NONE, ); // === Bloom downSampler === @@ -393,7 +410,9 @@ export function buildBloomPass (camera: Camera, bloomDownSamplePass.addRenderTarget(bloomPassDownSampleRTName, LoadOp.CLEAR, StoreOp.STORE, bloomClearColor); bloomData.bloomMaterial.setProperty('texSize', texSize, BLOOM_DOWNSAMPLEPASS_INDEX + i); bloomDownSamplePass.addQueue(QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, bloomData.bloomMaterial, BLOOM_DOWNSAMPLEPASS_INDEX + i, + camera, + bloomData.bloomMaterial, + BLOOM_DOWNSAMPLEPASS_INDEX + i, SceneFlags.NONE, ); } @@ -421,7 +440,9 @@ export function buildBloomPass (camera: Camera, bloomUpSamplePass.addRenderTarget(bloomPassUpSampleRTName, LoadOp.CLEAR, StoreOp.STORE, bloomClearColor); bloomData.bloomMaterial.setProperty('texSize', texSize, BLOOM_UPSAMPLEPASS_INDEX + i); bloomUpSamplePass.addQueue(QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, bloomData.bloomMaterial, BLOOM_UPSAMPLEPASS_INDEX + i, + camera, + bloomData.bloomMaterial, + BLOOM_UPSAMPLEPASS_INDEX + i, SceneFlags.NONE, ); } @@ -445,7 +466,9 @@ export function buildBloomPass (camera: Camera, bloomCombinePass.addRenderTarget(bloomPassCombineRTName, LoadOp.CLEAR, StoreOp.STORE, bloomClearColor); bloomData.bloomMaterial.setProperty('texSize', new Vec4(0, 0, 0, bloomData.intensity), BLOOM_COMBINEPASS_INDEX); bloomCombinePass.addQueue(QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, bloomData.bloomMaterial, BLOOM_COMBINEPASS_INDEX, + camera, + bloomData.bloomMaterial, + BLOOM_COMBINEPASS_INDEX, SceneFlags.NONE, ); return { rtName: bloomPassCombineRTName, dsName: bloomPassCombineDSName }; @@ -476,9 +499,11 @@ export class PostInfo { let postInfo: PostInfo; -export function buildPostprocessPass (camera: Camera, +export function buildPostprocessPass ( + camera: Camera, ppl: BasicPipeline, - inputTex: string): { rtName: string; dsName: string; } { + inputTex: string, +): { rtName: string; dsName: string; } { if (!postInfo) { postInfo = new PostInfo(); } @@ -506,24 +531,38 @@ export function buildPostprocessPass (camera: Camera, postClearColor.y = camera.clearColor.y; postClearColor.z = camera.clearColor.z; } - postprocessPass.addRenderTarget(postprocessPassRTName, - getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.RENDER_TARGET), StoreOp.STORE, postClearColor); - postprocessPass.addDepthStencil(postprocessPassDS, + postprocessPass.addRenderTarget( + postprocessPassRTName, + getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.RENDER_TARGET), + + StoreOp.STORE, + + postClearColor, + ); + postprocessPass.addDepthStencil( + postprocessPassDS, getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.DEPTH_STENCIL), - StoreOp.STORE, camera.clearDepth, camera.clearStencil, camera.clearFlag); - postprocessPass.addQueue(QueueHint.NONE).addFullscreenQuad( - postInfo.postMaterial, 0, SceneFlags.NONE, + StoreOp.STORE, + + camera.clearDepth, + + camera.clearStencil, + + camera.clearFlag, ); + postprocessPass.addQueue(QueueHint.NONE).addFullscreenQuad(postInfo.postMaterial, 0, SceneFlags.NONE); if (getProfilerCamera() === camera) { postprocessPass.showStatistics = true; } return { rtName: postprocessPassRTName, dsName: postprocessPassDS }; } -export function buildForwardPass (camera: Camera, +export function buildForwardPass ( + camera: Camera, ppl: BasicPipeline, isOffScreen: boolean, - enabledAlpha = true): { rtName: string; dsName: string; } { + enabledAlpha = true, +): { rtName: string; dsName: string; } { if (EDITOR) { ppl.setMacroInt('CC_PIPELINE_TYPE', 0); } @@ -564,22 +603,29 @@ export function buildForwardPass (camera: Camera, forwardPass.addTexture(spotShadowName, 'cc_spotShadowMap'); } } - forwardPass.addRenderTarget(forwardPassRTName, + forwardPass.addRenderTarget( + forwardPassRTName, isOffScreen ? LoadOp.CLEAR : getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.RENDER_TARGET), StoreOp.STORE, - new Color(camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w)); - forwardPass.addDepthStencil(forwardPassDSName, + new Color(camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w), + ); + forwardPass.addDepthStencil( + forwardPassDSName, isOffScreen ? LoadOp.CLEAR : getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.DEPTH_STENCIL), // If the depth texture is used by subsequent passes, it must be set to store. isOffScreen ? StoreOp.DISCARD : StoreOp.STORE, camera.clearDepth, camera.clearStencil, - camera.clearFlag); + camera.clearFlag, + ); forwardPass .addQueue(QueueHint.RENDER_OPAQUE) - .addSceneOfCamera(camera, new LightInfo(), + .addSceneOfCamera( + camera, + new LightInfo(), SceneFlags.OPAQUE_OBJECT | SceneFlags.PLANAR_SHADOW | SceneFlags.CUTOUT_OBJECT - | SceneFlags.DEFAULT_LIGHTING | SceneFlags.DRAW_INSTANCING); + | SceneFlags.DEFAULT_LIGHTING | SceneFlags.DRAW_INSTANCING, + ); let sceneFlags = SceneFlags.TRANSPARENT_OBJECT | SceneFlags.GEOMETRY; if (!isOffScreen) { sceneFlags |= SceneFlags.UI; @@ -594,10 +640,15 @@ export function buildForwardPass (camera: Camera, } let shadowPass; -export function buildShadowPass (passName: Readonly, +export function buildShadowPass ( + passName: Readonly, ppl: BasicPipeline, - camera: Camera, light: Light, level: number, - width: Readonly, height: Readonly): void { + camera: Camera, + light: Light, + level: number, + width: Readonly, + height: Readonly, +): void { const fboW = width; const fboH = height; const area = getRenderArea(camera, width, height, light, level); @@ -617,25 +668,37 @@ export function buildShadowPass (passName: Readonly, shadowPass.name = passName; shadowPass.setViewport(new Viewport(0, 0, fboW, fboH)); shadowPass.addRenderTarget(shadowMapName, LoadOp.CLEAR, StoreOp.STORE, new Color(1, 1, 1, camera.clearColor.w)); - shadowPass.addDepthStencil(`${shadowMapName}Depth`, LoadOp.CLEAR, StoreOp.DISCARD, - camera.clearDepth, camera.clearStencil, ClearFlagBit.DEPTH_STENCIL); + shadowPass.addDepthStencil( + `${shadowMapName}Depth`, + LoadOp.CLEAR, + StoreOp.DISCARD, + camera.clearDepth, + camera.clearStencil, + ClearFlagBit.DEPTH_STENCIL, + ); } const queue = shadowPass.addQueue(QueueHint.RENDER_OPAQUE, 'shadow-caster'); - queue.addSceneOfCamera(camera, new LightInfo(light, level), - SceneFlags.SHADOW_CASTER); + queue.addSceneOfCamera( + camera, + new LightInfo(light, level), + SceneFlags.SHADOW_CASTER, + ); queue.setViewport(new Viewport(area.x, area.y, area.width, area.height)); } -export function buildReflectionProbePasss (camera: Camera, - ppl: BasicPipeline): void { - if (!cclegacy.internal.reflectionProbeManager) return; - const probes = cclegacy.internal.reflectionProbeManager.getProbes(); +export function buildReflectionProbePasss ( + camera: Camera, + ppl: BasicPipeline, +): void { + const reflectionProbeManager = cclegacy.internal.reflectionProbeManager as ReflectionProbeManager; + if (!reflectionProbeManager) return; + const probes = reflectionProbeManager.getProbes(); if (probes.length === 0) return; for (let i = 0; i < probes.length; i++) { const probe = probes[i]; if (probe.needRender) { if (probes[i].probeType === ProbeType.PLANAR) { - buildReflectionProbePass(camera, ppl, probe, probe.realtimePlanarTexture.window!, 0); + buildReflectionProbePass(camera, ppl, probe, probe.realtimePlanarTexture!.window!, 0); } else if (EDITOR) { for (let faceIdx = 0; faceIdx < probe.bakedCubeTextures.length; faceIdx++) { probe.updateCameraDir(faceIdx); @@ -647,8 +710,13 @@ export function buildReflectionProbePasss (camera: Camera, } } -export function buildReflectionProbePass (camera: Camera, - ppl: BasicPipeline, probe: ReflectionProbe, renderWindow: RenderWindow, faceIdx: number): void { +export function buildReflectionProbePass ( + camera: Camera, + ppl: BasicPipeline, + probe: ReflectionProbe, + renderWindow: RenderWindow, + faceIdx: number, +): void { const cameraName = `Camera${faceIdx}`; const area = probe.renderArea(); const width = area.x; @@ -668,10 +736,20 @@ export function buildReflectionProbePass (camera: Camera, const probePass = ppl.addRenderPass(width, height, 'default'); probePass.name = `ReflectionProbePass${faceIdx}`; probePass.setViewport(new Viewport(0, 0, width, height)); - probePass.addRenderTarget(probePassRTName, getLoadOpOfClearFlag(probeCamera.clearFlag, AttachmentType.RENDER_TARGET), - StoreOp.STORE, new Color(probeCamera.clearColor.x, probeCamera.clearColor.y, probeCamera.clearColor.z, probeCamera.clearColor.w)); - probePass.addDepthStencil(probePassDSName, getLoadOpOfClearFlag(probeCamera.clearFlag, AttachmentType.DEPTH_STENCIL), - StoreOp.STORE, probeCamera.clearDepth, probeCamera.clearStencil, probeCamera.clearFlag); + probePass.addRenderTarget( + probePassRTName, + getLoadOpOfClearFlag(probeCamera.clearFlag, AttachmentType.RENDER_TARGET), + StoreOp.STORE, + new Color(probeCamera.clearColor.x, probeCamera.clearColor.y, probeCamera.clearColor.z, probeCamera.clearColor.w), + ); + probePass.addDepthStencil( + probePassDSName, + getLoadOpOfClearFlag(probeCamera.clearFlag, AttachmentType.DEPTH_STENCIL), + StoreOp.STORE, + probeCamera.clearDepth, + probeCamera.clearStencil, + probeCamera.clearFlag, + ); const passBuilder = probePass.addQueue(QueueHint.RENDER_OPAQUE); passBuilder.addSceneOfCamera(camera, new LightInfo(), SceneFlags.REFLECTION_PROBE); updateCameraUBO(passBuilder as unknown as any, probeCamera, ppl); @@ -720,14 +798,28 @@ export function buildShadowPasses (cameraName: string, camera: Camera, ppl: Basi if (mainLight && mainLight.shadowEnabled) { shadowInfo.mainLightShadowNames[0] = `MainLightShadow${cameraName}`; if (mainLight.shadowFixedArea) { - buildShadowPass(shadowInfo.mainLightShadowNames[0], ppl, - camera, mainLight, 0, mapWidth, mapHeight); + buildShadowPass( + shadowInfo.mainLightShadowNames[0], + ppl, + camera, + mainLight, + 0, + mapWidth, + mapHeight, + ); } else { const csmLevel = pipeline.pipelineSceneData.csmSupported ? mainLight.csmLevel : 1; shadowInfo.mainLightShadowNames[0] = `MainLightShadow${cameraName}`; for (let i = 0; i < csmLevel; i++) { - buildShadowPass(shadowInfo.mainLightShadowNames[0], ppl, - camera, mainLight, i, mapWidth, mapHeight); + buildShadowPass( + shadowInfo.mainLightShadowNames[0], + ppl, + camera, + mainLight, + i, + mapWidth, + mapHeight, + ); } } } @@ -736,8 +828,15 @@ export function buildShadowPasses (cameraName: string, camera: Camera, ppl: Basi const light = shadowInfo.validLights[l]; const passName = `SpotLightShadow${l.toString()}${cameraName}`; shadowInfo.spotLightShadowNames[l] = passName; - buildShadowPass(passName, ppl, - camera, light, 0, mapWidth, mapHeight); + buildShadowPass( + passName, + ppl, + camera, + light, + 0, + mapWidth, + mapHeight, + ); } return shadowInfo; } @@ -750,8 +849,10 @@ export class GBufferInfo { ds!: string; } // deferred passes -export function buildGBufferPass (camera: Camera, - ppl: BasicPipeline): GBufferInfo { +export function buildGBufferPass ( + camera: Camera, + ppl: BasicPipeline, +): GBufferInfo { const cameraID = getCameraUniqueID(camera); const area = getRenderArea(camera, camera.window.width, camera.window.height); const width = area.width; @@ -869,7 +970,9 @@ export function buildLightingPass (camera: Camera, ppl: BasicPipeline, gBuffer: lightingClearColor.w = 0; lightingPass.addRenderTarget(deferredLightingPassRTName, LoadOp.CLEAR, StoreOp.STORE, lightingClearColor); lightingPass.addQueue(QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, lightingInfo.deferredLightingMaterial, 0, + camera, + lightingInfo.deferredLightingMaterial, + 0, SceneFlags.VOLUMETRIC_LIGHTING, ); // lightingPass.addQueue(QueueHint.RENDER_TRANSPARENT).addSceneOfCamera(camera, new LightInfo(), @@ -899,8 +1002,10 @@ function getClearFlags (attachment: AttachmentType, clearFlag: ClearFlagBit, loa } } -export function buildUIPass (camera: Camera, - ppl: BasicPipeline): void { +export function buildUIPass ( + camera: Camera, + ppl: BasicPipeline, +): void { const cameraID = getCameraUniqueID(camera); const cameraName = `Camera${cameraID}`; const area = getRenderArea(camera, camera.window.width, camera.window.height); @@ -918,14 +1023,22 @@ export function buildUIPass (camera: Camera, const uiAndProfilerPass = ppl.addRenderPass(width, height, 'default'); uiAndProfilerPass.name = `CameraUIAndProfilerPass${cameraID}`; uiAndProfilerPass.setViewport(new Viewport(area.x, area.y, width, height)); - uiAndProfilerPass.addRenderTarget(dsUIAndProfilerPassRTName, + uiAndProfilerPass.addRenderTarget( + dsUIAndProfilerPassRTName, getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.RENDER_TARGET), StoreOp.STORE, - new Color(camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w)); - uiAndProfilerPass.addDepthStencil(dsUIAndProfilerPassDSName, + new Color(camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w), + ); + uiAndProfilerPass.addDepthStencil( + dsUIAndProfilerPassDSName, getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.DEPTH_STENCIL), StoreOp.STORE, - camera.clearDepth, camera.clearStencil, camera.clearFlag); + camera.clearDepth, + + camera.clearStencil, + + camera.clearFlag, + ); const sceneFlags = SceneFlags.UI; uiAndProfilerPass .addQueue(QueueHint.RENDER_TRANSPARENT) @@ -936,7 +1049,7 @@ export function buildUIPass (camera: Camera, } export function updateCameraUBO (setter: any, camera: Readonly, ppl: Readonly): void { - const pipeline = cclegacy.director.root.pipeline; + const pipeline = director.root!.pipeline as WebPipeline; const sceneData = ppl.pipelineSceneData; const skybox = sceneData.skybox; setter.addConstant('CCCamera'); @@ -986,7 +1099,7 @@ export function getDescBindingFromName (bindingName: string): number { const layoutGraph = pipeline.layoutGraph; const vertIds = layoutGraph.vertices(); const descId = layoutGraph.attributeIndex.get(bindingName); - let currDesData; + let currDesData: DescriptorSetData; for (const i of vertIds) { const layout = layoutGraph.getLayout(i); for (const [k, descData] of layout.descriptorSets) { @@ -1020,10 +1133,12 @@ function applyGlobalDescBinding (data: RenderData, layout: string, isUpdate = fa let buffer = descriptorSet.getBuffer(bindId); let haveBuff = true; if (!buffer && !isUpdate) { - buffer = device.createBuffer(new BufferInfo(BufferUsageBit.UNIFORM | BufferUsageBit.TRANSFER_DST, + buffer = device.createBuffer(new BufferInfo( + BufferUsageBit.UNIFORM | BufferUsageBit.TRANSFER_DST, MemoryUsageBit.HOST | MemoryUsageBit.DEVICE, value.length * 4, - value.length * 4)); + value.length * 4, + )); haveBuff = false; } if (isUpdate) { @@ -1198,7 +1313,7 @@ class SSSSBlurData { const o = -range + i * step; const sign = o < 0.0 ? -1.0 : 1.0; // eslint-disable-next-line no-restricted-properties - this._kernel[i].w = range * sign * Math.abs(Math.pow(o, EXPONENT)) / Math.pow(range, EXPONENT); + this._kernel[i].w = range * sign * Math.abs(o ** EXPONENT) / range ** EXPONENT; } // Calculate the weights: @@ -1295,10 +1410,12 @@ export function hasSkinObject (ppl: BasicPipeline): boolean { return sceneData.skin.enabled && sceneData.standardSkinModel !== null; } -function _buildSSSSBlurPass (camera: Camera, +function _buildSSSSBlurPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): { rtName: string; dsName: string; } { + inputDS: string, +): { rtName: string; dsName: string; } { const sceneData = ppl.pipelineSceneData; const skin = sceneData.skin; const standardSkinModel = sceneData.standardSkinModel; @@ -1350,10 +1467,18 @@ function _buildSSSSBlurPass (camera: Camera, sampler.mipFilter = Filter.NONE; copyInputDSPass.addTexture(inputDS, 'depthRaw'); } - copyInputDSPass.addRenderTarget(ssssBlurDSName, - LoadOp.CLEAR, StoreOp.STORE, new Color(1.0, 0.0, 0.0, 0.0)); + copyInputDSPass.addRenderTarget( + ssssBlurDSName, + LoadOp.CLEAR, + + StoreOp.STORE, + + new Color(1.0, 0.0, 0.0, 0.0), + ); copyInputDSPass.addQueue(QueueHint.RENDER_OPAQUE | QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, ssssBlurData.ssssBlurMaterial, COPY_INPUT_DS_PASS_INDEX, + camera, + ssssBlurData.ssssBlurMaterial, + COPY_INPUT_DS_PASS_INDEX, SceneFlags.NONE, ); @@ -1378,13 +1503,25 @@ function _buildSSSSBlurPass (camera: Camera, ssssblurXPass.addTexture(ssssBlurDSName, 'depthTex'); } ssssblurXPass.addRenderTarget(ssssBlurRTName, LoadOp.CLEAR, StoreOp.STORE, ssssBlurClearColor); - ssssblurXPass.addDepthStencil(inputDS, LoadOp.LOAD, StoreOp.STORE, - camera.clearDepth, camera.clearStencil, camera.clearFlag); - ssssBlurData.ssssBlurMaterial.setProperty('blurInfo', new Vec4(ssssBlurData.ssssFov, ssssBlurData.ssssWidth, - ssssBlurData.boundingBox, ssssBlurData.ssssScale), SSSS_BLUR_X_PASS_INDEX); + ssssblurXPass.addDepthStencil( + inputDS, + LoadOp.LOAD, + StoreOp.STORE, + camera.clearDepth, + camera.clearStencil, + camera.clearFlag, + ); + ssssBlurData.ssssBlurMaterial.setProperty('blurInfo', new Vec4( + ssssBlurData.ssssFov, + ssssBlurData.ssssWidth, + ssssBlurData.boundingBox, + ssssBlurData.ssssScale, + ), SSSS_BLUR_X_PASS_INDEX); ssssBlurData.ssssBlurMaterial.setProperty('kernel', ssssBlurData.kernel, SSSS_BLUR_X_PASS_INDEX); ssssblurXPass.addQueue(QueueHint.RENDER_OPAQUE | QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, ssssBlurData.ssssBlurMaterial, SSSS_BLUR_X_PASS_INDEX, + camera, + ssssBlurData.ssssBlurMaterial, + SSSS_BLUR_X_PASS_INDEX, SceneFlags.NONE, ); @@ -1409,13 +1546,25 @@ function _buildSSSSBlurPass (camera: Camera, ssssblurYPass.addTexture(ssssBlurDSName, 'depthTex'); } ssssblurYPass.addRenderTarget(inputRT, LoadOp.LOAD, StoreOp.STORE, ssssBlurClearColor); - ssssblurYPass.addDepthStencil(inputDS, LoadOp.LOAD, StoreOp.STORE, - camera.clearDepth, camera.clearStencil, camera.clearFlag); - ssssBlurData.ssssBlurMaterial.setProperty('blurInfo', new Vec4(ssssBlurData.ssssFov, ssssBlurData.ssssWidth, - ssssBlurData.boundingBox, ssssBlurData.ssssScale), SSSS_BLUR_Y_PASS_INDEX); + ssssblurYPass.addDepthStencil( + inputDS, + LoadOp.LOAD, + StoreOp.STORE, + camera.clearDepth, + camera.clearStencil, + camera.clearFlag, + ); + ssssBlurData.ssssBlurMaterial.setProperty('blurInfo', new Vec4( + ssssBlurData.ssssFov, + ssssBlurData.ssssWidth, + ssssBlurData.boundingBox, + ssssBlurData.ssssScale, + ), SSSS_BLUR_Y_PASS_INDEX); ssssBlurData.ssssBlurMaterial.setProperty('kernel', ssssBlurData.kernel, SSSS_BLUR_Y_PASS_INDEX); ssssblurYPass.addQueue(QueueHint.RENDER_OPAQUE | QueueHint.RENDER_TRANSPARENT).addCameraQuad( - camera, ssssBlurData.ssssBlurMaterial, SSSS_BLUR_Y_PASS_INDEX, + camera, + ssssBlurData.ssssBlurMaterial, + SSSS_BLUR_Y_PASS_INDEX, SceneFlags.NONE, ); return { rtName: inputRT, dsName: inputDS }; @@ -1439,10 +1588,12 @@ class ToneMappingInfo { } let toneMappingInfo: ToneMappingInfo | null = null; -export function buildToneMappingPass (camera: Camera, +export function buildToneMappingPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): { rtName: string; dsName: string; } { + inputDS: string, +): { rtName: string; dsName: string; } { if (!ppl.pipelineSceneData.isHDR || !ppl.getMacroBool('CC_USE_FLOAT_OUTPUT')) return { rtName: inputRT, dsName: inputDS }; if (!toneMappingInfo) { toneMappingInfo = new ToneMappingInfo(); @@ -1474,29 +1625,42 @@ export function buildToneMappingPass (camera: Camera, if (ppl.containsResource(inputRT)) { toneMappingPass.addTexture(inputRT, 'u_texSampler'); } - toneMappingPass.addRenderTarget(toneMappingPassRTName, + toneMappingPass.addRenderTarget( + toneMappingPassRTName, getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.RENDER_TARGET), - StoreOp.STORE, toneMappingClearColor); - toneMappingPass.addDepthStencil(toneMappingPassDS, + StoreOp.STORE, + + toneMappingClearColor, + ); + toneMappingPass.addDepthStencil( + toneMappingPassDS, getLoadOpOfClearFlag(camera.clearFlag, AttachmentType.DEPTH_STENCIL), StoreOp.STORE, - camera.clearDepth, camera.clearStencil, camera.clearFlag); - toneMappingPass.addQueue(QueueHint.NONE).addFullscreenQuad( - toneMappingInfo.toneMappingMaterial, 0, SceneFlags.NONE, + camera.clearDepth, + + camera.clearStencil, + + camera.clearFlag, + ); + toneMappingPass.addQueue(QueueHint.NONE).addFullscreenQuad(toneMappingInfo.toneMappingMaterial, 0, SceneFlags.NONE); + toneMappingPass.addQueue(QueueHint.RENDER_TRANSPARENT).addSceneOfCamera( + camera, + new LightInfo(), + SceneFlags.UI, ); - toneMappingPass.addQueue(QueueHint.RENDER_TRANSPARENT).addSceneOfCamera(camera, new LightInfo(), - SceneFlags.UI); if (getProfilerCamera() === camera) { toneMappingPass.showStatistics = true; } return { rtName: toneMappingPassRTName, dsName: toneMappingPassDS }; } -export function buildTransparencyPass (camera: Camera, +export function buildTransparencyPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, inputDS: string, - hasDeferredTransparencyObject: boolean): { rtName: string; dsName: string; } { + hasDeferredTransparencyObject: boolean, +): { rtName: string; dsName: string; } { if (hasDeferredTransparencyObject) return { rtName: inputRT, dsName: inputDS }; const cameraID = getCameraUniqueID(camera); @@ -1519,22 +1683,36 @@ export function buildTransparencyPass (camera: Camera, alphaPass.addTexture(spotShadowName, 'cc_spotShadowMap'); } } - alphaPass.addRenderTarget(inputRT, - LoadOp.LOAD, StoreOp.STORE, - new Color(camera.clearDepth, camera.clearStencil, 0, 0)); - alphaPass.addDepthStencil(inputDS, - LoadOp.LOAD, StoreOp.STORE, - camera.clearDepth, camera.clearStencil, camera.clearFlag); + alphaPass.addRenderTarget( + inputRT, + LoadOp.LOAD, + + StoreOp.STORE, + new Color(camera.clearDepth, camera.clearStencil, 0, 0), + ); + alphaPass.addDepthStencil( + inputDS, + LoadOp.LOAD, + + StoreOp.STORE, + camera.clearDepth, + + camera.clearStencil, + + camera.clearFlag, + ); alphaPass .addQueue(QueueHint.RENDER_TRANSPARENT) .addSceneOfCamera(camera, new LightInfo(), SceneFlags.TRANSPARENT_OBJECT | SceneFlags.GEOMETRY); return { rtName: inputRT, dsName: inputDS }; } -function _buildSpecularPass (camera: Camera, +function _buildSpecularPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): { rtName: string; dsName: string; } { + inputDS: string, +): { rtName: string; dsName: string; } { if (EDITOR) { ppl.setMacroInt('CC_PIPELINE_TYPE', 0); } @@ -1558,29 +1736,49 @@ function _buildSpecularPass (camera: Camera, specalurPass.addTexture(spotShadowName, 'cc_spotShadowMap'); } } - specalurPass.addRenderTarget(inputRT, - LoadOp.LOAD, StoreOp.STORE, - new Color(camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w)); - specalurPass.addDepthStencil(inputDS, - LoadOp.LOAD, StoreOp.STORE, - camera.clearDepth, camera.clearStencil, camera.clearFlag); + specalurPass.addRenderTarget( + inputRT, + LoadOp.LOAD, + + StoreOp.STORE, + new Color(camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w), + ); + specalurPass.addDepthStencil( + inputDS, + LoadOp.LOAD, + + StoreOp.STORE, + camera.clearDepth, + + camera.clearStencil, + + camera.clearFlag, + ); specalurPass .addQueue(QueueHint.RENDER_OPAQUE, 'default') - .addSceneOfCamera(camera, new LightInfo(), + .addSceneOfCamera( + camera, + new LightInfo(), SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING | SceneFlags.PLANAR_SHADOW - | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING | SceneFlags.GEOMETRY); + | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING | SceneFlags.GEOMETRY, + ); specalurPass .addQueue(QueueHint.RENDER_TRANSPARENT, 'forward-add') - .addSceneOfCamera(camera, new LightInfo(), + .addSceneOfCamera( + camera, + new LightInfo(), SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING | SceneFlags.PLANAR_SHADOW - | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING | SceneFlags.GEOMETRY); + | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING | SceneFlags.GEOMETRY, + ); return { rtName: inputRT, dsName: inputDS }; } -export function buildSSSSPass (camera: Camera, +export function buildSSSSPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): { rtName: string; dsName: string; } { + inputDS: string, +): { rtName: string; dsName: string; } { if (hasSkinObject(ppl)) { forceEnableFloatOutput(ppl); const blurInfo = _buildSSSSBlurPass(camera, ppl, inputRT, inputDS); @@ -1736,10 +1934,12 @@ class HBAOParams { let _hbaoParams: HBAOParams | null = null; const vec2 = new Vec2(); -function _buildHBAOPass (camera: Camera, +function _buildHBAOPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): { rtName: string; dsName: string; } { + inputDS: string, +): { rtName: string; dsName: string; } { if (!_hbaoParams) return { rtName: inputRT, dsName: inputDS }; const cameraID = getCameraUniqueID(camera); @@ -1780,17 +1980,21 @@ function _buildHBAOPass (camera: Camera, _hbaoParams.hbaoMaterial.setProperty('randomTexSize', new Vec4(_hbaoParams.randomTexture.width, _hbaoParams.randomTexture.height, 1.0 / _hbaoParams.randomTexture.width, 1.0 / _hbaoParams.randomTexture.height), passIdx); _hbaoParams.hbaoMaterial.setProperty('blurParam', _hbaoParams.blurParam, passIdx); hbaoPass.addQueue(QueueHint.RENDER_TRANSPARENT | QueueHint.RENDER_OPAQUE).addCameraQuad( - camera, _hbaoParams.hbaoMaterial, passIdx, + camera, + _hbaoParams.hbaoMaterial, + passIdx, SceneFlags.NONE, ); return { rtName: hbaoRTName, dsName: inputDS }; } -function _buildHBAOBlurPass (camera: Camera, +function _buildHBAOBlurPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, inputDS: string, - isYPass: boolean): { rtName: string; dsName: string; } { + isYPass: boolean, +): { rtName: string; dsName: string; } { if (!_hbaoParams) return { rtName: inputRT, dsName: inputDS }; const cameraID = getCameraUniqueID(camera); @@ -1848,17 +2052,21 @@ function _buildHBAOBlurPass (camera: Camera, _hbaoParams.hbaoMaterial.setProperty('miscParam', _hbaoParams.miscParam, passIdx); _hbaoParams.hbaoMaterial.setProperty('blurParam', _hbaoParams.blurParam, passIdx); blurPass.addQueue(QueueHint.RENDER_TRANSPARENT | QueueHint.RENDER_OPAQUE).addCameraQuad( - camera, _hbaoParams.hbaoMaterial, passIdx, + camera, + _hbaoParams.hbaoMaterial, + passIdx, SceneFlags.NONE, ); return { rtName: outputRTName, dsName: inputDS }; } -function _buildHBAOCombinedPass (camera: Camera, +function _buildHBAOCombinedPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, inputDS: string, - outputRT: string): { rtName: string; dsName: string; } { + outputRT: string, +): { rtName: string; dsName: string; } { if (!_hbaoParams) return { rtName: inputRT, dsName: inputDS }; const cameraID = getCameraUniqueID(camera); @@ -1900,13 +2108,16 @@ function _buildHBAOCombinedPass (camera: Camera, _hbaoParams.hbaoMaterial.setProperty('miscParam', _hbaoParams.miscParam, passIdx); _hbaoParams.hbaoMaterial.setProperty('blurParam', _hbaoParams.blurParam, passIdx); hbaoPass.addQueue(QueueHint.RENDER_TRANSPARENT | QueueHint.RENDER_OPAQUE).addCameraQuad( - camera, _hbaoParams.hbaoMaterial, passIdx, + camera, + _hbaoParams.hbaoMaterial, + passIdx, SceneFlags.NONE, ); return { rtName: outputRTName, dsName: inputDS }; } -export function buildHBAOPasses (camera: Camera, +export function buildHBAOPasses ( + camera: Camera, ppl: BasicPipeline, inputRT: string, inputDS: string, @@ -1915,7 +2126,8 @@ export function buildHBAOPasses (camera: Camera, blurSharpness = 3, aoSaturation = 1.0, aoStrength = 1.0, - needBlur = true): { rtName: string; dsName: string; } { + needBlur = true, +): { rtName: string; dsName: string; } { const area = getRenderArea(camera, camera.window.width, camera.window.height); const width = area.width; const height = area.height; @@ -1967,7 +2179,7 @@ export const CLUSTER_COUNT = CLUSTERS_X * CLUSTERS_Y * CLUSTERS_Z; class ClusterLightData { declare clusterBuildCS: Material; - declare clusterLightCullingCS: Material + declare clusterLightCullingCS: Material; clusters_x_threads = 16; clusters_y_threads = 8; clusters_z_threads = 1; @@ -2000,8 +2212,11 @@ class ClusterLightData { } let _clusterLightData: ClusterLightData | null = null; -export function buildLightClusterBuildPass (camera: Camera, clusterData: ClusterLightData, - ppl: Pipeline): void { +export function buildLightClusterBuildPass ( + camera: Camera, + clusterData: ClusterLightData, + ppl: Pipeline, +): void { const cameraID = getCameraUniqueID(camera); const clusterBufferName = `clusterBuffer${cameraID}`; @@ -2025,8 +2240,11 @@ export function buildLightClusterBuildPass (camera: Camera, clusterData: Cluster clusterPass.setMat4('cc_matProjInv', camera.matProjInv); } -export function buildLightClusterCullingPass (camera: Camera, clusterData: ClusterLightData, - ppl: Pipeline): void { +export function buildLightClusterCullingPass ( + camera: Camera, + clusterData: ClusterLightData, + ppl: Pipeline, +): void { const cameraID = getCameraUniqueID(camera); const clusterBufferName = `clusterBuffer${cameraID}`; const clusterLightBufferName = `clusterLightBuffer${cameraID}`; diff --git a/cocos/rendering/post-process/passes/fxaa-pass.ts b/cocos/rendering/post-process/passes/fxaa-pass.ts index 41baed363e7..1689fa22e81 100644 --- a/cocos/rendering/post-process/passes/fxaa-pass.ts +++ b/cocos/rendering/post-process/passes/fxaa-pass.ts @@ -11,9 +11,9 @@ import { FXAA } from '../components/fxaa'; export class FxaaPass extends SettingPass { get setting (): FXAA { return getSetting(FXAA); } - name = 'FxaaPass' + name = 'FxaaPass'; effectName = 'pipeline/post-process/fxaa-hq'; - outputNames = ['FxaaColor'] + outputNames = ['FxaaColor']; public render (camera: Camera, ppl: Pipeline): void { const cameraID = getCameraUniqueID(camera); diff --git a/cocos/spine/assembler/simple.ts b/cocos/spine/assembler/simple.ts index 4dfd998eb1d..f7e853bc516 100644 --- a/cocos/spine/assembler/simple.ts +++ b/cocos/spine/assembler/simple.ts @@ -98,11 +98,11 @@ export const simple: IAssembler = { const batcher = director.root!.batcher2D; const attributes = useTint ? vfmtPosUvTwoColor4B : vfmtPosUvColor4B; if (useTint) { - accessor = _tintAccessor = new StaticVBAccessor(device, attributes, this.vCount); + accessor = _tintAccessor = new StaticVBAccessor(device, attributes, this.vCount as number); // Register to batcher so that batcher can upload buffers after batching process batcher.registerBufferAccessor(Number.parseInt('SPINETINT', 36), _tintAccessor); } else { - accessor = _accessor = new StaticVBAccessor(device, attributes, this.vCount); + accessor = _accessor = new StaticVBAccessor(device, attributes, this.vCount as number); // Register to batcher so that batcher can upload buffers after batching process batcher.registerBufferAccessor(Number.parseInt('SPINE', 36), _accessor); } @@ -148,8 +148,8 @@ function realTimeTraverse (comp: Skeleton): void { const floatStride = (_useTint ? _byteStrideTwoColor : _byteStrideOneColor) / Float32Array.BYTES_PER_ELEMENT; const model = comp.updateRenderData(); if (!model) return; - const vc = model.vCount; - const ic = model.iCount; + const vc = model.vCount as number; + const ic = model.iCount as number; const rd = comp.renderData!; if (rd.vertexCount !== vc || rd.indexCount !== ic) { @@ -165,7 +165,7 @@ function realTimeTraverse (comp: Skeleton): void { const vLength = vc * Float32Array.BYTES_PER_ELEMENT * floatStride; // eslint-disable-next-line @typescript-eslint/restrict-plus-operands const vData = spine.wasmUtil.wasm.HEAPU8.subarray(vPtr, vPtr + vLength); - vUint8Buf.set(vData); + vUint8Buf.set(vData as TypedArray); const iPtr = model.iPtr; const ibuf = rd.indices!; @@ -173,7 +173,7 @@ function realTimeTraverse (comp: Skeleton): void { // eslint-disable-next-line @typescript-eslint/restrict-plus-operands const iData = spine.wasmUtil.wasm.HEAPU8.subarray(iPtr, iPtr + iLength); const iUint8Buf = new Uint8Array(ibuf.buffer); - iUint8Buf.set(iData); + iUint8Buf.set(iData as TypedArray); const chunkOffset = rd.chunk.vertexOffset; for (let i = 0; i < ic; i++) { ibuf[i] += chunkOffset; @@ -185,8 +185,8 @@ function realTimeTraverse (comp: Skeleton): void { let indexCount = 0; for (let i = 0; i < count; i++) { const mesh = meshes.get(i); - const material = _getSlotMaterial(mesh.blendMode, comp); - const textureID = mesh.textureID; + const material = _getSlotMaterial(mesh.blendMode as number, comp); + const textureID = mesh.textureID as number; indexCount = mesh.iCount; comp.requestDrawData(material, textureID, indexOffset, indexCount); indexOffset += indexCount; @@ -278,8 +278,8 @@ function cacheTraverse (comp: Skeleton): void { const model = comp.updateRenderData(); if (!model) return; - const vc = model.vCount; - const ic = model.iCount; + const vc = model.vCount as number; + const ic = model.iCount as number; const rd = comp.renderData!; if (rd.vertexCount !== vc || rd.indexCount !== ic) { rd.resize(vc, ic); @@ -289,7 +289,7 @@ function cacheTraverse (comp: Skeleton): void { const vbuf = rd.chunk.vb; const vUint8Buf = new Uint8Array(vbuf.buffer, vbuf.byteOffset, Float32Array.BYTES_PER_ELEMENT * vbuf.length); - vUint8Buf.set(model.vData); + vUint8Buf.set(model.vData as TypedArray); const nodeColor = comp.color; if (nodeColor._val !== 0xffffffff || _premultipliedAlpha) { @@ -318,7 +318,7 @@ function cacheTraverse (comp: Skeleton): void { } const iUint16Buf = rd.indices!; - iUint16Buf.set(model.iData); + iUint16Buf.set(model.iData as TypedArray); const chunkOffset = rd.chunk.vertexOffset; for (let i = 0; i < ic; i++) { iUint16Buf[i] += chunkOffset; @@ -330,10 +330,10 @@ function cacheTraverse (comp: Skeleton): void { let indexCount = 0; for (let i = 0; i < count; i++) { const mesh = meshes[i]; - const material = _getSlotMaterial(mesh.blendMode, comp); + const material = _getSlotMaterial(mesh.blendMode as number, comp); const textureID = mesh.textureID; indexCount = mesh.iCount; - comp.requestDrawData(material, textureID, indexOffset, indexCount); + comp.requestDrawData(material, textureID as number, indexOffset, indexCount); indexOffset += indexCount; } diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index 6844673b69c..691702d985a 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -25,7 +25,7 @@ import { EDITOR_NOT_IN_PREVIEW, JSB } from 'internal:constants'; import { ccclass, executeInEditMode, help, menu, serializable, type, displayName, override, displayOrder, editable, tooltip } from 'cc.decorator'; import { Material, Texture2D } from '../asset/assets'; import { error, logID, warn } from '../core/platform/debug'; -import { Enum, ccenum } from '../core/value-types/enum'; +import { Enum, EnumType, ccenum } from '../core/value-types/enum'; import { Node } from '../scene-graph'; import { CCObject, Color, RecyclePool, js } from '../core'; import { SkeletonData } from './skeleton-data'; @@ -65,6 +65,11 @@ export const timeScale = 1.0; * @zh Spine 动画缓存类型。 */ export enum AnimationCacheMode { + /** + * @en Unset mode. + * @zh 未设置模式。 + */ + UNSET = -1, /** * @en The realtime mode. * @zh 实时计算模式。 @@ -207,7 +212,7 @@ export class Skeleton extends UIRenderer { @serializable protected _timeScale = 1; @serializable - protected _preCacheMode = -1; + protected _preCacheMode: AnimationCacheMode = AnimationCacheMode.UNSET; @serializable protected _cacheMode = AnimationCacheMode.REALTIME; @serializable @@ -241,8 +246,8 @@ export class Skeleton extends UIRenderer { }), 1); protected _materialCache: { [key: string]: MaterialInstance } = {} as any; public paused = false; - protected _enumSkins: any = Enum({}); - protected _enumAnimations: any = Enum({}); + protected _enumSkins: EnumType = Enum({}); + protected _enumAnimations: EnumType = Enum({}); protected attachUtil: AttachUtil; protected _socketNodes: Map = new Map(); protected _cachedSockets: Map = new Map(); @@ -725,7 +730,7 @@ export class Skeleton extends UIRenderer { if (this.debugBones || this.debugSlots) { warn('Debug bones or slots is invalid in cached mode'); } - const skeletonInfo = this._skeletonCache!.getSkeletonCache((this.skeletonData as any).uuid, skeletonData); + const skeletonInfo = this._skeletonCache!.getSkeletonCache(this.skeletonData!.uuid, skeletonData); this._skeleton = skeletonInfo.skeleton; } else { this._skeleton = this._instance.initSkeleton(skeletonData); @@ -1396,9 +1401,9 @@ export class Skeleton extends UIRenderer { } this._cachedSockets.clear(); const bones = this._skeleton.bones; - const getBoneName = (bone: spine.Bone): any => { + const getBoneName = (bone: spine.Bone): string => { if (bone.parent == null) return bone.data.name || ''; - return `${getBoneName(bones[bone.parent.data.index]) as string}/${bone.data.name}`; + return `${getBoneName(bones[bone.parent.data.index])}/${bone.data.name}`; }; for (let i = 0, l = bones.length; i < l; i++) { const bd = bones[i].data; @@ -1494,7 +1499,7 @@ export class Skeleton extends UIRenderer { /** * @engineInternal */ - protected _updateColor (): void { + public _updateColor (): void { this.node._uiProps.colorDirty = true; const r = this._color.r / 255.0; const g = this._color.g / 255.0; From 546b36209fcd0a7e981843e797fe8d07def3a978 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 26 Jul 2023 13:16:34 +0800 Subject: [PATCH 026/184] Fix circular dependencies --- cocos/rendering/deferred/lighting-stage.ts | 13 ++++-- cocos/rendering/forward/forward-pipeline.ts | 6 +++ cocos/rendering/index.ts | 8 +--- cocos/rendering/pipeline-scene-data.ts | 7 ++-- .../reflection-probe/reflection-probe-flow.ts | 7 ++-- .../rendering/render-additive-light-queue.ts | 16 +++++-- .../render-reflection-probe-queue.ts | 8 ++-- cocos/rendering/shadow/csm-layers.ts | 42 +++++++++++++++---- cocos/rendering/shadow/shadow-stage.ts | 24 ++++++++--- cocos/root.ts | 14 +++++-- 10 files changed, 105 insertions(+), 40 deletions(-) diff --git a/cocos/rendering/deferred/lighting-stage.ts b/cocos/rendering/deferred/lighting-stage.ts index ebb09a9efc7..e420c39ab2a 100644 --- a/cocos/rendering/deferred/lighting-stage.ts +++ b/cocos/rendering/deferred/lighting-stage.ts @@ -28,7 +28,8 @@ */ import { ccclass, displayOrder, type, serializable } from 'cc.decorator'; -import { Camera, LightType } from '../../render-scene/scene'; +import { Camera } from '../../render-scene/scene/camera'; +import { LightType } from '../../render-scene/scene/light'; import { UBODeferredLight, SetIndex, UBOForwardLight, UBOLocal } from '../define'; import { getPhaseID } from '../pass-phase'; import { Color, Rect, Buffer, BufferUsageBit, MemoryUsageBit, BufferInfo, BufferViewInfo, DescriptorSet, @@ -355,8 +356,14 @@ export class LightingStage extends RenderStage { pipeline.pipelineUBO.updateShadowUBO(camera); - cmdBuff.beginRenderPass(renderPass, framebuffer, this._renderArea, - colors, camera.clearDepth, camera.clearStencil); + cmdBuff.beginRenderPass( + renderPass, + framebuffer, + this._renderArea, + colors, + camera.clearDepth, + camera.clearStencil, + ); cmdBuff.setScissor(pipeline.generateScissor(camera)); cmdBuff.setViewport(pipeline.generateViewport(camera)); cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, pipeline.descriptorSet); diff --git a/cocos/rendering/forward/forward-pipeline.ts b/cocos/rendering/forward/forward-pipeline.ts index a8bdcaf1832..48322d0c130 100644 --- a/cocos/rendering/forward/forward-pipeline.ts +++ b/cocos/rendering/forward/forward-pipeline.ts @@ -39,6 +39,12 @@ import { ReflectionProbeFlow } from '../reflection-probe/reflection-probe-flow'; const PIPELINE_TYPE = 0; +export function createDefaultPipeline (): ForwardPipeline { + const rppl = new ForwardPipeline(); + rppl.initialize({ flows: [] }); + return rppl; +} + /** * @en The forward render pipeline * @zh 前向渲染管线。 diff --git a/cocos/rendering/index.ts b/cocos/rendering/index.ts index 68a0d0434a8..df06cd7656e 100644 --- a/cocos/rendering/index.ts +++ b/cocos/rendering/index.ts @@ -35,7 +35,7 @@ export { RenderFlow } from './render-flow'; export { RenderStage } from './render-stage'; export { PipelineSceneData } from './pipeline-scene-data'; -export { ForwardPipeline } from './forward/forward-pipeline'; +export { ForwardPipeline, createDefaultPipeline } from './forward/forward-pipeline'; export { ForwardFlow } from './forward/forward-flow'; export { ForwardStage } from './forward/forward-stage'; export { DeferredPipeline } from './deferred/deferred-pipeline'; @@ -55,9 +55,3 @@ export { DebugView } from './debug-view'; export { ReflectionProbeFlow } from './reflection-probe/reflection-probe-flow'; export { ReflectionProbeStage } from './reflection-probe/reflection-probe-stage'; - -export function createDefaultPipeline (): ForwardPipeline { - const rppl = new ForwardPipeline(); - rppl.initialize({ flows: [] }); - return rppl; -} diff --git a/cocos/rendering/pipeline-scene-data.ts b/cocos/rendering/pipeline-scene-data.ts index 529d6c44cb9..314539ec16a 100644 --- a/cocos/rendering/pipeline-scene-data.ts +++ b/cocos/rendering/pipeline-scene-data.ts @@ -32,9 +32,10 @@ import { Light } from '../render-scene/scene/light'; import { Material } from '../asset/assets'; import { Pass } from '../render-scene/core/pass'; import { CSMLayers } from './shadow/csm-layers'; -import { cclegacy } from '../core'; +import { legacyCC } from '../core/global-exports'; import { Skin } from '../render-scene/scene/skin'; -import { Model, PostSettings } from '../render-scene/scene'; +import { Model } from '../render-scene/scene/model'; +import { PostSettings } from '../render-scene/scene/post-settings'; import { MeshRenderer } from '../3d/framework/mesh-renderer'; const GEOMETRY_RENDERER_TECHNIQUE_COUNT = 6; @@ -109,7 +110,7 @@ export class PipelineSceneData { public octree: Octree = new Octree(); public skin: Skin = new Skin(); public postSettings: PostSettings = new PostSettings(); - public lightProbes = cclegacy.internal.LightProbes ? new cclegacy.internal.LightProbes() : null; + public lightProbes = legacyCC.internal.LightProbes ? new legacyCC.internal.LightProbes() : null; /** * @en The list for valid punctual Lights, only available after the scene culling of the current frame. diff --git a/cocos/rendering/reflection-probe/reflection-probe-flow.ts b/cocos/rendering/reflection-probe/reflection-probe-flow.ts index 20611207a19..3ceabf5a832 100644 --- a/cocos/rendering/reflection-probe/reflection-probe-flow.ts +++ b/cocos/rendering/reflection-probe/reflection-probe-flow.ts @@ -26,8 +26,9 @@ import { ccclass } from 'cc.decorator'; import { IRenderFlowInfo, RenderFlow } from '../render-flow'; import { ReflectionProbeStage } from './reflection-probe-stage'; import { RenderFlowTag } from '../pipeline-serialization'; -import { RenderPipeline } from '..'; -import { Camera, ProbeType, ReflectionProbe } from '../../render-scene/scene'; +import { RenderPipeline } from '../render-pipeline'; +import { Camera } from '../../render-scene/scene/camera'; +import { ProbeType, ReflectionProbe } from '../../render-scene/scene/reflection-probe'; import { cclegacy } from '../../core'; /** @@ -61,7 +62,7 @@ export class ReflectionProbeFlow extends RenderFlow { if (!cclegacy.internal.reflectionProbeManager) { return; } - const probes = cclegacy.internal.reflectionProbeManager.getProbes(); + const probes = cclegacy.internal.reflectionProbeManager.getProbes() as ReflectionProbe[]; for (let i = 0; i < probes.length; i++) { if (probes[i].needRender) { if (EDITOR || probes[i].probeType === ProbeType.PLANAR) { diff --git a/cocos/rendering/render-additive-light-queue.ts b/cocos/rendering/render-additive-light-queue.ts index 94b8e02841e..ce569f7260e 100644 --- a/cocos/rendering/render-additive-light-queue.ts +++ b/cocos/rendering/render-additive-light-queue.ts @@ -38,7 +38,8 @@ import { getPhaseID } from './pass-phase'; import { Light, LightType } from '../render-scene/scene/light'; import { SetIndex, UBOForwardLight, UBOShadow, UNIFORM_SHADOWMAP_BINDING, UNIFORM_SPOT_SHADOW_MAP_TEXTURE_BINDING, supportsR32FloatTexture, isEnableEffect } from './define'; -import { Camera, ShadowType } from '../render-scene/scene'; +import { Camera } from '../render-scene/scene/camera'; +import { ShadowType } from '../render-scene/scene/shadows'; import { GlobalDSManager } from './global-descriptor-set-manager'; import { PipelineUBO } from './pipeline-ubo'; import { PipelineRuntime } from './custom/pipeline'; @@ -386,8 +387,17 @@ export class RenderAdditiveLightQueue { Mat4.invert(_matShadowView, (light as SpotLight).node!.getWorldMatrix()); // light proj - Mat4.perspective(_matShadowViewProj, (light as SpotLight).angle, 1.0, 0.001, (light as SpotLight).range, - true, cap.clipSpaceMinZ, cap.clipSpaceSignY, 0); + Mat4.perspective( + _matShadowViewProj, + (light as SpotLight).angle, + 1.0, + 0.001, + (light as SpotLight).range, + true, + cap.clipSpaceMinZ, + cap.clipSpaceSignY, + 0, + ); matShadowProj = _matShadowViewProj.clone(); matShadowInvProj = _matShadowViewProj.clone().invert(); diff --git a/cocos/rendering/render-reflection-probe-queue.ts b/cocos/rendering/render-reflection-probe-queue.ts index 725b4a4ec6f..4f78db4a021 100644 --- a/cocos/rendering/render-reflection-probe-queue.ts +++ b/cocos/rendering/render-reflection-probe-queue.ts @@ -27,11 +27,11 @@ import { isEnableEffect, SetIndex } from './define'; import { Device, RenderPass, Shader, CommandBuffer } from '../gfx'; import { getPhaseID } from './pass-phase'; import { PipelineStateManager } from './pipeline-state-manager'; -import { Pass, BatchingSchemes } from '../render-scene/core/pass'; +import { Pass, BatchingSchemes, IMacroPatch } from '../render-scene/core/pass'; import { Model } from '../render-scene/scene/model'; -import { Camera, ProbeType, ReflectionProbe, SKYBOX_FLAG } from '../render-scene/scene'; +import { ProbeType, ReflectionProbe } from '../render-scene/scene/reflection-probe'; +import { Camera, SKYBOX_FLAG } from '../render-scene/scene/camera'; import { PipelineRuntime } from './custom/pipeline'; -import { IMacroPatch, RenderScene } from '../render-scene'; import { RenderInstancedQueue } from './render-instanced-queue'; import { cclegacy, geometry } from '../core'; import { Layers } from '../scene-graph/layers'; @@ -77,7 +77,7 @@ export class RenderReflectionProbeQueue { private _subModelsArray: SubModel[] = []; private _passArray: Pass[] = []; private _shaderArray: Shader[] = []; - private _rgbeSubModelsArray: SubModel[]=[] + private _rgbeSubModelsArray: SubModel[] = []; private _instancedQueue: RenderInstancedQueue; private _patches: IMacroPatch[] = []; diff --git a/cocos/rendering/shadow/csm-layers.ts b/cocos/rendering/shadow/csm-layers.ts index fcf74e54312..bed455e4bbe 100644 --- a/cocos/rendering/shadow/csm-layers.ts +++ b/cocos/rendering/shadow/csm-layers.ts @@ -20,7 +20,9 @@ THE SOFTWARE. */ -import { DirectionalLight, Camera, Shadows, CSMLevel, CSMOptimizationMode } from '../../render-scene/scene'; +import { Shadows, CSMLevel, CSMOptimizationMode } from '../../render-scene/scene/shadows'; +import { DirectionalLight } from '../../render-scene/scene/directional-light'; +import { Camera } from '../../render-scene/scene/camera'; import { Mat4, Vec3, Vec2, Vec4 } from '../../core/math'; import { Frustum, AABB } from '../../core/geometry'; import { IRenderObject } from '../define'; @@ -186,8 +188,17 @@ export class ShadowLayerVolume { // snap to whole texels const halfOrthoSizeWidth = orthoSizeWidth * 0.5; const halfOrthoSizeHeight = orthoSizeHeight * 0.5; - Mat4.ortho(_matShadowProj, -halfOrthoSizeWidth, halfOrthoSizeWidth, -halfOrthoSizeHeight, halfOrthoSizeHeight, - 0.1, this._shadowCameraFar, device.capabilities.clipSpaceMinZ, device.capabilities.clipSpaceSignY); + Mat4.ortho( + _matShadowProj, + -halfOrthoSizeWidth, + halfOrthoSizeWidth, + -halfOrthoSizeHeight, + halfOrthoSizeHeight, + 0.1, + this._shadowCameraFar, + device.capabilities.clipSpaceMinZ, + device.capabilities.clipSpaceSignY, + ); Mat4.multiply(_matShadowViewProjArbitaryPos, _matShadowProj, shadowViewArbitaryPos); Vec3.transformMat4(_projPos, _shadowPos, _matShadowViewProjArbitaryPos); @@ -209,8 +220,14 @@ export class ShadowLayerVolume { Mat4.copy(this._matShadowViewProj, _matShadowViewProj); } - Frustum.createOrtho(this._validFrustum, orthoSizeWidth, orthoSizeHeight, - 0.1, this._shadowCameraFar, _matShadowTrans); + Frustum.createOrtho( + this._validFrustum, + orthoSizeWidth, + orthoSizeHeight, + 0.1, + this._shadowCameraFar, + _matShadowTrans, + ); } } export class CSMShadowLayer extends ShadowLayerVolume { @@ -335,8 +352,17 @@ export class CSMLayers { const far = dirLight.shadowFar; Mat4.fromRT(_matShadowTrans, dirLight.node!.getWorldRotation(), dirLight.node!.getWorldPosition()); Mat4.invert(_matShadowView, _matShadowTrans); - Mat4.ortho(_matShadowProj, -x, x, -y, y, near, far, - device.capabilities.clipSpaceMinZ, device.capabilities.clipSpaceSignY); + Mat4.ortho( + _matShadowProj, + -x, + x, + -y, + y, + near, + far, + device.capabilities.clipSpaceMinZ, + device.capabilities.clipSpaceSignY, + ); Mat4.multiply(_matShadowViewProj, _matShadowProj, _matShadowView); this._specialLayer.matShadowView = _matShadowView; this._specialLayer.matShadowProj = _matShadowProj; @@ -356,7 +382,7 @@ export class CSMLayers { // i ÷ numbers of level const si = i / level; // eslint-disable-next-line no-restricted-properties - const preNear = lambda * (nd * Math.pow(ratio, si)) + (1 - lambda) * (nd + (fd - nd) * si); + const preNear = lambda * (nd * ratio ** si) + (1 - lambda) * (nd + (fd - nd) * si); // Slightly increase the overlap to avoid fracture const nextFar = preNear * 1.005; this._layers[i].splitCameraNear = preNear; diff --git a/cocos/rendering/shadow/shadow-stage.ts b/cocos/rendering/shadow/shadow-stage.ts index edae01d16ac..020bd72715e 100644 --- a/cocos/rendering/shadow/shadow-stage.ts +++ b/cocos/rendering/shadow/shadow-stage.ts @@ -31,7 +31,9 @@ import { ForwardPipeline } from '../forward/forward-pipeline'; import { SetIndex } from '../define'; import { Light, LightType } from '../../render-scene/scene/light'; import { ShadowFlow } from './shadow-flow'; -import { Camera, CSMLevel, DirectionalLight } from '../../render-scene/scene'; +import { DirectionalLight } from '../../render-scene/scene/directional-light'; +import { CSMLevel } from '../../render-scene/scene/shadows'; +import { Camera } from '../../render-scene/scene/camera'; const colors: Color[] = [new Color(1, 1, 1, 1)]; @@ -98,8 +100,14 @@ export class ShadowStage extends RenderStage { const cmdBuff = pipeline.commandBuffers[0]; const renderPass = this._shadowFrameBuffer.renderPass; - cmdBuff.beginRenderPass(renderPass, this._shadowFrameBuffer, this._renderArea, - colors, camera.clearDepth, camera.clearStencil); + cmdBuff.beginRenderPass( + renderPass, + this._shadowFrameBuffer, + this._renderArea, + colors, + camera.clearDepth, + camera.clearStencil, + ); cmdBuff.endRenderPass(); this._isShadowMapCleared = true; } @@ -151,8 +159,14 @@ export class ShadowStage extends RenderStage { const renderPass = this._shadowFrameBuffer.renderPass; - cmdBuff.beginRenderPass(renderPass, this._shadowFrameBuffer, this._renderArea, - colors, camera.clearDepth, camera.clearStencil); + cmdBuff.beginRenderPass( + renderPass, + this._shadowFrameBuffer, + this._renderArea, + colors, + camera.clearDepth, + camera.clearStencil, + ); cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, descriptorSet); this._additiveShadowQueue.recordCommandBuffer(device, renderPass, cmdBuff); diff --git a/cocos/root.ts b/cocos/root.ts index efab7abacb0..99c2d28dd60 100644 --- a/cocos/root.ts +++ b/cocos/root.ts @@ -23,7 +23,9 @@ */ import { Pool, cclegacy, warnID, settings, Settings, macro } from './core'; -import { RenderPipeline, createDefaultPipeline, DeferredPipeline } from './rendering'; +import type { RenderPipeline } from './rendering/render-pipeline'; +import { DeferredPipeline } from './rendering/deferred/deferred-pipeline'; +import { createDefaultPipeline } from './rendering/forward/forward-pipeline'; import { DebugView } from './rendering/debug-view'; import { Camera, CameraType, Light, Model, TrackingType } from './render-scene/scene'; import type { DataPoolManager } from './3d/skeletal-animation/data-pool-manager'; @@ -41,6 +43,7 @@ import { Batcher2D } from './2d/renderer/batcher-2d'; import { IPipelineEvent } from './rendering/pipeline-event'; import { localDescriptorSetLayout_ResizeMaxJoints, UBOCamera, UBOGlobal, UBOLocal, UBOShadow, UBOWorldBound } from './rendering/define'; import { XREye, XRPoseType } from './xr/xr-enums'; +import { ICustomJointTextureLayout } from './3d/skeletal-animation/skeletal-animation-utils'; /** * @en Initialization information for the Root @@ -311,7 +314,10 @@ export class Root { swapchain, }); this._curWindow = this._mainWindow; - const customJointTextureLayouts = settings.querySettings(Settings.Category.ANIMATION, 'customJointTextureLayouts') || []; + const customJointTextureLayouts = settings.querySettings( + Settings.Category.ANIMATION, + 'customJointTextureLayouts', + ) as ICustomJointTextureLayout[] || []; this._dataPoolMgr?.jointTexturePool.registerCustomTextureLayouts(customJointTextureLayouts); this._resizeMaxJointForDS(); } @@ -717,7 +723,7 @@ export class Root { let allcameras: Camera[] = []; const webxrHmdPoseInfos = xr.webxrHmdPoseInfos; - for (let xrEye = 0; xrEye < viewCount; xrEye++) { + for (let xrEye: XREye = 0; xrEye < viewCount; xrEye++) { for (const window of windows) { allcameras = allcameras.concat(window.cameras); if (window.swapchain) { @@ -789,7 +795,7 @@ export class Root { if (this._pipeline && cameraList.length > 0) { this._device.acquire([deviceManager.swapchain]); const scenes = this._scenes; - const stamp = director.getTotalFrames(); + const stamp = director.getTotalFrames() as number; if (this._batcher) { this._batcher.update(); From e0bfd7e1cf46979ac85b735794ce83a180b165c7 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 26 Jul 2023 13:16:46 +0800 Subject: [PATCH 027/184] Fix DS_Store ignore in tempaltes --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4dfa79f089c..229c3ea39a6 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,7 @@ native/external/ scripts/typedoc-plugin/lib/ !templates/**/* +templates/**/.DS_Store @types/consts.d.ts From 61422450d3bb76e4f40881d2d70ab4ba68391bfa Mon Sep 17 00:00:00 2001 From: pandamicro Date: Wed, 26 Jul 2023 13:50:04 +0800 Subject: [PATCH 028/184] Fix circular dependencies --- cocos/render-scene/scene/reflection-probe.ts | 10 ++++----- cocos/rendering/custom/define.ts | 16 +++++++++----- .../global-descriptor-set-manager.ts | 3 +-- .../reflection-probe-stage.ts | 22 ++++++++++++++----- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/cocos/render-scene/scene/reflection-probe.ts b/cocos/render-scene/scene/reflection-probe.ts index 43bc0526fe0..9c794c75172 100644 --- a/cocos/render-scene/scene/reflection-probe.ts +++ b/cocos/render-scene/scene/reflection-probe.ts @@ -24,12 +24,11 @@ import { EDITOR } from 'internal:constants'; import { Camera, CameraAperture, CameraFOVAxis, CameraISO, CameraProjection, CameraShutter, CameraType, SKYBOX_FLAG, TrackingType } from './camera'; import { Node } from '../../scene-graph/node'; -import { Color, Quat, Rect, toRadian, Vec2, Vec3, geometry, cclegacy, Vec4 } from '../../core'; +import { Color, Quat, Rect, toRadian, Vec2, Vec3, geometry, cclegacy, Vec4, Size } from '../../core'; import { CAMERA_DEFAULT_MASK } from '../../rendering/define'; import { ClearFlagBit, Framebuffer } from '../../gfx'; import { TextureCube } from '../../asset/assets/texture-cube'; import { RenderTexture } from '../../asset/assets/render-texture'; -import { view } from '../../ui/view'; export enum ProbeClearFlag { SKYBOX = SKYBOX_FLAG | ClearFlagBit.DEPTH_STENCIL, @@ -309,7 +308,7 @@ export class ReflectionProbe { public renderPlanarReflection (sourceCamera: Camera): void { if (!sourceCamera) return; if (!this.realtimePlanarTexture) { - const canvasSize = view.getDesignResolutionSize(); + const canvasSize = cclegacy.view.getDesignResolutionSize() as Size; this.realtimePlanarTexture = this._createTargetTexture(canvasSize.width, canvasSize.height); cclegacy.internal.reflectionProbeManager.updatePlanarMap(this, this.realtimePlanarTexture.getGFXTexture()); } @@ -422,14 +421,13 @@ export class ReflectionProbe { private _createCamera (cameraNode: Node): Camera | null { const root = cclegacy.director.root; if (!this._camera) { - this._camera = (cclegacy.director.root).createCamera(); + this._camera = root.createCamera(); if (!this._camera) return null; this._camera.initialize({ name: cameraNode.name, node: cameraNode, projection: CameraProjection.PERSPECTIVE, - window: EDITOR ? cclegacy.director.root && cclegacy.director.root.mainWindow - : cclegacy.director.root && cclegacy.director.root.tempWindow, + window: EDITOR ? root && root.mainWindow : root && root.tempWindow, priority: 0, cameraType: CameraType.DEFAULT, trackingType: TrackingType.NO_TRACKING, diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index 21769f3a145..a2a983c9b3b 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -25,10 +25,15 @@ import { EDITOR } from 'internal:constants'; import { BufferInfo, Buffer, BufferUsageBit, ClearFlagBit, Color, DescriptorSet, LoadOp, Format, Rect, Sampler, StoreOp, Texture, Viewport, MemoryUsageBit, Filter, Address } from '../../gfx'; -import { - Camera, CSMLevel, DirectionalLight, Light, LightType, ProbeType, ReflectionProbe, - ShadowType, SKYBOX_FLAG, SpotLight, PointLight, RangedDirectionalLight, SphereLight, -} from '../../render-scene/scene'; +import { ProbeType, ReflectionProbe } from '../../render-scene/scene/reflection-probe'; +import { Camera, SKYBOX_FLAG } from '../../render-scene/scene/camera'; +import { CSMLevel, ShadowType } from '../../render-scene/scene/shadows'; +import { Light, LightType } from '../../render-scene/scene/light'; +import { DirectionalLight } from '../../render-scene/scene/directional-light'; +import { RangedDirectionalLight } from '../../render-scene/scene/ranged-directional-light'; +import { PointLight } from '../../render-scene/scene/point-light'; +import { SphereLight } from '../../render-scene/scene/sphere-light'; +import { SpotLight } from '../../render-scene/scene/spot-light'; import { supportsR32FloatTexture, supportsRGBA16HalfFloatTexture } from '../define'; import { BasicPipeline, Pipeline } from './pipeline'; import { @@ -45,7 +50,6 @@ import { DescriptorSetData } from './layout-graph'; import { AABB } from '../../core/geometry'; import { DebugViewCompositeType, DebugViewSingleType } from '../debug-view'; import { ReflectionProbeManager } from '../../3d/reflection-probe/reflection-probe-manager'; -import { director } from '../../game/director'; const _rangedDirLightBoundingBox = new AABB(0.0, 0.0, 0.0, 0.5, 0.5, 0.5); const _tmpBoundingBox = new AABB(); @@ -1049,7 +1053,7 @@ export function buildUIPass ( } export function updateCameraUBO (setter: any, camera: Readonly, ppl: Readonly): void { - const pipeline = director.root!.pipeline as WebPipeline; + const pipeline = cclegacy.director.root!.pipeline as WebPipeline; const sceneData = ppl.pipelineSceneData; const skybox = sceneData.skybox; setter.addConstant('CCCamera'); diff --git a/cocos/rendering/global-descriptor-set-manager.ts b/cocos/rendering/global-descriptor-set-manager.ts index aff3b5a0798..e0c2a27ef58 100644 --- a/cocos/rendering/global-descriptor-set-manager.ts +++ b/cocos/rendering/global-descriptor-set-manager.ts @@ -22,10 +22,9 @@ THE SOFTWARE. */ -import { cclegacy } from '../core'; import { Device, BufferUsageBit, MemoryUsageBit, BufferInfo, Filter, Address, Sampler, DescriptorSet, DescriptorSetInfo, Buffer, Texture, DescriptorSetLayoutInfo, DescriptorSetLayout, SamplerInfo } from '../gfx'; -import { Light } from '../render-scene/scene'; +import { Light } from '../render-scene/scene/light'; import { getDescBindingFromName, getDescriptorSetDataFromLayout } from './custom/define'; import { UBOShadow, globalDescriptorSetLayout, PipelineGlobalBindings, isEnableEffect } from './define'; diff --git a/cocos/rendering/reflection-probe/reflection-probe-stage.ts b/cocos/rendering/reflection-probe/reflection-probe-stage.ts index beacaacb375..1514374938d 100644 --- a/cocos/rendering/reflection-probe/reflection-probe-stage.ts +++ b/cocos/rendering/reflection-probe/reflection-probe-stage.ts @@ -29,7 +29,7 @@ import { ForwardStagePriority } from '../enum'; import { ForwardPipeline } from '../forward/forward-pipeline'; import { SetIndex } from '../define'; import { ReflectionProbeFlow } from './reflection-probe-flow'; -import { Camera, ProbeType, ReflectionProbe } from '../../render-scene/scene'; +import { Camera, ReflectionProbe } from '../../render-scene/scene'; import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; import { Vec3 } from '../../core'; import { packRGBE } from '../../core/math/color'; @@ -90,8 +90,14 @@ export class ReflectionProbeStage extends RenderStage { const cmdBuff = pipeline.commandBuffers[0]; const renderPass = this._frameBuffer.renderPass; - cmdBuff.beginRenderPass(renderPass, this._frameBuffer, this._renderArea, - colors, camera.clearDepth, camera.clearStencil); + cmdBuff.beginRenderPass( + renderPass, + this._frameBuffer, + this._renderArea, + colors, + camera.clearDepth, + camera.clearStencil, + ); cmdBuff.endRenderPass(); } @@ -119,8 +125,14 @@ export class ReflectionProbeStage extends RenderStage { colors[0].w = rgbe.w; } const device = pipeline.device; - cmdBuff.beginRenderPass(renderPass, this._frameBuffer!, this._renderArea, - colors, this._probe!.camera.clearDepth, this._probe!.camera.clearStencil); + cmdBuff.beginRenderPass( + renderPass, + this._frameBuffer!, + this._renderArea, + colors, + this._probe!.camera.clearDepth, + this._probe!.camera.clearStencil, + ); cmdBuff.bindDescriptorSet(SetIndex.GLOBAL, pipeline.descriptorSet); this._probeRenderQueue.recordCommandBuffer(device, renderPass, cmdBuff); From 0d4e5497e242ddec11e960290d2579ee90eabde4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=A3=AE=E6=96=8C?= Date: Wed, 26 Jul 2023 17:25:33 +0800 Subject: [PATCH 029/184] [Bug] fix widget undo bug (#15741) * fix widget undo bug * next tick snapshot --- editor/inspector/components/widget.js | 28 ++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/editor/inspector/components/widget.js b/editor/inspector/components/widget.js index 2b6fafc7193..8c7b0b371a0 100644 --- a/editor/inspector/components/widget.js +++ b/editor/inspector/components/widget.js @@ -565,6 +565,12 @@ exports.methods = { this.$refs.summitProp.dispatch('change-dump'); }, + snapshot() { + // next tick snapshot + setTimeout(() => { + this.$refs.summitProp.dispatch('confirm-dump'); + }); + }, getUnit(type) { const data = this.dump.value; @@ -661,6 +667,7 @@ exports.methods = { const { dump } = update(this.dump, true); this.$refs.summitProp.dump = dump; this.$refs.summitProp.dispatch('change-dump'); + this.snapshot(); }, select(event) { @@ -892,7 +899,7 @@ exports.methods = { this.dimensionVertical = this.getDimensionVertical(); } - this.$refs.summitProp.dispatch('confirm-dump'); + this.snapshot(); }, toggleLock(direction) { @@ -931,6 +938,7 @@ exports.methods = { } this.$refs.summitProp.dispatch('change-dump'); + this.snapshot(); }, isLock(direction) { const lockValue = this.dump.value._lockFlags.value; @@ -1046,7 +1054,9 @@ const template = /* html*/` @@ -1065,6 +1075,7 @@ const template = /* html*/` :disabled="!dump.value.isAlignHorizontalCenter.value" :value="dump.value.editorHorizontalCenter.value" @change="change('editorHorizontalCenter', $event.target.value)" + @confirm="snapshot()" @unit-click="changeUnit('editorHorizontalCenter')"> @@ -1078,7 +1089,9 @@ const template = /* html*/` @@ -1121,7 +1134,9 @@ const template = /* html*/` @@ -1139,6 +1154,7 @@ const template = /* html*/` @@ -1153,7 +1169,9 @@ const template = /* html*/` From a9ffcad7ea774793e50a184f4d996c1bade09317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=A3=AE=E6=96=8C?= Date: Wed, 26 Jul 2023 17:26:01 +0800 Subject: [PATCH 030/184] =?UTF-8?q?[Bug]=20when=20editor=20change=20langua?= =?UTF-8?q?ge=EF=BC=8Cupdate=20fbx=20editing=20interface=20(#15762)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * when editor change language,update fbx editing interface * update --- editor/inspector/assets/fbx/model.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/editor/inspector/assets/fbx/model.js b/editor/inspector/assets/fbx/model.js index 63c6561fb2a..6fac16493b2 100644 --- a/editor/inspector/assets/fbx/model.js +++ b/editor/inspector/assets/fbx/model.js @@ -889,6 +889,27 @@ const Elements = { }, }, // lods end + // when lang change + i18n: { + ready() { + const panel = this; + + Elements.i18n.changeBind = Elements.i18n.change.bind(panel); + Editor.Message.addBroadcastListener('i18n:change', Elements.i18n.changeBind); + }, + close() { + Editor.Message.removeBroadcastListener('i18n:change', Elements.i18n.changeBind); + Elements.i18n.changeBind = undefined; + }, + change() { + const panel = this; + + Elements.normals.update.call(panel); + Elements.tangents.update.call(panel); + Elements.morphNormals.update.call(panel); + Elements.meshOptimizerAlgorithm.update.call(panel); + }, + }, }; exports.methods = { From 30061b151dafb76ec940f2f3d08d5266630f0528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Wed, 26 Jul 2023 17:59:31 +0800 Subject: [PATCH 031/184] reflectionprobe manager add function for users (#15824) --- .../reflection-probe-component.ts | 18 +++++++------ .../reflection-probe-manager.ts | 26 +++++++++++++++---- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/cocos/3d/reflection-probe/reflection-probe-component.ts b/cocos/3d/reflection-probe/reflection-probe-component.ts index dcd2f840c9a..2f3c06e53d6 100644 --- a/cocos/3d/reflection-probe/reflection-probe-component.ts +++ b/cocos/3d/reflection-probe/reflection-probe-component.ts @@ -326,12 +326,14 @@ export class ReflectionProbe extends Component { ReflectionProbeManager.probeManager.onUpdateProbes(true); this._probe.enable(); } + this.node.on(Node.EventType.TRANSFORM_CHANGED, this._onProbeTransformChanged, this); } onDisable (): void { if (this._probe) { ReflectionProbeManager.probeManager.unregister(this._probe); this._probe.disable(); } + this.node.off(Node.EventType.TRANSFORM_CHANGED, this._onProbeTransformChanged); } public start (): void { @@ -363,14 +365,6 @@ export class ReflectionProbe extends Component { } } } - - if (this.node.hasChangedFlags) { - this.probe.updateBoundingBox(); - } - if (this.node.hasChangedFlags & TransformBit.POSITION) { - ReflectionProbeManager.probeManager.onUpdateProbes(true); - ReflectionProbeManager.probeManager.updateProbeData(); - } } if (this.probeType === ProbeType.PLANAR && this.sourceCamera) { if ((this.sourceCamera.node.hasChangedFlags & TransformBit.TRS) @@ -391,6 +385,14 @@ export class ReflectionProbe extends Component { ReflectionProbeManager.probeManager.updatePreviewSphere(this.probe); } + private _onProbeTransformChanged (type: TransformBit): void { + this.probe.updateBoundingBox(); + if (type & Node.TransformBit.POSITION) { + ReflectionProbeManager.probeManager.onUpdateProbes(true); + ReflectionProbeManager.probeManager.updateProbeData(); + } + } + private _createProbe (): void { if (this._probeId === -1 || ReflectionProbeManager.probeManager.exists(this._probeId)) { this._probeId = ReflectionProbeManager.probeManager.getNewReflectionProbeId(); diff --git a/cocos/3d/reflection-probe/reflection-probe-manager.ts b/cocos/3d/reflection-probe/reflection-probe-manager.ts index 9b114aff0f4..88dc20c07d3 100644 --- a/cocos/3d/reflection-probe/reflection-probe-manager.ts +++ b/cocos/3d/reflection-probe/reflection-probe-manager.ts @@ -86,7 +86,7 @@ export class ReflectionProbeManager { if (!scene || !scene.renderScene) { return; } - const models = scene.renderScene.models; + const models = scene.renderScene.models as Model[]; for (let i = 0; i < models.length; i++) { const model = models[i]; if (!model.node) continue; @@ -106,7 +106,7 @@ export class ReflectionProbeManager { if (!scene || !scene.renderScene) { return; } - const models = scene.renderScene.models; + const models = scene.renderScene.models as Model[]; for (let i = 0; i < models.length; i++) { const model = models[i]; if (!model.node) continue; @@ -441,6 +441,22 @@ export class ReflectionProbeManager { return null; } + /** + * @en Set reflection probe used by the model. + * @zh 手动设置模型使用的反射探针。 + * @param model set the probe for this model + * @param probe reflection probe to be set + * @param blendProbe reflection probe for blend + */ + public setReflectionProbe (model: Model, probe: ReflectionProbe, blendProbe: ReflectionProbe | null = null): void { + if (!probe) return; + this._useCubeModels.set(model, probe); + this._updateCubemapOfModel(model, probe); + if (blendProbe) { + this._updateBlendProbeInfo(model, probe, blendProbe); + } + } + /** * @en * select the probe with the nearest distance. @@ -535,7 +551,8 @@ export class ReflectionProbeManager { if (probe) { meshRender.updateReflectionProbeDataMap(this._dataTexture); if (this._isUsedBlending(model)) { - this._updateBlendProbeInfo(model, probe); + const blendProbe = this._getBlendProbe(model); + this._updateBlendProbeInfo(model, probe, blendProbe); } } } @@ -559,7 +576,7 @@ export class ReflectionProbeManager { return false; } - private _updateBlendProbeInfo (model: Model, probe: ReflectionProbe): void { + private _updateBlendProbeInfo (model: Model, probe: ReflectionProbe, blendProbe: ReflectionProbe | null): void { const node = model.node; if (!node) { return; @@ -568,7 +585,6 @@ export class ReflectionProbeManager { if (!meshRender) { return; } - const blendProbe = this._getBlendProbe(model); if (blendProbe) { meshRender.updateReflectionProbeBlendId(blendProbe.getProbeId()); meshRender.updateProbeBlendCubemap(blendProbe.cubemap); From cd90419f2e453872f60877bf66ccd8a8d294f265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=A3=AE=E6=96=8C?= Date: Wed, 26 Jul 2023 18:00:51 +0800 Subject: [PATCH 032/184] fix editing fbx animation events interface bug (#15718) * fix the bug of changing select fbx, the preview interface did not update * fix editing fbx animation events interface bug --- .../assets/fbx/event-editor/editor.js | 70 ++++++++------ .../assets/fbx/event-editor/event-item.js | 27 +----- .../assets/fbx/event-editor/index.js | 15 ++- editor/inspector/assets/fbx/events/events.js | 95 +++++++------------ editor/inspector/assets/fbx/events/index.js | 95 +++++++++++++++---- editor/inspector/assets/fbx/preview.js | 63 ++++++++---- 6 files changed, 212 insertions(+), 153 deletions(-) diff --git a/editor/inspector/assets/fbx/event-editor/editor.js b/editor/inspector/assets/fbx/event-editor/editor.js index ecf08c083d8..a7f3af354d0 100644 --- a/editor/inspector/assets/fbx/event-editor/editor.js +++ b/editor/inspector/assets/fbx/event-editor/editor.js @@ -6,15 +6,15 @@ const eventItem = require('./event-item'); exports.template = `
- - + +
:index="index" :key="index" @update="updateValue" + @delete="deleteValue" >
@@ -50,8 +51,8 @@ exports.data = function() { dirty: false, debounceSave: null, // time value - frame: 0, - RealFrame: 0, + frame: -1, + RealFrame: -1, show: false, }; }; @@ -71,26 +72,27 @@ exports.methods = { that.showToast(Editor.I18n.t('animator.event.enter_func_name')); return; } - that.value.push({ - func: that.newFuncName, - params: [], - frame: that.frame, + that.$emit('addFunc', that.frame, that.newFuncName); + setTimeout(() => { + that.newFuncName = ''; }); - that.dirty = true; - that.debounceSave(); }, updateValue(eventInfo, index) { const that = this; - if (!eventInfo) { - that.value.splice(index, 1); - } else { - that.value[index] = eventInfo; - } + that.value[index] = eventInfo; that.dirty = true; that.debounceSave(); }, + deleteValue(index) { + const that = this; + const eventInfo = that.value[index]; + if (eventInfo) { + that.$emit('delFunc', eventInfo.frame, eventInfo); + } + }, + showToast(msg, time = 800) { const that = this; if (that.toast) { @@ -106,23 +108,37 @@ exports.methods = { }, time); }, - async saveData() { + saveData() { const that = this; - that.$emit('update', that.frame, that.value); + that.$emit('update', that.value); that.dirty = false; }, - refresh() { + refresh(events) { const that = this; - let data = that.events.filter((item) => { - return item.frame === that.frame; - }); - if (data.length < 1) { - that.value = []; - return; + const infos = []; + + if (Array.isArray(events)) { + if (!events.length) { + this.frame = -1; + } + + events.forEach((item) => { + if (item.info.frame === that.frame) { + infos.push(item.info); + } + }); } - that.value = JSON.parse(JSON.stringify(data)); - that.newFuncName = ''; + + that.value = infos; + that.show = !!infos.length; + + }, + hide() { + this.$emit('hide'); + }, + unselect() { + this.show = false; }, }; diff --git a/editor/inspector/assets/fbx/event-editor/event-item.js b/editor/inspector/assets/fbx/event-editor/event-item.js index 65c525958cb..88865cd5e69 100644 --- a/editor/inspector/assets/fbx/event-editor/event-item.js +++ b/editor/inspector/assets/fbx/event-editor/event-item.js @@ -80,16 +80,6 @@ exports.props = [ 'index', ]; -exports.computed = { - selectEvent() { - const that = this; - if (!that.selectInfo) { - return null; - } - return that.selectInfo.data; - }, -}; - exports.methods = { onConfirm(event) { const that = this; @@ -126,27 +116,20 @@ exports.methods = { const that = this; const name = event.target.getAttribute('name'); let index = event.target.getAttribute('index'); - const eventInfo = that.event; - let dirty = false; switch (name) { case 'delFunc': - that.$emit('update', null, that.index); + that.$emit('delete', that.index); return; case 'addParams': - dirty = true; - eventInfo.params.splice(eventInfo.params.length - 1, 0, 'param'); + that.event.params.splice(that.event.params.length - 1, 0, 'param'); break; case 'delParams': - dirty = true; - eventInfo.params.splice(index, 1); + that.event.params.splice(index, 1); break; case 'clearParams': - if (eventInfo.params.length) { - dirty = true; - eventInfo.params = []; - } + that.event.params = []; break; } - dirty && that.$emit('update', that.event, that.index); + that.$emit('update', that.event, that.index); }, }; diff --git a/editor/inspector/assets/fbx/event-editor/index.js b/editor/inspector/assets/fbx/event-editor/index.js index 1e549ac1983..c15d4562a38 100644 --- a/editor/inspector/assets/fbx/event-editor/index.js +++ b/editor/inspector/assets/fbx/event-editor/index.js @@ -14,8 +14,19 @@ exports.ready = function() { components: eventEditor.components, mounted: eventEditor.mounted, }); - this.eventEditorVm.$on('update', (frame, eventInfos) => { - this.events.updateEventInfo.call(this, frame, eventInfos); + this.eventEditorVm.$on('update', (eventInfos) => { + this.events.updateEventInfo.call(this, eventInfos); + }); + + this.eventEditorVm.$on('addFunc', (frame, newFuncName) => { + this.events.addEvent.call(this, frame, newFuncName); + }); + + this.eventEditorVm.$on('delFunc', (frame, eventInfo) => { + this.events.delEvent.call(this, frame, eventInfo); + }); + this.eventEditorVm.$on('hide', (frame, eventInfo) => { + this.events.unselect.call(this, frame, eventInfo); }); }; diff --git a/editor/inspector/assets/fbx/events/events.js b/editor/inspector/assets/fbx/events/events.js index 8d476c3a8c6..71bc60abc97 100644 --- a/editor/inspector/assets/fbx/events/events.js +++ b/editor/inspector/assets/fbx/events/events.js @@ -4,25 +4,16 @@ exports.template = /* html */`
-
@@ -31,18 +22,7 @@ exports.template = /* html */` exports.data = { events: [], offset: 0, - selectEvent: [], - eventEditorInfo: { - frame: 0, - events: [{ - func: '', - params: [], - frame: 0, - }], - }, - selectInfo: { - frames: [], - }, + frame: -1, }; exports.methods = { @@ -53,45 +33,40 @@ exports.methods = { onPopMenu(event, eventInfo) { const that = this; const menu = [{ - label: Editor.I18n.t(`animator.event.edit`), - click() { - that.openEventEditor(eventInfo); - }, - }, { label: Editor.I18n.t(`animator.event.delete`), click() { that.$emit('del', eventInfo); }, - }, - ]; + }]; Editor.Menu.popup({ - x: event.pageX, - y: event.pageY, menu, }); }, - onMouseDown(event, info) { + onMouseDown(event, item) { const that = this; event.stopPropagation(); - const data = JSON.parse(JSON.stringify(info)); - let selectIndex = that.selectInfo && that.selectInfo.frames.indexOf(info.frame); - if (typeof selectIndex !== 'number' || selectIndex === -1) { - that.selectInfo = { - startX: event.x, - data: [data], - offset: 0, - offsetFrame: 0, - frames: [info.frame], - }; - } else { - that.selectInfo.startX = event.x; + this.frame = item.info.frame; + + const clientX = event.clientX; + const startX = item.x; + function mousemove(event) { + const timelineX = startX + (event.clientX - clientX); + that.$emit('move', item, timelineX); + } + + function mouseup() { + that.$emit('moveEnd', item); + document.removeEventListener('mousemove', mousemove); + document.removeEventListener('mouseup', mouseup); } + document.addEventListener('mousemove', mousemove); + document.addEventListener('mouseup', mouseup); }, openEventEditor(eventInfo) { - // HACK 目前的事件帧会有重复关键帧重叠的情况 - this.selectInfo.frames = [eventInfo.frame]; + // 目前的事件帧会有重复关键帧重叠的情况 + this.frame = eventInfo.frame; this.$emit('edit', eventInfo); }, @@ -99,17 +74,15 @@ exports.methods = { return `transform: translateX(${x || 0}px);`; }, - onDomMouseDown() { - this.selectInfo = { - frames: [], - }; + refresh(eventInfos) { + this.events = eventInfos; + if (!eventInfos.some((item) => item.info.frame === this.frame)) { + this.unselect(); + } }, -}; -exports.mounted = function() { - document.addEventListener('mousedown', this.onDomMouseDown); + unselect() { + this.frame = -1; + }, }; -exports.beforeDestroy = function() { - document.removeEventListener('mousedown', this.onDomMouseDown); -}; diff --git a/editor/inspector/assets/fbx/events/index.js b/editor/inspector/assets/fbx/events/index.js index 29e11f4c141..18e64467ee2 100644 --- a/editor/inspector/assets/fbx/events/index.js +++ b/editor/inspector/assets/fbx/events/index.js @@ -20,11 +20,9 @@ exports.ready = function() { if (this.checkDisabledEditEvent()) { return; } - this.eventEditorVm.events = this.eventVm.events; this.eventEditorVm.frame = eventInfo.frame; this.eventEditorVm.RealFrame = Math.round(eventInfo && eventInfo.frame * this.curEditClipInfo.fps || 0); - this.eventEditorVm.refresh(); - this.eventEditorVm.show = true; + this.eventEditorVm.refresh(this.eventVm.events); }); this.eventVm.$on('del', (eventInfo) => { if (this.checkDisabledEditEvent()) { @@ -32,10 +30,26 @@ exports.ready = function() { } this.events.delEvent.call(this, eventInfo.frame); }); + + this.eventVm.$on('move', (eventItem, timelineX) => { + if (this.checkDisabledEditEvent()) { + return; + } + this.events.moveEvent.call(this, eventItem, timelineX); + }); + + this.eventVm.$on('moveEnd', (eventItem) => { + if (this.checkDisabledEditEvent()) { + return; + } + this.eventVm.openEventEditor(eventItem.info); + this.dispatch('snapshot'); + }); }; -exports.update = function(eventInfo) { - this.eventVm.events = eventInfo; +exports.update = function(eventInfos) { + this.eventVm.refresh(eventInfos); + this.eventEditorVm.refresh(eventInfos); }; exports.apply = async function() { @@ -52,45 +66,84 @@ exports.apply = async function() { this.events.eventsMap = {}; }; -exports.addNewEvent = function(time) { +exports.addEvent = function(time, newFuncName = '') { const newInfo = { + // 注意: frame 是时间 frame: time, - func: '', + func: newFuncName, params: [], }; + const userData = this.curEditClipInfo.userData; if (!userData.events) { userData.events = [newInfo]; } else { - userData.events.push(newInfo); - userData.events.sort((a, b) => a.frame - b.frame); + // 已经存在空记录 + if (!newFuncName && userData.events.some(event => event.frame === time && event.func === newFuncName)) { + return; + } + + let exist = false; + for (const event of userData.events) { + if (event.frame === time && event.func === '') { + event.func = newFuncName; + exist = true; + break; + } + } + + if (!exist) { + userData.events.push(newInfo); + userData.events.sort((a, b) => a.frame - b.frame); + } } - this.events.eventsMap[this.curEditClipInfo.clipUUID] = userData.events; + this.updateEventInfo(); this.dispatch('change'); this.dispatch('snapshot'); + + this.eventVm.openEventEditor(newInfo); }; -exports.delEvent = function(time) { +exports.delEvent = function(frame, info) { const userData = this.curEditClipInfo.userData; - userData.events = userData.events.filter((item) => item.frame !== time); - this.events.eventsMap[this.curEditClipInfo.clipUUID] = userData.events; + if (info) { + userData.events = userData.events.filter((item) => item !== info); + } else { + // 删除多个 + userData.events = userData.events.filter((item) => item.frame !== frame); + } + this.updateEventInfo(); this.dispatch('change'); this.dispatch('snapshot'); }; -exports.updateEventInfo = function(time, eventInfos) { +exports.moveEvent = function(eventItem, timelineX) { + const frame = Math.min(this.$.animationTime._config.max, Math.max(0, Math.round(this.$.animationTime.pixelToValue(timelineX)))); + + eventItem.info.frame = frame / this.curEditClipInfo.fps; + eventItem.x = this.$.animationTime.valueToPixel(frame); + + this.dispatch('change'); +}; + +exports.unselect = function() { + this.eventVm.unselect(); + this.eventEditorVm.unselect(); +}; + +exports.updateEventInfo = function(eventInfos) { const userData = this.curEditClipInfo.userData; - let newEvents = []; - if (userData.events) { - newEvents = userData.events.filter((item) => item.frame !== time); + if (userData && userData.events && Array.isArray(eventInfos)) { + eventInfos.forEach((eventInfo) => { + if (!userData.events.includes(eventInfo)) { + userData.events.push(eventInfo); + } + }); } - newEvents.push(...eventInfos); - userData.events = newEvents; - this.events.eventsMap[this.curEditClipInfo.clipUUID] = newEvents; this.updateEventInfo(); this.dispatch('change'); - this.dispatch('update'); + this.dispatch('snapshot'); }; diff --git a/editor/inspector/assets/fbx/preview.js b/editor/inspector/assets/fbx/preview.js index 0937b7c346e..8b4fed5d2bb 100644 --- a/editor/inspector/assets/fbx/preview.js +++ b/editor/inspector/assets/fbx/preview.js @@ -27,7 +27,7 @@ exports.template = /* html */`
- +
@@ -168,6 +168,7 @@ ui-icon { background: var(--color-normal-fill); } #event-editor { + position: relative; line-height: 20px; width: 100%; height: 70%; @@ -186,6 +187,9 @@ ui-icon { background: var(--color-normal-fill-emphasis); padding: 2px 4px; } + #event-editor > header .title { + color: var(--color-focus-fill); + } #event-editor > .header .name { margin: 0 4px; } @@ -194,7 +198,6 @@ ui-icon { margin: 0 2px; } #event-editor > .functions { - padding: 4px; overflow-y: auto; flex: 1; height: 100%; @@ -234,6 +237,7 @@ ui-icon { #event-editor ui-checkbox, #event-editor ui-num-input { flex: 1; + margin-left: 4px; } #event-editor ui-section { width: 100%; @@ -259,6 +263,15 @@ ui-icon { font-style: italic; text-align: center; } + #event-editor .toast { + position: absolute; + top: 54px; + right: 4px; + z-index: 1; + padding: 0 4px; + background-color: var(--color-normal-fill-emphasis); + color: var(--color-warn-fill); + } `; exports.$ = { @@ -484,7 +497,11 @@ exports.methods = { async onTabChanged(activeTab) { if (typeof activeTab === 'string') { this.activeTab = activeTab; - this.$.animationInfo.style.display = this.activeTab === 'animation' ? 'block' : 'none'; + const isAnimationTab = this.activeTab === 'animation'; + this.$.animationInfo.style.display = isAnimationTab ? 'block' : 'none'; + if (!isAnimationTab) { + this.eventEditorVm.show = false; + } this.$.modelInfo.style.display = this.activeTab === 'model' ? 'block' : 'none'; await this.stopAnimation(); } @@ -534,19 +551,22 @@ exports.methods = { }, addEventToCurTime() { - this.events.addNewEvent.call(this, this.$.animationTime.value / this.curEditClipInfo.fps); + this.events.addEvent.call(this, this.$.animationTime.value / this.curEditClipInfo.fps); }, updateEventInfo() { let eventInfos = []; - const events = this.curEditClipInfo.userData.events; - if (Array.isArray(events)) { - eventInfos = events.map((info) => { - return { - ...info, - x: this.$.animationTime.valueToPixel(info.frame * this.curEditClipInfo.fps), - }; - }); + + if (this.curEditClipInfo && this.curEditClipInfo.userData) { + const events = this.curEditClipInfo.userData.events; + if (Array.isArray(events)) { + eventInfos = events.map((info) => { + return { + info, + x: this.$.animationTime.valueToPixel(info.frame * this.curEditClipInfo.fps), + }; + }); + } } this.events.update.call(this, eventInfos); @@ -633,22 +653,16 @@ exports.methods = { }, async setCurEditClipInfo(clipInfo) { this.curEditClipInfo = clipInfo; + this.curTotalFrames = 0; if (clipInfo) { this.curTotalFrames = Math.round(clipInfo.duration * clipInfo.fps); - this.$.animationTime.setConfig({ - max: this.curTotalFrames, - }); - this.$.duration.innerHTML = `Duration: ${this.curTotalFrames}`; + // update animation events, clipInfo.clipUUID may be undefined if (clipInfo.clipUUID) { const subId = clipInfo.clipUUID.match(/@(.*)/)[1]; this.curEditClipInfo.userData = this.meta.subMetas[subId] && this.meta.subMetas[subId].userData || {}; - this.updateEventInfo(); } - if (this.$.animationTimeSlider) { - this.$.animationTimeSlider.max = this.curTotalFrames; - } await callModelPreviewFunction( 'setPlaybackRange', clipInfo.from, @@ -665,6 +679,12 @@ exports.methods = { await this.stopAnimation(); } + + this.$.animationTime.setConfig({ + max: this.curTotalFrames, + }); + this.$.duration.innerHTML = `Totals: ${this.curTotalFrames}`; + this.updateEventInfo(); }, onAnimationPlayStateChanged(state) { this.setCurPlayState(state); @@ -757,7 +777,10 @@ exports.update = async function(assetList, metaList) { this.splitClipIndex = 0; const clipInfo = animation.methods.getCurClipInfo.call(this); await this.onEditClipInfoChanged(clipInfo); + } else { + await this.setCurEditClipInfo(); } + this.eventEditorVm.show = false; this.setCurPlayState(PLAY_STATE.STOP); this.isPreviewDataDirty = true; this.refreshPreview(); From f20bf8ce110a04c69489f3f392f7e423a57f7b8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Fri, 28 Jul 2023 16:24:35 +0800 Subject: [PATCH 033/184] init reflection probe id with native engine (#15829) --- native/cocos/scene/Model.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/cocos/scene/Model.h b/native/cocos/scene/Model.h index 07b953f6910..7085d355383 100644 --- a/native/cocos/scene/Model.h +++ b/native/cocos/scene/Model.h @@ -298,7 +298,7 @@ class Model : public RefCounted { Vec3 _lastWorldBoundCenter{INFINITY, INFINITY, INFINITY}; - Vec4 _shadowBias; + Vec4 _shadowBias{0.F, 0.F, -1.F, -1.F}; Vec4 _lightmapUVParam; // For JS From 44795e465ff034d3b51338f70f7b538f405db2f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 31 Jul 2023 10:54:17 +0800 Subject: [PATCH 034/184] Workflow: fix interface check workflow comment (#15795) --- .../web-interface-check-pr-comment.yml | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/.github/workflows/web-interface-check-pr-comment.yml b/.github/workflows/web-interface-check-pr-comment.yml index ec549062ed7..79816558b63 100644 --- a/.github/workflows/web-interface-check-pr-comment.yml +++ b/.github/workflows/web-interface-check-pr-comment.yml @@ -14,14 +14,29 @@ jobs: if: github.event.workflow_run.conclusion == 'success' runs-on: ubuntu-latest steps: - - name: Download artifacts + - name: 'Get source run informations' + uses: potiuk/get-workflow-origin@v1_1 + id: source_run_info + with: + token: ${{ secrets.GITHUB_TOKEN }} + sourceRunId: ${{ github.event.workflow_run.id }} + + - name: 'Debug' + run: | + Write-Host "Source PR Number: ${{ github.event.workflow_run.pull_requests[0].number }}" + shell: pwsh + + - name: Download artifacts env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} RUN_ID: ${{ github.event.workflow_run.id }} run: | - gh run download -R "${{ github.repository }}" --name "interface-diff.txt" "$RUN_ID" + gh run download -R "${{ github.repository }}" --name "interface-diff.txt" "$RUN_ID" + - name: Post interface-diff.txt as comment uses: marocchino/sticky-pull-request-comment@v2 with: - path: interface-diff.txt - number: ${{ github.event.workflow_run.pull_requests[0].number }} \ No newline at end of file + path: interface-diff.txt + number: ${{ steps.source_run_info.outputs.pullRequestNumber }} + # The following matters, see: https://github.com/orgs/community/discussions/25220 + # number: ${{ github.event.workflow_run.pull_requests[0].number }} \ No newline at end of file From 75add41002db8be9ea1f9dcf8553a343bf92a43d Mon Sep 17 00:00:00 2001 From: PP Date: Mon, 31 Jul 2023 11:33:59 +0800 Subject: [PATCH 035/184] fix: asm.js subpackage without spine module (#15822) # Conflicts: # pal/wasm/wasm-minigame.ts --- pal/wasm/wasm-minigame.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pal/wasm/wasm-minigame.ts b/pal/wasm/wasm-minigame.ts index a7527f15235..cd5e2c88f06 100644 --- a/pal/wasm/wasm-minigame.ts +++ b/pal/wasm/wasm-minigame.ts @@ -26,6 +26,7 @@ import { HUAWEI, TAOBAO_MINIGAME, WASM_SUBPACKAGE, XIAOMI } from 'internal:const import { minigame } from 'pal/minigame'; import { basename } from '../../cocos/core/utils/path'; import { checkPalIntegrity, withImpl } from '../integrity-check'; +import { log } from '../../cocos/core/platform/debug'; export function instantiateWasm (wasmUrl: string, importObject: WebAssembly.Imports): Promise { return getPlatformBinaryUrl(wasmUrl).then((url) => WebAssembly.instantiate(url, importObject)); @@ -55,7 +56,8 @@ function loadSubpackage (name: string): Promise { resolve(); }, fail (err) { - reject(err); + log(`Load subpacakge '${name}' failed, maybe we don't need this subpacakge or it's an engine build issue, for detailed: `, err); + resolve(); }, }); } else { From da25afce01596081b9df6cc8af0082e7b68da745 Mon Sep 17 00:00:00 2001 From: bofeng-song Date: Mon, 31 Jul 2023 11:34:43 +0800 Subject: [PATCH 036/184] Modify compileType's default value to minigame (#15815) --- templates/taobao-mini-game/mini.project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/taobao-mini-game/mini.project.json b/templates/taobao-mini-game/mini.project.json index c0457aca825..9dd8e2c19d2 100644 --- a/templates/taobao-mini-game/mini.project.json +++ b/templates/taobao-mini-game/mini.project.json @@ -1,7 +1,7 @@ { "miniprogramRoot": "client", "pluginRoot": "widget", - "compileType": "plugin", + "compileType": "minigame", "enableAppxNg": true, "widgetRuntimeVersion": "3.0-vue" } From 715d5d11b943e43e3c3f4c511e78604a1674cb16 Mon Sep 17 00:00:00 2001 From: James Chen Date: Mon, 31 Jul 2023 11:36:12 +0800 Subject: [PATCH 037/184] fixed scene._instantiate on native platforms. (#15771) * fixed scene._instantiate/updateWorldTransform on native platforms. --- cocos/scene-graph/scene.jsb.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cocos/scene-graph/scene.jsb.ts b/cocos/scene-graph/scene.jsb.ts index 2b94ca35c48..65365bda651 100644 --- a/cocos/scene-graph/scene.jsb.ts +++ b/cocos/scene-graph/scene.jsb.ts @@ -138,5 +138,7 @@ sceneProto._activate = function (active: boolean) { } }; +sceneProto._instantiate = function(): void {}; + // handle meta data, it is generated automatically patch_cc_Scene({Scene, SceneGlobals}); From 45926d262c0125bb801ab674ad3de68122e1ff6d Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Mon, 31 Jul 2023 14:12:30 +0800 Subject: [PATCH 038/184] fix shader lighting flow (#15833) * fix shader lighting flow * code --- editor/assets/chunks/common/math/number.chunk | 7 +++++++ .../data-structures/lighting-result.chunk | 1 + .../lighting-models/lighting-flow/common-flow.chunk | 3 ++- .../chunks/surfaces/data-structures/standard.chunk | 13 +++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/editor/assets/chunks/common/math/number.chunk b/editor/assets/chunks/common/math/number.chunk index 843fa2ba750..f4a840be943 100644 --- a/editor/assets/chunks/common/math/number.chunk +++ b/editor/assets/chunks/common/math/number.chunk @@ -52,6 +52,13 @@ float rand(vec2 seeds_zero_to_one) { return fract(sin(dot(seeds_zero_to_one.xy, vec2(12.9898, 78.233))) * 43758.5453); } +// like smoothstep, but it's linear interpolation +float linearstep(float minValue, float maxValue, float value) { return saturate((value - minValue) / (maxValue - minValue)); } +vec2 linearstep(vec2 minValue, vec2 maxValue, vec2 value) { return saturate((value - minValue) / (maxValue - minValue)); } +vec3 linearstep(vec3 minValue, vec3 maxValue, vec3 value) { return saturate((value - minValue) / (maxValue - minValue)); } +vec4 linearstep(vec4 minValue, vec4 maxValue, vec4 value) { return saturate((value - minValue) / (maxValue - minValue)); } + + #if __VERSION__ <= 100 mat4 transpose(mat4 v) { mat4 tmp; diff --git a/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk b/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk index d6310b378a2..fd148768dde 100644 --- a/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk +++ b/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk @@ -44,4 +44,5 @@ struct LightingResultPerLayer vec3 diffuseColorWithLighting, specularColorWithLighting; vec3 directDiffuse, directSpecular, directGF; vec3 environmentDiffuse, environmentSpecular, environmentGF; + vec3 directSubLayerF, environmentSubLayerF; }*/ diff --git a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk index ad2dc2efcae..4bce62ff3eb 100644 --- a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk +++ b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk @@ -19,7 +19,8 @@ vec3 diff; SurfacesMaterialData surfaceData2ndSpecular; CCSurfacesGetSurfacesMaterialData2ndSpecular(surfaceData2ndSpecular, surfaceData); - CCSurfacesLightingInitializeColorWithLighting(diff, lightingResultAccumulated.specularColorWithLighting2ndSpecular, surfaceData2ndSpecular, lightingData); + CCSurfacesLightingInitializeColorWithLighting(diff, lightingResult.specularColorWithLighting2ndSpecular, surfaceData2ndSpecular, lightingData); + lightingResultAccumulated.specularColorWithLighting2ndSpecular = lightingResult.specularColorWithLighting2ndSpecular; #endif int numLights = CC_PIPELINE_TYPE == CC_PIPELINE_TYPE_FORWARD ? LIGHTS_PER_PASS : int(cc_lightDir[0].w); diff --git a/editor/assets/chunks/surfaces/data-structures/standard.chunk b/editor/assets/chunks/surfaces/data-structures/standard.chunk index fd8f052538a..a45f0309095 100644 --- a/editor/assets/chunks/surfaces/data-structures/standard.chunk +++ b/editor/assets/chunks/surfaces/data-structures/standard.chunk @@ -44,3 +44,16 @@ struct SurfacesMaterialData vec4 sssParams; #endif }; + +/* +struct SurfacesMaterialDataPerLayer +{ + vec3 baseColor, layerColoration; + float intensity, roughness, metallic; + vec3 worldNormal, worldTangent, worldBinormal; + #if CC_SURFACES_LIGHTING_ANISOTROPIC + float anisotropyShape; + #endif + float ior, opacity; +} +*/ \ No newline at end of file From d73096a1c5d5e19513a69e830aa300268fed1ea1 Mon Sep 17 00:00:00 2001 From: bofeng-song Date: Mon, 31 Jul 2023 14:13:03 +0800 Subject: [PATCH 039/184] Fix the problem of noise when playing web audio for more than 5 minutes. (#15807) * Fix the problem of noise when playing web audio for more than 5 minutes. --- pal/audio/minigame/player-web.ts | 3 +++ pal/audio/web/player-web.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/pal/audio/minigame/player-web.ts b/pal/audio/minigame/player-web.ts index 5d972be780c..869da1306cb 100644 --- a/pal/audio/minigame/player-web.ts +++ b/pal/audio/minigame/player-web.ts @@ -81,6 +81,7 @@ export class OneShotAudioWeb { this._bufferSourceNode.onended = null; // stop will call ended callback audioBufferManager.tryReleasingCache(this._url); this._bufferSourceNode.stop(); + this._bufferSourceNode.disconnect(); this._bufferSourceNode.buffer = null; } } @@ -278,7 +279,9 @@ export class AudioPlayerWeb implements OperationQueueable { if (this._sourceNode) { this._sourceNode.onended = null; // stop will call ended callback this._sourceNode.stop(); + this._sourceNode.disconnect(); this._sourceNode.buffer = null; + this._sourceNode = undefined; } } catch (e) { // sourceNode can't be stopped twice, especially on Safari. diff --git a/pal/audio/web/player-web.ts b/pal/audio/web/player-web.ts index 7b7a0bc1d5f..5d703d35d63 100644 --- a/pal/audio/web/player-web.ts +++ b/pal/audio/web/player-web.ts @@ -206,6 +206,7 @@ export class OneShotAudioWeb { clearTimeout(this._currentTimer); audioBufferManager.tryReleasingCache(this._url); this._bufferSourceNode.stop(); + this._bufferSourceNode.disconnect(); this._bufferSourceNode.buffer = null; } } @@ -438,7 +439,9 @@ export class AudioPlayerWeb implements OperationQueueable { try { if (this._sourceNode) { this._sourceNode.stop(); + this._sourceNode.disconnect(); this._sourceNode.buffer = null; + this._sourceNode = undefined; } } catch (e) { // sourceNode can't be stopped twice, especially on Safari. From 74872602b9df40d08540a44ab1bf02400ccc62fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 31 Jul 2023 14:19:28 +0800 Subject: [PATCH 040/184] Eslint: fix indent rule for decorators (#15735) --- .eslintrc.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 6b0db3f8be9..839c15e7fa4 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -70,7 +70,14 @@ rules: import/extensions: off # typescript doesn't support this import/no-unresolved: off # TODO: fix internal modules import/prefer-default-export: off # prefer named exports - indent: off # use @typescript-eslint/indent instead for better compatibility + indent: [error, 4, { + SwitchCase: 0, + ignoredNodes: [ # https://stackoverflow.com/a/72897089 + "FunctionExpression > .params[decorators.length > 0]", + "FunctionExpression > .params > :matches(Decorator, :not(:first-child))", + "ClassBody.body > PropertyDefinition[decorators.length > 0] > .key", + ] + }] lines-between-class-members: off # be more lenient on member declarations max-classes-per-file: off # helper classes are common @@ -103,9 +110,6 @@ rules: 'ts-nocheck': true, 'ts-check': false, }] - '@typescript-eslint/indent': [warn, 4, { - SwitchCase: 0 - }] '@typescript-eslint/no-unused-expressions': warn # TODO: this is just too much work From 762fd501c7cf991f8a24c25eb4c1273431ae6851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 31 Jul 2023 14:20:52 +0800 Subject: [PATCH 041/184] Eslint: off default-case-last (#15733) --- .eslintrc.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 839c15e7fa4..09f5032bf31 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -101,6 +101,7 @@ rules: prefer-destructuring: off # auto-fix is not smart enough to merge different instances linebreak-style: off # we don't enforce this on everyone's dev environment for now spaced-comment: off # for license declarations + default-case-last: off # Place default case clause to first make it more clear that this switch statement has handled all cases ##### TYPESCRIPT-SPECIFIC RULE OVERRIDES ##### From 95cd245055658c14df3e36a2570aeb60883d6dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 31 Jul 2023 14:21:36 +0800 Subject: [PATCH 042/184] ESLint: replace no-empty-function with typescript version (#15732) --- .eslintrc.yaml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 09f5032bf31..397a8ee08d4 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -61,6 +61,7 @@ rules: quotes: [warn, single, { allowTemplateLiterals: true }] # force single, but allow template literal no-else-return: off # else-return is a common pattern which clearly expresses the control flow no-unused-expressions: off # taken over by '@typescript-eslint/no-unused-expressions' + no-empty-function: off # taken over by '@typescript-eslint/no-empty-function' ##### AIRBNB-SPECIFIC RULE OVERRIDES ##### @@ -126,7 +127,16 @@ rules: '@typescript-eslint/unbound-method': off # we exploit prototype methods sometimes to acheive better performace '@typescript-eslint/no-explicit-any': off # still relevant for some heavily templated usages - '@typescript-eslint/no-empty-function': off # may become useful in some parent classes + + '@typescript-eslint/no-empty-function': [error, { + allow: [ + private-constructors, + protected-constructors, + decoratedFunctions, + overrideMethods, + ] + }] + '@typescript-eslint/no-unused-vars': off # may become useful in some parent classes '@typescript-eslint/no-non-null-assertion': off # sometimes we just know better than the compiler '@typescript-eslint/no-namespace': [warn, { # we need to declare static properties From 54c81416ec928d8fd6607f0ca22312a83af1e087 Mon Sep 17 00:00:00 2001 From: dogeFu <609075410@qq.com> Date: Mon, 31 Jul 2023 14:42:25 +0800 Subject: [PATCH 043/184] refactor : call safeMeasureText when needed (#15754) --- cocos/2d/utils/font-loader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos/2d/utils/font-loader.ts b/cocos/2d/utils/font-loader.ts index 5ede5e34ca5..a4940d8a903 100644 --- a/cocos/2d/utils/font-loader.ts +++ b/cocos/2d/utils/font-loader.ts @@ -167,7 +167,6 @@ export function loadFont (url: string, options: Record, onComplete: // Default width reference to test whether new font is loaded correctly const fontDesc = `40px ${fontFamilyName}`; - const refWidth = safeMeasureText(_canvasContext!, _testString, fontDesc); // Setup font face style const fontStyle = ccdocument.createElement('style'); @@ -195,6 +194,7 @@ export function loadFont (url: string, options: Record, onComplete: if (useNativeCheck()) { nativeCheckFontLoaded(Date.now(), fontFamilyName, onComplete); } else { + const refWidth = safeMeasureText(_canvasContext!, _testString, fontDesc); // Save loading font const fontLoadHandle = { fontFamilyName, From 4a2f290516dca33675bb3219fe2133238e0fbbed Mon Sep 17 00:00:00 2001 From: bofeng-song Date: Tue, 1 Aug 2023 11:34:40 +0800 Subject: [PATCH 044/184] Fix audio can not be paused & resume on mini game platform (#15811) * Fix audio can not be paused & resume on mini game platform --- pal/audio/minigame/player-minigame.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/pal/audio/minigame/player-minigame.ts b/pal/audio/minigame/player-minigame.ts index 88e03a50be9..a5cc67e40e6 100644 --- a/pal/audio/minigame/player-minigame.ts +++ b/pal/audio/minigame/player-minigame.ts @@ -30,7 +30,6 @@ import { AudioEvent, AudioPCMDataView, AudioState, AudioType } from '../type'; import { clamp, clamp01 } from '../../../cocos/core'; import { enqueueOperation, OperationInfo, OperationQueueable } from '../operation-queue'; import { OS } from '../../system-info/enum-type'; -import { Game, game } from '../../../cocos/game'; export class OneShotAudioMinigame { private _innerAudioContext: InnerAudioContext; @@ -58,6 +57,8 @@ export class OneShotAudioMinigame { }); const endCallback = (): void => { if (this._innerAudioContext) { + systemInfo.off('hide', this._onInterruptedBegin, this); + systemInfo.off('show', this._onInterruptedEnd, this); this._onEndCb?.(); nativeAudio.destroy(); // NOTE: Type 'null' is not assignable to type 'InnerAudioContext'. @@ -66,6 +67,18 @@ export class OneShotAudioMinigame { }; nativeAudio.onEnded(endCallback); nativeAudio.onStop(endCallback);//OneShotAudio can not be reused. + + // event + systemInfo.on('hide', this._onInterruptedBegin, this); + systemInfo.on('show', this._onInterruptedEnd, this); + } + + private _onInterruptedBegin (): void { + this._innerAudioContext.pause(); + } + + private _onInterruptedEnd (): void { + this._innerAudioContext.play(); } public play (): void { @@ -109,8 +122,8 @@ export class AudioPlayerMinigame implements OperationQueueable { this._eventTarget = new EventTarget(); // event - game.on(Game.EVENT_PAUSE, this._onInterruptedBegin, this); - game.on(Game.EVENT_RESUME, this._onInterruptedEnd, this); + systemInfo.on('hide', this._onInterruptedBegin, this); + systemInfo.on('show', this._onInterruptedEnd, this); const eventTarget = this._eventTarget; this._onPlay = (): void => { this._state = AudioState.PLAYING; @@ -171,8 +184,8 @@ export class AudioPlayerMinigame implements OperationQueueable { innerAudioContext.onEnded(this._onEnded); } destroy (): void { - game.off(Game.EVENT_PAUSE, this._onInterruptedBegin, this); - game.off(Game.EVENT_RESUME, this._onInterruptedEnd, this); + systemInfo.off('hide', this._onInterruptedBegin, this); + systemInfo.off('show', this._onInterruptedEnd, this); if (this._innerAudioContext) { ['Play', 'Pause', 'Stop', 'Seeked', 'Ended'].forEach((event) => { this._offEvent(event); @@ -196,7 +209,7 @@ export class AudioPlayerMinigame implements OperationQueueable { private _onInterruptedEnd (): void { // We don't know whether onShow or resolve callback in pause promise is called at first. if (!this._readyToHandleOnShow) { - this._eventTarget.once(AudioEvent.INTERRUPTION_BEGIN, this._onInterruptedEnd, this); + this._eventTarget.once(AudioEvent.INTERRUPTION_END, this._onInterruptedEnd, this); return; } if (this._state === AudioState.INTERRUPTED) { From 22388ba7019b3b95b33c1d26f1acaf7f1c08cdc2 Mon Sep 17 00:00:00 2001 From: bofeng-song Date: Tue, 1 Aug 2023 14:24:27 +0800 Subject: [PATCH 045/184] The Taobao platform has improved the implementation of innerAudioContext. (#15839) --- pal/audio/minigame/player-minigame.ts | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/pal/audio/minigame/player-minigame.ts b/pal/audio/minigame/player-minigame.ts index a5cc67e40e6..e363567f403 100644 --- a/pal/audio/minigame/player-minigame.ts +++ b/pal/audio/minigame/player-minigame.ts @@ -151,9 +151,14 @@ export class AudioPlayerMinigame implements OperationQueueable { // Reset all properties this._resetSeekCache(); eventTarget.emit(AudioEvent.STOPPED); - const currentTime = this._innerAudioContext ? this._innerAudioContext.currentTime : 0; - if (currentTime !== 0) { - this._innerAudioContext.seek(0); + if (TAOBAO || TAOBAO_MINIGAME) { + /**Unable to seek again after stop; After stop, regardless of whether the starttime has been set, + the playback will always start from 0 again**/ + } else { + const currentTime = this._innerAudioContext ? this._innerAudioContext.currentTime : 0; + if (currentTime !== 0) { + this._innerAudioContext.seek(0); + } } }; innerAudioContext.onStop(this._onStop); @@ -168,12 +173,6 @@ export class AudioPlayerMinigame implements OperationQueueable { this._needSeek = false; } } - - // TaoBao iOS: After calling pause or stop, when seek is called, it will automatically play and call onPlay. - if ((TAOBAO || TAOBAO_MINIGAME) && systemInfo.os === OS.IOS - && (this._state === AudioState.PAUSED || this._state === AudioState.STOPPED)) { - innerAudioContext.pause(); - } }; innerAudioContext.onSeeked(this._onSeeked); this._onEnded = (): void => { @@ -350,14 +349,6 @@ export class AudioPlayerMinigame implements OperationQueueable { @enqueueOperation stop (): Promise { - // NOTE: on Taobao, it is designed that innerAudioContext is useless after calling stop. - // so we implement stop as pase + seek. - if (TAOBAO || TAOBAO_MINIGAME) { - this._innerAudioContext.pause(); - this._innerAudioContext.seek(0); - this._onStop?.(); - return Promise.resolve(); - } return new Promise((resolve) => { this._eventTarget.once(AudioEvent.STOPPED, resolve); this._innerAudioContext.stop(); From 5eddce91f13526e43496d8ad97cd363b1cc22419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Tue, 1 Aug 2023 14:50:45 +0800 Subject: [PATCH 046/184] PoseGraph: support editor decorators on node inputs (#15819) * PoseGraph: support editor decorators on node inputs * Fix lint error --- .../marionette/pose-graph/decorator/input.ts | 25 ++++++++++++++++--- .../pose-graph/graph-output-node.ts | 7 ++---- .../pose-graph/pose-nodes/additively-blend.ts | 3 ++- .../pose-graph/pose-nodes/apply-transform.ts | 7 +++--- .../pose-nodes/blend-in-proportion.ts | 3 ++- .../pose-nodes/blend-two-pose-base.ts | 3 ++- .../pose-nodes/ik/two-bone-ik-solver.ts | 8 +++--- .../pose-nodes/intensity-specification.ts | 3 ++- .../pose-graph/pose-nodes/play-motion.ts | 5 ++-- .../src/marionette/pose-graph-editor-api.ts | 12 +++++++++ .../pose-graph/pose-graph-authoring.test.ts | 17 +++++++++++++ 11 files changed, 72 insertions(+), 21 deletions(-) diff --git a/cocos/animation/marionette/pose-graph/decorator/input.ts b/cocos/animation/marionette/pose-graph/decorator/input.ts index 38e2f2135af..2c223606ccb 100644 --- a/cocos/animation/marionette/pose-graph/decorator/input.ts +++ b/cocos/animation/marionette/pose-graph/decorator/input.ts @@ -1,6 +1,8 @@ /* eslint-disable @typescript-eslint/ban-types */ import { error, js } from '../../../../core'; +import { PropertyStashInternalFlag } from '../../../../core/data/class-stash'; +import { getOrCreatePropertyStash } from '../../../../core/data/decorators/property'; import { PoseGraphNodeInputMappingOptions, globalPoseGraphNodeInputManager } from '../foundation/authoring/input-authoring'; import { PoseGraphType } from '../foundation/type-system'; import { PoseNode } from '../pose-node'; @@ -38,10 +40,6 @@ export type { PoseGraphNodeInputMappingOptions }; */ export function input (options: PoseGraphNodeInputMappingOptions): PropertyDecorator { return (target, propertyKey): void => { - if (typeof propertyKey !== 'string') { - error(`@input can be only applied to string-named fields.`); - return; - } const targetConstructor = target.constructor; if (options.type === PoseGraphType.POSE) { if (!js.isChildClassOf(targetConstructor, PoseNode)) { @@ -55,6 +53,25 @@ export function input (options: PoseGraphNodeInputMappingOptions): PropertyDecor error(`@input can be only applied to fields of subclasses of PoseNode or PureValueNode.`); return; } + inputUnchecked(options)(target, propertyKey); + }; +} + +/** + * Unchecked version of `@input()`. + * @internal + */ +export function inputUnchecked (options: PoseGraphNodeInputMappingOptions): PropertyDecorator { + return (target, propertyKey) => { + if (typeof propertyKey !== 'string') { + error(`@input can be only applied to string-named fields.`); + return; + } + + const targetConstructor = target.constructor; globalPoseGraphNodeInputManager.setPropertyNodeInputRecord(targetConstructor, propertyKey, options); + + const propertyStash = getOrCreatePropertyStash(target, propertyKey); + propertyStash.__internalFlags |= (PropertyStashInternalFlag.STANDALONE | PropertyStashInternalFlag.IMPLICIT_VISIBLE); }; } diff --git a/cocos/animation/marionette/pose-graph/graph-output-node.ts b/cocos/animation/marionette/pose-graph/graph-output-node.ts index 6c8711eca18..422f14103a2 100644 --- a/cocos/animation/marionette/pose-graph/graph-output-node.ts +++ b/cocos/animation/marionette/pose-graph/graph-output-node.ts @@ -4,8 +4,8 @@ import { CLASS_NAME_PREFIX_ANIM } from '../../define'; import { PoseNode } from './pose-node'; import { PoseGraphType } from './foundation/type-system'; import { PoseGraphNode } from './foundation/pose-graph-node'; -import { globalPoseGraphNodeInputManager } from './foundation/authoring/input-authoring'; import { poseGraphNodeAppearance } from './decorator/node'; +import { inputUnchecked } from './decorator/input'; @ccclass(`${CLASS_NAME_PREFIX_ANIM}PoseGraphOutputNode`) @poseGraphNodeAppearance({ @@ -15,9 +15,6 @@ import { poseGraphNodeAppearance } from './decorator/node'; export class PoseGraphOutputNode extends PoseGraphNode { // Don't use @input since it requires the owner class being subclass of `PoseNode`. @serializable + @inputUnchecked({ type: PoseGraphType.POSE }) pose: PoseNode | null = null; } - -globalPoseGraphNodeInputManager.setPropertyNodeInputRecord(PoseGraphOutputNode, 'pose', { - type: PoseGraphType.POSE, -}); diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/additively-blend.ts b/cocos/animation/marionette/pose-graph/pose-nodes/additively-blend.ts index 77cffebd07f..81c9d200c47 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/additively-blend.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/additively-blend.ts @@ -1,4 +1,4 @@ -import { ccclass, serializable } from '../../../../core/data/decorators'; +import { ccclass, range, serializable } from '../../../../core/data/decorators'; import { Pose, applyDeltaPose } from '../../../core/pose'; import { CLASS_NAME_PREFIX_ANIM } from '../../../define'; import { poseGraphNodeAppearance, poseGraphNodeCategory } from '../decorator/node'; @@ -29,6 +29,7 @@ export class PoseNodeAdditivelyBlend extends PoseNode { @serializable @input({ type: PoseGraphType.FLOAT }) + @range([0.0, 1.0, 0.01]) public ratio = 1.0; public bind (context: AnimationGraphBindingContext): void { diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/apply-transform.ts b/cocos/animation/marionette/pose-graph/pose-nodes/apply-transform.ts index 2909c1f2bcc..fb3e2eb4e45 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/apply-transform.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/apply-transform.ts @@ -1,5 +1,5 @@ import { EDITOR } from 'internal:constants'; -import { ccclass, editable, serializable, type, visible } from '../../../../core/data/decorators'; +import { ccclass, editable, range, serializable, type, visible } from '../../../../core/data/decorators'; import { CLASS_NAME_PREFIX_ANIM } from '../../../define'; import { PoseNode, PoseTransformSpaceRequirement } from '../pose-node'; import { @@ -47,7 +47,7 @@ export class PoseNodeApplyTransform extends PoseNodeModifyPoseBase { @serializable @editable @input({ type: PoseGraphType.VEC3 }) - @visible(function visible(this: PoseNodeApplyTransform) { return this.positionOperation !== TransformOperation.LEAVE_UNCHANGED; }) + @visible(function visible (this: PoseNodeApplyTransform) { return this.positionOperation !== TransformOperation.LEAVE_UNCHANGED; }) public position = new Vec3(); @serializable @@ -58,11 +58,12 @@ export class PoseNodeApplyTransform extends PoseNodeModifyPoseBase { @serializable @editable @input({ type: PoseGraphType.QUAT }) - @visible(function visible(this: PoseNodeApplyTransform) { return this.rotationOperation !== TransformOperation.LEAVE_UNCHANGED; }) + @visible(function visible (this: PoseNodeApplyTransform) { return this.rotationOperation !== TransformOperation.LEAVE_UNCHANGED; }) public rotation = new Quat(); @serializable @editable + @range([0.0, 1.0, 0.01]) public intensity = new IntensitySpecification(); @serializable diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/blend-in-proportion.ts b/cocos/animation/marionette/pose-graph/pose-nodes/blend-in-proportion.ts index ed84d2a146e..e7f2d732048 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/blend-in-proportion.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/blend-in-proportion.ts @@ -1,5 +1,5 @@ import { EDITOR } from 'internal:constants'; -import { ccclass, serializable } from '../../../../core/data/decorators'; +import { ccclass, range, serializable } from '../../../../core/data/decorators'; import { blendPoseInto, Pose } from '../../../core/pose'; import { CLASS_NAME_PREFIX_ANIM } from '../../../define'; import { PoseNode, PoseTransformSpaceRequirement } from '../pose-node'; @@ -29,6 +29,7 @@ export class PoseNodeBlendInProportion extends PoseNode { arraySyncGroup: 'blend-item', arraySyncGroupFollower: true, }) + @range([0.0, Number.POSITIVE_INFINITY]) public readonly proportions: number[] = []; public bind (context: AnimationGraphBindingContext): void { diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/blend-two-pose-base.ts b/cocos/animation/marionette/pose-graph/pose-nodes/blend-two-pose-base.ts index e87ce7e4b8e..dc8e30b1cfd 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/blend-two-pose-base.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/blend-two-pose-base.ts @@ -1,4 +1,4 @@ -import { ccclass, editable, serializable, type } from '../../../../core/data/decorators'; +import { ccclass, editable, range, serializable, type } from '../../../../core/data/decorators'; import { Pose } from '../../../core/pose'; import { CLASS_NAME_PREFIX_ANIM } from '../../../define'; import { PoseNode, PoseTransformSpaceRequirement } from '../pose-node'; @@ -22,6 +22,7 @@ export abstract class PoseNodeBlendTwoPoseBase extends PoseNode { @serializable @input({ type: PoseGraphType.FLOAT }) + @range([0.0, 1.0, 0.01]) ratio = 1.0; public bind (context: AnimationGraphBindingContext): void { diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/ik/two-bone-ik-solver.ts b/cocos/animation/marionette/pose-graph/pose-nodes/ik/two-bone-ik-solver.ts index 5e92050e114..fa0006bb10a 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/ik/two-bone-ik-solver.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/ik/two-bone-ik-solver.ts @@ -56,18 +56,18 @@ class TargetSpecification { @serializable @editable - @visible(function visible(this: TargetSpecification) { return this.type === TargetSpecificationType.VALUE; }) + @visible(function visible (this: TargetSpecification) { return this.type === TargetSpecificationType.VALUE; }) public targetPosition = new Vec3(); @serializable @editable @type(TransformSpace) - @visible(function visible(this: TargetSpecification) { return this.type === TargetSpecificationType.VALUE; }) + @visible(function visible (this: TargetSpecification) { return this.type === TargetSpecificationType.VALUE; }) public targetPositionSpace = TransformSpace.WORLD; @serializable @editable - @visible(function visible(this: TargetSpecification) { return this.type === TargetSpecificationType.BONE; }) + @visible(function visible (this: TargetSpecification) { return this.type === TargetSpecificationType.BONE; }) public targetBone = ''; public bind (context: AnimationGraphBindingContext, sourceBoneHandle: TransformHandle): void { @@ -117,6 +117,7 @@ export class PoseNodeTwoBoneIKSolver extends PoseNodeModifyPoseBase { public readonly endEffectorTarget = new TargetSpecification(TargetSpecificationType.VALUE); @input({ type: PoseGraphType.VEC3 }) + @visible(function visible (this: PoseNodeTwoBoneIKSolver) { return this.endEffectorTarget.type === TargetSpecificationType.VALUE; }) get endEffectorTargetPosition (): Vec3 { return this.endEffectorTarget.targetPosition; } @@ -130,6 +131,7 @@ export class PoseNodeTwoBoneIKSolver extends PoseNodeModifyPoseBase { public readonly poleTarget = new TargetSpecification(TargetSpecificationType.NONE); @input({ type: PoseGraphType.VEC3 }) + @visible(function visible (this: PoseNodeTwoBoneIKSolver) { return this.poleTarget.type === TargetSpecificationType.VALUE; }) get poleTargetPosition (): Vec3 { return this.poleTarget.targetPosition; } diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/intensity-specification.ts b/cocos/animation/marionette/pose-graph/pose-nodes/intensity-specification.ts index 36a779ba580..85922a169b4 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/intensity-specification.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/intensity-specification.ts @@ -1,5 +1,5 @@ import { ccenum } from '../../../../core'; -import { ccclass, editable, serializable, type, visible } from '../../../../core/data/decorators'; +import { ccclass, editable, range, serializable, type, visible } from '../../../../core/data/decorators'; import { AuxiliaryCurveHandle } from '../../../core/animation-handle'; import { Pose } from '../../../core/pose'; import { CLASS_NAME_PREFIX_ANIM } from '../../../define'; @@ -22,6 +22,7 @@ export class IntensitySpecification { @serializable @editable @visible(function visible (this: IntensitySpecification): boolean { return this.type === IntensityType.VALUE; }) + @range([0.0, 1.0, 0.01]) public value = 1.0; @serializable diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/play-motion.ts b/cocos/animation/marionette/pose-graph/pose-nodes/play-motion.ts index a93d7606d64..78e8b8b3c5f 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/play-motion.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/play-motion.ts @@ -1,5 +1,5 @@ import { EDITOR } from 'internal:constants'; -import { ccclass, displayName, editable, serializable } from '../../../../core/data/decorators'; +import { ccclass, displayName, editable, serializable, unit } from '../../../../core/data/decorators'; import { CLASS_NAME_PREFIX_ANIM } from '../../../define'; import { ClipMotion } from '../../motion/clip-motion'; import { createEval } from '../../create-eval'; @@ -43,6 +43,7 @@ export class PoseNodePlayMotion extends PoseNode { @serializable @input({ type: PoseGraphType.FLOAT }) + @unit('s') public startTime = 0.0; @serializable @@ -79,7 +80,7 @@ export class PoseNodePlayMotion extends PoseNode { } public settle (context: AnimationGraphSettleContext): void { - + // override } public reenter (): void { diff --git a/editor/src/marionette/pose-graph-editor-api.ts b/editor/src/marionette/pose-graph-editor-api.ts index 8cfc4354570..cbd1cb20487 100644 --- a/editor/src/marionette/pose-graph-editor-api.ts +++ b/editor/src/marionette/pose-graph-editor-api.ts @@ -13,6 +13,7 @@ import { PoseGraphStash, StateMachine } from "../../../cocos/animation/marionett import { PoseNodeLocation, visitPoseNodeInLayer } from "./visit/visit-pose-node"; import { PoseGraph } from '../../../cocos/animation/marionette/pose-graph/pose-graph'; import { PoseNodeStateMachine } from "../../../cocos/animation/marionette/pose-graph/pose-nodes/state-machine"; +import { attr } from "../../../cocos/core/data/utils/attribute"; type Constructor = new (...args: any[]) => T; @@ -92,6 +93,17 @@ export function getInputDefaultDisplayName(inputKey: poseGraphOp.InputKey) { } } +export function getPoseGraphNodeInputAttrs(node: PoseGraphNode, inputKey: poseGraphOp.InputKey) { + const [propertyName] = inputKey; + const attrs = attr(node.constructor, propertyName); + delete attrs.type; + delete attrs.ctor; + if (Array.isArray(node[propertyName])) { + delete attrs['default']; + } + return attrs; +} + function clonePoseGraphNode(node: PoseGraphNode) { return instantiate(node); } diff --git a/tests/animation/new-gen-anim/pose-graph/pose-graph-authoring.test.ts b/tests/animation/new-gen-anim/pose-graph/pose-graph-authoring.test.ts index 1400fcce30d..ce29bd5dbb8 100644 --- a/tests/animation/new-gen-anim/pose-graph/pose-graph-authoring.test.ts +++ b/tests/animation/new-gen-anim/pose-graph/pose-graph-authoring.test.ts @@ -13,6 +13,9 @@ import { poseGraphCreateNodeFactory, poseGraphNodeAppearance, poseGraphNodeHide, import { PoseGraphNodeEditorMetadata, getPoseGraphNodeEditorMetadata } from "../../../../cocos/animation/marionette/pose-graph/foundation/authoring/node-authoring"; import { composeInputKeyInternally, createPoseGraph, getTheOnlyInputKey, getTheOnlyOutputKey, normalizeNodeInputMetadata, UnimplementedPoseNode, UnimplementedPVNode } from "./utils/misc"; import { PoseNode } from "../../../../cocos/animation/marionette/pose-graph/pose-node"; +import { ccclass } from "../../../../cocos/core/data/class-decorator"; +import { unregisterClass } from "../../../../cocos/core/utils/js-typed"; +import { attr } from "../../../../cocos/core/data/utils/attribute"; describe(`Class PoseGraph`, () => { test(`Default`, () => { @@ -162,6 +165,20 @@ describe(`Input decorator @input`, () => { return _Node; } }); + + test(`@input implies default visibility`, () => { + @ccclass('C') + class Node extends UnimplementedPoseNode { + @input({ type: PoseGraphType.FLOAT }) + p = 0.0; + } + + expect(attr(Node, 'p')).toStrictEqual(expect.objectContaining({ + visible: true, + })); + + unregisterClass(Node); + }); }); describe(`Node editor decorators`, () => { From 06341f3037ce74068f6612d1dc5b578a5ab4ec9c Mon Sep 17 00:00:00 2001 From: qiuguohua Date: Wed, 2 Aug 2023 14:20:24 +0800 Subject: [PATCH 047/184] Uncapture global mouse events. (#15834) --- native/cocos/platform/SDLHelper.cpp | 4 ---- native/external-config.json | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/native/cocos/platform/SDLHelper.cpp b/native/cocos/platform/SDLHelper.cpp index b588395f33d..56e71618b8c 100644 --- a/native/cocos/platform/SDLHelper.cpp +++ b/native/cocos/platform/SDLHelper.cpp @@ -198,10 +198,6 @@ void SDLHelper::dispatchWindowEvent(uint32_t windowId, const SDL_WindowEvent &we events::WindowEvent::broadcast(ev); break; } - case SDL_WINDOWEVENT_ENTER: { - SDL_CaptureMouse(SDL_TRUE); - break; - } case SDL_WINDOWEVENT_CLOSE: { ev.type = WindowEvent::Type::CLOSE; events::WindowEvent::broadcast(ev); diff --git a/native/external-config.json b/native/external-config.json index 082f542393f..5427b2b8bfa 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-8" + "checkout": "v3.8.1-9" } } From 326ba66a9a4334cd4d592fd974c55b5790219159 Mon Sep 17 00:00:00 2001 From: mmyduckx <308303735@qq.com> Date: Wed, 2 Aug 2023 14:34:50 +0800 Subject: [PATCH 048/184] implement some wechat splashScreen features (#15827) * implement some wechat splashScreen features * fix unit-test may not get logo&background condition * fix eslint --- cocos/game/splash-screen.ts | 299 ++++++++++++++++---------- templates/wechatgame/first-screen.ejs | 61 ++++-- 2 files changed, 227 insertions(+), 133 deletions(-) diff --git a/cocos/game/splash-screen.ts b/cocos/game/splash-screen.ts index fb85f3f1c59..87ee4f71ff3 100644 --- a/cocos/game/splash-screen.ts +++ b/cocos/game/splash-screen.ts @@ -28,7 +28,7 @@ import { clamp01, Mat4, Vec2, Settings, settings, sys, cclegacy, easing, preTran import { Sampler, SamplerInfo, Shader, Texture, TextureInfo, Device, InputAssembler, InputAssemblerInfo, Attribute, Buffer, BufferInfo, Rect, Color, BufferTextureCopy, CommandBuffer, BufferUsageBit, Format, - MemoryUsageBit, TextureType, TextureUsageBit, Address, Swapchain, + MemoryUsageBit, TextureType, TextureUsageBit, Address, Swapchain, Framebuffer, } from '../gfx'; import { PipelineStateManager } from '../rendering'; import { SetIndex } from '../rendering/define'; @@ -36,7 +36,8 @@ import { ccwindow, legacyCC } from '../core/global-exports'; import { XREye } from '../xr/xr-enums'; const v2_0 = new Vec2(); -type SplashEffectType = 'default' | 'custom' | 'off'; +type SplashLogoType = 'default' | 'none' | 'custom'; +type SplashBackgroundType = 'default' | 'color' | 'custom'; type WatermarkLocationType = 'default' | 'topLeft' | 'topRight' | 'topCenter' | 'bottomLeft' | 'bottomCenter' | 'bottomRight'; interface ISplashSetting { @@ -44,12 +45,21 @@ interface ISplashSetting { totalTime: number; watermarkLocation: WatermarkLocationType; autoFit: boolean; + logo?: SplashLogo; + background?: SplashBackground; +} - url?: string; - type?: SplashEffectType; +interface SplashBackground { + type: SplashBackgroundType; + color?: Color; + image?: string; + base64?: string; +} - bgBase64: string; - base64src: string; +interface SplashLogo { + type: SplashLogoType; + image?: string; + base64?: string; } export class SplashScreen { @@ -117,14 +127,12 @@ export class SplashScreen { totalTime: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'totalTime') ?? 3000, watermarkLocation: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'watermarkLocation') ?? 'default', autoFit: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'autoFit') ?? true, - url: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'url') ?? '', - type: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'type') ?? 'default', - bgBase64: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'bgBase64') ?? '', - base64src: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'base64src') ?? '', + logo: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'logo') ?? undefined, + background: settings.querySettings(Settings.Category.SPLASH_SCREEN, 'background') ?? undefined, }; this._curTime = 0; - if (EDITOR || this.settings.base64src === '' || this.settings.totalTime <= 0) { + if (EDITOR || this.settings.totalTime <= 0 || this.settings.logo === undefined || this.settings.background === undefined) { this.settings.totalTime = 0; } else { this.device = cclegacy.director.root!.device; @@ -133,36 +141,45 @@ export class SplashScreen { this.preInit(); this.initLayout(); - this.initWaterMark(); - const bgPromise = new Promise((resolve, reject): void => { - this.bgImage = new ccwindow.Image(); - this.bgImage.onload = (): void => { - this.initBG(); - resolve(); - }; - this.bgImage.onerror = (): void => { - reject(); - }; - this.bgImage.src = this.settings.bgBase64; - }); - const logoPromise = new Promise((resolve, reject): void => { - this.logoImage = new ccwindow.Image(); - this.logoImage.onload = (): void => { - this.initLogo(); - resolve(); - }; - this.logoImage.onerror = (): void => { - reject(); - }; - this.logoImage.src = this.settings.base64src; - }); + if (this.settings.logo.type === 'default') { + this.initWaterMark(); + } + let bgPromise = Promise.resolve(); + let logoPromise = Promise.resolve(); + if (this.settings.background.type === 'custom') { + bgPromise = new Promise((resolve, reject): void => { + this.bgImage = new ccwindow.Image(); + this.bgImage.onload = (): void => { + this.initBG(); + resolve(); + }; + this.bgImage.onerror = (): void => { + reject(); + }; + this.bgImage.src = this.settings.background!.base64!; + }); + } + if (this.settings.logo.type !== 'none') { + logoPromise = new Promise((resolve, reject): void => { + this.logoImage = new ccwindow.Image(); + this.logoImage.onload = (): void => { + this.initLogo(); + resolve(); + }; + this.logoImage.onerror = (): void => { + reject(); + }; + this.logoImage.src = this.settings.logo!.base64!; + }); + } return Promise.all([bgPromise, logoPromise]); } return Promise.resolve([]); } private preInit (): void { - this.clearColors = [new Color(0, 0, 0, 255)]; // clean to black + const clearColor = this.settings.background?.color; + this.clearColors = clearColor ? [new Color(clearColor.x, clearColor.y, clearColor.z, clearColor.w)] : [new Color(0, 0, 0, 1)]; const { device, swapchain } = this; this.renderArea = new Rect(0, 0, swapchain.width, swapchain.height); this.cmdBuff = device.commandBuffer; @@ -174,7 +191,9 @@ export class SplashScreen { const vbSize = vbStride * 4; this.vertexBuffers = device.createBuffer(new BufferInfo( BufferUsageBit.VERTEX | BufferUsageBit.TRANSFER_DST, - MemoryUsageBit.DEVICE, vbSize, vbStride, + MemoryUsageBit.DEVICE, + vbSize, + vbStride, )); this.vertexBuffers.update(verts); @@ -184,7 +203,9 @@ export class SplashScreen { const ibSize = ibStride * 6; this.indicesBuffers = device.createBuffer(new BufferInfo( BufferUsageBit.INDEX | BufferUsageBit.TRANSFER_DST, - MemoryUsageBit.DEVICE, ibSize, ibStride, + MemoryUsageBit.DEVICE, + ibSize, + ibStride, )); this.indicesBuffers.update(indices); @@ -196,8 +217,18 @@ export class SplashScreen { this.quadAssmebler = device.createInputAssembler(IAInfo); this.projection = new Mat4(); - Mat4.ortho(this.projection, -1, 1, -1, 1, -1, 1, device.capabilities.clipSpaceMinZ, - device.capabilities.clipSpaceSignY, swapchain.surfaceTransform); + Mat4.ortho( + this.projection, + -1, + 1, + -1, + 1, + -1, + 1, + device.capabilities.clipSpaceMinZ, + device.capabilities.clipSpaceSignY, + swapchain.surfaceTransform, + ); this.isMobile = sys.isMobile; } @@ -250,8 +281,18 @@ export class SplashScreen { public update (deltaTime: number): void { const settings = this.settings; const { device, swapchain } = this; - Mat4.ortho(this.projection, -1, 1, -1, 1, -1, 1, device.capabilities.clipSpaceMinZ, - device.capabilities.clipSpaceSignY, swapchain.surfaceTransform); + Mat4.ortho( + this.projection, + -1, + 1, + -1, + 1, + -1, + 1, + device.capabilities.clipSpaceMinZ, + device.capabilities.clipSpaceSignY, + swapchain.surfaceTransform, + ); const dw = swapchain.width; const dh = swapchain.height; this.initScale(); @@ -259,40 +300,41 @@ export class SplashScreen { const percent = clamp01(this._curTime / settings.totalTime); const u_p = easing.cubicOut(percent); - // update bg uniform let scaleX = 1; let scaleY = 1; - if (dw < dh) { - scaleX = dh * this.bgRatio; - scaleY = dh; - } else { - scaleX = dw; - scaleY = dw * this.bgRatio; - } - - this.bgMat.setProperty('resolution', v2_0.set(dw, dh), 0); - this.bgMat.setProperty('scale', v2_0.set(scaleX, scaleY), 0); - this.bgMat.setProperty('translate', v2_0.set(dw * 0.5, dh * 0.5), 0); - this.bgMat.setProperty('percent', 1.0); - this.bgMat.setProperty('u_projection', this.projection); - this.bgMat.passes[0].update(); + // update bg uniform + if (this.settings.background!.type === 'custom') { + if (dw < dh) { + scaleX = dh * this.bgRatio; + scaleY = dh; + } else { + scaleX = dw; + scaleY = dw * this.bgRatio; + } + this.bgMat.setProperty('resolution', v2_0.set(dw, dh), 0); + this.bgMat.setProperty('scale', v2_0.set(scaleX, scaleY), 0); + this.bgMat.setProperty('translate', v2_0.set(dw * 0.5, dh * 0.5), 0); + this.bgMat.setProperty('percent', 1.0); + this.bgMat.setProperty('u_projection', this.projection); + this.bgMat.passes[0].update(); + } // update logo uniform - scaleX = 1; - scaleY = 1; - scaleX = this.logoWidth * this.scaleSize * settings.displayRatio; - scaleY = this.logoHeight * this.scaleSize * settings.displayRatio; const logoYTrans = dh * this.logoYTrans; - - this.logoMat.setProperty('resolution', v2_0.set(dw, dh), 0); - this.logoMat.setProperty('scale', v2_0.set(scaleX, scaleY), 0); - this.logoMat.setProperty('translate', v2_0.set(dw * this.logoXTrans, logoYTrans), 0); - this.logoMat.setProperty('percent', u_p); - this.logoMat.setProperty('u_projection', this.projection); - this.logoMat.passes[0].update(); + if (this.settings.logo!.type !== 'none') { + scaleX = this.logoWidth * this.scaleSize * settings.displayRatio; + scaleY = this.logoHeight * this.scaleSize * settings.displayRatio; + + this.logoMat.setProperty('resolution', v2_0.set(dw, dh), 0); + this.logoMat.setProperty('scale', v2_0.set(scaleX, scaleY), 0); + this.logoMat.setProperty('translate', v2_0.set(dw * this.logoXTrans, logoYTrans), 0); + this.logoMat.setProperty('percent', u_p); + this.logoMat.setProperty('u_projection', this.projection); + this.logoMat.passes[0].update(); + } // update watermark uniform - if (this.watermarkMat) { + if (this.settings.logo!.type === 'default' && this.watermarkMat) { const watermarkTW = this.watermarkTexture.width; const watermarkTH = this.watermarkTexture.height; scaleX = watermarkTW; scaleY = watermarkTH; @@ -406,8 +448,11 @@ export class SplashScreen { region.texExtent.height = watermarkImg.height; region.texExtent.depth = 1; this.watermarkTexture = this.device.createTexture(new TextureInfo( - TextureType.TEX2D, TextureUsageBit.SAMPLED | TextureUsageBit.TRANSFER_DST, - Format.RGBA8, watermarkImg.width, watermarkImg.height, + TextureType.TEX2D, + TextureUsageBit.SAMPLED | TextureUsageBit.TRANSFER_DST, + Format.RGBA8, + watermarkImg.width, + watermarkImg.height, )); this.device.copyTexImagesToTexture([watermarkImg], this.watermarkTexture, [region]); // create material @@ -431,13 +476,23 @@ export class SplashScreen { // device's fov may be asymmetry let radioLeft = 1.0; let radioRight = 1.0; - if (xrEye === XREye.LEFT) { - radioLeft = Math.abs(Math.tan(xrFov[0])) / Math.abs(Math.tan(xrFov[1])); - } else if (xrEye === XREye.RIGHT) { - radioRight = Math.abs(Math.tan(xrFov[1])) / Math.abs(Math.tan(xrFov[0])); + if (xrEye === XREye.LEFT as number) { + radioLeft = Math.abs(Math.tan(xrFov[0] as number)) / Math.abs(Math.tan(xrFov[1] as number)); + } else if (xrEye === XREye.RIGHT as number) { + radioRight = Math.abs(Math.tan(xrFov[1] as number)) / Math.abs(Math.tan(xrFov[0] as number)); } - Mat4.ortho(this.projection, -radioLeft, radioRight, -1, 1, -1, 1, device.capabilities.clipSpaceMinZ, - device.capabilities.clipSpaceSignY, swapchain.surfaceTransform); + Mat4.ortho( + this.projection, + -radioLeft, + radioRight, + -1, + 1, + -1, + 1, + device.capabilities.clipSpaceMinZ, + device.capabilities.clipSpaceSignY, + swapchain.surfaceTransform, + ); // keep scale to [-1, 1] only use offset this.projection.m00 = preTransforms[swapchain.surfaceTransform][0]; this.projection.m05 = preTransforms[swapchain.surfaceTransform][3] * device.capabilities.clipSpaceSignY; @@ -457,7 +512,7 @@ export class SplashScreen { device.acquire([swapchain]); // record command const cmdBuff = this.cmdBuff; - const framebuffer = cclegacy.director.root!.mainWindow!.framebuffer; + const framebuffer = cclegacy.director.root!.mainWindow!.framebuffer as Framebuffer; const renderArea = this.renderArea; renderArea.width = swapchain.width; @@ -466,28 +521,48 @@ export class SplashScreen { cmdBuff.begin(); cmdBuff.beginRenderPass(framebuffer.renderPass, framebuffer, renderArea, this.clearColors, 1.0, 0); - const bgPass = this.bgMat.passes[0]; - const bgPso = PipelineStateManager.getOrCreatePipelineState(device, bgPass, this.shader, framebuffer.renderPass, - this.quadAssmebler); - - cmdBuff.bindPipelineState(bgPso); - cmdBuff.bindDescriptorSet(SetIndex.MATERIAL, bgPass.descriptorSet); - cmdBuff.bindInputAssembler(this.quadAssmebler); - cmdBuff.draw(this.quadAssmebler); - - const logoPass = this.logoMat.passes[0]; - const logoPso = PipelineStateManager.getOrCreatePipelineState(device, logoPass, this.shader, framebuffer.renderPass, - this.quadAssmebler); + if (this.settings.background!.type === 'custom') { + const bgPass = this.bgMat.passes[0]; + const bgPso = PipelineStateManager.getOrCreatePipelineState( + device, + bgPass, + this.shader, + framebuffer.renderPass, + this.quadAssmebler, + ); + + cmdBuff.bindPipelineState(bgPso); + cmdBuff.bindDescriptorSet(SetIndex.MATERIAL, bgPass.descriptorSet); + cmdBuff.bindInputAssembler(this.quadAssmebler); + cmdBuff.draw(this.quadAssmebler); + } - cmdBuff.bindPipelineState(logoPso); - cmdBuff.bindDescriptorSet(SetIndex.MATERIAL, logoPass.descriptorSet); - cmdBuff.bindInputAssembler(this.quadAssmebler); - cmdBuff.draw(this.quadAssmebler); + if (this.settings.logo!.type !== 'none') { + const logoPass = this.logoMat.passes[0]; + const logoPso = PipelineStateManager.getOrCreatePipelineState( + device, + logoPass, + this.shader, + framebuffer.renderPass, + this.quadAssmebler, + ); + + cmdBuff.bindPipelineState(logoPso); + cmdBuff.bindDescriptorSet(SetIndex.MATERIAL, logoPass.descriptorSet); + cmdBuff.bindInputAssembler(this.quadAssmebler); + cmdBuff.draw(this.quadAssmebler); + } - if (this.watermarkMat) { + if (this.settings.logo!.type === 'default' && this.watermarkMat) { const wartermarkPass = this.watermarkMat.passes[0]; - const watermarkPso = PipelineStateManager.getOrCreatePipelineState(device, - wartermarkPass, this.shader, framebuffer.renderPass, this.quadAssmebler); + const watermarkPso = PipelineStateManager.getOrCreatePipelineState( + device, + wartermarkPass, + this.shader, + framebuffer.renderPass, + this.quadAssmebler, + ); + cmdBuff.bindPipelineState(watermarkPso); cmdBuff.bindDescriptorSet(SetIndex.MATERIAL, wartermarkPass.descriptorSet); cmdBuff.bindInputAssembler(this.quadAssmebler); @@ -512,21 +587,25 @@ export class SplashScreen { this.device = null!; this.swapchain = null!; this.clearColors = null!; - if ((this.bgImage as any).destroy) (this.bgImage as any).destroy(); - this.bgImage = null!; - this.bgMat.destroy(); - this.bgMat = null!; - this.bgTexture.destroy(); - this.bgTexture = null!; - if ((this.logoImage as any).destroy) (this.logoImage as any).destroy(); - this.logoImage = null!; + if (this.settings.background!.type === 'custom') { + if ((this.bgImage as any).destroy) (this.bgImage as any).destroy(); + this.bgImage = null!; + this.bgMat.destroy(); + this.bgMat = null!; + this.bgTexture.destroy(); + this.bgTexture = null!; + } + if (this.settings.logo!.type !== 'none') { + if ((this.logoImage as any).destroy) (this.logoImage as any).destroy(); + this.logoImage = null!; + this.logoMat.destroy(); + this.logoMat = null!; + this.logoTexture.destroy(); + this.logoTexture = null!; + } this.renderArea = null!; this.cmdBuff = null!; this.shader = null!; - this.logoMat.destroy(); - this.logoMat = null!; - this.logoTexture.destroy(); - this.logoTexture = null!; this.quadAssmebler.destroy(); this.quadAssmebler = null!; this.vertexBuffers.destroy(); @@ -536,7 +615,7 @@ export class SplashScreen { this.sampler = null!; /** text */ - if (this.watermarkTexture) { + if (this.settings.logo!.type === 'default' && this.watermarkTexture) { this.watermarkMat.destroy(); this.watermarkMat = null!; this.watermarkTexture.destroy(); @@ -554,7 +633,7 @@ export class SplashScreen { } return SplashScreen._ins; } - + // eslint-disable-next-line no-empty-function private constructor () {} } diff --git a/templates/wechatgame/first-screen.ejs b/templates/wechatgame/first-screen.ejs index 1e25ee187fe..1025e60e115 100644 --- a/templates/wechatgame/first-screen.ejs +++ b/templates/wechatgame/first-screen.ejs @@ -27,9 +27,14 @@ void main() { const FS_BG = ` precision mediump float; uniform sampler2D u_Sampler; +uniform float u_flip; varying vec2 v_TexCoord; void main() { - gl_FragColor = texture2D(u_Sampler, v_TexCoord); + vec2 texCoord = v_TexCoord; + if(u_flip > 0.5) { + texCoord.y = 1.0 - texCoord.y; + } + gl_FragColor = texture2D(u_Sampler, texCoord); }`; const VS_PROGRESSBAR = ` @@ -82,7 +87,14 @@ let progress = 0.0; let progressBarColor = [61 / 255, 197 / 255, 222 / 255, 1]; let progressBackground = [100 / 255, 111 / 255, 118 / 255, 1]; let afterTick = null; +let backgroundFilp = 1.0; // set 0 to not flip let displayRatio = <%= displayRatio%>; +let bgColor = [<%= bgColor%>]; +let useCustomBg = <%= useCustomBg%>; +let useLogo = <%= useLogo%>; +let useDefaultLogo = <%= useDefaultLogo%>; +let logoName = '<%= logoName %>'; +let bgName = '<%= bgName %>'; function initShaders(vshader, fshader) { return createProgram(vshader, fshader); @@ -333,6 +345,8 @@ function drawTexture(gl, program, texture, vertexBuffer, vertexFormatLength) { gl.bindTexture(gl.TEXTURE_2D, texture); var uSampler = gl.getUniformLocation(program, 'u_Sampler'); gl.uniform1i(uSampler, 0); + var uFlip = gl.getUniformLocation(program, 'u_flip'); + gl.uniform1f(uFlip, backgroundFilp); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); var aPosition = gl.getAttribLocation(program, 'a_Position'); gl.enableVertexAttribArray(aPosition); @@ -363,20 +377,16 @@ function drawProgressBar(gl, program, vertexBuffer, vertexFormatLength, progress } function draw() { - gl.disable(gl.SCISSOR_TEST); - gl.disable(gl.CULL_FACE); - gl.disable(gl.DEPTH_TEST); - gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); - gl.clearColor(0.0, 0.0, 0.0, 0.0); + gl.clearColor(bgColor[0], bgColor[1], bgColor[2], bgColor[3]); gl.clear(gl.COLOR_BUFFER_BIT); // draw background - drawTexture(gl, programBg, bgTexture, bgVertexBuffer, 4); + useCustomBg && drawTexture(gl, programBg, bgTexture, bgVertexBuffer, 4); // draw logo - drawTexture(gl, program, logoTexture, vertexBuffer, 4); + useLogo && drawTexture(gl, program, logoTexture, vertexBuffer, 4); // draw slogan - drawTexture(gl, program, sloganTexture, sloganVertexBuffer, 4); + useLogo && useDefaultLogo && drawTexture(gl, program, sloganTexture, sloganVertexBuffer, 4); // draw progress bar drawProgressBar(gl, programProgress, vertexBufferProgress, 3, progress, progressBarColor, progressBackground); } @@ -398,12 +408,12 @@ function end() { gl.useProgram(null); gl.bindTexture(gl.TEXTURE_2D, null); gl.bindBuffer(gl.ARRAY_BUFFER, null); - gl.deleteTexture(logoTexture); - gl.deleteTexture(sloganTexture); - gl.deleteTexture(bgTexture); + useLogo && gl.deleteTexture(logoTexture); + useLogo && useDefaultLogo && gl.deleteTexture(sloganTexture); + useCustomBg && gl.deleteTexture(bgTexture); gl.deleteBuffer(vertexBuffer); - gl.deleteBuffer(bgVertexBuffer); - gl.deleteBuffer(sloganVertexBuffer); + useCustomBg && gl.deleteBuffer(bgVertexBuffer); + useLogo && useDefaultLogo && gl.deleteBuffer(sloganVertexBuffer); gl.deleteBuffer(vertexBufferProgress); gl.deleteProgram(program); gl.deleteProgram(programBg); @@ -434,30 +444,35 @@ function start(alpha, antialias, useWebgl2) { gl = window.canvas.getContext("webgl", options); } initVertexBuffer(); - initBgVertexBuffer(); - initSloganVertexBuffer(); + useCustomBg && initBgVertexBuffer(); + useLogo && useDefaultLogo && initSloganVertexBuffer(); initProgressVertexBuffer(); initLogoTexture(); - initBgTexture(); - initSloganTexture(); + useCustomBg && initBgTexture(); + useLogo && useDefaultLogo && initSloganTexture(); - program = initShaders(VS_LOGO, FS_LOGO); - programBg = initShaders(VS_BG, FS_BG); + if (useLogo) { + program = initShaders(VS_LOGO, FS_LOGO); + } + if (useCustomBg) { + programBg = initShaders(VS_BG, FS_BG); + } programProgress = initShaders(VS_PROGRESSBAR, FS_PROGRESSBAR); tick(); + return Promise.all([ //logo should be loaded earlier than slogan - loadImage('logo.png').then(() => { + useLogo && loadImage(logoName).then(() => { updateVertexBuffer(); updateLogoTexture(); }).then(() => { - return loadSlogan('slogan.png').then(() => { + return useLogo && useDefaultLogo && loadSlogan('slogan.png').then(() => { updateSloganVertexBuffer(); updateSloganTexture(); }); }), - loadBackground('background.png').then(() => { + useCustomBg && loadBackground(bgName).then(() => { updateBgVertexBuffer(); updateBgTexture(); }) From 3c6a84934e0df9b3474921c64a7d675ec84754f9 Mon Sep 17 00:00:00 2001 From: PP Date: Thu, 3 Aug 2023 10:29:33 +0800 Subject: [PATCH 049/184] fix some bugs for cyberpunk demo on OH platform (#15846) * fix: bug on Destructuring Assignment syntax on OH * [AOT] workaround skip Storage type checking on OH * reuse fullscreen on OH platform --- .../marionette/animation-graph-animation-clip-binding.ts | 4 +++- cocos/core/platform/sys.ts | 7 +++++-- .../entry/src/main/ets/MainAbility/MainAbility.ts | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/cocos/animation/marionette/animation-graph-animation-clip-binding.ts b/cocos/animation/marionette/animation-graph-animation-clip-binding.ts index 298a61777a5..0c2ab2d0297 100644 --- a/cocos/animation/marionette/animation-graph-animation-clip-binding.ts +++ b/cocos/animation/marionette/animation-graph-animation-clip-binding.ts @@ -356,8 +356,10 @@ class AnimationClipAGEvaluationRegular implements AnimationClipAGEvaluation { const { tracks, - [exoticAnimationTag]: exoticAnimation, + // NOTE: on OH platform, there is a bug on Destructuring Assignment syntax. + // [exoticAnimationTag]: exoticAnimation, } = clip; + const exoticAnimation = clip[exoticAnimationTag]; for (const track of tracks) { if (track instanceof UntypedTrack) { diff --git a/cocos/core/platform/sys.ts b/cocos/core/platform/sys.ts index 8c475705488..3a6dbeebcb6 100644 --- a/cocos/core/platform/sys.ts +++ b/cocos/core/platform/sys.ts @@ -33,6 +33,9 @@ import { warnID, log } from './debug'; import { NetworkType, Language, OS, Platform, BrowserType, Feature } from '../../../pal/system-info/enum-type'; import { screen } from './screen'; +// TODO: the type Storage conflicts with the one on OH platform. +type Storage = any; + export declare namespace sys { /** * @en @@ -292,7 +295,7 @@ export const sys = { * @zh 尝试打开一个 web 页面,并非在所有平台都有效。 * @param url @zh 访问的链接。 @en Visited links. */ - openURL (url): void { + openURL (url: string): void { systemInfo.openURL(url); }, @@ -304,7 +307,7 @@ export const sys = { .then((): any => systemInfo.init()) .then((): void => { try { - let localStorage: Storage | null = sys.localStorage = window.localStorage; + let localStorage: Storage = sys.localStorage = window.localStorage; localStorage.setItem('storage', ''); localStorage.removeItem('storage'); localStorage = null; diff --git a/templates/openharmony/entry/src/main/ets/MainAbility/MainAbility.ts b/templates/openharmony/entry/src/main/ets/MainAbility/MainAbility.ts index 5f9c7db98b5..51b6bbd2d4f 100644 --- a/templates/openharmony/entry/src/main/ets/MainAbility/MainAbility.ts +++ b/templates/openharmony/entry/src/main/ets/MainAbility/MainAbility.ts @@ -61,9 +61,9 @@ export default class MainAbility extends UIAbility { } }); // Set full screen - //windowStage.getMainWindow().then((window: window.Window) => { - // window.setFullScreen(true); - //}); + windowStage.getMainWindow().then((window: window.Window) => { + window.setWindowSystemBarEnable([]); + }); nativeContext.writablePathInit(this.context.cacheDir); } From c7195e8cf636f1e54f44f413d1fa3dbdb8a8febe Mon Sep 17 00:00:00 2001 From: dogeFu <609075410@qq.com> Date: Fri, 4 Aug 2023 10:48:43 +0800 Subject: [PATCH 050/184] fix 2d particle and tiledMap prefab position problem (#15836) --- editor/assets/default_prefab/ui/ParticleSystem2D.prefab | 6 +++--- editor/assets/default_prefab/ui/TiledMap.prefab | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/editor/assets/default_prefab/ui/ParticleSystem2D.prefab b/editor/assets/default_prefab/ui/ParticleSystem2D.prefab index 673afadd40f..9f7c9901cff 100644 --- a/editor/assets/default_prefab/ui/ParticleSystem2D.prefab +++ b/editor/assets/default_prefab/ui/ParticleSystem2D.prefab @@ -31,9 +31,9 @@ }, "_lpos": { "__type__": "cc.Vec3", - "x": -480, - "y": -320, - "z": -1 + "x": 0, + "y": 0, + "z": 0 }, "_lrot": { "__type__": "cc.Quat", diff --git a/editor/assets/default_prefab/ui/TiledMap.prefab b/editor/assets/default_prefab/ui/TiledMap.prefab index 853e6d0571f..dc0ee1acdb6 100644 --- a/editor/assets/default_prefab/ui/TiledMap.prefab +++ b/editor/assets/default_prefab/ui/TiledMap.prefab @@ -31,8 +31,8 @@ }, "_lpos": { "__type__": "cc.Vec3", - "x": -480, - "y": -320, + "x": 0, + "y": 0, "z": 0 }, "_lrot": { From 31324e5c658f91138e9ebf9e2cee5b5f77a7beb1 Mon Sep 17 00:00:00 2001 From: dogeFu <609075410@qq.com> Date: Fri, 4 Aug 2023 10:49:17 +0800 Subject: [PATCH 051/184] cancel restore prefab undo record (#15808) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix : prefab undo problems removed/apply components undo; revert-prefab undo; * 还原部分不需要的undo * fix : node._instantiate has different behavior in native scene * Revert "fix : node._instantiate has different behavior in native scene" This reverts commit a896450198ff466cf32c8a72888b082ce40818fa. * remove reset prefab undo record --- editor/inspector/contributions/node.js | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/editor/inspector/contributions/node.js b/editor/inspector/contributions/node.js index bf17bebb444..07504266776 100644 --- a/editor/inspector/contributions/node.js +++ b/editor/inspector/contributions/node.js @@ -643,20 +643,6 @@ const Elements = { const role = button.getAttribute('role'); - const recordings = []; - for (const dump of panel.dumps) { - const prefab = dump.__prefab__; - switch (role) { - case 'reset': { - recordings.push(prefab.rootUuid); - } - } - } - let undoID; - if (recordings.length) { - undoID = await beginRecording(recordings); - } - for (const dump of panel.dumps) { const prefab = dump.__prefab__; @@ -688,10 +674,6 @@ const Elements = { } } } - - if (recordings.length && undoID) { - await endRecording(undoID); - } }); }, async update() { From c6cc635840e70566ebf0a98755763f21790a0e73 Mon Sep 17 00:00:00 2001 From: dogeFu <609075410@qq.com> Date: Fri, 4 Aug 2023 10:53:07 +0800 Subject: [PATCH 052/184] fix: terrain data lost when open prefab in editor (#15841) * fix: terrain data lost when open prefab in editor * fix spell error and eslint check failed --- cocos/terrain/terrain.ts | 140 ++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 62 deletions(-) diff --git a/cocos/terrain/terrain.ts b/cocos/terrain/terrain.ts index 66855790fda..d5e3e6c1ff1 100644 --- a/cocos/terrain/terrain.ts +++ b/cocos/terrain/terrain.ts @@ -23,6 +23,7 @@ */ import { ccclass, disallowMultiple, executeInEditMode, help, visible, type, serializable, editable, disallowAnimation } from 'cc.decorator'; +import { EDITOR } from 'internal:constants'; import { builtinResMgr } from '../asset/asset-manager'; import { ModelRenderer } from '../misc/model-renderer'; import { EffectAsset, Texture2D } from '../asset/assets'; @@ -32,7 +33,7 @@ import { RenderingSubMesh } from '../asset/assets/rendering-sub-mesh'; import { Component } from '../scene-graph/component'; import { CCObject, isValid } from '../core/data/object'; import { director } from '../game/director'; -import { AttributeName, BufferUsageBit, Format, MemoryUsageBit, PrimitiveMode, Attribute, Buffer, BufferInfo, deviceManager } from '../gfx'; +import { AttributeName, BufferUsageBit, Format, MemoryUsageBit, PrimitiveMode, Attribute, Buffer, BufferInfo, deviceManager, Texture } from '../gfx'; import { clamp, Rect, Size, Vec2, Vec3, Vec4 } from '../core/math'; import { MacroRecord } from '../render-scene/core/pass-utils'; import { Pass, scene } from '../render-scene'; @@ -293,7 +294,7 @@ class TerrainRenderable extends ModelRenderer { return false; } - /** + /** * @deprecated since v3.5.0, this is an engine private interface that will be removed in the future. */ public _updateLightingmap (texture: Texture2D | null, uvParam: Vec4): void { @@ -445,8 +446,14 @@ export class TerrainBlock { new Attribute(AttributeName.ATTR_TEX_COORD, Format.RG32F), ]; - this._renderable._meshData = new RenderingSubMesh([vertexBuffer], gfxAttributes, - PrimitiveMode.TRIANGLE_LIST, this._terrain._getSharedIndexBuffer(), null, false); + this._renderable._meshData = new RenderingSubMesh( + [vertexBuffer], + gfxAttributes, + PrimitiveMode.TRIANGLE_LIST, + this._terrain._getSharedIndexBuffer(), + null, + false, + ); this._renderable._model = (legacyCC.director.root as Root).createModel(scene.Model); this._renderable._model.createBoundingShape(this._bbMin, this._bbMax); this._renderable._model.node = this._renderable._model.transform = this._node; @@ -455,7 +462,7 @@ export class TerrainBlock { this.visible = true; } - // reset weightmap + // reset weightMap this._updateWeightMap(); // reset material @@ -507,7 +514,7 @@ export class TerrainBlock { const getNormalTex = (layer: TerrainLayer|null): Texture2D | null => { let normalTex = layer !== null ? layer.normalMap : null; if (normalTex === null) { - normalTex = legacyCC.builtinResMgr.get('normal-texture'); + normalTex = builtinResMgr.get('normal-texture'); } return normalTex; @@ -515,12 +522,12 @@ export class TerrainBlock { const mtl = this._renderable._currentMaterial; if (mtl !== null) { - const nlayers = this.getMaxLayer(); + const nLayers = this.getMaxLayer(); const uvScale = new Vec4(1, 1, 1, 1); const roughness = new Vec4(1, 1, 1, 1); const metallic = new Vec4(0, 0, 0, 0); - if (nlayers === 0) { + if (nLayers === 0) { if (this.layers[0] !== -1) { const l0 = this._terrain.getLayer(this.layers[0]); @@ -535,12 +542,12 @@ export class TerrainBlock { mtl.setProperty('normalMap0', getNormalTex(l0)); } } else { - mtl.setProperty('detailMap0', legacyCC.builtinResMgr.get('default-texture')); + mtl.setProperty('detailMap0', builtinResMgr.get('default-texture')); if (useNormalMap) { - mtl.setProperty('normalMap0', legacyCC.builtinResMgr.get('normal-texture')); + mtl.setProperty('normalMap0', builtinResMgr.get('normal-texture')); } } - } else if (nlayers === 1) { + } else if (nLayers === 1) { const l0 = this._terrain.getLayer(this.layers[0]); const l1 = this._terrain.getLayer(this.layers[1]); @@ -562,7 +569,7 @@ export class TerrainBlock { mtl.setProperty('normalMap0', getNormalTex(l0)); mtl.setProperty('normalMap1', getNormalTex(l1)); } - } else if (nlayers === 2) { + } else if (nLayers === 2) { const l0 = this._terrain.getLayer(this.layers[0]); const l1 = this._terrain.getLayer(this.layers[1]); const l2 = this._terrain.getLayer(this.layers[2]); @@ -592,7 +599,7 @@ export class TerrainBlock { mtl.setProperty('normalMap1', getNormalTex(l1)); mtl.setProperty('normalMap2', getNormalTex(l2)); } - } else if (nlayers === 3) { + } else if (nLayers === 3) { const l0 = this._terrain.getLayer(this.layers[0]); const l1 = this._terrain.getLayer(this.layers[1]); const l2 = this._terrain.getLayer(this.layers[2]); @@ -853,7 +860,7 @@ export class TerrainBlock { return 0; } - public _getMaterialDefines (nlayers: number): MacroRecord { + public _getMaterialDefines (nLayers: number): MacroRecord { let lightmapMacroValue = 1; /*static*/ if (this._terrain.node && this._terrain.node.scene) { if (this._terrain.node.scene.globals.bakedWithStationaryMainLight) { @@ -861,7 +868,7 @@ export class TerrainBlock { } } return { - LAYERS: nlayers + 1, + LAYERS: nLayers + 1, CC_USE_LIGHTMAP: this.lightmap !== null ? lightmapMacroValue : 0, USE_NORMALMAP: this._terrain.useNormalMap ? 1 : 0, USE_PBR: this._terrain.usePBR ? 1 : 0, @@ -903,9 +910,9 @@ export class TerrainBlock { } public _updateWeightMap (): void { - const nlayers = this.getMaxLayer(); + const nLayers = this.getMaxLayer(); - if (nlayers === 0) { + if (nLayers === 0) { if (this._weightMap != null) { this._weightMap.destroy(); this._weightMap = null; @@ -1047,18 +1054,18 @@ export class TerrainBlock { return verts[idx * TERRAIN_BLOCK_VERTEX_SIZE + 1]; } - private _updateLodBuffer (vertecs: Float32Array): void { + private _updateLodBuffer (vertices: Float32Array): void { this._lodLevel = 0; this._lodKey = new TerrainLodKey(); - this._calcErrorMetrics(vertecs); - this._calcLevelDistances(vertecs); + this._calcErrorMetrics(vertices); + this._calcLevelDistances(vertices); } - private _calcErrorMetrics (vertecs: Float32Array): void { + private _calcErrorMetrics (vertices: Float32Array): void { this._errorMetrics[0] = 0; for (let i = 1; i < TERRAIN_LOD_LEVELS; ++i) { - this._errorMetrics[i] = this._calcErrorMetric(i, vertecs); + this._errorMetrics[i] = this._calcErrorMetric(i, vertices); } for (let i = 2; i < TERRAIN_LOD_LEVELS; ++i) { @@ -1066,23 +1073,23 @@ export class TerrainBlock { } } - private _calcErrorMetric (level: number, vertecs: Float32Array): number { + private _calcErrorMetric (level: number, vertices: Float32Array): number { let err = 0.0; const step = 1 << level; - const xSectionVerts = TERRAIN_BLOCK_VERTEX_COMPLEXITY; - const ySectionVerts = TERRAIN_BLOCK_VERTEX_COMPLEXITY; - const xSides = (xSectionVerts - 1) >> level; - const ySides = (ySectionVerts - 1) >> level; + const xSectionVertices = TERRAIN_BLOCK_VERTEX_COMPLEXITY; + const ySectionVertices = TERRAIN_BLOCK_VERTEX_COMPLEXITY; + const xSides = (xSectionVertices - 1) >> level; + const ySides = (ySectionVertices - 1) >> level; - for (let y = 0; y < ySectionVerts; y += step) { + for (let y = 0; y < ySectionVertices; y += step) { for (let x = 0; x < xSides; ++x) { const x0 = x * step; const x1 = x0 + step; const xm = (x1 + x0) / 2; - const h0 = this._getHeight(x0, y, vertecs); - const h1 = this._getHeight(x1, y, vertecs); - const hm = this._getHeight(xm, y, vertecs); + const h0 = this._getHeight(x0, y, vertices); + const h1 = this._getHeight(x1, y, vertices); + const hm = this._getHeight(xm, y, vertices); const hmi = (h0 + h1) / 2; const delta = Math.abs(hm - hmi); @@ -1091,15 +1098,15 @@ export class TerrainBlock { } } - for (let x = 0; x < xSectionVerts; x += step) { + for (let x = 0; x < xSectionVertices; x += step) { for (let y = 0; y < ySides; ++y) { const y0 = y * step; const y1 = y0 + step; const ym = (y0 + y1) / 2; - const h0 = this._getHeight(x, y0, vertecs); - const h1 = this._getHeight(x, y1, vertecs); - const hm = this._getHeight(x, ym, vertecs); + const h0 = this._getHeight(x, y0, vertices); + const h1 = this._getHeight(x, y1, vertices); + const hm = this._getHeight(x, ym, vertices); const hmi = (h0 + h1) / 2; const delta = Math.abs(hm - hmi); @@ -1118,9 +1125,9 @@ export class TerrainBlock { const x1 = x0 + step; const xm = (x0 + x1) / 2; - const h0 = this._getHeight(x0, y0, vertecs); - const h1 = this._getHeight(x1, y1, vertecs); - const hm = this._getHeight(xm, ym, vertecs); + const h0 = this._getHeight(x0, y0, vertices); + const h1 = this._getHeight(x1, y1, vertices); + const hm = this._getHeight(xm, ym, vertices); const hmi = (h0 + h1) / 2; const delta = Math.abs(hm - hmi); @@ -1132,10 +1139,10 @@ export class TerrainBlock { return err; } - private _calcLevelDistances (vertecs: Float32Array): void { - const pixelerr = 4; + private _calcLevelDistances (vertices: Float32Array): void { + const pixelErr = 4; const resolution = 768; - const c = 1.0 / (2 * pixelerr / resolution); + const c = 1.0 / (2 * pixelErr / resolution); for (let i = 1; i < TERRAIN_LOD_LEVELS; ++i) { const e = this._errorMetrics[i]; @@ -1265,7 +1272,7 @@ export class Terrain extends Component { } this._blocks = []; - // restore to defualt + // restore to default if (this.__asset === null) { this._effectAsset = null; this._lightmapInfos = []; @@ -1829,6 +1836,9 @@ export class Terrain extends Component { public setHeight (i: number, j: number, h: number): void { h = clamp(h, TERRAIN_HEIGHT_FMIN, TERRAIN_HEIGHT_FMAX); this._heights[j * this.vertexCount[0] + i] = TERRAIN_HEIGHT_BASE + h / TERRAIN_HEIGHT_FACTORY; + if (EDITOR && this._asset) { + this._asset.heights[j * this.vertexCount[0] + i] = TERRAIN_HEIGHT_BASE + h / TERRAIN_HEIGHT_FACTORY; + } } /** @@ -1984,6 +1994,12 @@ export class Terrain extends Component { this._weights[index * 4 + 1] = w.y * 255; this._weights[index * 4 + 2] = w.z * 255; this._weights[index * 4 + 3] = w.w * 255; + if (EDITOR && this._asset) { + this._asset.weights[index * 4 + 0] = w.x * 255; + this._asset.weights[index * 4 + 1] = w.y * 255; + this._asset.weights[index * 4 + 2] = w.x * 255; + this._asset.weights[index * 4 + 3] = w.w * 255; + } } /** @@ -2007,14 +2023,14 @@ export class Terrain extends Component { * @zh 根据点的坐标获得权重 */ public getWeightAt (x: number, y: number): Vec4 | null { - const uWeigthComplexity = this.weightMapSize * this.blockCount[0]; - const vWeigthComplexity = this.weightMapSize * this.blockCount[1]; - if (uWeigthComplexity === 0 || vWeigthComplexity === 0) { + const uWeightComplexity = this.weightMapSize * this.blockCount[0]; + const vWeightComplexity = this.weightMapSize * this.blockCount[1]; + if (uWeightComplexity === 0 || vWeightComplexity === 0) { return null; } - const fx = x / uWeigthComplexity; - const fy = y / vWeigthComplexity; + const fx = x / uWeightComplexity; + const fy = y / vWeightComplexity; let ix0 = Math.floor(fx); let iz0 = Math.floor(fy); @@ -2023,14 +2039,14 @@ export class Terrain extends Component { const dx = fx - ix0; const dz = fy - iz0; - if (ix0 < 0 || ix0 > uWeigthComplexity - 1 || iz0 < 0 || iz0 > vWeigthComplexity - 1) { + if (ix0 < 0 || ix0 > uWeightComplexity - 1 || iz0 < 0 || iz0 > vWeightComplexity - 1) { return null; } - ix0 = clamp(ix0, 0, uWeigthComplexity - 1); - iz0 = clamp(iz0, 0, vWeigthComplexity - 1); - ix1 = clamp(ix1, 0, uWeigthComplexity - 1); - iz1 = clamp(iz1, 0, vWeigthComplexity - 1); + ix0 = clamp(ix0, 0, uWeightComplexity - 1); + iz0 = clamp(iz0, 0, vWeightComplexity - 1); + ix1 = clamp(ix1, 0, uWeightComplexity - 1); + iz1 = clamp(iz1, 0, vWeightComplexity - 1); let a = this.getWeight(ix0, iz0); const b = this.getWeight(ix1, iz0); @@ -2062,18 +2078,18 @@ export class Terrain extends Component { * @zh 根据点的坐标获得权重最大的纹理层 */ public getMaxWeightLayerAt (x: number, y: number): TerrainLayer | null { - const uWeigthComplexity = this.weightMapSize * this.blockCount[0]; - const vWeigthComplexity = this.weightMapSize * this.blockCount[1]; - if (uWeigthComplexity === 0 || vWeigthComplexity === 0) { + const uWeightComplexity = this.weightMapSize * this.blockCount[0]; + const vWeightComplexity = this.weightMapSize * this.blockCount[1]; + if (uWeightComplexity === 0 || vWeightComplexity === 0) { return null; } - const fx = x / uWeigthComplexity; - const fy = y / vWeigthComplexity; + const fx = x / uWeightComplexity; + const fy = y / vWeightComplexity; const ix0 = Math.floor(fx); const iz0 = Math.floor(fy); - if (ix0 < 0 || ix0 > uWeigthComplexity - 1 || iz0 < 0 || iz0 > vWeigthComplexity - 1) { + if (ix0 < 0 || ix0 > uWeightComplexity - 1 || iz0 < 0 || iz0 > vWeightComplexity - 1) { return null; } @@ -2295,9 +2311,9 @@ export class Terrain extends Component { /** * @deprecated since v3.5.0, this is an engine private interface that will be removed in the future. */ - public _resetLightmap (enble: boolean): void { + public _resetLightmap (enable: boolean): void { this._lightmapInfos.length = 0; - if (enble) { + if (enable) { for (let i = 0; i < this._blockCount[0] * this._blockCount[1]; ++i) { this._lightmapInfos.push(new TerrainBlockLightmapInfo()); } @@ -2310,12 +2326,12 @@ export class Terrain extends Component { public _updateLightmap (blockId: number, tex: Texture2D|null, uOff: number, vOff: number, uScale: number, vScale: number): void { if (tex) { // ensure the lightmap infos is initialized - if (this._lightmapInfos.length == 0) { + if (this._lightmapInfos.length === 0) { for (let i = 0; i < this._blockCount[0] * this._blockCount[1]; ++i) { this._lightmapInfos.push(new TerrainBlockLightmapInfo()); } } - } else if (this._lightmapInfos.length == 0) { + } else if (this._lightmapInfos.length === 0) { return; } From 1cbe27b4009629a2a2b08d3088621929b42d26d8 Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Fri, 4 Aug 2023 11:37:12 +0800 Subject: [PATCH 053/184] fix reflection probe affected by sky rotation (#15857) --- editor/assets/chunks/common/texture/cubemap.chunk | 10 ++++------ .../model-functions/standard-common.chunk | 2 ++ editor/assets/effects/advanced/glass.effect | 10 ++++++++++ editor/assets/effects/advanced/sky.effect | 3 ++- .../util/dcc/imported-specular-glossiness.effect | 11 ++++++----- 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/editor/assets/chunks/common/texture/cubemap.chunk b/editor/assets/chunks/common/texture/cubemap.chunk index 4cf105bcb20..4d310f151ac 100644 --- a/editor/assets/chunks/common/texture/cubemap.chunk +++ b/editor/assets/chunks/common/texture/cubemap.chunk @@ -36,6 +36,7 @@ float RoughnessToPerceptualRoughness(float roughness) #endif } + // for skybox IBL vec3 EnvReflection(samplerCube tex, vec3 R, float roughness, float mipCount) { // simulate GGX convolution #if !CC_SURFACES_USE_LEGACY_COMPATIBLE_LIGHTING && !CC_IBL_CONVOLUTED @@ -52,16 +53,13 @@ float RoughnessToPerceptualRoughness(float roughness) } + // for reflection probe vec3 EnvReflectionOfReflectionProbe(samplerCube tex, vec3 R, float roughness, float mipCount, bool isRGBE) { // simulate GGX convolution #if !CC_SURFACES_USE_LEGACY_COMPATIBLE_LIGHTING && !CC_IBL_CONVOLUTED roughness = RoughnessToPerceptualRoughness(roughness); #endif - vec3 rotationDir = RotationVecFromAxisY(R.xyz, cc_surfaceTransform.z, cc_surfaceTransform.w); - vec4 envmap = fragTextureLod(tex, rotationDir, roughness * (mipCount - 1.0)); - if (isRGBE) - return unpackRGBE(envmap); - else - return SRGBToLinear(envmap.rgb); + vec4 envmap = fragTextureLod(tex, R, roughness * (mipCount - 1.0)); + return isRGBE ? unpackRGBE(envmap) : SRGBToLinear(envmap.rgb); } diff --git a/editor/assets/chunks/lighting-models/model-functions/standard-common.chunk b/editor/assets/chunks/lighting-models/model-functions/standard-common.chunk index db9fb783137..78ab23eba1f 100644 --- a/editor/assets/chunks/lighting-models/model-functions/standard-common.chunk +++ b/editor/assets/chunks/lighting-models/model-functions/standard-common.chunk @@ -62,6 +62,7 @@ vec3 CalculateDirectSpecular(in LightingIntermediateData lightingData, in vec4 l } #endif +// for skybox IBL vec3 SampleEnvironmentSpecular(samplerCube tex, in LightingIntermediateData lightingData, float mipCount) { vec3 envSpec = vec3(0.0); @@ -84,6 +85,7 @@ vec3 SampleEnvironmentSpecular(samplerCube tex, in LightingIntermediateData ligh return envSpec; } +// for reflection probe vec3 SampleEnvironmentSpecular(samplerCube tex, in LightingIntermediateData lightingData, float mipCount, vec3 worldPos, vec3 cubeCenterPos, vec3 boxHalfSize, bool isRGBE) { vec3 envSpec = vec3(0.0); diff --git a/editor/assets/effects/advanced/glass.effect b/editor/assets/effects/advanced/glass.effect index 8fd1228902a..e16bf1878c1 100644 --- a/editor/assets/effects/advanced/glass.effect +++ b/editor/assets/effects/advanced/glass.effect @@ -87,6 +87,8 @@ CCEffect %{ - vert: standard-vs frag: standard-fs embeddedMacros: { CC_FORCE_FORWARD_SHADING: true } + rasterizerState: + cullMode: Front depthStencilState: &d1 depthTest: true depthWrite: false @@ -97,6 +99,14 @@ CCEffect %{ blendDst: one_minus_src_alpha blendDstAlpha: one_minus_src_alpha properties: *props + - vert: standard-vs + frag: standard-fs + embeddedMacros: { CC_FORCE_FORWARD_SHADING: true } + rasterizerState: + cullMode: Back + depthStencilState: *d1 + blendState: *b1 + properties: *props - *forward-add - *shadow-caster - *planar-shadow diff --git a/editor/assets/effects/advanced/sky.effect b/editor/assets/effects/advanced/sky.effect index b7e2e59ff2f..c2f5232529f 100644 --- a/editor/assets/effects/advanced/sky.effect +++ b/editor/assets/effects/advanced/sky.effect @@ -11,6 +11,7 @@ CCEffect %{ positionScaling: { value: 1.0, target: params.w, editor: { tooltip: 'Set a smaller value (such as less than 1.0) to remove the effects of fog' } } blendEnvironmentMap: { value: grey, editor: { parent: BLEND_ENV_MAP } } blendWeight: { value: 0.0, target: params.x, editor: { parent: BLEND_ENV_MAP } } + brightMultiplier: { value: 1.0, target: params.y } priority : max - 10 rasterizerState : &r1 cullMode : none @@ -69,7 +70,7 @@ CCProgram surface-fragment %{ c = mix(c, sampleEnvMap(blendEnvironmentMap, rotationDir), params.x); #endif #endif - return vec4(c * cc_ambientSky.w, 1.0); + return vec4(c * cc_ambientSky.w * params.y, 1.0); } }% diff --git a/editor/assets/effects/util/dcc/imported-specular-glossiness.effect b/editor/assets/effects/util/dcc/imported-specular-glossiness.effect index fe4565b98bc..3707e2168ba 100644 --- a/editor/assets/effects/util/dcc/imported-specular-glossiness.effect +++ b/editor/assets/effects/util/dcc/imported-specular-glossiness.effect @@ -15,12 +15,12 @@ CCEffect %{ emissiveMap: { value: grey } emissiveScale: { value: 1.0 } emissiveScaleMap: { value: grey } - shininessExponentMap: { value: grey, editor: { parent: '!HAS_EXPORTED_GLOSSINESS' } } - shininessExponent: { value: 100.0, editor: { parent: '!HAS_EXPORTED_GLOSSINESS' } } - specularGlossinessMap: { value: grey, editor: { parent: '!HAS_EXPORTED_GLOSSINESS' } } + shininessExponentMap: { value: grey } + shininessExponent: { value: 100.0 } + specularGlossinessMap: { value: grey } specularColor: { value: [0.0, 0.0, 0.0, 0.0], linear: true, editor: { displayName: SpecularColor, type: color } } - specularMap: { value: grey, editor: { parent: '!HAS_EXPORTED_METALLIC' } } - specularFactor: { value: 1.0, editor: { parent: '!HAS_EXPORTED_METALLIC' } } + specularMap: { value: grey } + specularFactor: { value: 1.0 } transparencyMap: { value: grey, editor: { displayName: TransparencyMap } } transparencyFactor: { value: 1.0, editor: { slide: true, range: [0, 1.0], step: 0.001 } } tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } @@ -81,6 +81,7 @@ CCEffect %{ blendSrc: src_alpha blendDst: one_minus_src_alpha blendDstAlpha: one_minus_src_alpha + properties: *props - *forward-add - *shadow-caster - &deferred-forward From b37b73a7b798810bd3660fa8e378567d4c9ac820 Mon Sep 17 00:00:00 2001 From: Jiujiang Liu <37231523+moshuying@users.noreply.github.com> Date: Fri, 4 Aug 2023 16:20:53 +0800 Subject: [PATCH 054/184] make allowDataAccess is only available at runtime. (#15835) * make allowDataAccess is only available at runtime. --- cocos/3d/assets/mesh.ts | 5 +++-- native/cocos/3d/assets/Mesh.cpp | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cocos/3d/assets/mesh.ts b/cocos/3d/assets/mesh.ts index 39b823bb07a..0ca33d88c63 100644 --- a/cocos/3d/assets/mesh.ts +++ b/cocos/3d/assets/mesh.ts @@ -23,6 +23,7 @@ */ import { ccclass, serializable } from 'cc.decorator'; +import { EDITOR } from 'internal:constants'; import { Asset } from '../../asset/assets/asset'; import { IDynamicGeometry } from '../../primitive/define'; import { BufferBlob } from '../misc/buffer-blob'; @@ -493,7 +494,7 @@ export class Mesh extends Asset { } this._isMeshDataUploaded = true; - if (!this._allowDataAccess) { + if (!this._allowDataAccess && !EDITOR) { this.releaseData(); } } @@ -1304,7 +1305,7 @@ export class Mesh extends Asset { */ public set allowDataAccess (allowDataAccess: boolean) { this._allowDataAccess = allowDataAccess; - if (this._isMeshDataUploaded && !this._allowDataAccess) { + if (this._isMeshDataUploaded && !this._allowDataAccess && !EDITOR) { this.releaseData(); } } diff --git a/native/cocos/3d/assets/Mesh.cpp b/native/cocos/3d/assets/Mesh.cpp index 588247e8d78..e0b2034f89c 100644 --- a/native/cocos/3d/assets/Mesh.cpp +++ b/native/cocos/3d/assets/Mesh.cpp @@ -439,9 +439,11 @@ void Mesh::initialize() { } _isMeshDataUploaded = true; +#if !CC_EDITOR if (!_allowDataAccess) { releaseData(); } +#endif } } @@ -1260,9 +1262,11 @@ void Mesh::initDefault(const ccstd::optional &uuid) { void Mesh::setAllowDataAccess(bool allowDataAccess) { _allowDataAccess = allowDataAccess; +#if !CC_EDITOR if (_isMeshDataUploaded && !_allowDataAccess) { releaseData(); } +#endif } void Mesh::releaseData() { From 6fec3201fd39c8d2dc2425ea3e195fd5037ffc25 Mon Sep 17 00:00:00 2001 From: Canvas Date: Mon, 7 Aug 2023 10:23:34 +0800 Subject: [PATCH 055/184] fix spine-skeleton-instance.cpp 3.8.0 -> 3.8.1 missing code issue. (#15876) --- .../spine-wasm/spine-type-export.cpp | 229 +++++++++--------- 1 file changed, 117 insertions(+), 112 deletions(-) diff --git a/native/cocos/editor-support/spine-wasm/spine-type-export.cpp b/native/cocos/editor-support/spine-wasm/spine-type-export.cpp index a574fc17fcc..b5c22169054 100644 --- a/native/cocos/editor-support/spine-wasm/spine-type-export.cpp +++ b/native/cocos/editor-support/spine-wasm/spine-type-export.cpp @@ -942,9 +942,11 @@ EMSCRIPTEN_BINDINGS(spine) { .constructor() .function("getDefaultMix", &AnimationStateData::getDefaultMix) .function("getSkeletonData", &AnimationStateData::getSkeletonData, allow_raw_pointers()) - .function("setMix", optional_override([](AnimationStateData &obj, std::string fromName, std::string toName, float duration) { - .function("setMixWith", optional_override([](AnimationStateData &obj, Animation *from, Animation *to, float duration) { return obj.setMix(from, to, duration); }), allow_raw_pointers()) - .function("getMix", &AnimationStateData::getMix, allow_raw_pointers()); + .function("setMix", optional_override([](AnimationStateData &obj, const std::string& fromName, const std::string& toName, float duration) { + return obj.setMix(STRING_STD2SP(fromName), STRING_STD2SP(toName), duration);})) + .function("setMixWith", optional_override([](AnimationStateData &obj, Animation* from, Animation* to, float duration) { + return obj.setMix(from, to, duration);}), allow_raw_pointers()) + .function("getMix", &AnimationStateData::getMix, allow_raw_pointers()); // .function("setMixWith", &Skeleton::setMixWith_Export) //.function("getMix", &Skeleton::setMix_Export); @@ -1071,116 +1073,119 @@ EMSCRIPTEN_BINDINGS(spine) { .function("setSkinByName", optional_override([](Skeleton &obj, const std::string& name) { return obj.setSkin(STRING_STD2SP(name));})) .function("setSkin", static_cast(&Skeleton::setSkin), allow_raw_pointer()) - .function("getAttachmentByName", optional_override([](Skeleton &obj, std::string slotName, std::string attachmentName) { - .function("getAttachment", optional_override([](Skeleton &obj, int slotIndex, std::string attachmentName) { - .function("setAttachment", optional_override([](Skeleton &obj, std::string slotName, std::string attachmentName) { - .function("findIkConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findIkConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findTransformConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findTransformConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findPathConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findPathConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - //.function("getBounds", &Skeleton::getBounds) - .function("update", &Skeleton::update); - - // incomplete - // class_("SkeletonBinary") - // .constructor() - // .function("setProp_scale", &SkeletonBinary::setScale); - //.function("getProp_scale", &SkeletonBinary::getScale) - //.function("readSkeletonData", &SkeletonBinary::readSkeletonData) - //.function("setCurve", &SkeletonBinary::setCurve); - // incomplete - - // class_("SkeletonJson") - // .constructor() - // .constructor(); - //.function("readSkeletonData", &SkeletonJson::readSkeletonData) - //.function("getProp_scale", &SkeletonJson::getScale) - - class_("VertexEffect") - .function("begin", &VertexEffect::begin, pure_virtual()) - //.function("transform", &VertexEffect::transform, pure_virtual()) - .function("end", &VertexEffect::end, pure_virtual()); - - class_>("JitterEffect") - .constructor() - .function("getJitterX", &JitterVertexEffect::getJitterX) - .function("setJitterX", &JitterVertexEffect::setJitterX) - .function("getJitterY", &JitterVertexEffect::getJitterY) - .function("setJitterY", &JitterVertexEffect::setJitterY) - .function("begin", &JitterVertexEffect::begin) - //.function("transform", &JitterVertexEffect::transform) - .function("end", &JitterVertexEffect::end); - - class_>("SwirlEffect") - .constructor() - .function("getCenterX", &SwirlVertexEffect::getCenterX) - .function("setCenterX", &SwirlVertexEffect::setCenterX) - .function("getCenterY", &SwirlVertexEffect::getCenterY) - .function("setCenterY", &SwirlVertexEffect::setCenterY) - .function("getRadius", &SwirlVertexEffect::getRadius) - .function("setRadius", &SwirlVertexEffect::setRadius) - .function("getAngle", &SwirlVertexEffect::getAngle) - .function("setAngle", &SwirlVertexEffect::setAngle) - .function("begin", &SwirlVertexEffect::begin) - //.function("transform", &SwirlVertexEffect::transform) - .function("end", &SwirlVertexEffect::end); - - class_("SlotMesh") - .property("vCount", &SlotMesh::vCount) - .property("iCount", &SlotMesh::iCount) - .property("blendMode", &SlotMesh::blendMode) - .property("textureID", &SlotMesh::textureID); - - register_vector("VectorSlotMesh"); - class_("SpineModel") - .property("vCount", &SpineModel::vCount) - .property("iCount", &SpineModel::iCount) - .property("vPtr", &SpineModel::vPtr) - .property("iPtr", &SpineModel::iPtr) - .function("getMeshes", &SpineModel::getMeshes); - - class_("SpineDebugShape") - .property("type", &SpineDebugShape::type) - .property("vOffset", &SpineDebugShape::vOffset) - .property("vCount", &SpineDebugShape::vCount) - .property("iOffset", &SpineDebugShape::iOffset) - .property("iCount", &SpineDebugShape::iCount); - - register_vector("VectorDebugShape"); - class_("SkeletonInstance") - .constructor<>() - .function("initSkeleton", &SpineSkeletonInstance::initSkeleton, allow_raw_pointers()) - .function("setAnimation", &SpineSkeletonInstance::setAnimation, allow_raw_pointers()) - .function("setSkin", &SpineSkeletonInstance::setSkin) - .function("updateAnimation", &SpineSkeletonInstance::updateAnimation) - .function("updateRenderData", &SpineSkeletonInstance::updateRenderData, allow_raw_pointer()) - .function("setPremultipliedAlpha", &SpineSkeletonInstance::setPremultipliedAlpha) - .function("setUseTint", &SpineSkeletonInstance::setUseTint) - .function("setColor", &SpineSkeletonInstance::setColor) - .function("setJitterEffect", &SpineSkeletonInstance::setJitterEffect, allow_raw_pointer()) - .function("setSwirlEffect", &SpineSkeletonInstance::setSwirlEffect, allow_raw_pointer()) - .function("clearEffect", &SpineSkeletonInstance::clearEffect) - .function("getAnimationState", &SpineSkeletonInstance::getAnimationState, allow_raw_pointer()) - .function("setMix", &SpineSkeletonInstance::setMix) - .function("setListener", &SpineSkeletonInstance::setListener) - .function("setDebugMode", &SpineSkeletonInstance::setDebugMode) - .function("getDebugShapes", &SpineSkeletonInstance::getDebugShapes) - .function("resizeSlotRegion", &SpineSkeletonInstance::resizeSlotRegion) - .function("setSlotTexture", &SpineSkeletonInstance::setSlotTexture); + .function("getAttachmentByName", optional_override([](Skeleton &obj, const std::string& slotName, const std::string& attachmentName) { + return obj.getAttachment(STRING_STD2SP(slotName), STRING_STD2SP(attachmentName));}), allow_raw_pointers()) + .function("getAttachment", optional_override([](Skeleton &obj, int slotIndex, const std::string& attachmentName) { + return obj.getAttachment(slotIndex, STRING_STD2SP(attachmentName));}),allow_raw_pointers()) + .function("setAttachment", optional_override([](Skeleton &obj, const std::string& slotName, const std::string& attachmentName) { + return obj.setAttachment(STRING_STD2SP(slotName), STRING_STD2SP(attachmentName));})) + .function("findIkConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findIkConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findTransformConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findTransformConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findPathConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findPathConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) + //.function("getBounds", &Skeleton::getBounds) + .function("update", &Skeleton::update); + + // incomplete + // class_("SkeletonBinary") + // .constructor() + // .function("setProp_scale", &SkeletonBinary::setScale); + //.function("getProp_scale", &SkeletonBinary::getScale) + //.function("readSkeletonData", &SkeletonBinary::readSkeletonData) + //.function("setCurve", &SkeletonBinary::setCurve); + // incomplete + + // class_("SkeletonJson") + // .constructor() + // .constructor(); + //.function("readSkeletonData", &SkeletonJson::readSkeletonData) + //.function("getProp_scale", &SkeletonJson::getScale) + + class_("VertexEffect") + .function("begin", &VertexEffect::begin, pure_virtual()) + //.function("transform", &VertexEffect::transform, pure_virtual()) + .function("end", &VertexEffect::end, pure_virtual()); + + class_>("JitterEffect") + .constructor() + .function("getJitterX", &JitterVertexEffect::getJitterX) + .function("setJitterX", &JitterVertexEffect::setJitterX) + .function("getJitterY", &JitterVertexEffect::getJitterY) + .function("setJitterY", &JitterVertexEffect::setJitterY) + .function("begin", &JitterVertexEffect::begin) + //.function("transform", &JitterVertexEffect::transform) + .function("end", &JitterVertexEffect::end); + + class_>("SwirlEffect") + .constructor() + .function("getCenterX", &SwirlVertexEffect::getCenterX) + .function("setCenterX", &SwirlVertexEffect::setCenterX) + .function("getCenterY", &SwirlVertexEffect::getCenterY) + .function("setCenterY", &SwirlVertexEffect::setCenterY) + .function("getRadius", &SwirlVertexEffect::getRadius) + .function("setRadius", &SwirlVertexEffect::setRadius) + .function("getAngle", &SwirlVertexEffect::getAngle) + .function("setAngle", &SwirlVertexEffect::setAngle) + .function("begin", &SwirlVertexEffect::begin) + //.function("transform", &SwirlVertexEffect::transform) + .function("end", &SwirlVertexEffect::end); + + class_("SlotMesh") + .property("vCount", &SlotMesh::vCount) + .property("iCount", &SlotMesh::iCount) + .property("blendMode", &SlotMesh::blendMode) + .property("textureID", &SlotMesh::textureID); + + register_vector("VectorSlotMesh"); + class_("SpineModel") + .property("vCount", &SpineModel::vCount) + .property("iCount", &SpineModel::iCount) + .property("vPtr", &SpineModel::vPtr) + .property("iPtr", &SpineModel::iPtr) + .function("getMeshes", &SpineModel::getMeshes); + + class_("SpineDebugShape") + .property("type", &SpineDebugShape::type) + .property("vOffset", &SpineDebugShape::vOffset) + .property("vCount", &SpineDebugShape::vCount) + .property("iOffset", &SpineDebugShape::iOffset) + .property("iCount", &SpineDebugShape::iCount); + + register_vector("VectorDebugShape"); + class_("SkeletonInstance") + .constructor<>() + .function("initSkeleton", &SpineSkeletonInstance::initSkeleton, allow_raw_pointers()) + .function("setAnimation", &SpineSkeletonInstance::setAnimation, allow_raw_pointers()) + .function("setSkin", &SpineSkeletonInstance::setSkin) + .function("updateAnimation", &SpineSkeletonInstance::updateAnimation) + .function("updateRenderData", &SpineSkeletonInstance::updateRenderData, allow_raw_pointer()) + .function("setPremultipliedAlpha", &SpineSkeletonInstance::setPremultipliedAlpha) + .function("setUseTint", &SpineSkeletonInstance::setUseTint) + .function("setColor", &SpineSkeletonInstance::setColor) + .function("setJitterEffect", &SpineSkeletonInstance::setJitterEffect, allow_raw_pointer()) + .function("setSwirlEffect", &SpineSkeletonInstance::setSwirlEffect, allow_raw_pointer()) + .function("clearEffect", &SpineSkeletonInstance::clearEffect) + .function("getAnimationState", &SpineSkeletonInstance::getAnimationState, allow_raw_pointer()) + .function("setMix", &SpineSkeletonInstance::setMix) + .function("setListener", &SpineSkeletonInstance::setListener) + .function("setDebugMode", &SpineSkeletonInstance::setDebugMode) + .function("getDebugShapes", &SpineSkeletonInstance::getDebugShapes) + .function("resizeSlotRegion", &SpineSkeletonInstance::resizeSlotRegion) + .function("setSlotTexture", &SpineSkeletonInstance::setSlotTexture); } EMSCRIPTEN_BINDINGS(cocos_spine) { - class_("SpineWasmUtil") - .class_function("spineWasmInit", &SpineWasmUtil::spineWasmInit) - .class_function("spineWasmDestroy", &SpineWasmUtil::spineWasmDestroy) - .class_function("queryStoreMemory", &SpineWasmUtil::queryStoreMemory) - .class_function("querySpineSkeletonDataByUUID", &SpineWasmUtil::querySpineSkeletonDataByUUID, allow_raw_pointers()) - .class_function("createSpineSkeletonDataWithJson", &SpineWasmUtil::createSpineSkeletonDataWithJson, allow_raw_pointers()) - .class_function("createSpineSkeletonDataWithBinary", &SpineWasmUtil::createSpineSkeletonDataWithBinary, allow_raw_pointers()) - .class_function("registerSpineSkeletonDataWithUUID", &SpineWasmUtil::registerSpineSkeletonDataWithUUID, allow_raw_pointers()) - .class_function("destroySpineSkeletonDataWithUUID", &SpineWasmUtil::destroySpineSkeletonDataWithUUID) - .class_function("destroySpineInstance", &SpineWasmUtil::destroySpineInstance, allow_raw_pointers()) - .class_function("getCurrentListenerID", &SpineWasmUtil::getCurrentListenerID) - .class_function("getCurrentEventType", &SpineWasmUtil::getCurrentEventType) - .class_function("getCurrentTrackEntry", &SpineWasmUtil::getCurrentTrackEntry, allow_raw_pointers()) - .class_function("getCurrentEvent", &SpineWasmUtil::getCurrentEvent, allow_raw_pointers()); + class_("SpineWasmUtil") + .class_function("spineWasmInit", &SpineWasmUtil::spineWasmInit) + .class_function("spineWasmDestroy", &SpineWasmUtil::spineWasmDestroy) + .class_function("queryStoreMemory", &SpineWasmUtil::queryStoreMemory) + .class_function("querySpineSkeletonDataByUUID", &SpineWasmUtil::querySpineSkeletonDataByUUID, allow_raw_pointers()) + .class_function("createSpineSkeletonDataWithJson", &SpineWasmUtil::createSpineSkeletonDataWithJson, allow_raw_pointers()) + .class_function("createSpineSkeletonDataWithBinary", &SpineWasmUtil::createSpineSkeletonDataWithBinary, allow_raw_pointers()) + .class_function("registerSpineSkeletonDataWithUUID", &SpineWasmUtil::registerSpineSkeletonDataWithUUID, allow_raw_pointers()) + .class_function("destroySpineSkeletonDataWithUUID", &SpineWasmUtil::destroySpineSkeletonDataWithUUID) + .class_function("destroySpineInstance", &SpineWasmUtil::destroySpineInstance, allow_raw_pointers()) + .class_function("getCurrentListenerID", &SpineWasmUtil::getCurrentListenerID) + .class_function("getCurrentEventType", &SpineWasmUtil::getCurrentEventType) + .class_function("getCurrentTrackEntry", &SpineWasmUtil::getCurrentTrackEntry, allow_raw_pointers()) + .class_function("getCurrentEvent", &SpineWasmUtil::getCurrentEvent, allow_raw_pointers()); } From a907d68d59071ae6061fd6a1f012068d3d108124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=88=98?= <40414978+PatriceJiang@users.noreply.github.com> Date: Mon, 7 Aug 2023 10:54:19 +0800 Subject: [PATCH 056/184] cmake/swig allow remove genereated/../temp directory (#15726) --- native/cmake/predefine.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/cmake/predefine.cmake b/native/cmake/predefine.cmake index bffb8619a7c..ad50d295355 100644 --- a/native/cmake/predefine.cmake +++ b/native/cmake/predefine.cmake @@ -301,7 +301,6 @@ function(cc_gen_swig_files cfg_directory output_dir) set(dep_files) get_filename_component(mod_name ${cfg} NAME_WE) - file(MAKE_DIRECTORY ${output_dir}/temp) set(output_file_tmp ${output_dir}/temp/jsb_${mod_name}_auto.cpp) set(output_file ${output_dir}/jsb_${mod_name}_auto.cpp) @@ -315,6 +314,7 @@ function(cc_gen_swig_files cfg_directory output_dir) ${output_hfile} ${output_file} COMMAND ${CMAKE_COMMAND} -E echo "Running swig with config file ${cfg} ..." + COMMAND ${CMAKE_COMMAND} -E make_directory ${output_dir}/temp COMMAND ${SWIG_EXEC} ${SWIG_ARGS} ${output_file_tmp} ${cfg} From 4b26cc878436e04aa89133073979878ba02b9062 Mon Sep 17 00:00:00 2001 From: troublemaker52025 Date: Mon, 7 Aug 2023 11:19:41 +0800 Subject: [PATCH 057/184] fix PipelineStateChanged updating issue by performance optimization (#15753) --- cocos/3d/framework/mesh-renderer.ts | 1 + cocos/render-scene/scene/submodel.ts | 17 +++++++++++++++++ native/cocos/scene/Define.h | 13 +++++++++++++ native/cocos/scene/SubModel.cpp | 15 +++++++++++++++ native/cocos/scene/SubModel.h | 1 + native/tools/swig-config/scene.i | 2 ++ 6 files changed, 49 insertions(+) diff --git a/cocos/3d/framework/mesh-renderer.ts b/cocos/3d/framework/mesh-renderer.ts index b1039d5e25a..8b277d23e4c 100644 --- a/cocos/3d/framework/mesh-renderer.ts +++ b/cocos/3d/framework/mesh-renderer.ts @@ -593,6 +593,7 @@ export class MeshRenderer extends ModelRenderer { if (!this._model) { this._updateModels(); } + this._model!.onGlobalPipelineStateChanged(); this._updateCastShadow(); this._updateReceiveShadow(); this._updateShadowBias(); diff --git a/cocos/render-scene/scene/submodel.ts b/cocos/render-scene/scene/submodel.ts index f2533ed7c26..a1e51f42617 100644 --- a/cocos/render-scene/scene/submodel.ts +++ b/cocos/render-scene/scene/submodel.ts @@ -32,6 +32,7 @@ import { DescriptorSet, DescriptorSetInfo, Device, InputAssembler, Texture, Text import { errorID, Mat4, cclegacy } from '../../core'; import { getPhaseID } from '../../rendering/pass-phase'; import { Root } from '../../root'; +import { MacroRecord } from '../core/pass-utils'; const _dsInfo = new DescriptorSetInfo(null!); const MAX_PASS_COUNT = 8; @@ -54,6 +55,7 @@ export class SubModel { protected _shaders: Shader[] | null = null; protected _subMesh: RenderingSubMesh | null = null; protected _patches: IMacroPatch[] | null = null; + protected _globalPatches: MacroRecord | null = null; protected _priority: RenderPriority = RenderPriority.DEFAULT; protected _inputAssembler: InputAssembler | null = null; protected _descriptorSet: DescriptorSet | null = null; @@ -294,6 +296,7 @@ export class SubModel { this.priority = RenderPriority.DEFAULT; this._patches = null; + this._globalPatches = null; this._subMesh = null; this._passes = null; @@ -324,6 +327,20 @@ export class SubModel { * @zh 管线更新回调 */ public onPipelineStateChanged (): void { + const root = cclegacy.director.root as Root; + const pipeline = root.pipeline; + const pipelinePatches = Object.entries(pipeline.macros); + if (!this._globalPatches && pipelinePatches.length === 0) { + return; + } else if (pipelinePatches.length) { + if (this._globalPatches && pipelinePatches.length === this._globalPatches.length) { + const globalPatches = Object.entries(this._globalPatches); + const patchesStateUnchanged = JSON.stringify(pipelinePatches.sort()) === JSON.stringify(globalPatches.sort()); + if (patchesStateUnchanged) return; + } + } + this._globalPatches = pipeline.macros; + const passes = this._passes; if (!passes) { return; } diff --git a/native/cocos/scene/Define.h b/native/cocos/scene/Define.h index 41920f1882e..e2cef2df8b2 100644 --- a/native/cocos/scene/Define.h +++ b/native/cocos/scene/Define.h @@ -24,6 +24,8 @@ #pragma once +#include + #include "base/std/container/string.h" #include "renderer/core/PassUtils.h" @@ -34,6 +36,17 @@ struct IMacroPatch { ccstd::string name; MacroValue value; + IMacroPatch() = default; + IMacroPatch(const ccstd::string& n, const MacroValue& v) { + name = n; + value = v; + } + + IMacroPatch(const std::pair& pair) { + name = pair.first; + value = pair.second; + } + bool operator==(const IMacroPatch& rhs) const { return rhs.name == name && rhs.value == value; } diff --git a/native/cocos/scene/SubModel.cpp b/native/cocos/scene/SubModel.cpp index d376bbdac5c..e244b169319 100644 --- a/native/cocos/scene/SubModel.cpp +++ b/native/cocos/scene/SubModel.cpp @@ -199,6 +199,7 @@ void SubModel::destroy() { _priority = pipeline::RenderPriority::DEFAULT; _patches.clear(); + _globalPatches.clear(); _subMesh = nullptr; _passes.reset(); _shaders.clear(); @@ -208,6 +209,20 @@ void SubModel::destroy() { } void SubModel::onPipelineStateChanged() { + const auto *pipeline = Root::getInstance()->getPipeline(); + ccstd::vector pipelinePatches(pipeline->getMacros().begin(), pipeline->getMacros().end()); + ccstd::vector globalPatches(_globalPatches.begin(), _globalPatches.end()); + if (pipelinePatches.empty() && globalPatches.empty()) { + return; + } + + std::sort(pipelinePatches.begin(), pipelinePatches.end(), IMacroPatch::compare); + std::sort(globalPatches.begin(), globalPatches.end(), IMacroPatch::compare); + if (std::equal(std::begin(pipelinePatches), std::end(pipelinePatches), std::begin(globalPatches), std::end(globalPatches))) { + return; + } + _globalPatches = pipeline->getMacros(); + const auto &passes = *_passes; if (passes.empty()) return; diff --git a/native/cocos/scene/SubModel.h b/native/cocos/scene/SubModel.h index 3f2104f803b..f92d9fffee4 100644 --- a/native/cocos/scene/SubModel.h +++ b/native/cocos/scene/SubModel.h @@ -114,6 +114,7 @@ class SubModel : public RefCounted { IntrusivePtr _subMesh; InstancedAttributeBlock _instancedAttributeBlock{}; + MacroRecord _globalPatches; ccstd::vector _patches; ccstd::vector> _shaders; diff --git a/native/tools/swig-config/scene.i b/native/tools/swig-config/scene.i index 73b03f4ddd3..6464584d826 100644 --- a/native/tools/swig-config/scene.i +++ b/native/tools/swig-config/scene.i @@ -105,6 +105,8 @@ using namespace cc; %ignore cc::Root::getEventProcessor; %ignore cc::Node::getEventProcessor; +%ignore cc::scene::IMacroPatch::IMacroPatch(const std::pair&); + %ignore cc::Node::setRTSInternal; %ignore cc::Node::setRTS; //FIXME: These methods binding code will generate SwigValueWrapper type which is not supported now. From b42a2faf6c15675bf033216e214144fc792827c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 7 Aug 2023 11:27:02 +0800 Subject: [PATCH 058/184] Optimize pack-manager for style&lint (#15872) * Optimize pack-manager for style&lint * Fix --- cocos/asset/asset-manager/pack-manager.ts | 59 +++++++++++++++-------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/cocos/asset/asset-manager/pack-manager.ts b/cocos/asset/asset-manager/pack-manager.ts index ae4275b2073..cab8fbc8aa7 100644 --- a/cocos/asset/asset-manager/pack-manager.ts +++ b/cocos/asset/asset-manager/pack-manager.ts @@ -25,17 +25,22 @@ import { ImageAsset } from '../assets/image-asset'; import { Texture2D } from '../assets/texture-2d'; import { packCustomObjData, unpackJSONs } from '../../serialization/deserialize'; -import { error, errorID, js } from '../../core'; +import { assertIsTrue, error, errorID, js } from '../../core'; import Cache from './cache'; import downloader from './downloader'; import { transform } from './helper'; import RequestItem from './request-item'; import { files } from './shared'; -export type Unpacker = (packUuid: string[], data: any, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)) => void; +export type Unpacker = ( + packUuid: string[], + data: any, + options: Record, + onComplete: ((err: Error | null, data?: any) => void), +) => void; interface IUnpackRequest { - onComplete: ((err: Error | null, data?: any | null) => void); + onComplete: ((err: Error | null, data?: any) => void); id: string; } @@ -73,12 +78,17 @@ export class PackManager { * }); * */ - public unpackJson (pack: string[], json: any, options: Record, onComplete: ((err: Error | null, data?: Record | null) => void)): void { - let out = js.createMap(true); + public unpackJson ( + pack: string[], + json: any, + options: Record, + onComplete: ((err: Error | null, data?: Record | null) => void), + ): void { + const out: Record = js.createMap(true); let err: Error | null = null; if (Array.isArray(json)) { - json = unpackJSONs(json as any); + json = unpackJSONs(json as unknown as Parameters[0]); if (json.length !== pack.length) { errorID(4915); @@ -107,7 +117,8 @@ export class PackManager { } } else { err = new Error('unmatched type pack!'); - out = null; + onComplete(err, null); + return; } } onComplete(err, out); @@ -170,7 +181,13 @@ export class PackManager { * }); * */ - public unpack (pack: string[], data: any, type: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)): void { + public unpack ( + pack: string[], + data: any, + type: string, + options: Record, + onComplete: ((err: Error | null, data?: any) => void), + ): void { if (!data) { onComplete(new Error('package data is wrong!')); return; @@ -200,7 +217,7 @@ export class PackManager { * packManager.load(requestItem, null, (err, data) => console.log(err)); * */ - public load (item: RequestItem, options: Record | null, onComplete: ((err: Error | null, data?: any | null) => void)): void { + public load (item: RequestItem, options: Record | null, onComplete: ((err: Error | null, data?: any) => void)): void { // if not in any package, download as uausl if (item.isNative || !item.info || !item.info.packs) { downloader.download(item.id, item.url, item.ext, item.options, onComplete); @@ -215,35 +232,39 @@ export class PackManager { const packs = item.info.packs; // find a loading package - let pack = packs.find((val): boolean => this._loading.has(val.uuid)); + const loadingPack = packs.find((val): boolean => this._loading.has(val.uuid)); - if (pack) { - this._loading.get(pack.uuid)!.push({ onComplete, id: item.id }); + if (loadingPack) { + const req = this._loading.get(loadingPack.uuid); + assertIsTrue(req); + req.push({ onComplete, id: item.id }); return; } // download a new package - pack = packs[0]; + const pack = packs[0]; this._loading.add(pack.uuid, [{ onComplete, id: item.id }]); // find the url of pack - const url = transform(pack.uuid, { ext: pack.ext, bundle: item.config!.name }) as string; + assertIsTrue(item.config); + const url = transform(pack.uuid, { ext: pack.ext, bundle: item.config.name }) as string; downloader.download(pack.uuid, url, pack.ext, item.options, (err, data): void => { - files.remove(pack!.uuid); + files.remove(pack.uuid); if (err) { error(err.message, err.stack); } // unpack package - this.unpack(pack!.packedUuids, data, pack!.ext, item.options, (err2, result): void => { + this.unpack(pack.packedUuids, data, pack.ext, item.options, (err2, result): void => { if (!err2) { for (const id in result) { files.add(id, result[id]); } } - const callbacks = this._loading.remove(pack!.uuid); - for (let i = 0, l = callbacks!.length; i < l; i++) { - const cb = callbacks![i]; + const callbacks = this._loading.remove(pack.uuid); + assertIsTrue(callbacks); + for (let i = 0, l = callbacks.length; i < l; i++) { + const cb = callbacks[i]; if (err || err2) { cb.onComplete(err || err2); continue; From 9f7bf8a8ebe96edd38d15b4d91cde206d9a1007e Mon Sep 17 00:00:00 2001 From: zhifenghu Date: Mon, 7 Aug 2023 13:41:48 +0800 Subject: [PATCH 059/184] =?UTF-8?q?Update=20utils.ts,=20replace=20the=20ra?= =?UTF-8?q?ndom=20function,=20to=20make=20particle=20scenes=E2=80=A6=20(#1?= =?UTF-8?q?5838)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update utils.ts, replace the random function, to make particle scenes support automated testing * core/math/utils.ts add method: setRandGenerator * core/math/utils.ts add method: setRandGenerator --------- Co-authored-by: 胡志锋 --- cocos/core/curves/gradient.ts | 6 +- cocos/core/math/utils.ts | 19 ++++++- cocos/particle-2d/particle-simulator-2d.ts | 58 ++++++++++---------- cocos/particle/animator/noise-module.ts | 6 +- cocos/particle/animator/texture-animation.ts | 12 ++-- 5 files changed, 57 insertions(+), 44 deletions(-) diff --git a/cocos/core/curves/gradient.ts b/cocos/core/curves/gradient.ts index 9ad938e15de..9d1b76ac11b 100644 --- a/cocos/core/curves/gradient.ts +++ b/cocos/core/curves/gradient.ts @@ -24,7 +24,7 @@ import { CCClass } from '../data'; import { Enum } from '../value-types'; -import { Color, lerp, repeat, EPSILON, approx } from '../math'; +import { Color, lerp, repeat, EPSILON, approx, random } from '../math'; const Mode = Enum({ Blend: 0, @@ -172,8 +172,8 @@ export class Gradient { * @returns @en Randomized color. @zh 随机生成的颜色。 */ public getRandomColor (out: Color): Color { - const c = this.colorKeys[Math.trunc(Math.random() * this.colorKeys.length)]; - const a = this.alphaKeys[Math.trunc(Math.random() * this.alphaKeys.length)]; + const c = this.colorKeys[Math.trunc(random() * this.colorKeys.length)]; + const a = this.alphaKeys[Math.trunc(random() * this.alphaKeys.length)]; out.set(c.color); out._set_a_unsafe(a.alpha); return out; diff --git a/cocos/core/math/utils.ts b/cocos/core/math/utils.ts index 0af2c7d624a..3b653aba193 100644 --- a/cocos/core/math/utils.ts +++ b/cocos/core/math/utils.ts @@ -31,6 +31,8 @@ const _d2r = Math.PI / 180.0; const _r2d = 180.0 / Math.PI; +let _random = Math.random; + export const HALF_PI = Math.PI * 0.5; export const TWO_PI = Math.PI * 2.0; @@ -121,7 +123,18 @@ export function toDegree (a: number): number { /** * @method random */ -export const random = Math.random; +export function random (): number { + return _random(); +} + +/** + * @en Set a custom random number generator, default to Math.random + * @zh 设置自定义随机数生成器,默认为 Math.random + * @param func custom random number generator + */ +export function setRandGenerator number> (func: TFunction): void { + _random = func; +} /** * @en Returns a floating-point random number between min (inclusive) and max (exclusive).
@@ -129,10 +142,10 @@ export const random = Math.random; * @method randomRange * @param min * @param max - * @return The random number. + * @return {Number} The random number. */ export function randomRange (min: number, max: number): number { - return Math.random() * (max - min) + min; + return random() * (max - min) + min; } /** diff --git a/cocos/particle-2d/particle-simulator-2d.ts b/cocos/particle-2d/particle-simulator-2d.ts index 2902322ea8a..96e68cf67b7 100644 --- a/cocos/particle-2d/particle-simulator-2d.ts +++ b/cocos/particle-2d/particle-simulator-2d.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { Vec2, Color, js, misc } from '../core'; +import { Vec2, Color, js, misc, random, IColorLike } from '../core'; import { vfmtPosUvColor, getComponentPerVertex } from '../2d/renderer/vertex-format'; import { PositionType, EmitterMode, START_SIZE_EQUAL_TO_END_SIZE, START_RADIUS_EQUAL_TO_END_RADIUS } from './define'; import { ParticleSystem2D } from './particle-system-2d'; @@ -150,12 +150,12 @@ export class Simulator { // Init particle // timeToLive // no negative life. prevent division by 0 - particle.timeToLive = psys.life + psys.lifeVar * (Math.random() - 0.5) * 2; + particle.timeToLive = psys.life + psys.lifeVar * (random() - 0.5) * 2; const timeToLive = particle.timeToLive = Math.max(0, particle.timeToLive); // position - particle.pos.x = psys.sourcePos.x + psys.posVar.x * (Math.random() - 0.5) * 2; - particle.pos.y = psys.sourcePos.y + psys.posVar.y * (Math.random() - 0.5) * 2; + particle.pos.x = psys.sourcePos.x + psys.posVar.x * (random() - 0.5) * 2; + particle.pos.y = psys.sourcePos.y + psys.posVar.y * (random() - 0.5) * 2; // Color let sr = 0; @@ -167,30 +167,30 @@ export class Simulator { const endColor = psys.endColor; const endColorVar = psys.endColorVar; - particle.color.r = sr = misc.clampf(startColor.r + startColorVar.r * (Math.random() - 0.5) * 2, 0, 255); - particle.color.g = sg = misc.clampf(startColor.g + startColorVar.g * (Math.random() - 0.5) * 2, 0, 255); - particle.color.b = sb = misc.clampf(startColor.b + startColorVar.b * (Math.random() - 0.5) * 2, 0, 255); - particle.color.a = sa = misc.clampf(startColor.a + startColorVar.a * (Math.random() - 0.5) * 2, 0, 255); - particle.deltaColor.r = (misc.clampf(endColor.r + endColorVar.r * (Math.random() - 0.5) * 2, 0, 255) - sr) / timeToLive; - particle.deltaColor.g = (misc.clampf(endColor.g + endColorVar.g * (Math.random() - 0.5) * 2, 0, 255) - sg) / timeToLive; - particle.deltaColor.b = (misc.clampf(endColor.b + endColorVar.b * (Math.random() - 0.5) * 2, 0, 255) - sb) / timeToLive; - particle.deltaColor.a = (misc.clampf(endColor.a + endColorVar.a * (Math.random() - 0.5) * 2, 0, 255) - sa) / timeToLive; + particle.color.r = sr = misc.clampf(startColor.r + startColorVar.r * (random() - 0.5) * 2, 0, 255); + particle.color.g = sg = misc.clampf(startColor.g + startColorVar.g * (random() - 0.5) * 2, 0, 255); + particle.color.b = sb = misc.clampf(startColor.b + startColorVar.b * (random() - 0.5) * 2, 0, 255); + particle.color.a = sa = misc.clampf(startColor.a + startColorVar.a * (random() - 0.5) * 2, 0, 255); + particle.deltaColor.r = (misc.clampf(endColor.r + endColorVar.r * (random() - 0.5) * 2, 0, 255) - sr) / timeToLive; + particle.deltaColor.g = (misc.clampf(endColor.g + endColorVar.g * (random() - 0.5) * 2, 0, 255) - sg) / timeToLive; + particle.deltaColor.b = (misc.clampf(endColor.b + endColorVar.b * (random() - 0.5) * 2, 0, 255) - sb) / timeToLive; + particle.deltaColor.a = (misc.clampf(endColor.a + endColorVar.a * (random() - 0.5) * 2, 0, 255) - sa) / timeToLive; // size - let startS = psys.startSize + psys.startSizeVar * (Math.random() - 0.5) * 2; + let startS = psys.startSize + psys.startSizeVar * (random() - 0.5) * 2; startS = Math.max(0, startS); // No negative value particle.size = startS; if (psys.endSize === START_SIZE_EQUAL_TO_END_SIZE) { particle.deltaSize = 0; } else { - let endS = psys.endSize + psys.endSizeVar * (Math.random() - 0.5) * 2; + let endS = psys.endSize + psys.endSizeVar * (random() - 0.5) * 2; endS = Math.max(0, endS); // No negative values particle.deltaSize = (endS - startS) / timeToLive; } // rotation - const startA = psys.startSpin + psys.startSpinVar * (Math.random() - 0.5) * 2; - const endA = psys.endSpin + psys.endSpinVar * (Math.random() - 0.5) * 2; + const startA = psys.startSpin + psys.startSpinVar * (random() - 0.5) * 2; + const endA = psys.endSpin + psys.endSpinVar * (random() - 0.5) * 2; particle.rotation = startA; particle.deltaRotation = (endA - startA) / timeToLive; @@ -202,18 +202,18 @@ export class Simulator { particle.aspectRatio = psys.aspectRatio || 1; // direction - const a = misc.degreesToRadians(psys.angle + this._worldRotation + psys.angleVar * (Math.random() - 0.5) * 2); + const a = misc.degreesToRadians(psys.angle + this._worldRotation + psys.angleVar * (random() - 0.5) * 2); // Mode Gravity: A if (psys.emitterMode === EmitterMode.GRAVITY) { - const s = psys.speed + psys.speedVar * (Math.random() - 0.5) * 2; + const s = psys.speed + psys.speedVar * (random() - 0.5) * 2; // direction particle.dir.x = Math.cos(a); particle.dir.y = Math.sin(a); particle.dir.multiplyScalar(s); // radial accel - particle.radialAccel = psys.radialAccel + psys.radialAccelVar * (Math.random() - 0.5) * 2; + particle.radialAccel = psys.radialAccel + psys.radialAccelVar * (random() - 0.5) * 2; // tangential accel - particle.tangentialAccel = psys.tangentialAccel + psys.tangentialAccelVar * (Math.random() - 0.5) * 2; + particle.tangentialAccel = psys.tangentialAccel + psys.tangentialAccelVar * (random() - 0.5) * 2; // rotation is dir if (psys.rotationIsDir) { particle.rotation = -misc.radiansToDegrees(Math.atan2(particle.dir.y, particle.dir.x)); @@ -221,12 +221,12 @@ export class Simulator { } else { // Mode Radius: B // Set the default diameter of the particle from the source position - const startRadius = psys.startRadius + psys.startRadiusVar * (Math.random() - 0.5) * 2; - const endRadius = psys.endRadius + psys.endRadiusVar * (Math.random() - 0.5) * 2; + const startRadius = psys.startRadius + psys.startRadiusVar * (random() - 0.5) * 2; + const endRadius = psys.endRadius + psys.endRadiusVar * (random() - 0.5) * 2; particle.radius = startRadius; particle.deltaRadius = (psys.endRadius === START_RADIUS_EQUAL_TO_END_RADIUS) ? 0 : (endRadius - startRadius) / timeToLive; particle.angle = a; - particle.degreesPerSecond = misc.degreesToRadians(psys.rotatePerS + psys.rotatePerSVar * (Math.random() - 0.5) * 2); + particle.degreesPerSecond = misc.degreesToRadians(psys.rotatePerS + psys.rotatePerSVar * (random() - 0.5) * 2); } } @@ -275,7 +275,7 @@ export class Simulator { const y1 = -halfHeight; const x2 = halfWidth; const y2 = halfHeight; - const rad = -misc.degreesToRadians(particle.rotation); + const rad = -misc.degreesToRadians(particle.rotation as number); const cr = Math.cos(rad); const sr = Math.sin(rad); // bl @@ -313,13 +313,13 @@ export class Simulator { vbuf[offset + 29] = 0; } // color - Color.toArray(vbuf, particle.color, offset + 5); - Color.toArray(vbuf, particle.color, offset + 14); - Color.toArray(vbuf, particle.color, offset + 23); - Color.toArray(vbuf, particle.color, offset + 32); + Color.toArray(vbuf, particle.color as IColorLike, offset + 5); + Color.toArray(vbuf, particle.color as IColorLike, offset + 14); + Color.toArray(vbuf, particle.color as IColorLike, offset + 23); + Color.toArray(vbuf, particle.color as IColorLike, offset + 32); } - public step (dt): void { + public step (dt: number): void { const assembler = this.sys.assembler!; const psys = this.sys; const node = psys.node; diff --git a/cocos/particle/animator/noise-module.ts b/cocos/particle/animator/noise-module.ts index b4106e54f90..0eb677aed3f 100644 --- a/cocos/particle/animator/noise-module.ts +++ b/cocos/particle/animator/noise-module.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { CCFloat, CCInteger, _decorator, Vec3 } from '../../core'; +import { CCFloat, CCInteger, _decorator, Vec3, random } from '../../core'; import { ParticleNoise } from '../noise'; import { Particle, PARTICLE_MODULE_NAME, ParticleModuleBase } from '../particle'; @@ -302,12 +302,12 @@ export class NoiseModule extends ParticleModuleBase { this.noise.setOctaves(this.octaves, this.octaveMultiplier, this.octaveScale); this.samplePosition.set(particle.position); - this.samplePosition.add3f(Math.random() * 1.0, Math.random() * 1.0, Math.random() * 1.0); + this.samplePosition.add3f(random() * 1.0, random() * 1.0, random() * 1.0); this.noise.setSamplePoint(this.samplePosition); this.noise.getNoiseParticle(); const noisePosition: Vec3 = this.noise.getResult(); - noisePosition.multiply3f(Math.random(), Math.random(), Math.random()); + noisePosition.multiply3f(random(), random(), random()); Vec3.add(particle.position, particle.position, noisePosition.multiplyScalar(dt)); } diff --git a/cocos/particle/animator/texture-animation.ts b/cocos/particle/animator/texture-animation.ts index a08dd4f5b05..fd15feccbc1 100644 --- a/cocos/particle/animator/texture-animation.ts +++ b/cocos/particle/animator/texture-animation.ts @@ -23,7 +23,7 @@ */ import { ccclass, tooltip, displayOrder, type, formerlySerializedAs, serializable, range } from 'cc.decorator'; -import { lerp, pseudoRandom, repeat, Enum } from '../../core'; +import { lerp, pseudoRandom, repeat, Enum, random, error } from '../../core'; import { Particle, ParticleModuleBase, PARTICLE_MODULE_NAME } from '../particle'; import CurveRange from './curve-range'; import { ModuleRandSeed } from '../enum'; @@ -117,7 +117,7 @@ export default class TextureAnimationModule extends ParticleModuleBase { set mode (val) { if (val !== Mode.Grid) { - console.error('particle texture animation\'s sprites is not supported!'); + error('particle texture animation\'s sprites is not supported!'); } } @@ -207,7 +207,7 @@ export default class TextureAnimationModule extends ParticleModuleBase { } set flipU (val) { - console.error('particle texture animation\'s flipU is not supported!'); + error('particle texture animation\'s flipU is not supported!'); } @serializable @@ -218,7 +218,7 @@ export default class TextureAnimationModule extends ParticleModuleBase { } set flipV (val) { - console.error('particle texture animation\'s flipV is not supported!'); + error('particle texture animation\'s flipV is not supported!'); } @serializable @@ -229,7 +229,7 @@ export default class TextureAnimationModule extends ParticleModuleBase { } set uvChannelMask (val) { - console.error('particle texture animation\'s uvChannelMask is not supported!'); + error('particle texture animation\'s uvChannelMask is not supported!'); } /** @@ -263,7 +263,7 @@ export default class TextureAnimationModule extends ParticleModuleBase { * @internal */ public init (p: Particle): void { - p.startRow = Math.floor(Math.random() * this.numTilesY); + p.startRow = Math.floor(random() * this.numTilesY); } /** From 5886a0066d040b71e4b5105030cbb2a9dfd792b2 Mon Sep 17 00:00:00 2001 From: oahc09 Date: Mon, 7 Aug 2023 14:33:07 +0800 Subject: [PATCH 060/184] fix:camera trackingtype/cameratype jsb attribute lost (#15867) (used in xr) --- native/tools/swig-config/scene.i | 2 ++ 1 file changed, 2 insertions(+) diff --git a/native/tools/swig-config/scene.i b/native/tools/swig-config/scene.i index 6464584d826..39aa6e93646 100644 --- a/native/tools/swig-config/scene.i +++ b/native/tools/swig-config/scene.i @@ -445,6 +445,8 @@ using namespace cc; %attribute(cc::scene::Camera, cc::pipeline::GeometryRenderer *, geometryRenderer, getGeometryRenderer); %attribute(cc::scene::Camera, uint32_t, systemWindowId, getSystemWindowId); %attribute(cc::scene::Camera, cc::scene::CameraUsage, cameraUsage, getCameraUsage, setCameraUsage); +%attribute(cc::scene::Camera, cc::scene::TrackingType, trackingType, getTrackingType, setTrackingType); +%attribute(cc::scene::Camera, cc::scene::CameraType, cameraType, getCameraType, setCameraType); %attribute(cc::scene::RenderScene, ccstd::string&, name, getName); %attribute(cc::scene::RenderScene, ccstd::vector>&, cameras, getCameras); From 29bd5d6aa4bdc820e27a2f044b58ebddc8c18971 Mon Sep 17 00:00:00 2001 From: oahc09 Date: Mon, 7 Aug 2023 14:33:43 +0800 Subject: [PATCH 061/184] improve:remove constraint-layout dependency on spaces template (#15868) --- templates/xr-spaces/template/app/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/xr-spaces/template/app/build.gradle b/templates/xr-spaces/template/app/build.gradle index 5d056b6b99e..2c4adb6f9cd 100644 --- a/templates/xr-spaces/template/app/build.gradle +++ b/templates/xr-spaces/template/app/build.gradle @@ -108,7 +108,6 @@ dependencies { implementation 'androidx.navigation:navigation-ui-ktx:2.4.2' implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2' implementation 'com.google.android.material:material:1.3.0' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31' // spaces controller implementation fileTree(dir: '../libs', include: ['*.jar','*.aar']) From b7ad5b1e6b2c16e96a841614739397930c8779e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Mon, 7 Aug 2023 15:23:45 +0800 Subject: [PATCH 062/184] fix skybox model not updated when onGlobalPipelineMacroChange (#15886) --- cocos/root.ts | 4 ++++ native/cocos/core/Root.cpp | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/cocos/root.ts b/cocos/root.ts index 99c2d28dd60..17c61a1b5b8 100644 --- a/cocos/root.ts +++ b/cocos/root.ts @@ -451,6 +451,10 @@ export class Root { this._scenes[i].onGlobalPipelineStateChanged(); } + if (this._pipeline!.pipelineSceneData.skybox.enabled) { + this._pipeline!.pipelineSceneData.skybox.model!.onGlobalPipelineStateChanged(); + } + this._pipeline!.onGlobalPipelineStateChanged(); } diff --git a/native/cocos/core/Root.cpp b/native/cocos/core/Root.cpp index 928d838f28c..a08d9d8fbca 100644 --- a/native/cocos/core/Root.cpp +++ b/native/cocos/core/Root.cpp @@ -48,6 +48,7 @@ #include "scene/Camera.h" #include "scene/DirectionalLight.h" #include "scene/SpotLight.h" +#include "scene/Skybox.h" namespace cc { @@ -358,6 +359,11 @@ void Root::onGlobalPipelineStateChanged() { scene->onGlobalPipelineStateChanged(); } + if (_pipelineRuntime->getPipelineSceneData()->getSkybox()->isEnabled()) + { + _pipelineRuntime->getPipelineSceneData()->getSkybox()->getModel()->onGlobalPipelineStateChanged(); + } + _pipelineRuntime->onGlobalPipelineStateChanged(); } From 592432c70e245c4c6aef1d40962db807bbbc7a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Tue, 8 Aug 2023 18:40:38 +0800 Subject: [PATCH 063/184] [Optimize] compiled deserialization related code (#15892) * Typing compiled deserialize * Optimize code structure * Rename * Tweak * Tweak * Update --- .../compiled/builtin-value-type.ts | 129 +++++++ cocos/serialization/deserialize-dynamic.ts | 12 +- .../deserialize-type-utilities.ts | 29 ++ cocos/serialization/deserialize.ts | 348 +++++++----------- editor/exports/serialization.ts | 4 + 5 files changed, 298 insertions(+), 224 deletions(-) create mode 100644 cocos/serialization/compiled/builtin-value-type.ts create mode 100644 cocos/serialization/deserialize-type-utilities.ts diff --git a/cocos/serialization/compiled/builtin-value-type.ts b/cocos/serialization/compiled/builtin-value-type.ts new file mode 100644 index 00000000000..c6b4afb7e72 --- /dev/null +++ b/cocos/serialization/compiled/builtin-value-type.ts @@ -0,0 +1,129 @@ +import { JSB } from 'internal:constants'; +import { Vec2, Vec3, Vec4, Color, Size, Rect, Quat, Mat4, assertIsTrue, ValueType } from '../../core'; +import type { IRuntimeFileData } from '../deserialize'; + +/** + * If a value type is not registered in this list, it will be serialized as plain class. + */ +const constructorMap = [ + Vec2, // 0 + Vec3, // 1 + Vec4, // 2 + Quat, // 3 + Color, // 4 + Size, // 5 + Rect, // 6 + Mat4, // 7 +] as const; + +type ConstructorMap = typeof constructorMap; + +export type ValueTypeData = [ + typeIndex: number, + ...values: number[], +]; + +type SetterInput = [reserved: number, ...values: number[]]; + +type Setter = (value: T, result: SetterInput) => void; + +type SetterMapImpl = T extends readonly [infer Head, ...infer Tails] + ? Head extends abstract new (...args: any) => any + ? readonly [Setter>, ...SetterMapImpl] + : readonly [Head, ...SetterMapImpl] + : readonly []; + +type SetterMap = SetterMapImpl; + +function vec4LikeSetter (obj: T, data: SetterInput): void { + obj.x = data[1]; + obj.y = data[2]; + obj.z = data[3]; + obj.w = data[4]; +} + +const setterMap: SetterMap = [ + (obj: Vec2, data: SetterInput): void => { + obj.x = data[1]; + obj.y = data[2]; + }, + (obj: Vec3, data: SetterInput): void => { + obj.x = data[1]; + obj.y = data[2]; + obj.z = data[3]; + }, + vec4LikeSetter, // Vec4 + vec4LikeSetter, // Quat + (obj: Color, data: SetterInput): void => { + obj._val = data[1]; + }, + (obj: Size, data: SetterInput): void => { + obj.width = data[1]; + obj.height = data[2]; + }, + (obj: Rect, data: SetterInput): void => { + obj.x = data[1]; + obj.y = data[2]; + obj.width = data[3]; + obj.height = data[4]; + }, + (obj: Mat4, data: SetterInput): void => { + Mat4.fromArray(obj, data, 1); + }, +]; + +export function serializeBuiltinValueType (obj: ValueType): ValueTypeData | null { + const ctor = obj.constructor; + const typeId = (constructorMap as readonly any[]).indexOf(ctor); + switch (ctor) { + case Vec2: + return [typeId, (obj as Vec2).x, (obj as Vec2).y]; + case Vec3: + return [typeId, (obj as Vec3).x, (obj as Vec3).y, (obj as Vec3).z]; + case Vec4: + case Quat: + return [typeId, (obj as Vec4).x, (obj as Vec4).y, (obj as Vec4).z, (obj as Vec4).w]; + case Color: + return [typeId, (obj as Color)._val]; + case Size: + return [typeId, (obj as Size).width, (obj as Size).height]; + case Rect: + return [typeId, (obj as Rect).x, (obj as Rect).y, (obj as Rect).width, (obj as Rect).height]; + case Mat4: { + const res: ValueTypeData = new Array(1 + 16) as ValueTypeData; + res[0] = typeId; + Mat4.toArray(res, obj as Mat4, 1); + return res; + } + default: + return null; + } +} + +export function deserializeBuiltinValueType (data: IRuntimeFileData, owner: any, key: string, value: ValueTypeData): void { + const typeIndex = value[0]; + assertIsTrue(typeIndex >= 0 && typeIndex < constructorMap.length); + const object = new (constructorMap[typeIndex])(); + const setter = setterMap[typeIndex] as Setter; + setter(object, value); + owner[key] = object; +} + +export function deserializeBuiltinValueTypeInto (data: IRuntimeFileData, owner: any, key: string, value: ValueTypeData): void { + const typeIndex = value[0]; + assertIsTrue(typeIndex >= 0 && typeIndex < constructorMap.length); + if (JSB) { + // The native layer type corresponding to the BuiltinValueTypes has not been exported exclude Color, + // so we need to set to native after value changed. + const tmp = owner[key]; + const setter = setterMap[typeIndex] as Setter; + setter(tmp, value); + owner[key] = tmp; + } else { + const object = owner[key]; + const setter = setterMap[typeIndex] as Setter; + setter(object, value); + } +} + +export {}; diff --git a/cocos/serialization/deserialize-dynamic.ts b/cocos/serialization/deserialize-dynamic.ts index 9b26fd27be5..d15266d3ad8 100644 --- a/cocos/serialization/deserialize-dynamic.ts +++ b/cocos/serialization/deserialize-dynamic.ts @@ -657,10 +657,12 @@ class _Deserializer { } const rawDeserialize: CompiledDeserializeFn = deserialize; - deserialize = function (deserializer: _Deserializer, + deserialize = function ( + deserializer: _Deserializer, object: Record, deserialized: Record, - constructor: AnyFunction): void { + constructor: AnyFunction, + ): void { rawDeserialize(deserializer, object, deserialized, constructor); if (!object._$erialized) { error(`Unable to stash previously serialized data. ${JSON.stringify(deserialized)}`); @@ -828,13 +830,15 @@ class _Deserializer { } } -export function deserializeDynamic (data: SerializedData | CCON, details: Details, options?: { +export interface DeserializeDynamicOptions { classFinder?: ClassFinder; ignoreEditorOnly?: boolean; createAssetRefs?: boolean; customEnv?: unknown; reportMissingClass?: ReportMissingClass; -}): any { +} + +export function deserializeDynamic (data: SerializedData | CCON, details: Details, options?: DeserializeDynamicOptions): any { options = options || {}; const classFinder = options.classFinder || js.getClassById; const createAssetRefs = options.createAssetRefs || sys.platform === Platform.EDITOR_CORE; diff --git a/cocos/serialization/deserialize-type-utilities.ts b/cocos/serialization/deserialize-type-utilities.ts new file mode 100644 index 00000000000..ddff611339b --- /dev/null +++ b/cocos/serialization/deserialize-type-utilities.ts @@ -0,0 +1,29 @@ +type EnumMapImpl< + Map extends Record, + _, + Minus1 extends any[] = [], + Index extends keyof Map = Minus1['length'] +> = [ + ...(Minus1 extends [infer _2, ...infer Remain] ? EnumMapImpl : []), + // Index, + Map[Index], +]; + +type MapTuple, T> = T extends [infer _1, ...infer Remain] ? EnumMapImpl : never; + +type Tuple = R['length'] extends N ? R : Tuple; + +export type MapEnum, Length extends number> = MapTuple>; + +type TupleSplit = + O['length'] extends N ? [O, T] : T extends readonly [infer F, ...infer R] ? + TupleSplit : [O, T]; + +type TakeFirst = + TupleSplit[0]; + +type SkipFirst = + TupleSplit[1]; + +export type TupleSlice = + SkipFirst, S>; diff --git a/cocos/serialization/deserialize.ts b/cocos/serialization/deserialize.ts index 05b6c7723a9..8f88ae4091a 100644 --- a/cocos/serialization/deserialize.ts +++ b/cocos/serialization/deserialize.ts @@ -23,18 +23,21 @@ */ import { EDITOR, TEST, PREVIEW, DEBUG, JSB, DEV } from 'internal:constants'; -import { cclegacy, ValueType, Vec2, Vec3, Vec4, Color, Size, Rect, Quat, Mat4, errorID, getError, js } from '../core'; +import { cclegacy, errorID, getError, js, assertIsTrue } from '../core'; -import { deserializeDynamic, parseUuidDependenciesDynamic } from './deserialize-dynamic'; +import { deserializeDynamic, DeserializeDynamicOptions, parseUuidDependenciesDynamic } from './deserialize-dynamic'; import { Asset } from '../asset/assets/asset'; -import type { CCON } from './ccon'; import type { CompiledDeserializeFn } from './deserialize-dynamic'; import { reportMissingClass as defaultReportMissingClass } from './report-missing-class'; +import type { MapEnum, TupleSlice } from './deserialize-type-utilities'; + const FORCE_COMPILED = false; // TODO: BUILD; +import { deserializeBuiltinValueType, deserializeBuiltinValueTypeInto } from './compiled/builtin-value-type'; + /** ************************************************************************** * BUILT-IN TYPES / CONSTAINTS *************************************************************************** */ @@ -42,102 +45,6 @@ const FORCE_COMPILED = false; // TODO: BUILD; const SUPPORT_MIN_FORMAT_VERSION = 1; const EMPTY_PLACEHOLDER = 0; -// Used for Data.ValueType. -// If a value type is not registered in this list, it will be serialized to Data.Class. -const BuiltinValueTypes: (typeof ValueType)[] = [ - Vec2, // 0 - Vec3, // 1 - Vec4, // 2 - Quat, // 3 - Color, // 4 - Size, // 5 - Rect, // 6 - Mat4, // 7 -]; - -// Used for Data.ValueTypeCreated. -function BuiltinValueTypeParsers_xyzw (obj: Vec4 | Quat, data: number[]): void { - obj.x = data[1]; - obj.y = data[2]; - obj.z = data[3]; - obj.w = data[4]; -} -const BuiltinValueTypeSetters: ((obj: any, data: number[]) => void)[] = [ - (obj: Vec2, data: number[]): void => { - obj.x = data[1]; - obj.y = data[2]; - }, - (obj: Vec3, data: number[]): void => { - obj.x = data[1]; - obj.y = data[2]; - obj.z = data[3]; - }, - BuiltinValueTypeParsers_xyzw, // Vec4 - BuiltinValueTypeParsers_xyzw, // Quat - (obj: Color, data: number[]): void => { - obj._val = data[1]; - }, - (obj: Size, data: number[]): void => { - obj.width = data[1]; - obj.height = data[2]; - }, - (obj: Rect, data: number[]): void => { - obj.x = data[1]; - obj.y = data[2]; - obj.width = data[3]; - obj.height = data[4]; - }, - (obj: Mat4, data: number[]): void => { - Mat4.fromArray(obj, data, 1); - }, -]; - -function serializeBuiltinValueTypes (obj: ValueType): IValueTypeData | null { - const ctor = obj.constructor as typeof ValueType; - const typeId = BuiltinValueTypes.indexOf(ctor); - switch (ctor) { - case Vec2: - return [typeId, (obj as Vec2).x, (obj as Vec2).y]; - case Vec3: - return [typeId, (obj as Vec3).x, (obj as Vec3).y, (obj as Vec3).z]; - case Vec4: - case Quat: - return [typeId, (obj as Vec4).x, (obj as Vec4).y, (obj as Vec4).z, (obj as Vec4).w]; - case Color: - return [typeId, (obj as Color)._val]; - case Size: - return [typeId, (obj as Size).width, (obj as Size).height]; - case Rect: - return [typeId, (obj as Rect).x, (obj as Rect).y, (obj as Rect).width, (obj as Rect).height]; - case Mat4: { - const res: IValueTypeData = new Array(1 + 16) as IValueTypeData; - res[VALUETYPE_SETTER] = typeId; - Mat4.toArray(res, obj as Mat4, 1); - return res; - } - default: - return null; - } -} - -// // TODO: Used for Data.TypedArray. -// const TypedArrays = [ -// Float32Array, -// Float64Array, -// -// Int8Array, -// Int16Array, -// Int32Array, -// -// Uint8Array, -// Uint16Array, -// Uint32Array, -// -// Uint8ClampedArray, -// // BigInt64Array, -// // BigUint64Array, -// ]; - /** ************************************************************************** * TYPE DECLARATIONS *************************************************************************** */ @@ -217,12 +124,6 @@ const enum DataTypeID { // Common TypedArray for legacyCC.Node only. Never be null. TRS, - // // From the point of view of simplified implementation, - // // it is not supported to deserialize TypedArray that is initialized to null in the constructor. - // // Also, the length of TypedArray cannot be changed. - // // Developers will rarely manually assign a null. - // TypedArray, - // ValueType without default value (in arrays, dictionaries). // Developers will rarely manually assign a null. ValueType, @@ -257,7 +158,6 @@ interface DataTypes { [DataTypeID.ValueTypeCreated]: IValueTypeData; [DataTypeID.AssetRefByInnerObj]: number; [DataTypeID.TRS]: ITRSData; - // [DataTypeID.TypedArray]: Array; [DataTypeID.ValueType]: IValueTypeData; [DataTypeID.Array_Class]: DataTypes[DataTypeID.Class][]; [DataTypeID.CustomizedClass]: ICustomObjectData; @@ -355,7 +255,6 @@ interface ICustomObjectData extends Array { [CUSTOM_OBJ_DATA_CONTENT]: ICustomObjectDataContent; } -const VALUETYPE_SETTER = 0; type IValueTypeData = [ // Predefined parsing function index number, @@ -400,13 +299,6 @@ export declare namespace deserialize.Internal { export type IArrayData_ = IArrayData; } -// const TYPEDARRAY_TYPE = 0; -// const TYPEDARRAY_ELEMENTS = 1; -// interface ITypedArrayData extends Array { -// [TYPEDARRAY_TYPE]: number, -// [TYPEDARRAY_ELEMENTS]: number[], -// } - const enum Refs { EACH_RECORD_LENGTH = 3, OWNER_OFFSET = 0, @@ -450,9 +342,9 @@ const enum File { } // Main file structure -interface IFileData extends Array { +interface IFileDataMap { // version - [File.Version]: number | FileInfo | any; + [File.Version]: number; // Shared data area, the higher the number of references, the higher the position @@ -481,13 +373,40 @@ interface IFileData extends Array { [File.DependUuidIndices]: (StringIndex|string)[]; } -// type Body = Pick -type Shared = Pick; -const PACKED_SECTIONS = File.Instances; -interface IPackedFileData extends Shared { - [PACKED_SECTIONS]: IFileData[]; +type IFileData = MapEnum<{ + [x in keyof IFileDataMap as `${x}`]: IFileDataMap[x]; +}, 11 /* Currently we should manually specify the enumerators count. */>; + +type IRuntimeFileDataMap = Omit & { + [File.Context]: FileInfo & DeserializeContext; } +/** + * At runtime, we intruded the original file data and injected some helpers. + */ +export type IRuntimeFileData = MapEnum<{ + [x in keyof IRuntimeFileDataMap as `${x}`]: IRuntimeFileDataMap[x]; +}, 11 /* Currently we should manually specify the enumerators count. */>; + +type IDeserializeInput = IFileData | IRuntimeFileData; + +type ISharedData = TupleSlice; + +type IPackedFileSection = [ + ...document: TupleSlice, +]; + +const PACKED_SECTIONS = File.Instances; + +type IPackedFileData = [ + /** Version. */ + version: number, + + ...shared: ISharedData, + + sections: IPackedFileSection[], +]; + export declare namespace deserialize.Internal { export import Refs_ = Refs; export type IRefs_ = IRefs; @@ -500,13 +419,17 @@ interface ICustomHandler { result: Details, customEnv: any, } -type ClassFinder = (type: string) => AnyCtor; +type ClassFinder = deserialize.ClassFinder; + +interface DeserializeContext extends ICustomHandler { + _version?: number; +} interface IOptions extends Partial { classFinder?: ClassFinder; - reportMissingClass: deserialize.ReportMissingClass; - _version?: number; + reportMissingClass?: deserialize.ReportMissingClass; } + interface ICustomClass { _deserialize?: (content: any, context: ICustomHandler) => void; } @@ -527,21 +450,21 @@ export class Details { * @zh * 对象列表,其中每个对象有属性需要通过 uuid 进行资源加载 */ - uuidObjList: IFileData[File.DependObjs] | null = null; + uuidObjList: IRuntimeFileData[File.DependObjs] | null = null; /** * @en * the corresponding field name which referenced to the asset * @zh * 引用着资源的字段名称 */ - uuidPropList: IFileData[File.DependKeys] | null = null; + uuidPropList: IRuntimeFileData[File.DependKeys] | null = null; /** * @en * list of the depends assets' uuid * @zh * 依赖资源的 uuid 列表 */ - uuidList: IFileData[File.DependUuidIndices] | null = null; + uuidList: IRuntimeFileData[File.DependUuidIndices] | null = null; /** * @en @@ -566,7 +489,7 @@ export class Details { * @method init * @param {Object} data */ - init (data?: IFileData): void { + init (data?: IDeserializeInput): void { if (FORCE_COMPILED || data) { this.uuidObjList = data![File.DependObjs]; this.uuidPropList = data![File.DependKeys]; @@ -641,7 +564,7 @@ if (EDITOR || TEST) { }; } -export function dereference (refs: IRefs, instances: IFileData[File.Instances], strings: IFileData[File.SharedStrings]): void { +export function dereference (refs: IRefs, instances: IRuntimeFileData[File.Instances], strings: IRuntimeFileData[File.SharedStrings]): void { const dataLength = refs.length - 1; let i = 0; // owner is object @@ -673,7 +596,7 @@ export function dereference (refs: IRefs, instances: IFileData[File.Instances], // -function deserializeCCObject (data: IFileData, objectData: IClassObjectData): Record { +function deserializeCCObject (data: IRuntimeFileData, objectData: IClassObjectData): Record { const mask = data[File.SharedMasks][objectData[OBJ_DATA_MASK]]; const clazz = mask[MASK_CLASS]; const ctor = clazz[CLASS_TYPE] as Exclude; @@ -707,7 +630,7 @@ function deserializeCCObject (data: IFileData, objectData: IClassObjectData): Re return obj; } -function deserializeCustomCCObject (data: IFileData, ctor: Ctor, value: ICustomObjectDataContent): ICustomClass { +function deserializeCustomCCObject (data: IRuntimeFileData, ctor: Ctor, value: ICustomObjectDataContent): ICustomClass { // eslint-disable-next-line new-cap const obj = new ctor(); if (obj._deserialize) { @@ -720,13 +643,13 @@ function deserializeCustomCCObject (data: IFileData, ctor: Ctor, v // Parse Functions -type ParseFunction = (data: IFileData, owner: any, key: string, value: T) => void; +type ParseFunction = (data: IRuntimeFileData, owner: any, key: string, value: T) => void; -function assignSimple (data: IFileData, owner: any, key: string, value: DataTypes[DataTypeID.SimpleType]): void { +function assignSimple (data: IRuntimeFileData, owner: any, key: string, value: DataTypes[DataTypeID.SimpleType]): void { owner[key] = value; } -function assignInstanceRef (data: IFileData, owner: any, key: string, value: InstanceBnotReverseIndex): void { +function assignInstanceRef (data: IRuntimeFileData, owner: any, key: string, value: InstanceBnotReverseIndex): void { if (value >= 0) { owner[key] = data[File.Instances][value]; } else { @@ -735,7 +658,7 @@ function assignInstanceRef (data: IFileData, owner: any, key: string, value: Ins } function genArrayParser (parser: ParseFunction): ParseFunction { - return (data: IFileData, owner: any, key: string, value: T[]): void => { + return (data: IRuntimeFileData, owner: any, key: string, value: T[]): void => { for (let i = 0; i < value.length; ++i) { parser(data, value, i as unknown as string, value[i]); } @@ -743,46 +666,26 @@ function genArrayParser (parser: ParseFunction): ParseFunction { }; } -function parseAssetRefByInnerObj (data: IFileData, owner: any, key: string, value: number): void { +function parseAssetRefByInnerObj (data: IRuntimeFileData, owner: any, key: string, value: number): void { owner[key] = null; data[File.DependObjs][value] = owner; } -function parseClass (data: IFileData, owner: any, key: string, value: IClassObjectData): void { +function parseClass (data: IRuntimeFileData, owner: any, key: string, value: IClassObjectData): void { owner[key] = deserializeCCObject(data, value); } -function parseCustomClass (data: IFileData, owner: any, key: string, value: ICustomObjectData): void { +function parseCustomClass (data: IRuntimeFileData, owner: any, key: string, value: ICustomObjectData): void { const ctor = data[File.SharedClasses][value[CUSTOM_OBJ_DATA_CLASS]] as CCClassConstructor; owner[key] = deserializeCustomCCObject(data, ctor, value[CUSTOM_OBJ_DATA_CONTENT]); } -function parseValueTypeCreated (data: IFileData, owner: any, key: string, value: IValueTypeData): void { - /**BuiltinValueTypes index: Vec2=0, Vec3=1, Vec4=2, Quat=3, Color=4, Size=5, Rect=6, Mat4=7 - The native layer type corresponding to the BuiltinValueTypes has not been exported exclude Color, - so we need to set to native after value changed - * */ - if (JSB) { - const tmp = owner[key]; - BuiltinValueTypeSetters[value[VALUETYPE_SETTER]](tmp, value); - owner[key] = tmp; - } else { - BuiltinValueTypeSetters[value[VALUETYPE_SETTER]](owner[key], value); - } -} - -function parseValueType (data: IFileData, owner: any, key: string, value: IValueTypeData): void { - const val: ValueType = new BuiltinValueTypes[value[VALUETYPE_SETTER]](); - BuiltinValueTypeSetters[value[VALUETYPE_SETTER]](val, value); - owner[key] = val; -} - -function parseTRS (data: IFileData, owner: any, key: string, value: ITRSData): void { +function parseTRS (data: IRuntimeFileData, owner: any, key: string, value: ITRSData): void { const typedArray = owner[key] as (Float32Array | Float64Array); typedArray.set(value); } -function parseDict (data: IFileData, owner: any, key: string, value: IDictData): void { +function parseDict (data: IRuntimeFileData, owner: any, key: string, value: IDictData): void { const dict = value[DICT_JSON_LAYOUT]; owner[key] = dict; for (let i = DICT_JSON_LAYOUT + 1; i < value.length; i += 3) { @@ -794,7 +697,7 @@ function parseDict (data: IFileData, owner: any, key: string, value: IDictData): } } -function parseArray (data: IFileData, owner: any, key: string, value: IArrayData): void { +function parseArray (data: IRuntimeFileData, owner: any, key: string, value: IArrayData): void { const array = value[ARRAY_ITEM_VALUES]; for (let i = 0; i < array.length; ++i) { const subValue = array[i]; @@ -808,17 +711,6 @@ function parseArray (data: IFileData, owner: any, key: string, value: IArrayData owner[key] = array; } -// function parseTypedArray (data: IFileData, owner: any, key: string, value: ITypedArrayData) { -// let val: ValueType = new TypedArrays[value[TYPEDARRAY_TYPE]](); -// BuiltinValueTypeSetters[value[VALUETYPE_SETTER]](val, value); -// // obj = new window[serialized.ctor](array.length); -// // for (let i = 0; i < array.length; ++i) { -// // obj[i] = array[i]; -// // } -// // return obj; -// owner[key] = val; -// } - const ASSIGNMENTS: { [K in keyof DataTypes]?: ParseFunction; // eslint-disable-next-line @typescript-eslint/ban-types @@ -828,17 +720,16 @@ ASSIGNMENTS[DataTypeID.InstanceRef] = assignInstanceRef; ASSIGNMENTS[DataTypeID.Array_InstanceRef] = genArrayParser(assignInstanceRef); ASSIGNMENTS[DataTypeID.Array_AssetRefByInnerObj] = genArrayParser(parseAssetRefByInnerObj); ASSIGNMENTS[DataTypeID.Class] = parseClass; -ASSIGNMENTS[DataTypeID.ValueTypeCreated] = parseValueTypeCreated; +ASSIGNMENTS[DataTypeID.ValueTypeCreated] = deserializeBuiltinValueTypeInto; ASSIGNMENTS[DataTypeID.AssetRefByInnerObj] = parseAssetRefByInnerObj; ASSIGNMENTS[DataTypeID.TRS] = parseTRS; -ASSIGNMENTS[DataTypeID.ValueType] = parseValueType; +ASSIGNMENTS[DataTypeID.ValueType] = deserializeBuiltinValueType; ASSIGNMENTS[DataTypeID.Array_Class] = genArrayParser(parseClass); ASSIGNMENTS[DataTypeID.CustomizedClass] = parseCustomClass; ASSIGNMENTS[DataTypeID.Dict] = parseDict; ASSIGNMENTS[DataTypeID.Array] = parseArray; -// ASSIGNMENTS[DataTypeID.TypedArray] = parseTypedArray; -function parseInstances (data: IFileData): RootInstanceIndex { +function parseInstances (data: IRuntimeFileData): RootInstanceIndex { const instances = data[File.Instances]; const instanceTypes = data[File.InstanceTypes]; const instanceTypesLen = instanceTypes === EMPTY_PLACEHOLDER ? 0 : (instanceTypes).length; @@ -929,7 +820,7 @@ function doLookupClass (classFinder, type: string, container: any[], index: numb container[index] = klass; } -function lookupClasses (data: IPackedFileData, silent: boolean, customFinder: ClassFinder | undefined, reportMissingClass: deserialize.ReportMissingClass): void { +function lookupClasses (data: [any, ...ISharedData, ...any[]], silent: boolean, customFinder: ClassFinder | undefined, reportMissingClass: deserialize.ReportMissingClass): void { const classFinder = customFinder || js.getClassById; const classes = data[File.SharedClasses]; for (let i = 0; i < classes.length; ++i) { @@ -948,7 +839,7 @@ function lookupClasses (data: IPackedFileData, silent: boolean, customFinder: Cl } } -function cacheMasks (data: IPackedFileData): void { +function cacheMasks (data: [any, ...ISharedData, ...any[]]): void { const masks = data[File.SharedMasks]; if (masks) { const classes = data[File.SharedClasses]; @@ -959,7 +850,7 @@ function cacheMasks (data: IPackedFileData): void { } } -function parseResult (data: IFileData): void { +function parseResult (data: IRuntimeFileData): void { const instances = data[File.Instances]; const sharedStrings = data[File.SharedStrings]; const dependSharedUuids = data[File.SharedUuids]; @@ -1005,9 +896,35 @@ export function isCompiledJson (json: unknown): boolean { } } -/** - * @module cc - */ +function initializeDeserializationContext( + data: IDeserializeInput, + details: Details, + options?: IOptions & DeserializeDynamicOptions, +) { + details.init(data); + + options ??= {}; + + let version = data[File.Version]; + let preprocessed = false; + if (typeof version === 'object') { + preprocessed = version.preprocessed; + version = version.version; + } + if (version < SUPPORT_MIN_FORMAT_VERSION) { + throw new Error(getError(5304, version)); + } + + const context = options as IRuntimeFileData[File.Context]; + context._version = version; + context.result = details; + data[File.Context] = context; + + if (!preprocessed) { + lookupClasses(data as IRuntimeFileData, false, options.classFinder, options.reportMissingClass ?? deserialize.reportMissingClass); + cacheMasks(data as IRuntimeFileData); + } +} /** * @en Deserializes a previously serialized object to reconstruct it to the original. @@ -1018,54 +935,47 @@ export function isCompiledJson (json: unknown): boolean { * @param options Deserialization Options. * @return The original object. */ -export function deserialize (data: IFileData | string | CCON | any, details: Details | any, options?: IOptions | any): unknown { +export function deserialize (data: IDeserializeInput | string | any, details?: Details, options?: IOptions & DeserializeDynamicOptions): unknown { if (typeof data === 'string') { data = JSON.parse(data); } - const borrowDetails = !details; - details = details || Details.pool.get(); + let isBorrowedDetails = false; + if (!details) { + const borrowedDetails = Details.pool.get(); + assertIsTrue(borrowedDetails, `Can not allocate deserialization details`); + details = borrowedDetails; + isBorrowedDetails = true; + } + let res; if (!FORCE_COMPILED && !isCompiledJson(data)) { res = deserializeDynamic(data, details, options); } else { - details.init(data); - options = options || {}; - - let version = data[File.Version]; - let preprocessed = false; - if (typeof version === 'object') { - preprocessed = version.preprocessed; - version = version.version; - } - if (version < SUPPORT_MIN_FORMAT_VERSION) { - throw new Error(getError(5304, version)); - } - options._version = version; - options.result = details; - data[File.Context] = options; + initializeDeserializationContext( + data, + details, + options, + ); - if (!preprocessed) { - lookupClasses(data, false, options.classFinder, options.reportMissingClass ?? deserialize.reportMissingClass); - cacheMasks(data); - } + const runtimeData = data as IRuntimeFileData; cclegacy.game._isCloning = true; - const instances = data[File.Instances]; - const rootIndex = parseInstances(data); + const instances = runtimeData[File.Instances]; + const rootIndex = parseInstances(runtimeData); cclegacy.game._isCloning = false; - if (data[File.Refs]) { - dereference(data[File.Refs] as IRefs, instances, data[File.SharedStrings]); + if (runtimeData[File.Refs]) { + dereference(runtimeData[File.Refs] as IRefs, instances, runtimeData[File.SharedStrings]); } - parseResult(data); + parseResult(runtimeData); res = instances[rootIndex]; } - if (borrowDetails) { + if (isBorrowedDetails) { Details.pool.put(details); } @@ -1095,7 +1005,8 @@ class FileInfo { } } -export function unpackJSONs (data: IPackedFileData, classFinder?: ClassFinder, reportMissingClass?: deserialize.ReportMissingClass): IFileData[] { +export function unpackJSONs ( + data: IPackedFileData, classFinder?: ClassFinder, reportMissingClass?: deserialize.ReportMissingClass): IDeserializeInput[] { if (data[File.Version] < SUPPORT_MIN_FORMAT_VERSION) { throw new Error(getError(5304, data[File.Version])); } @@ -1110,9 +1021,10 @@ export function unpackJSONs (data: IPackedFileData, classFinder?: ClassFinder, r const sections = data[PACKED_SECTIONS]; for (let i = 0; i < sections.length; ++i) { - sections[i].unshift(version, sharedUuids, sharedStrings, sharedClasses, sharedMasks); + const section = sections[i]; + (section as any[]).unshift(version, sharedUuids, sharedStrings, sharedClasses, sharedMasks); } - return sections; + return sections as unknown as IDeserializeInput[]; } export function packCustomObjData (type: string, data: IClassObjectData|OtherObjectData, hasNativeDep?: boolean): IFileData { @@ -1126,7 +1038,7 @@ export function packCustomObjData (type: string, data: IClassObjectData|OtherObj ]; } -export function hasNativeDep (data: IFileData): boolean { +export function hasNativeDep (data: IRuntimeFileData): boolean { const instances = data[File.Instances]; const rootInfo = instances[instances.length - 1]; if (typeof rootInfo !== 'number') { @@ -1136,7 +1048,7 @@ export function hasNativeDep (data: IFileData): boolean { } } -function getDependUuidList (json: IFileData): string[] { +function getDependUuidList (json: IRuntimeFileData): string[] { const sharedUuids = json[File.SharedUuids]; // eslint-disable-next-line @typescript-eslint/no-unsafe-return return json[File.DependUuidIndices].map((index) => sharedUuids[index]); @@ -1145,7 +1057,7 @@ function getDependUuidList (json: IFileData): string[] { export function parseUuidDependencies (serialized: unknown): string[] { // eslint-disable-next-line @typescript-eslint/ban-types if (!DEV || isCompiledJson(serialized as object)) { - return getDependUuidList(serialized as IFileData); + return getDependUuidList(serialized as IRuntimeFileData); } else { return parseUuidDependenciesDynamic(serialized); } @@ -1182,8 +1094,6 @@ if (EDITOR || TEST) { ARRAY_ITEM_VALUES: typeof ARRAY_ITEM_VALUES, PACKED_SECTIONS: typeof PACKED_SECTIONS, }; - deserialize._BuiltinValueTypes = BuiltinValueTypes; - deserialize._serializeBuiltinValueTypes = serializeBuiltinValueTypes; } if (TEST) { @@ -1224,9 +1134,7 @@ if (TEST) { CustomizedClass: DataTypeID.CustomizedClass, Dict: DataTypeID.Dict, Array: DataTypeID.Array, - // TypedArray: DataTypeID.TypedArray, }, - BuiltinValueTypes, unpackJSONs, }; } diff --git a/editor/exports/serialization.ts b/editor/exports/serialization.ts index cc3ac576bab..00b297fa884 100644 --- a/editor/exports/serialization.ts +++ b/editor/exports/serialization.ts @@ -7,3 +7,7 @@ export { decodeCCONBinary, parseCCONJson, } from '../../cocos/serialization/ccon'; + +export { + serializeBuiltinValueType, +} from '../../cocos/serialization/compiled/builtin-value-type'; From f55abfa9492bb2bf8a7d0bdc9232121930eb25d0 Mon Sep 17 00:00:00 2001 From: Jiujiang Liu <37231523+moshuying@users.noreply.github.com> Date: Wed, 9 Aug 2023 10:05:39 +0800 Subject: [PATCH 064/184] remove _fitDesignResolution function call in EVENT_AFTER_UPDATE (#15802) * fix can't adjust the 2D camera in editor * simple code * update function name * remove unused import function * use anchorX * update code --- cocos/2d/framework/canvas.ts | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/cocos/2d/framework/canvas.ts b/cocos/2d/framework/canvas.ts index a4aef03ff73..87e4eb5e422 100644 --- a/cocos/2d/framework/canvas.ts +++ b/cocos/2d/framework/canvas.ts @@ -124,7 +124,7 @@ export class Canvas extends RenderRoot2D { protected _thisOnCameraResized: () => void; // fit canvas node to design resolution - protected _fitDesignResolution: (() => void) | undefined; + protected fitDesignResolution_EDITOR: (() => void) | undefined; private _pos = new Vec3(); private _renderMode = RenderMode.OVERLAY; @@ -134,16 +134,33 @@ export class Canvas extends RenderRoot2D { this._thisOnCameraResized = this._onResizeCamera.bind(this); if (EDITOR) { - this._fitDesignResolution = (): void => { + this.fitDesignResolution_EDITOR = (): void => { // TODO: support paddings of locked widget this.node.getPosition(this._pos); const nodeSize = view.getDesignResolutionSize(); - Vec3.set(_worldPos, nodeSize.width * 0.5, nodeSize.height * 0.5, 0); + const trans = this.node._uiProps.uiTransformComp!; + + let scaleX = this.node.scale.x; + let anchorX = trans.anchorX; + if (scaleX < 0) { + anchorX = 1.0 - anchorX; + scaleX = -scaleX; + } + nodeSize.width = scaleX === 0 ? nodeSize.width : nodeSize.width / scaleX; + + let scaleY = this.node.scale.y; + let anchorY = trans.anchorY; + if (scaleY < 0) { + anchorY = 1.0 - anchorY; + scaleY = -scaleY; + } + nodeSize.height = scaleY === 0 ? nodeSize.height : nodeSize.height / scaleY; + + Vec3.set(_worldPos, nodeSize.width * anchorX, nodeSize.height * anchorY, 0); if (!this._pos.equals(_worldPos)) { this.node.setPosition(_worldPos); } - const trans = this.node._uiProps.uiTransformComp!; if (trans.width !== nodeSize.width) { trans.width = nodeSize.width; } @@ -160,7 +177,7 @@ export class Canvas extends RenderRoot2D { if (widget) { widget.updateAlignment(); } else if (EDITOR) { - this._fitDesignResolution!(); + this.fitDesignResolution_EDITOR!(); } if (!EDITOR) { @@ -173,9 +190,6 @@ export class Canvas extends RenderRoot2D { this._onResizeCamera(); if (EDITOR) { - // Constantly align canvas node in edit mode - cclegacy.director.on(cclegacy.Director.EVENT_AFTER_UPDATE, this._fitDesignResolution!, this); - // In Editor can not edit these attrs. // (Position in Node, contentSize in uiTransform) // (anchor in uiTransform, but it can edit, this is different from cocos creator) @@ -203,11 +217,7 @@ export class Canvas extends RenderRoot2D { public onDestroy (): void { super.onDestroy(); - if (EDITOR) { - cclegacy.director.off(cclegacy.Director.EVENT_AFTER_UPDATE, this._fitDesignResolution!, this); - } else { - this.node.off(NodeEventType.TRANSFORM_CHANGED, this._thisOnCameraResized); - } + this.node.off(NodeEventType.TRANSFORM_CHANGED, this._thisOnCameraResized); } protected _onResizeCamera (): void { From 0abd8c4da5fe89fefe3ace24cd3192aeb67a799f Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Wed, 9 Aug 2023 10:35:13 +0800 Subject: [PATCH 065/184] fix metal pvrtc upload issue (#15894) --- native/cocos/renderer/gfx-metal/MTLTexture.mm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/native/cocos/renderer/gfx-metal/MTLTexture.mm b/native/cocos/renderer/gfx-metal/MTLTexture.mm index edab24a636a..96d7b9a1bc1 100644 --- a/native/cocos/renderer/gfx-metal/MTLTexture.mm +++ b/native/cocos/renderer/gfx-metal/MTLTexture.mm @@ -225,17 +225,21 @@ of this software and associated engine source code (the "Software"), a limited, descriptor.mipmapLevelCount = _info.levelCount; descriptor.arrayLength = _info.type == TextureType::CUBE ? 1 : _info.layerCount; - descriptor.storageMode = MTLStorageModePrivate; + bool memoryless = false; if (@available(macos 11.0, ios 10.0, *)) { - bool memoryless = hasFlag(_info.flags, TextureFlagBit::LAZILY_ALLOCATED) && - hasFlag(_info.usage, TextureUsageBit::COLOR_ATTACHMENT) && - hasFlag(_info.usage, TextureUsageBit::DEPTH_STENCIL_ATTACHMENT); + memoryless = hasFlag(_info.flags, TextureFlagBit::LAZILY_ALLOCATED) && + hasAllFlags(TextureUsageBit::COLOR_ATTACHMENT | TextureUsageBit::DEPTH_STENCIL_ATTACHMENT | TextureUsageBit::INPUT_ATTACHMENT, _info.usage); if (memoryless) { descriptor.storageMode = MTLStorageModeMemoryless; _allocateMemory = false; } } + if (!memoryless && !_isPVRTC) { + // pvrtc can not use blit encoder to upload data. + descriptor.storageMode = MTLStorageModePrivate; + } + id mtlDevice = id(CCMTLDevice::getInstance()->getMTLDevice()); _mtlTexture = [mtlDevice newTextureWithDescriptor:descriptor]; From 1adef66108ca1af649515cb75b4f1ccf831a4dd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Wed, 9 Aug 2023 10:50:48 +0800 Subject: [PATCH 066/184] Mesh renderer(s) I18N (#15823) * Mesh renderers i18n * Update editor/i18n/en/rendering.js * Fix mesh renderer i18n * Update editor/i18n/en/modules/rendering.js --- cocos/3d/framework/mesh-renderer.ts | 49 ++++----- .../skinned-mesh-renderer.ts | 3 +- editor/i18n/en/localization.js | 10 +- editor/i18n/en/modules/rendering.js | 101 ++++++++++++++++++ editor/i18n/zh/localization.js | 10 +- editor/i18n/zh/modules/rendering.js | 101 ++++++++++++++++++ 6 files changed, 230 insertions(+), 44 deletions(-) create mode 100644 editor/i18n/en/modules/rendering.js create mode 100644 editor/i18n/zh/modules/rendering.js diff --git a/cocos/3d/framework/mesh-renderer.ts b/cocos/3d/framework/mesh-renderer.ts index 8b277d23e4c..ab371efe3d5 100644 --- a/cocos/3d/framework/mesh-renderer.ts +++ b/cocos/3d/framework/mesh-renderer.ts @@ -23,7 +23,7 @@ THE SOFTWARE. */ import { JSB } from 'internal:constants'; -import { displayName, displayOrder, group, range } from 'cc.decorator'; +import { displayOrder, group, range } from 'cc.decorator'; import { Texture2D, TextureCube } from '../../asset/assets'; import { Material } from '../../asset/assets/material'; import { Mesh } from '../assets/mesh'; @@ -44,7 +44,7 @@ import { SubModel } from '../../render-scene/scene'; import { isEnableEffect } from '../../rendering/define'; import type { Model } from '../../render-scene/scene'; -const { property, ccclass, help, executeInEditMode, executionOrder, menu, tooltip, visible, type, +const { ccclass, help, executeInEditMode, executionOrder, menu, visible, type, formerlySerializedAs, serializable, editable, disallowAnimation } = _decorator; let _phaseID = getPhaseID('specular-pass'); @@ -152,7 +152,7 @@ class ModelBakeSettings extends EventTarget { * @zh 模型是否是静态的并可以烘培光照贴图。 * 注意:模型顶点数据必须包含第二套 UV 属性来支持光照贴图烘焙。 */ - @group({ id: 'LightMap', name: 'LightMapSettings', displayOrder: 0, style: 'section' }) + @group({ id: 'LightMap', name: 'i18n:ENGINE.classes.cc.ModelBakeSettings.groups.LightMap.displayName', displayOrder: 0, style: 'section' }) @editable get bakeable (): boolean { return this._bakeable; @@ -166,7 +166,7 @@ class ModelBakeSettings extends EventTarget { * @en Whether to cast shadow in light map baking. * @zh 在光照贴图烘焙中是否投射阴影。 */ - @group({ id: 'LightMap', name: 'LightMapSettings' }) + @group({ id: 'LightMap', name: 'i18n:ENGINE.classes.cc.ModelBakeSettings.groups.LightMap.displayName' }) @editable get castShadow (): boolean { return this._castShadow; @@ -180,7 +180,7 @@ class ModelBakeSettings extends EventTarget { * @en Whether to receive shadow in light map baking. * @zh 在光照贴图烘焙中是否接受阴影。 */ - @group({ id: 'LightMap', name: 'LightMapSettings' }) + @group({ id: 'LightMap', name: 'i18n:ENGINE.classes.cc.ModelBakeSettings.groups.LightMap.displayName' }) @editable get receiveShadow (): boolean { return this._receiveShadow; @@ -194,7 +194,7 @@ class ModelBakeSettings extends EventTarget { * @en The lightmap size. * @zh 光照图大小。 */ - @group({ id: 'LightMap', name: 'LightMapSettings' }) + @group({ id: 'LightMap', name: 'i18n:ENGINE.classes.cc.ModelBakeSettings.groups.LightMap.displayName' }) @editable @type(CCInteger) @range([0, 1024]) @@ -210,7 +210,7 @@ class ModelBakeSettings extends EventTarget { * @en Whether to use light probe which provides indirect light to dynamic objects. * @zh 模型是否使用光照探针,光照探针为动态物体提供间接光。 */ - @group({ id: 'LightProbe', name: 'LightProbeSettings', displayOrder: 1, style: 'section' }) + @group({ id: 'LightProbe', name: 'i18n:ENGINE.classes.cc.ModelBakeSettings.groups.LightProbe.displayName', displayOrder: 1, style: 'section' }) @editable @type(CCBoolean) get useLightProbe (): boolean { @@ -226,7 +226,7 @@ class ModelBakeSettings extends EventTarget { * @en Whether the model is used to calculate light probe * @zh 模型是否用于计算光照探针 */ - @group({ id: 'LightProbe', name: 'LightProbeSettings' }) + @group({ id: 'LightProbe', name: 'i18n:ENGINE.classes.cc.ModelBakeSettings.groups.LightProbe.displayName' }) @editable @type(CCBoolean) get bakeToLightProbe (): boolean { @@ -241,7 +241,12 @@ class ModelBakeSettings extends EventTarget { * @en Used to set whether to use the reflection probe or set probe's type. * @zh 用于设置是否使用反射探针或者设置反射探针的类型。 */ - @group({ id: 'ReflectionProbe', name: 'ReflectionProbeSettings', displayOrder: 2, style: 'section' }) + @group({ + id: 'ReflectionProbe', + name: 'i18n:ENGINE.classes.cc.ModelBakeSettings.groups.ReflectionProbe.displayName', + displayOrder: 2, + style: 'section', + }) @type(Enum(ReflectionProbeType)) get reflectionProbe (): ReflectionProbeType { return this._reflectionProbeType; @@ -256,7 +261,7 @@ class ModelBakeSettings extends EventTarget { * @en Whether the model can be render by the reflection probe * @zh 模型是否能被反射探针渲染 */ - @group({ id: 'ReflectionProbe', name: 'ReflectionProbeSettings' }) + @group({ id: 'ReflectionProbe', name: 'i18n:ENGINE.classes.cc.ModelBakeSettings.groups.ReflectionProbe.displayName' }) @type(CCBoolean) get bakeToReflectionProbe (): boolean { return this._bakeToReflectionProbe; @@ -338,8 +343,12 @@ export class MeshRenderer extends ModelRenderer { * @zh 实时光照下模型局部的阴影偏移。 */ @type(CCFloat) - @tooltip('i18n:model.shadow_bias') - @group({ id: 'DynamicShadow', name: 'DynamicShadowSettings', displayOrder: 2, style: 'section' }) + @group({ + id: 'DynamicShadow', + name: 'i18n:ENGINE.classes.cc.MeshRenderer.groups.DynamicShadow.displayName', + displayOrder: 2, + style: 'section', + }) @disallowAnimation get shadowBias (): number { return this._shadowBias; @@ -356,8 +365,7 @@ export class MeshRenderer extends ModelRenderer { * @zh 实时光照下模型局部的阴影法线偏移。 */ @type(CCFloat) - @tooltip('i18n:model.shadow_normal_bias') - @group({ id: 'DynamicShadow', name: 'DynamicShadowSettings' }) + @group({ id: 'DynamicShadow', name: 'i18n:ENGINE.classes.cc.MeshRenderer.groups.DynamicShadow.displayName' }) @disallowAnimation get shadowNormalBias (): number { return this._shadowNormalBias; @@ -374,8 +382,7 @@ export class MeshRenderer extends ModelRenderer { * @zh 实时光照下阴影投射方式。 */ @type(ModelShadowCastingMode) - @tooltip('i18n:model.shadow_casting_model') - @group({ id: 'DynamicShadow', name: 'DynamicShadowSettings' }) + @group({ id: 'DynamicShadow', name: 'i18n:ENGINE.classes.cc.MeshRenderer.groups.DynamicShadow.displayName' }) @disallowAnimation @visible(false) get shadowCastingMode (): number { @@ -387,9 +394,7 @@ export class MeshRenderer extends ModelRenderer { this._updateCastShadow(); } - @displayName('Shadow Casting Mode') - @tooltip('i18n:model.shadow_casting_model') - @group({ id: 'DynamicShadow', name: 'DynamicShadowSettings' }) + @group({ id: 'DynamicShadow', name: 'i18n:ENGINE.classes.cc.MeshRenderer.groups.DynamicShadow.displayName' }) @disallowAnimation get shadowCastingModeForInspector (): boolean { return this.shadowCastingMode === ModelShadowCastingMode.ON; @@ -431,9 +436,7 @@ export class MeshRenderer extends ModelRenderer { this._updateReceiveShadow(); } - @displayName('Receive Shadow') - @tooltip('i18n:model.shadow_receiving_model') - @group({ id: 'DynamicShadow', name: 'DynamicShadowSettings' }) + @group({ id: 'DynamicShadow', name: 'i18n:ENGINE.classes.cc.MeshRenderer.groups.DynamicShadow.displayName' }) @disallowAnimation get receiveShadowForInspector (): boolean { return this._shadowReceivingMode === ModelShadowReceivingMode.ON; @@ -451,7 +454,6 @@ export class MeshRenderer extends ModelRenderer { */ @type(Mesh) @displayOrder(1) - @tooltip('i18n:model.mesh') get mesh (): Mesh | null { return this._mesh; } @@ -508,7 +510,6 @@ export class MeshRenderer extends ModelRenderer { * @zh 设置是否是全局的4s标准模型组件 */ @type(CCBoolean) - @tooltip('i18n:model.standard_skin_model') @disallowAnimation get isGlobalStandardSkinObject (): boolean { return this._enabledGlobalStandardSkinObject; diff --git a/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts b/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts index ef6a78cc522..7f3125b3275 100644 --- a/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts +++ b/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts @@ -24,7 +24,7 @@ */ import { - ccclass, executeInEditMode, executionOrder, help, menu, tooltip, type, + ccclass, executeInEditMode, executionOrder, help, menu, type, } from 'cc.decorator'; import type { AnimationClip } from '../../animation/animation-clip'; import { Material } from '../../asset/assets'; @@ -74,7 +74,6 @@ export class SkinnedMeshRenderer extends MeshRenderer { * @zh 骨骼根节点的引用,对应控制此模型的动画组件所在节点。 */ @type(Node) - @tooltip('i18n:model.skinning_root') get skinningRoot (): Node | null { return this._skinningRoot; } diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 287be46a1b1..58c8f5f6fe2 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -296,15 +296,6 @@ module.exports = link(mixin({ csmLayersTransition: 'Enable or disable CSM layers transition(Improve quality, reduce performance)', csmTransitionRange: 'CSM layers transition range(in NDC space: value range is 0 to 1)', }, - model: { - shadow_receiving_model: 'Shadow receive mode', - shadow_casting_model: 'Shadow projection mode', - mesh: 'The mesh of the model', - skinning_root: 'The skinning root, where the controlling Animation is located', - shadow_bias: 'Bias value (world space unit) that can avoid moire artifacts with shadows for model.
The more the value, the more the light leakage', - shadow_normal_bias: 'Bias value (world space unit) that can avoid moire artifacts with surfaces that parallel to the directional light', - standard_skin_model: 'Bias value (world space unit) that ensure globally unique standard skin model', - }, sprite: { gray_scale: 'Whether turn on grayscale rendering mode', sprite_frame: 'Sprite Frame image to use', @@ -1324,6 +1315,7 @@ module.exports = link(mixin({ }, }, +require('./modules/rendering'), require('./animation'), )); diff --git a/editor/i18n/en/modules/rendering.js b/editor/i18n/en/modules/rendering.js new file mode 100644 index 00000000000..3806a1f47a6 --- /dev/null +++ b/editor/i18n/en/modules/rendering.js @@ -0,0 +1,101 @@ +/* eslint-disable quote-props */ + +module.exports = { + classes: { + 'cc': { + 'ModelBakeSettings': { + groups: { + LightMap: { + displayName: 'Light Map Settings', + }, + LightProbe: { + displayName: 'Light Probe Settings', + }, + ReflectionProbe: { + displayName: 'Reflection Probe Settings', + }, + }, + properties: { + 'bakeable': { + displayName: 'Bakeable', + }, + 'castShadow': { + displayName: 'Cast Shadows', + }, + 'receiveShadow': { + displayName: 'Receive Shadows', + }, + 'lightmapSize': { + displayName: 'Light Map Size', + }, + 'useLightProbe': { + displayName: 'Use Light Probe', + }, + 'bakeToLightProbe': { + displayName: 'Bake To Light Probe', + }, + 'reflectionProbe': { + displayName: 'Reflection Probe', + }, + 'bakeToReflectionProbe': { + displayName: 'Bake To Reflection Probe', + }, + }, + }, + 'MeshRenderer': { + groups: { + DynamicShadow: { + displayName: 'Dynamic Shadow Settings', + }, + }, + properties: { + 'mesh': { + displayName: 'Mesh', + tooltip: 'The mesh asset.', + }, + 'sharedMaterials': { + displayName: 'Materials', + tooltip: 'Material array. Each item in turn specifies material of sub mesh.', + }, + 'shadowCastingModeForInspector': { + displayName: 'Cast Shadows', + tooltip: 'Whether if this mesh casts shadows.', + }, + 'receiveShadowForInspector': { + displayName: 'Receive Shadows', + tooltip: 'Whether if this mesh receives shadows.', + }, + 'shadowBias': { + displayName: 'Shadow Bias', + tooltip: 'Bias value (world space unit) that can avoid moire artifacts with shadows for model.
The more the value, the more the light leakage.', + }, + 'shadowNormalBias': { + displayName: 'Shadow Normal Bias', + tooltip: 'Bias value (world space unit) that can avoid moire artifacts with surfaces that parallel to the directional light.', + }, + 'bakeSettings': { + displayName: 'Bake Settings', + tooltip: 'Bake settings related to global lighting.', + }, + 'isGlobalStandardSkinObject': { + displayName: 'Global Standard Skin Object', + tooltip: 'The engine needs to know the scale of the model corresponding to the skin material in order to calculate the skin scattered light correctly. If no model is checked, the model with the skin material will be automatically selected for calculation.', + }, + }, + }, + 'SkinnedMeshRenderer': { + properties: { + __extends__: 'classes.cc.MeshRenderer.properties', + 'skeleton': { + displayName: 'Skeleton', + tooltip: 'Skeleton asset.', + }, + 'skinningRoot': { + displayName: 'Skinning Root', + tooltip: 'Reference to the root bone. In general, it\'s the node where animation component is located.', + }, + }, + }, + }, + }, +}; diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index fbb81ad5f56..7dd090de518 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -286,15 +286,6 @@ module.exports = link(mixin({ csmLayersTransition: '是否开启级联阴影层级过渡(提升质量,降低性能)', csmTransitionRange: '级联阴影层级过渡范围(NDC空间: 取值范围为 0 ~ 1)', }, - model: { - shadow_receiving_model: '阴影接受方式', - shadow_casting_model: '阴影投射方式', - mesh: '模型的网格数据', - skinning_root: '骨骼根节点的引用,对应控制此模型的动画组件所在节点', - shadow_bias: '模型额外增加深度偏移值(世界空间单位)可以有效消除阴影摩尔纹,但是过大的值可能造成漏光现象', - shadow_normal_bias: '模型额外增加法线深度偏移值(世界空间单位),可以消除物体表面朝向平行于阳光方向的阴影摩尔纹,
防止曲面出现锯齿状;但是过大的值可能会造成阴影位置偏差', - standard_skin_model: '模型额外设定全局唯一的标准皮肤模型', - }, sprite: { gray_scale: '是否开启灰度渲染模式', atlas: '图片资源所属的 Atlas 图集资源', @@ -1298,6 +1289,7 @@ module.exports = link(mixin({ }, }, +require('./modules/rendering'), require('./animation'), )); diff --git a/editor/i18n/zh/modules/rendering.js b/editor/i18n/zh/modules/rendering.js new file mode 100644 index 00000000000..c202e2eda20 --- /dev/null +++ b/editor/i18n/zh/modules/rendering.js @@ -0,0 +1,101 @@ +/* eslint-disable quote-props */ + +module.exports = { + classes: { + 'cc': { + 'ModelBakeSettings': { + groups: { + LightMap: { + displayName: '光照贴图设置', + }, + LightProbe: { + displayName: '光照探针设置', + }, + ReflectionProbe: { + displayName: '反射探针设置', + }, + }, + properties: { + 'bakeable': { + displayName: '可烘焙', + }, + 'castShadow': { + displayName: '投射阴影', + }, + 'receiveShadow': { + displayName: '接收阴影', + }, + 'lightmapSize': { + displayName: '光照贴图尺寸', + }, + 'useLightProbe': { + displayName: '使用光照探针', + }, + 'bakeToLightProbe': { + displayName: '烘焙至光照探针', + }, + 'reflectionProbe': { + displayName: '反射探针', + }, + 'bakeToReflectionProbe': { + displayName: '烘焙至反射探针', + }, + }, + }, + 'MeshRenderer': { + groups: { + DynamicShadow: { + displayName: '动态阴影设置', + }, + }, + properties: { + 'mesh': { + displayName: '网格', + tooltip: '网格资源。', + }, + 'sharedMaterials': { + displayName: '材质', + tooltip: '材质资源数组。每一项依次指定了子网格的材质。', + }, + 'shadowCastingModeForInspector': { + displayName: '投射阴影', + tooltip: '此网格是否投射阴影。', + }, + 'receiveShadowForInspector': { + displayName: '接收阴影', + tooltip: '此网格是否接收阴影。', + }, + 'shadowBias': { + displayName: '阴影偏移', + tooltip: '模型额外增加深度偏移值(世界空间单位)可以有效消除阴影摩尔纹,但是过大的值可能造成漏光现象。', + }, + 'shadowNormalBias': { + displayName: '阴影法线偏移', + tooltip: '模型额外增加法线深度偏移值(世界空间单位),可以消除物体表面朝向平行于阳光方向的阴影摩尔纹,
防止曲面出现锯齿状;但是过大的值可能会造成阴影位置偏差。', + }, + 'bakeSettings': { + displayName: '烘焙设置', + tooltip: '全局光照相关的烘焙设置。', + }, + 'isGlobalStandardSkinObject': { + displayName: '全局标准蒙皮模型', + tooltip: '模型额外设定全局唯一的标准皮肤模型', + }, + }, + }, + 'SkinnedMeshRenderer': { + properties: { + __extends__: 'classes.cc.MeshRenderer.properties', + 'skeleton': { + displayName: '骨骼', + tooltip: '骨骼资源。', + }, + 'skinningRoot': { + displayName: '蒙皮根', + tooltip: '骨骼根节点的引用,对应控制此模型的动画组件所在节点。', + }, + }, + }, + }, + }, +}; From 71eedef4faa85a2dc374c7143f31db64ffa08add Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Wed, 9 Aug 2023 11:23:30 +0800 Subject: [PATCH 067/184] add sorting & tiled help doc (#15900) * add sorting help doc * add tiled tile doc --- cocos/sorting/sorting.ts | 3 ++- editor/i18n/en/localization.js | 2 ++ editor/i18n/zh/localization.js | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/cocos/sorting/sorting.ts b/cocos/sorting/sorting.ts index a6516221c71..23d96b60451 100644 --- a/cocos/sorting/sorting.ts +++ b/cocos/sorting/sorting.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { ccclass, disallowMultiple, editable, executeInEditMode, menu, range, serializable, type } from 'cc.decorator'; +import { ccclass, disallowMultiple, editable, executeInEditMode, help, menu, range, serializable, type } from 'cc.decorator'; import { clamp } from '../core/math'; import { SortingLayers } from './sorting-layers'; import { Component } from '../scene-graph/component'; @@ -41,6 +41,7 @@ const MIN_INT16 = -1 << 15; */ @ccclass('cc.Sorting') @menu('Sorting/Sorting') +@help('i18n:cc.Sorting') @disallowMultiple @executeInEditMode export class Sorting extends Component { diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index 58c8f5f6fe2..ac6f45fe483 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -130,6 +130,7 @@ module.exports = link(mixin({ SafeArea: `${url}/${version}/manual/en/ui-system/components/editor/safearea.html`, Terrain: `${url}/${version}/manual/en/editor/terrain/`, TiledMap: `${url}/${version}/manual/en/editor/components/tiledmap.html`, + TiledTile: `${url}/${version}/manual/en/editor/components/tiledtile.html`, Spine: `${url}/${version}/manual/en/editor/components/spine.html`, DragonBones: `${url}/${version}/manual/en/editor/components/dragonbones.html`, OctreeCulling: `${url}/${version}/manual/en/advanced-topics/native-scene-culling.html`, @@ -145,6 +146,7 @@ module.exports = link(mixin({ Skin: `${url}/${version}/manual/en/shader/advanced-shader/skin.html`, RenderRoot2D: `${url}/${version}/manual/en/ui-system/components/editor/renderroot2d.html`, ReflectionProbe: `${url}/${version}/manual/en/concepts/scene/light/probe/reflection-art-workflow.html`, + Sorting: `${url}/${version}/manual/en/engine/rendering/sorting.html`, }, assets: { javascript: `${url}/${version}/manual/en/concepts/scene/node-component.html`, diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index 7dd090de518..a2c1052c6fb 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -130,6 +130,7 @@ module.exports = link(mixin({ SafeArea: `${url}/${version}/manual/zh/ui-system/components/editor/safearea.html`, Terrain: `${url}/${version}/manual/zh/editor/terrain/`, TiledMap: `${url}/${version}/manual/zh/editor/components/tiledmap.html`, + TiledTile: `${url}/${version}/manual/zh/editor/components/tiledtile.html`, Spine: `${url}/${version}/manual/zh/editor/components/spine.html`, DragonBones: `${url}/${version}/manual/zh/editor/components/dragonbones.html`, OctreeCulling: `${url}/${version}/manual/zh/advanced-topics/native-scene-culling.html`, @@ -145,6 +146,7 @@ module.exports = link(mixin({ Skin: `${url}/${version}/manual/zh/shader/advanced-shader/skin.html`, RenderRoot2D: `${url}/${version}/manual/zh/ui-system/components/editor/renderroot2d.html`, ReflectionProbe: `${url}/${version}/manual/zh/concepts/scene/light/probe/reflection-art-workflow.html`, + Sorting: `${url}/${version}/manual/zh/engine/rendering/sorting.html`, }, assets: { javascript: `${url}/${version}/manual/zh/concepts/scene/node-component.html`, From 904cdd8664d49dbb90f9ad5ce714f937989dee2f Mon Sep 17 00:00:00 2001 From: PP Date: Wed, 9 Aug 2023 11:25:38 +0800 Subject: [PATCH 068/184] fix: api issues in typedoc (#15826) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: typedoc wrong typeArguments update * fix: cull engineInternal tag * export Screen class * Update cocos/core/platform/index.ts Co-authored-by: Leslie Leigh (李的序) * fix typing * fix eslint # Conflicts: # cocos/core/platform/screen.ts * fix: cull engine internal with groups culling * Update cocos/core/platform/index.ts Co-authored-by: Leslie Leigh (李的序) * fix eslint * Update scripts/typedoc-plugin/src/cull-engine-internal.ts * optimize --------- Co-authored-by: Leslie Leigh (李的序) --- cocos/core/platform/index.ts | 1 + cocos/core/platform/screen.ts | 14 +- .../src/cull-engine-internal.ts | 146 ++++++++++ scripts/typedoc-plugin/src/plugin.ts | 23 +- .../engine-internal.test.ts.snap | 269 ++++++++++++++++++ .../fix-type-arguments.test.ts.snap | 229 +++++++++++++++ .../test/engine-internal.test.ts | 6 + .../test/fix-type-arguments.test.ts | 6 + .../test/inputs/link/engine-internal.ts | 74 +++++ .../test/inputs/link/fix-type-arguments.ts | 5 + 10 files changed, 765 insertions(+), 8 deletions(-) create mode 100644 scripts/typedoc-plugin/src/cull-engine-internal.ts create mode 100644 scripts/typedoc-plugin/test/__snapshots__/engine-internal.test.ts.snap create mode 100644 scripts/typedoc-plugin/test/__snapshots__/fix-type-arguments.test.ts.snap create mode 100644 scripts/typedoc-plugin/test/engine-internal.test.ts create mode 100644 scripts/typedoc-plugin/test/fix-type-arguments.test.ts create mode 100644 scripts/typedoc-plugin/test/inputs/link/engine-internal.ts create mode 100644 scripts/typedoc-plugin/test/inputs/link/fix-type-arguments.ts diff --git a/cocos/core/platform/index.ts b/cocos/core/platform/index.ts index 9109c0d9f05..7dd81eabbf4 100644 --- a/cocos/core/platform/index.ts +++ b/cocos/core/platform/index.ts @@ -45,3 +45,4 @@ export { } from './debug'; export { screen } from './screen'; +export type { Screen } from './screen'; diff --git a/cocos/core/platform/screen.ts b/cocos/core/platform/screen.ts index 0cfb92be0e6..97cffce324a 100644 --- a/cocos/core/platform/screen.ts +++ b/cocos/core/platform/screen.ts @@ -29,13 +29,13 @@ import { IScreenOptions, screenAdapter } from 'pal/screen-adapter'; import { legacyCC } from '../global-exports'; import { Size } from '../math'; import { Settings, settings } from '../settings'; -import { warnID } from './debug'; +import { error, warn, warnID } from './debug'; import { PalScreenEvent } from '../../../pal/screen-adapter/enum-type'; /** * @en The screen API provides an easy way to do some screen managing stuff. * @zh screen 单例对象提供简单的方法来做屏幕管理相关的工作。 */ -class Screen { +export class Screen { /** * @internal */ @@ -157,7 +157,7 @@ class Screen { return screenAdapter.requestFullScreen().then((): void => { onFullScreenChange?.call(document); // this case is only used on Web platforms, which is deprecated since v3.3.0 }).catch((err): void => { - console.error(err); + error(err); onFullScreenError?.call(document); // this case is only used on Web platforms, which is deprecated since v3.3.0 }); } @@ -180,7 +180,7 @@ class Screen { * @deprecated since v3.3, please use screen.requestFullScreen() instead. */ public autoFullScreen (element: HTMLElement, onFullScreenChange: (this: Document, ev: any) => any): void { - this.requestFullScreen(element, onFullScreenChange)?.catch((e): void => {}); + this.requestFullScreen(element, onFullScreenChange)?.catch((e): void => { warn(e); }); } /** @@ -198,7 +198,7 @@ class Screen { * @zh * 注册screen事件回调。 */ - public on (type: PalScreenEvent, callback: any, target?: any): void { + public on (type: PalScreenEvent, callback: (...args: any) => void, target?: any): void { screenAdapter.on(type, callback, target); } @@ -208,7 +208,7 @@ class Screen { * @zh * 注册单次的screen事件回调。 */ - public once (type: PalScreenEvent, callback?: any, target?: any): void { + public once (type: PalScreenEvent, callback: (...args: any) => void, target?: any): void { screenAdapter.once(type, callback, target); } @@ -218,7 +218,7 @@ class Screen { * @zh * 取消注册screen事件回调。 */ - public off (type: PalScreenEvent, callback?: any, target?: any): void { + public off (type: PalScreenEvent, callback?: (...args: any) => void, target?: any): void { screenAdapter.off(type, callback, target); } } diff --git a/scripts/typedoc-plugin/src/cull-engine-internal.ts b/scripts/typedoc-plugin/src/cull-engine-internal.ts new file mode 100644 index 00000000000..bce54586778 --- /dev/null +++ b/scripts/typedoc-plugin/src/cull-engine-internal.ts @@ -0,0 +1,146 @@ +import { Reflection, ReflectionKind, SerializeEvent } from "typedoc"; + +const TAG_ENGINE_INTERNAL = 'engineInternal'.toLowerCase(); + +export function cullEngineInternal (serializeOutput: SerializeEvent['output']): void { + traverseObject(serializeOutput); +} + +function hasTagEngineInternal (obj: Reflection): boolean { + if (obj.comment?.tags) { + for (const tagItem of obj.comment.tags) { + // @ts-expect-error Property 'tag' does not exist on type 'CommentTag'. + if (tagItem.tag === TAG_ENGINE_INTERNAL) { + return true; + } + } + return false; + } + return false; +} + +function traverseObject (obj: Record, recentGroups?: any[]): void { + for (const key in obj) { + if (key === 'groups') { + continue; + } + const item = obj[key]; + if (typeof item === 'number' || typeof item === 'string' || typeof item === 'undefined') { + continue; + } + if (Array.isArray(item)) { + traverseArray(item, obj.groups ?? recentGroups); + } else { + traverseObject(item, obj.groups ?? recentGroups); + } + } +} + +function traverseArray (arr: Array, recentGroups?: any[]): void { + for (let i = arr.length - 1; i >= 0; --i) { + const item = arr[i]; + if (typeof item === 'number' || typeof item === 'string') { + continue; + } + if (Array.isArray(item)) { + traverseArray(item, recentGroups); + } else { + if (handleObject(item)) { + const index = arr.indexOf(item); + if (index > -1) { + arr.splice(index, 1); + } + if (recentGroups) { + const group = recentGroups.find((group: Record) => group.kind === item.kind); + if (group) { + const groupChildIndex = group.children.indexOf(item.id); + if (groupChildIndex > -1) { + group.children.splice(groupChildIndex, 1); + } + if (group.children.length === 0) { + const groupIndex = recentGroups.findIndex((group: Record) => group.kind === item.kind); + if (groupIndex > -1) { + recentGroups.splice(groupIndex, 1); + } + } + } + } + } else { + traverseObject(item, recentGroups); + } + } + } +} + +function isReflection (obj: Record): obj is Reflection { + return typeof obj.kind !== 'undefined'; +} + +/** + * @returns whether we need to remove the object from array + */ +function handleObject (obj: Record): boolean { + if (!isReflection(obj)) { + return false; + } + switch(obj.kind) { + case ReflectionKind.Namespace: + case ReflectionKind.Enum: + case ReflectionKind.EnumMember: + case ReflectionKind.Variable: + case ReflectionKind.Class: + case ReflectionKind.Interface: + case ReflectionKind.Constructor: + case ReflectionKind.Property: + case ReflectionKind.CallSignature: + case ReflectionKind.IndexSignature: + case ReflectionKind.ConstructorSignature: + case ReflectionKind.TypeLiteral: + case ReflectionKind.TypeAlias: + case ReflectionKind.GetSignature: + case ReflectionKind.SetSignature: + return hasTagEngineInternal(obj); + case ReflectionKind.Function: + case ReflectionKind.Method: + return handleFunctionOrMethod(obj); + case ReflectionKind.Accessor: + return handleAccessor(obj); + default: + return false; + + } +} + +/** + * @returns whether we need to remove the object from array + */ +function handleFunctionOrMethod (funcOrMethod: Record): boolean { + if (Array.isArray(funcOrMethod.signatures)) { + traverseArray(funcOrMethod.signatures); + if (funcOrMethod.signatures.length === 0) { + return true; + } + } + return false; +} + +/** + * @returns whether we need to remove the object from array + */ +function handleAccessor (accessor: Record): boolean { + let needRemove = true; + if (Array.isArray(accessor.getSignature)) { + traverseArray(accessor.getSignature); + if (accessor.getSignature.length !== 0) { + needRemove = false; + } + } + if (Array.isArray(accessor.setSignature)) { + traverseArray(accessor.setSignature); + if (accessor.setSignature.length !== 0) { + needRemove = false; + } + } + return needRemove; +} + diff --git a/scripts/typedoc-plugin/src/plugin.ts b/scripts/typedoc-plugin/src/plugin.ts index 2a41cfbf11a..5cdec3328b8 100644 --- a/scripts/typedoc-plugin/src/plugin.ts +++ b/scripts/typedoc-plugin/src/plugin.ts @@ -1,8 +1,9 @@ // eslint-disable-next-line import/no-extraneous-dependencies -import { Application, Converter, Context, Reflection, Comment, CommentTag, SerializerComponent, ReflectionKind, SignatureReflection, ProjectReflection, ContainerReflection, DeclarationReflection, ParameterReflection, ReferenceReflection } from 'typedoc'; +import { Application, Converter, Context, Reflection, Comment, CommentTag, SerializerComponent, ReflectionKind, SignatureReflection, ProjectReflection, ContainerReflection, DeclarationReflection, Serializer, SerializeEvent, ReferenceReflection } from 'typedoc'; import ts from 'typescript'; import fs from 'fs-extra'; import ps from 'path'; +import { cullEngineInternal } from './cull-engine-internal'; const TAG_NAME_CC_CATEGORY = 'ccCategory'; @@ -55,6 +56,10 @@ export function load (app: Application) { }); }); + app.serializer.on(Serializer.EVENT_END, (serializeEvent: SerializeEvent) => { + cullEngineInternal(serializeEvent.output) + }); + type ReflectionId = Reflection['id']; type CategoryInfo = { @@ -114,6 +119,7 @@ export function load (app: Application) { } function onCreateSignature (_context: Context, reflection: SignatureReflection, node?: ts.Node) { + fixTypeArguments(_context, reflection, node); handleTagLegacyPublic(_context, reflection, node); } @@ -163,6 +169,21 @@ export function load (app: Application) { comment.tags.push(new CommentTag('deprecated', undefined, 'This key is reserved for internal usage.')); } + // NOTE: this is a bug on typedoc, we fix in this plugin. + // should not generate typeArguments field in typeParameters' type field. + function fixTypeArguments (_context: Context, reflection: SignatureReflection, node?: ts.Node) { + if (reflection.typeParameters) { + for (const typeParam of reflection.typeParameters) { + // @ts-ignore + const typeArguments = typeParam.type?.typeArguments; + if (typeArguments?.[0]?.name === typeParam.name) { + // @ts-ignore + delete typeParam.type.typeArguments; + } + } + } + } + function setCategory (reflectionId: ReflectionId, categoryId: string, categoryConfig: CategoryConfig) { (categoryMap[categoryId] ??= { ...categoryConfig, diff --git a/scripts/typedoc-plugin/test/__snapshots__/engine-internal.test.ts.snap b/scripts/typedoc-plugin/test/__snapshots__/engine-internal.test.ts.snap new file mode 100644 index 00000000000..5d7aa31f2ca --- /dev/null +++ b/scripts/typedoc-plugin/test/__snapshots__/engine-internal.test.ts.snap @@ -0,0 +1,269 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`fix type arguments 1`] = ` +Object { + "categories": undefined, + "ccCategories": Array [], + "children": Array [ + Object { + "categories": undefined, + "children": Array [ + Object { + "categories": undefined, + "children": undefined, + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": undefined, + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object {}, + "groups": undefined, + "id": 10, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 512, + "kindString": "Constructor", + "name": "constructor", + "overwrites": undefined, + "signatures": Array [ + Object { + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "flags": Object {}, + "id": 11, + "implementationOf": undefined, + "inheritedFrom": undefined, + "kind": 16384, + "kindString": "Constructor signature", + "name": "new Class2", + "overwrites": undefined, + "parameters": undefined, + "type": Object { + "id": 6, + "name": "Class2", + "type": "reference", + }, + "typeParameter": undefined, + }, + ], + "sources": undefined, + "type": undefined, + "typeParameter": undefined, + }, + ], + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": undefined, + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object {}, + "groups": Array [ + Object { + "children": Array [ + 10, + ], + "kind": 512, + "title": "Constructors", + }, + ], + "id": 6, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 128, + "kindString": "Class", + "name": "Class2", + "overwrites": undefined, + "signatures": undefined, + "sources": Array [ + Object { + "character": 13, + "fileName": "engine-internal.ts", + "line": 6, + }, + ], + "type": undefined, + "typeParameter": undefined, + }, + Object { + "categories": undefined, + "children": Array [], + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": undefined, + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object {}, + "groups": Array [], + "id": 27, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 256, + "kindString": "Interface", + "name": "Interface2", + "overwrites": undefined, + "signatures": undefined, + "sources": Array [ + Object { + "character": 17, + "fileName": "engine-internal.ts", + "line": 55, + }, + ], + "type": undefined, + "typeParameter": undefined, + }, + Object { + "categories": undefined, + "children": undefined, + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": "...", + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object { + "isConst": true, + }, + "groups": undefined, + "id": 21, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 32, + "kindString": "Variable", + "name": "obj2", + "overwrites": undefined, + "signatures": undefined, + "sources": Array [ + Object { + "character": 13, + "fileName": "engine-internal.ts", + "line": 38, + }, + ], + "type": Object { + "declaration": Object { + "categories": undefined, + "children": Array [ + Object { + "categories": undefined, + "children": undefined, + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": "1", + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object {}, + "groups": undefined, + "id": 23, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 1024, + "kindString": "Property", + "name": "testProp", + "overwrites": undefined, + "signatures": undefined, + "sources": undefined, + "type": Object { + "name": "number", + "type": "intrinsic", + }, + "typeParameter": undefined, + }, + ], + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": undefined, + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object {}, + "groups": Array [ + Object { + "children": Array [ + 23, + ], + "kind": 1024, + "title": "Properties", + }, + ], + "id": 22, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 65536, + "kindString": "Type literal", + "name": "__type", + "overwrites": undefined, + "signatures": undefined, + "sources": undefined, + "type": undefined, + "typeParameter": undefined, + }, + "type": "reflection", + }, + "typeParameter": undefined, + }, + ], + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "flags": Object {}, + "groups": Array [ + Object { + "children": Array [ + 6, + ], + "kind": 128, + "title": "Classes", + }, + Object { + "children": Array [ + 27, + ], + "kind": 256, + "title": "Interfaces", + }, + Object { + "children": Array [ + 21, + ], + "kind": 32, + "title": "Variables", + }, + ], + "id": 0, + "kind": 1, + "kindString": "Project", + "name": "typedoc-plugin-cc", + "originalName": "", + "sources": Array [ + Object { + "character": 0, + "fileName": "engine-internal.ts", + "line": 4, + }, + ], +} +`; diff --git a/scripts/typedoc-plugin/test/__snapshots__/fix-type-arguments.test.ts.snap b/scripts/typedoc-plugin/test/__snapshots__/fix-type-arguments.test.ts.snap new file mode 100644 index 00000000000..574e4c8c8dd --- /dev/null +++ b/scripts/typedoc-plugin/test/__snapshots__/fix-type-arguments.test.ts.snap @@ -0,0 +1,229 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`fix type arguments 1`] = ` +Object { + "categories": undefined, + "ccCategories": Array [], + "children": Array [ + Object { + "categories": undefined, + "children": Array [ + Object { + "categories": undefined, + "children": undefined, + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": undefined, + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object {}, + "groups": undefined, + "id": 6, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 512, + "kindString": "Constructor", + "name": "constructor", + "overwrites": undefined, + "signatures": Array [ + Object { + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "flags": Object {}, + "id": 7, + "implementationOf": undefined, + "inheritedFrom": undefined, + "kind": 16384, + "kindString": "Constructor signature", + "name": "new A", + "overwrites": undefined, + "parameters": undefined, + "type": Object { + "id": 5, + "name": "A", + "type": "reference", + }, + "typeParameter": undefined, + }, + ], + "sources": undefined, + "type": undefined, + "typeParameter": undefined, + }, + ], + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": undefined, + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object {}, + "groups": Array [ + Object { + "children": Array [ + 6, + ], + "kind": 512, + "title": "Constructors", + }, + ], + "id": 5, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 128, + "kindString": "Class", + "name": "A", + "overwrites": undefined, + "signatures": undefined, + "sources": Array [ + Object { + "character": 13, + "fileName": "fix-type-arguments.ts", + "line": 1, + }, + ], + "type": undefined, + "typeParameter": undefined, + }, + Object { + "categories": undefined, + "children": undefined, + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": undefined, + "extendedBy": undefined, + "extendedTypes": undefined, + "flags": Object {}, + "groups": undefined, + "id": 1, + "implementationOf": undefined, + "implementedBy": undefined, + "implementedTypes": undefined, + "indexSignature": undefined, + "inheritedFrom": undefined, + "kind": 64, + "kindString": "Function", + "name": "test", + "overwrites": undefined, + "signatures": Array [ + Object { + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "flags": Object {}, + "id": 2, + "implementationOf": undefined, + "inheritedFrom": undefined, + "kind": 4096, + "kindString": "Call signature", + "name": "test", + "overwrites": undefined, + "parameters": Array [ + Object { + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "defaultValue": undefined, + "flags": Object {}, + "id": 4, + "kind": 32768, + "kindString": "Parameter", + "name": "t", + "type": Object { + "id": 5, + "name": "A", + "type": "reference", + }, + }, + ], + "type": Object { + "name": "Record", + "package": "typescript", + "qualifiedName": "Record", + "type": "reference", + "typeArguments": Array [ + Object { + "name": "string", + "type": "intrinsic", + }, + Object { + "id": 3, + "name": "T", + "type": "reference", + }, + ], + }, + "typeParameter": Array [ + Object { + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "default": undefined, + "flags": Object {}, + "id": 3, + "kind": 131072, + "kindString": "Type parameter", + "name": "T", + "type": Object { + "id": 5, + "name": "A", + "type": "reference", + }, + }, + ], + }, + ], + "sources": Array [ + Object { + "character": 16, + "fileName": "fix-type-arguments.ts", + "line": 3, + }, + ], + "type": undefined, + "typeParameter": undefined, + }, + ], + "comment": undefined, + "decorates": undefined, + "decorators": undefined, + "flags": Object {}, + "groups": Array [ + Object { + "children": Array [ + 5, + ], + "kind": 128, + "title": "Classes", + }, + Object { + "children": Array [ + 1, + ], + "kind": 64, + "title": "Functions", + }, + ], + "id": 0, + "kind": 1, + "kindString": "Project", + "name": "typedoc-plugin-cc", + "originalName": "", + "sources": Array [ + Object { + "character": 0, + "fileName": "fix-type-arguments.ts", + "line": 1, + }, + ], +} +`; diff --git a/scripts/typedoc-plugin/test/engine-internal.test.ts b/scripts/typedoc-plugin/test/engine-internal.test.ts new file mode 100644 index 00000000000..2c822b23de8 --- /dev/null +++ b/scripts/typedoc-plugin/test/engine-internal.test.ts @@ -0,0 +1,6 @@ +import ps from 'path'; +import { runTest } from './test-util'; + +test(`fix type arguments`, async () => { + await runTest(ps.join(__dirname, './inputs/link/'), 'engine-internal.ts'); +}); diff --git a/scripts/typedoc-plugin/test/fix-type-arguments.test.ts b/scripts/typedoc-plugin/test/fix-type-arguments.test.ts new file mode 100644 index 00000000000..ec63153deff --- /dev/null +++ b/scripts/typedoc-plugin/test/fix-type-arguments.test.ts @@ -0,0 +1,6 @@ +import ps from 'path'; +import { runTest } from './test-util'; + +test(`fix type arguments`, async () => { + await runTest(ps.join(__dirname, './inputs/link/'), 'fix-type-arguments.ts'); +}); diff --git a/scripts/typedoc-plugin/test/inputs/link/engine-internal.ts b/scripts/typedoc-plugin/test/inputs/link/engine-internal.ts new file mode 100644 index 00000000000..091d0c9ecd4 --- /dev/null +++ b/scripts/typedoc-plugin/test/inputs/link/engine-internal.ts @@ -0,0 +1,74 @@ +/** + * @engineInternal + */ +export class Class1 {} + +export class Class2 { + /** + * @engineInternal + */ + static testStaticProp: number; + /** + * @engineInternal + */ + static testStaticMdthod() {}; + /** + * @engineInternal + */ + get getterSetter (): number { return 1; } + /** + * @engineInternal + */ + set getterSetter (a: number) {} + /** + * @engineInternal + */ + testProp: number; + /** + * @engineInternal + */ + testMethod () {} +} + +/** + * @engineInternal + */ +export const obj1 = {} + +export const obj2 = { + /** + * @engineInternal + */ + testProp: 1, + /** + * @engineInternal + */ + testMethod () {}, + +} + +/** + * @engineInternal + */ +export interface Interface1 {} + +export interface Interface2 { + /** + * @engineInternal + */ + testProp: number; + /** + * @engineInternal + */ + testMethod (); +} + +/** + * @engineInternal + */ +export function testFunc () {} + +/** + * @engineInternal + */ +export enum TestEnum {} \ No newline at end of file diff --git a/scripts/typedoc-plugin/test/inputs/link/fix-type-arguments.ts b/scripts/typedoc-plugin/test/inputs/link/fix-type-arguments.ts new file mode 100644 index 00000000000..5b353bacb20 --- /dev/null +++ b/scripts/typedoc-plugin/test/inputs/link/fix-type-arguments.ts @@ -0,0 +1,5 @@ +export class A {} + +export function test(t: A): Record { + throw 'not impl'; +} From 8c1a005d215591b76ac2a364db5a802aa11b6e18 Mon Sep 17 00:00:00 2001 From: mmyduckx <308303735@qq.com> Date: Wed, 9 Aug 2023 11:27:39 +0800 Subject: [PATCH 069/184] add http patch request process (#15898) --- .../bindings/manual/jsb_xmlhttprequest.cpp | 5 ++++- native/cocos/network/HttpClient-apple.mm | 6 +++++- native/cocos/network/HttpClient-java.cpp | 8 +++++++- native/cocos/network/HttpClient.cpp | 18 ++++++++++++++++++ native/cocos/network/HttpRequest.h | 1 + .../com/cocos/lib/CocosHttpURLConnection.java | 3 ++- .../com/cocos/lib/CocosHttpURLConnection.java | 1 + platforms/native/builtin/jsb-adapter/fetch.js | 2 +- 8 files changed, 39 insertions(+), 5 deletions(-) diff --git a/native/cocos/bindings/manual/jsb_xmlhttprequest.cpp b/native/cocos/bindings/manual/jsb_xmlhttprequest.cpp index dd37ca74f4c..fdf44d48355 100644 --- a/native/cocos/bindings/manual/jsb_xmlhttprequest.cpp +++ b/native/cocos/bindings/manual/jsb_xmlhttprequest.cpp @@ -261,6 +261,9 @@ bool XMLHttpRequest::open(const ccstd::string &method, const ccstd::string &url) requestType = HttpRequest::Type::HEAD; } else if (_method == "delete" || _method == "DELETE") { requestType = HttpRequest::Type::DELETE; + } else if (_method == "patch" || _method == "PATCH") { + requestType = HttpRequest::Type::PATCH; + } CC_ASSERT(requestType != HttpRequest::Type::UNKNOWN); @@ -513,7 +516,7 @@ void XMLHttpRequest::sendRequest() { void XMLHttpRequest::setHttpRequestData(const char *data, size_t len) { if (len > 0 && - (_method == "post" || _method == "POST" || _method == "put" || _method == "PUT")) { + (_method == "post" || _method == "POST" || _method == "put" || _method == "PUT" || _method == "patch" || _method == "PATCH")) { _httpRequest->setRequestData(data, len); } } diff --git a/native/cocos/network/HttpClient-apple.mm b/native/cocos/network/HttpClient-apple.mm index b0335c69952..bcafaf913e6 100644 --- a/native/cocos/network/HttpClient-apple.mm +++ b/native/cocos/network/HttpClient-apple.mm @@ -165,7 +165,7 @@ static int processTask(HttpClient *client, HttpRequest *request, NSString *reque } //if request type is post or put,set header and data - if ([requestType isEqual:@"POST"] || [requestType isEqual:@"PUT"]) { + if ([requestType isEqual:@"POST"] || [requestType isEqual:@"PUT"] || [requestType isEqual:@"PATCH"]) { char *requestDataBuffer = request->getRequestData(); if (nullptr != requestDataBuffer && 0 != request->getRequestDataSize()) { NSData *postData = [NSData dataWithBytes:requestDataBuffer length:request->getRequestDataSize()]; @@ -466,6 +466,10 @@ static int processTask(HttpClient *client, HttpRequest *request, NSString *reque requestType = @"DELETE"; break; + case HttpRequest::Type::PATCH: + requestType = @"PATCH"; + break; + default: CC_ABORT(); break; diff --git a/native/cocos/network/HttpClient-java.cpp b/native/cocos/network/HttpClient-java.cpp index 0e1ec005a3d..86b1d94ddce 100644 --- a/native/cocos/network/HttpClient-java.cpp +++ b/native/cocos/network/HttpClient-java.cpp @@ -634,6 +634,11 @@ void HttpClient::processResponse(HttpResponse *response, char *responseMessage) case HttpRequest::Type::DELETE: urlConnection.setRequestMethod("DELETE"); break; + + case HttpRequest::Type::PATCH: + urlConnection.setRequestMethod("PATCH"); + break; + default: break; } @@ -647,7 +652,8 @@ void HttpClient::processResponse(HttpResponse *response, char *responseMessage) } if (HttpRequest::Type::POST == requestType || - HttpRequest::Type::PUT == requestType) { + HttpRequest::Type::PUT == requestType || + HttpRequest::Type::PATCH == requestType) { urlConnection.sendRequest(request); } diff --git a/native/cocos/network/HttpClient.cpp b/native/cocos/network/HttpClient.cpp index 5476f9c79ac..f4a728992a5 100644 --- a/native/cocos/network/HttpClient.cpp +++ b/native/cocos/network/HttpClient.cpp @@ -76,6 +76,7 @@ static int processGetTask(HttpClient *client, HttpRequest *request, write_callba static int processPostTask(HttpClient *client, HttpRequest *request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char *errorBuffer); static int processPutTask(HttpClient *client, HttpRequest *request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char *errorBuffer); static int processDeleteTask(HttpClient *client, HttpRequest *request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char *errorBuffer); +static int processPatchTask(HttpClient *client, HttpRequest *request, write_callback callback, void *stream, long *errorCode, write_callback headerCallback, void *headerStream, char *errorBuffer); // int processDownloadTask(HttpRequest *task, write_callback callback, void *stream, int32_t *errorCode); // Worker thread @@ -307,6 +308,13 @@ static int processDeleteTask(HttpClient *client, HttpRequest *request, write_cal return ok ? 0 : 1; } +//Process PATCH Request +static int processPatchTask(HttpClient *client, HttpRequest *request, write_callback callback, void *stream, long *responseCode, write_callback headerCallback, void *headerStream, char *errorBuffer) { + CURLRaii curl; + bool ok = curl.init(client, request, callback, stream, headerCallback, headerStream, errorBuffer) && curl.setOption(CURLOPT_CUSTOMREQUEST, "PATCH") && curl.setOption(CURLOPT_POSTFIELDS, request->getRequestData()) && curl.setOption(CURLOPT_POSTFIELDSIZE, request->getRequestDataSize()) && curl.perform(responseCode); + return ok ? 0 : 1; +} + // HttpClient implementation HttpClient *HttpClient::getInstance() { if (_httpClient == nullptr) { @@ -511,6 +519,16 @@ void HttpClient::processResponse(HttpResponse *response, char *responseMessage) responseMessage); break; + case HttpRequest::Type::PATCH: + retValue = processPatchTask(this, request, + writeData, + response->getResponseData(), + &responseCode, + writeHeaderData, + response->getResponseHeader(), + responseMessage); + break; + default: CC_ABORT(); break; diff --git a/native/cocos/network/HttpRequest.h b/native/cocos/network/HttpRequest.h index 31d01f04b6e..ef0ffbf4a2c 100644 --- a/native/cocos/network/HttpRequest.h +++ b/native/cocos/network/HttpRequest.h @@ -72,6 +72,7 @@ class CC_DLL HttpRequest : public RefCounted { PUT, DELETE, HEAD, + PATCH, UNKNOWN, }; diff --git a/native/cocos/platform/android/java/src/com/cocos/lib/CocosHttpURLConnection.java b/native/cocos/platform/android/java/src/com/cocos/lib/CocosHttpURLConnection.java index c5bb2e72c44..221298649c7 100644 --- a/native/cocos/platform/android/java/src/com/cocos/lib/CocosHttpURLConnection.java +++ b/native/cocos/platform/android/java/src/com/cocos/lib/CocosHttpURLConnection.java @@ -59,6 +59,7 @@ public class CocosHttpURLConnection private static String TAG = "CocosHttpURLConnection"; private static final String POST_METHOD = "POST" ; private static final String PUT_METHOD = "PUT" ; + private static final String PATCH_METHOD = "PATCH" ; static HttpURLConnection createHttpURLConnection(String linkURL) { URL url; @@ -86,7 +87,7 @@ static void setReadAndConnectTimeout(HttpURLConnection urlConnection, int readMi static void setRequestMethod(HttpURLConnection urlConnection, String method){ try { urlConnection.setRequestMethod(method); - if(method.equalsIgnoreCase(POST_METHOD) || method.equalsIgnoreCase(PUT_METHOD)) { + if(method.equalsIgnoreCase(POST_METHOD) || method.equalsIgnoreCase(PUT_METHOD) || method.equalsIgnoreCase(PATCH_METHOD)) { urlConnection.setDoOutput(true); } } catch (ProtocolException e) { diff --git a/native/cocos/platform/ohos/libcocos/src/main/java/com/cocos/lib/CocosHttpURLConnection.java b/native/cocos/platform/ohos/libcocos/src/main/java/com/cocos/lib/CocosHttpURLConnection.java index e2faea71ed6..fb3d202a455 100644 --- a/native/cocos/platform/ohos/libcocos/src/main/java/com/cocos/lib/CocosHttpURLConnection.java +++ b/native/cocos/platform/ohos/libcocos/src/main/java/com/cocos/lib/CocosHttpURLConnection.java @@ -61,6 +61,7 @@ public class CocosHttpURLConnection { private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0, "CocosHttpURLConnection"); private static final String POST_METHOD = "POST"; private static final String PUT_METHOD = "PUT"; + private static final String PATCH_METHOD = "PATCH"; @SuppressWarnings("unused") static HttpURLConnection createHttpURLConnection(String linkURL) { diff --git a/platforms/native/builtin/jsb-adapter/fetch.js b/platforms/native/builtin/jsb-adapter/fetch.js index 2ec5efb8686..e776a89f9ee 100644 --- a/platforms/native/builtin/jsb-adapter/fetch.js +++ b/platforms/native/builtin/jsb-adapter/fetch.js @@ -289,7 +289,7 @@ function Body () { } // HTTP methods whose capitalization should be normalized -const methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']; +const methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'PATCH']; function normalizeMethod (method) { const upcased = method.toUpperCase(); From b48581d91a42a3bf5419ff2dc503c9cb23cca89c Mon Sep 17 00:00:00 2001 From: hyde zhou Date: Wed, 9 Aug 2023 15:23:40 +0800 Subject: [PATCH 070/184] V3.8.1 pipeline (#15875) --- cocos/core/geometry/intersect.ts | 54 +- cocos/gfx/base/define.ts | 3 +- cocos/render-scene/scene/camera.ts | 39 +- cocos/rendering/custom/compiler.ts | 118 +- cocos/rendering/custom/define.ts | 65 +- cocos/rendering/custom/executor.ts | 418 +- cocos/rendering/custom/scene-culling.ts | 416 ++ cocos/rendering/custom/web-pipeline-types.ts | 234 + cocos/rendering/custom/web-pipeline.ts | 36 +- .../post-process/passes/forward-pass.ts | 20 +- .../post-process/passes/skin-pass.ts | 52 +- .../cocos/renderer/gfx-base/GFXDef-common.h | 16 +- native/cocos/renderer/gfx-base/GFXTexture.cpp | 2 + native/cocos/renderer/gfx-base/GFXTexture.h | 2 +- .../renderer/gfx-gles3/GLES3Commands.cpp | 19 +- .../renderer/gfx-gles3/GLES3GPUObjects.h | 2 + .../renderer/gfx-gles3/GLES3PipelineState.cpp | 12 +- .../cocos/renderer/gfx-gles3/GLES3Texture.cpp | 2 + .../renderer/gfx-metal/MTLCommandBuffer.mm | 11 +- native/cocos/renderer/gfx-metal/MTLDevice.mm | 2 +- .../renderer/gfx-metal/MTLPipelineState.mm | 5 +- .../cocos/renderer/gfx-metal/MTLRenderPass.mm | 8 +- native/cocos/renderer/gfx-metal/MTLShader.mm | 8 +- native/cocos/renderer/gfx-metal/MTLTexture.mm | 11 +- native/cocos/renderer/gfx-metal/MTLUtils.h | 3 +- native/cocos/renderer/gfx-metal/MTLUtils.mm | 20 +- .../cocos/renderer/gfx-vulkan/VKCommands.cpp | 31 +- .../cocos/renderer/gfx-vulkan/VKGPUObjects.h | 2 + .../cocos/renderer/gfx-vulkan/VKTexture.cpp | 4 + .../pipeline/custom/FGDispatcherGraphs.h | 1786 +++---- .../pipeline/custom/FGDispatcherTypes.cpp | 280 +- .../pipeline/custom/FGDispatcherTypes.h | 953 ++-- .../pipeline/custom/FrameGraphDispatcher.cpp | 4130 ++++++++--------- .../pipeline/custom/NativeExecutor.cpp | 359 +- .../pipeline/custom/NativePipeline.cpp | 50 +- .../pipeline/custom/NativeRenderGraph.cpp | 36 +- .../pipeline/custom/NativeRenderGraphUtils.h | 13 + .../pipeline/custom/NativeResourceGraph.cpp | 35 +- .../pipeline/custom/NativeSceneCulling.cpp | 55 +- .../renderer/pipeline/custom/test/test.h | 300 +- .../src/complicated_barrier_case.cpp | 201 +- .../unit-test/src/simple_barrier_test.cpp | 40 +- .../src/simple_closed_barrier_test.cpp | 137 +- 43 files changed, 4951 insertions(+), 5039 deletions(-) create mode 100644 cocos/rendering/custom/scene-culling.ts create mode 100644 cocos/rendering/custom/web-pipeline-types.ts diff --git a/cocos/core/geometry/intersect.ts b/cocos/core/geometry/intersect.ts index 157b6578dfa..fff0a2702dc 100644 --- a/cocos/core/geometry/intersect.ts +++ b/cocos/core/geometry/intersect.ts @@ -413,10 +413,12 @@ const lineTriangle = (function (): (line: Line, triangle: Triangle, outPt?: Vec3 const u = 1.0 - v - w; // outPt = u*a + v*d + w*c; - Vec3.set(outPt, + Vec3.set( + outPt, triangle.a.x * u + triangle.b.x * v + triangle.c.x * w, triangle.a.y * u + triangle.b.y * v + triangle.c.y * w, - triangle.a.z * u + triangle.b.z * v + triangle.c.z * w); + triangle.a.z * u + triangle.b.z * v + triangle.c.z * w, + ); } return 1; @@ -527,38 +529,54 @@ function getAABBVertices (min: Vec3, max: Vec3, out: Vec3[]): void { } function getOBBVertices (c: Vec3, e: Vec3, a1: Vec3, a2: Vec3, a3: Vec3, out: Vec3[]): void { - Vec3.set(out[0], + Vec3.set( + out[0], c.x + a1.x * e.x + a2.x * e.y + a3.x * e.z, c.y + a1.y * e.x + a2.y * e.y + a3.y * e.z, - c.z + a1.z * e.x + a2.z * e.y + a3.z * e.z); - Vec3.set(out[1], + c.z + a1.z * e.x + a2.z * e.y + a3.z * e.z, + ); + Vec3.set( + out[1], c.x - a1.x * e.x + a2.x * e.y + a3.x * e.z, c.y - a1.y * e.x + a2.y * e.y + a3.y * e.z, - c.z - a1.z * e.x + a2.z * e.y + a3.z * e.z); - Vec3.set(out[2], + c.z - a1.z * e.x + a2.z * e.y + a3.z * e.z, + ); + Vec3.set( + out[2], c.x + a1.x * e.x - a2.x * e.y + a3.x * e.z, c.y + a1.y * e.x - a2.y * e.y + a3.y * e.z, - c.z + a1.z * e.x - a2.z * e.y + a3.z * e.z); - Vec3.set(out[3], + c.z + a1.z * e.x - a2.z * e.y + a3.z * e.z, + ); + Vec3.set( + out[3], c.x + a1.x * e.x + a2.x * e.y - a3.x * e.z, c.y + a1.y * e.x + a2.y * e.y - a3.y * e.z, - c.z + a1.z * e.x + a2.z * e.y - a3.z * e.z); - Vec3.set(out[4], + c.z + a1.z * e.x + a2.z * e.y - a3.z * e.z, + ); + Vec3.set( + out[4], c.x - a1.x * e.x - a2.x * e.y - a3.x * e.z, c.y - a1.y * e.x - a2.y * e.y - a3.y * e.z, - c.z - a1.z * e.x - a2.z * e.y - a3.z * e.z); - Vec3.set(out[5], + c.z - a1.z * e.x - a2.z * e.y - a3.z * e.z, + ); + Vec3.set( + out[5], c.x + a1.x * e.x - a2.x * e.y - a3.x * e.z, c.y + a1.y * e.x - a2.y * e.y - a3.y * e.z, - c.z + a1.z * e.x - a2.z * e.y - a3.z * e.z); - Vec3.set(out[6], + c.z + a1.z * e.x - a2.z * e.y - a3.z * e.z, + ); + Vec3.set( + out[6], c.x - a1.x * e.x + a2.x * e.y - a3.x * e.z, c.y - a1.y * e.x + a2.y * e.y - a3.y * e.z, - c.z - a1.z * e.x + a2.z * e.y - a3.z * e.z); - Vec3.set(out[7], + c.z - a1.z * e.x + a2.z * e.y - a3.z * e.z, + ); + Vec3.set( + out[7], c.x - a1.x * e.x - a2.x * e.y + a3.x * e.z, c.y - a1.y * e.x - a2.y * e.y + a3.y * e.z, - c.z - a1.z * e.x - a2.z * e.y + a3.z * e.z); + c.z - a1.z * e.x - a2.z * e.y + a3.z * e.z, + ); } function getInterval (vertices: any[] | Vec3[], axis: Vec3): number[] { diff --git a/cocos/gfx/base/define.ts b/cocos/gfx/base/define.ts index 53eeb4062cb..6e614fb3630 100644 --- a/cocos/gfx/base/define.ts +++ b/cocos/gfx/base/define.ts @@ -407,7 +407,8 @@ export enum TextureFlagBit { GENERAL_LAYOUT = 0x2, // For inout framebuffer attachments EXTERNAL_OES = 0x4, // External oes texture EXTERNAL_NORMAL = 0x8, // External normal texture - LAZILY_ALLOCATED = 0x10 // Try lazily allocated mode. + LAZILY_ALLOCATED = 0x10, // Try lazily allocated mode. + MUTABLE_VIEW_FORMAT = 0x40, // texture view as different format } export enum FormatFeatureBit { diff --git a/cocos/render-scene/scene/camera.ts b/cocos/render-scene/scene/camera.ts index 31171d10aca..ab8cedbd6c2 100644 --- a/cocos/render-scene/scene/camera.ts +++ b/cocos/render-scene/scene/camera.ts @@ -1032,14 +1032,33 @@ export class Camera { const wndXREye = xr.webXRWindowMap.get(this._window); this._matProj.set(xr.webXRMatProjs[wndXREye]); } else { - Mat4.perspective(this._matProj, this._fov, this._aspect, this._nearClip, this._farClip, - this._fovAxis === CameraFOVAxis.VERTICAL, this._device.capabilities.clipSpaceMinZ, projectionSignY, orientation); + Mat4.perspective( + this._matProj, + this._fov, + this._aspect, + this._nearClip, + this._farClip, + this._fovAxis === CameraFOVAxis.VERTICAL, + this._device.capabilities.clipSpaceMinZ, + projectionSignY, + orientation, + ); } } else { const x = this._orthoHeight * this._aspect; const y = this._orthoHeight; - Mat4.ortho(this._matProj, -x, x, -y, y, this._nearClip, this._farClip, - this._device.capabilities.clipSpaceMinZ, projectionSignY, orientation); + Mat4.ortho( + this._matProj, + -x, + x, + -y, + y, + this._nearClip, + this._farClip, + this._device.capabilities.clipSpaceMinZ, + projectionSignY, + orientation, + ); } Mat4.invert(this._matProjInv, this._matProj); viewProjDirty = true; @@ -1240,10 +1259,12 @@ export class Camera { if (this._proj === CameraProjection.PERSPECTIVE) { // calculate screen pos in far clip plane - Vec3.set(out, + Vec3.set( + out, (screenPos.x - cx) / cw * 2 - 1, (screenPos.y - cy) / ch * 2 - 1, - 1.0); + 1.0, + ); // transform to world const { x, y } = out; @@ -1256,10 +1277,12 @@ export class Camera { Vec3.lerp(out, v_a, out, lerp(this._nearClip / this._farClip, 1, screenPos.z)); } else { - Vec3.set(out, + Vec3.set( + out, (screenPos.x - cx) / cw * 2 - 1, (screenPos.y - cy) / ch * 2 - 1, - screenPos.z * 2 - 1); + screenPos.z * 2 - 1, + ); // transform to world const { x, y } = out; diff --git a/cocos/rendering/custom/compiler.ts b/cocos/rendering/custom/compiler.ts index 651729239d3..da170462e25 100644 --- a/cocos/rendering/custom/compiler.ts +++ b/cocos/rendering/custom/compiler.ts @@ -32,68 +32,50 @@ import { Blit, ClearView, ComputePass, ComputeSubpass, CopyPass, Dispatch, Forma RasterPass, RasterSubpass, RaytracePass, RenderGraph, RenderGraphVisitor, RasterView, ComputeView, RenderQueue, RenderSwapchain, ResolvePass, ResourceGraph, ResourceGraphVisitor, SceneData, SubresourceView } from './render-graph'; import { AccessType, ResourceResidency, SceneFlags } from './types'; +import { hashCombineNum, hashCombineStr } from './define'; -let hashCode = 0; - -function hashCombine (hash): void { - hashCode ^= (hash >>> 0) + 0x9e3779b9 + (hashCode << 6) + (hashCode >> 2); -} - -function hashCombineNum (val: number): void { - const hash = 5381; - hashCombine((hash * 33) ^ val); -} - -function hashCombineStr (str: string): void { - // DJB2 HASH - let hash = 5381; - for (let i = 0; i < str.length; i++) { - hash = (hash * 33) ^ str.charCodeAt(i); - } - hashCombine(hash); -} function genHashValue (pass: RasterPass): void { - hashCode = 0; + let hashCode = 0; for (const [name, raster] of pass.rasterViews) { - hashCombineStr('raster'); - hashCombineStr(name); - hashCombineStr(raster.slotName); - hashCombineNum(raster.accessType); - hashCombineNum(raster.attachmentType); - hashCombineNum(raster.loadOp); - hashCombineNum(raster.storeOp); - hashCombineNum(raster.clearFlags); - hashCombineNum(raster.clearColor.x); - hashCombineNum(raster.clearColor.y); - hashCombineNum(raster.clearColor.z); - hashCombineNum(raster.clearColor.w); - hashCombineNum(raster.slotID); - hashCombineNum(raster.shaderStageFlags); + hashCode = hashCombineStr('raster', hashCode); + hashCode = hashCombineStr(name, hashCode); + hashCode = hashCombineStr(raster.slotName, hashCode); + hashCode = hashCombineNum(raster.accessType, hashCode); + hashCode = hashCombineNum(raster.attachmentType, hashCode); + hashCode = hashCombineNum(raster.loadOp, hashCode); + hashCode = hashCombineNum(raster.storeOp, hashCode); + hashCode = hashCombineNum(raster.clearFlags, hashCode); + hashCode = hashCombineNum(raster.clearColor.x, hashCode); + hashCode = hashCombineNum(raster.clearColor.y, hashCode); + hashCode = hashCombineNum(raster.clearColor.z, hashCode); + hashCode = hashCombineNum(raster.clearColor.w, hashCode); + hashCode = hashCombineNum(raster.slotID, hashCode); + hashCode = hashCombineNum(raster.shaderStageFlags, hashCode); } for (const [name, computes] of pass.computeViews) { - hashCombineStr(name); + hashCode = hashCombineStr(name, hashCode); for (const compute of computes) { - hashCombineStr('compute'); - hashCombineStr(compute.name); - hashCombineNum(compute.accessType); - hashCombineNum(compute.clearFlags); - hashCombineNum(compute.clearValueType); - hashCombineNum(compute.clearValue.x); - hashCombineNum(compute.clearValue.y); - hashCombineNum(compute.clearValue.z); - hashCombineNum(compute.clearValue.w); - hashCombineNum(compute.shaderStageFlags); + hashCode = hashCombineStr('compute', hashCode); + hashCode = hashCombineStr(compute.name, hashCode); + hashCode = hashCombineNum(compute.accessType, hashCode); + hashCode = hashCombineNum(compute.clearFlags, hashCode); + hashCode = hashCombineNum(compute.clearValueType, hashCode); + hashCode = hashCombineNum(compute.clearValue.x, hashCode); + hashCode = hashCombineNum(compute.clearValue.y, hashCode); + hashCode = hashCombineNum(compute.clearValue.z, hashCode); + hashCode = hashCombineNum(compute.clearValue.w, hashCode); + hashCode = hashCombineNum(compute.shaderStageFlags, hashCode); } } - hashCombineNum(pass.width); - hashCombineNum(pass.height); - hashCombineNum(pass.viewport.left); - hashCombineNum(pass.viewport.top); - hashCombineNum(pass.viewport.width); - hashCombineNum(pass.viewport.height); - hashCombineNum(pass.viewport.minDepth); - hashCombineNum(pass.viewport.maxDepth); - hashCombineNum(pass.showStatistics ? 1 : 0); + hashCode = hashCombineNum(pass.width, hashCode); + hashCode = hashCombineNum(pass.height, hashCode); + hashCode = hashCombineNum(pass.viewport.left, hashCode); + hashCode = hashCombineNum(pass.viewport.top, hashCode); + hashCode = hashCombineNum(pass.viewport.width, hashCode); + hashCode = hashCombineNum(pass.viewport.height, hashCode); + hashCode = hashCombineNum(pass.viewport.minDepth, hashCode); + hashCode = hashCombineNum(pass.viewport.maxDepth, hashCode); + hashCode = hashCombineNum(pass.showStatistics ? 1 : 0, hashCode); pass.hashValue = hashCode; } @@ -157,8 +139,10 @@ class PassVisitor implements RenderGraphVisitor { isPreRaster = true; // TODO: Shadow map is rather special, as it will be merged into one pass later, and then this determination can be removed. if (!this._isShadowMap(this.sceneID)) { - assert(currRaster.loadOp === LoadOp.LOAD, - `The resource with name ${input} is being used, and the pass that uses this resource must have loadOp set to 'load'`); + assert( + currRaster.loadOp === LoadOp.LOAD, + `The resource with name ${input} is being used, and the pass that uses this resource must have loadOp set to 'load'`, + ); } } } @@ -287,7 +271,7 @@ class PassVisitor implements RenderGraphVisitor { this._currPass = value; const outputId = this.resID; const outputName = resourceGraph.vertexName(outputId); - let vertID; + let vertID: number; for (const pair of value.copyPairs) { if (pair.target === outputName) { rg.setValid(this.passID, true); @@ -345,7 +329,7 @@ class PassManagerVisitor extends DefaultVisitor { class ResourceVisitor implements ResourceGraphVisitor { private readonly _context: CompilerContext; public resID = 0xFFFFFFFF; - private _passManagerVis; + private _passManagerVis!: PassManagerVisitor; constructor (context: CompilerContext) { this._context = context; } @@ -392,10 +376,12 @@ class ResourceUseContext { computes: Map = new Map(); } class CompilerContext { - set (pipeline: BasicPipeline, + set ( + pipeline: BasicPipeline, resGraph: ResourceGraph, renderGraph: RenderGraph, - layoutGraph: LayoutGraphData): void { + layoutGraph: LayoutGraphData, + ): void { this.pipeline = pipeline; this.resourceGraph = resGraph; this.renderGraph = renderGraph; @@ -417,10 +403,12 @@ export class Compiler { private _pipeline: BasicPipeline; private _layoutGraph: LayoutGraphData; private _visitor: ResourceManagerVisitor; - constructor (pipeline: BasicPipeline, + constructor ( + pipeline: BasicPipeline, renderGraph: RenderGraph, resGraph: ResourceGraph, - layoutGraph: LayoutGraphData) { + layoutGraph: LayoutGraphData, + ) { this._pipeline = pipeline; this._resourceGraph = resGraph; this._layoutGraph = layoutGraph; @@ -447,8 +435,10 @@ export class Compiler { const firstRaster = use.rasters.get(min)!; switch (trait.residency) { case ResourceResidency.PERSISTENT: - assert(firstRaster.loadOp !== LoadOp.DISCARD, - `The loadOp for persistent resources in the top-level pass cannot be set to 'discard'.`); + assert( + firstRaster.loadOp !== LoadOp.DISCARD, + `The loadOp for persistent resources in the top-level pass cannot be set to 'discard'.`, + ); break; case ResourceResidency.MANAGED: assert(firstRaster.loadOp === LoadOp.CLEAR, `The loadOp for Managed resources in the top-level pass can only be set to 'clear'.`); diff --git a/cocos/rendering/custom/define.ts b/cocos/rendering/custom/define.ts index a2a983c9b3b..b131e820357 100644 --- a/cocos/rendering/custom/define.ts +++ b/cocos/rendering/custom/define.ts @@ -44,9 +44,9 @@ import { Vec2, Vec3, Vec4, macro, geometry, toRadian, cclegacy, assert, nextPow2 import { ImageAsset, Material, Texture2D } from '../../asset/assets'; import { getProfilerCamera, SRGBToLinear } from '../pipeline-funcs'; import { RenderWindow } from '../../render-scene/core/render-window'; -import { RenderData } from './render-graph'; +import { RenderData, RenderGraph } from './render-graph'; import { WebPipeline } from './web-pipeline'; -import { DescriptorSetData } from './layout-graph'; +import { DescriptorSetData, LayoutGraph, LayoutGraphData } from './layout-graph'; import { AABB } from '../../core/geometry'; import { DebugViewCompositeType, DebugViewSingleType } from '../debug-view'; import { ReflectionProbeManager } from '../../3d/reflection-probe/reflection-probe-manager'; @@ -685,7 +685,7 @@ export function buildShadowPass ( queue.addSceneOfCamera( camera, new LightInfo(light, level), - SceneFlags.SHADOW_CASTER, + SceneFlags.SHADOW_CASTER | SceneFlags.OPAQUE_OBJECT | SceneFlags.TRANSPARENT_OBJECT, ); queue.setViewport(new Viewport(area.x, area.y, area.width, area.height)); } @@ -706,6 +706,7 @@ export function buildReflectionProbePasss ( } else if (EDITOR) { for (let faceIdx = 0; faceIdx < probe.bakedCubeTextures.length; faceIdx++) { probe.updateCameraDir(faceIdx); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument buildReflectionProbePass(camera, ppl, probe, probe.bakedCubeTextures[faceIdx].window!, faceIdx); } probe.needRender = false; @@ -1127,7 +1128,9 @@ function applyGlobalDescBinding (data: RenderData, layout: string, isUpdate = fa const constants = data.constants; const samplers = data.samplers; const textures = data.textures; - const device = cclegacy.director.root.device; + const root = cclegacy.director.root; + const device = root.device; + const pipeline = root.pipeline as WebPipeline; const descriptorSetData = getDescriptorSetDataFromLayout(layout)!; const descriptorSet = descriptorSetData.descriptorSet!; for (const [key, value] of constants) { @@ -1160,7 +1163,7 @@ function applyGlobalDescBinding (data: RenderData, layout: string, isUpdate = fa const bindId = getDescBinding(key, descriptorSetData); if (bindId === -1) { continue; } const tex = descriptorSet.getTexture(bindId); - if (!tex || isUpdate) { + if (!tex || (isUpdate && value !== pipeline.defaultTexture)) { bindGlobalDesc(descriptorSet, bindId, value); } } @@ -1168,7 +1171,7 @@ function applyGlobalDescBinding (data: RenderData, layout: string, isUpdate = fa const bindId = getDescBinding(key, descriptorSetData); if (bindId === -1) { continue; } const sampler = descriptorSet.getSampler(bindId); - if (!sampler || isUpdate) { + if (!sampler || (isUpdate && value !== pipeline.defaultSampler)) { bindGlobalDesc(descriptorSet, bindId, value); } } @@ -2440,3 +2443,53 @@ export function buildClusterPasses (camera: Camera, pipeline: BasicPipeline): vo buildLightClusterBuildPass(camera, _clusterLightData, ppl); buildLightClusterCullingPass(camera, _clusterLightData, ppl); } + +function hashCombine (hash, currHash: number): number { + return currHash ^= (hash >>> 0) + 0x9e3779b9 + (currHash << 6) + (currHash >> 2); +} + +export function hashCombineNum (val: number, currHash: number): number { + const hash = 5381; + return hashCombine((hash * 33) ^ val, currHash); +} + +export function hashCombineStr (str: string, currHash: number): number { + // DJB2 HASH + let hash = 5381; + for (let i = 0; i < str.length; i++) { + hash = (hash * 33) ^ str.charCodeAt(i); + } + return hashCombine(hash, currHash); +} + +export function bool (val): boolean { + return !!val; +} + +export function getSubpassOrPassID (sceneId: number, rg: RenderGraph, lg: LayoutGraphData): number { + const queueId = rg.getParent(sceneId); + assert(queueId !== 0xFFFFFFFF); + const subpassOrPassID = rg.getParent(queueId); + assert(subpassOrPassID !== 0xFFFFFFFF); + const passId = rg.getParent(subpassOrPassID); + let layoutId = lg.nullVertex(); + // single render pass + if (passId === rg.nullVertex()) { + const layoutName: string = rg.getLayout(subpassOrPassID); + assert(!!layoutName); + layoutId = lg.locateChild(lg.nullVertex(), layoutName); + } else { + const passLayoutName: string = rg.getLayout(passId); + assert(!!passLayoutName); + const passLayoutId = lg.locateChild(lg.nullVertex(), passLayoutName); + assert(passLayoutId !== lg.nullVertex()); + + const subpassLayoutName: string = rg.getLayout(subpassOrPassID); + assert(!!subpassLayoutName); + const subpassLayoutId = lg.locateChild(passLayoutId, subpassLayoutName); + assert(subpassLayoutId !== lg.nullVertex()); + layoutId = subpassLayoutId; + } + assert(layoutId !== lg.nullVertex()); + return layoutId; +} diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 548ab24cc3d..445a712e1ed 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -72,7 +72,7 @@ import { import { legacyCC } from '../../core/global-exports'; import { Vec3 } from '../../core/math/vec3'; import { Vec4 } from '../../core/math/vec4'; -import { BatchingSchemes, Pass } from '../../render-scene'; +import { Pass } from '../../render-scene'; import { Camera } from '../../render-scene/scene/camera'; import { ShadowType } from '../../render-scene/scene/shadows'; import { Root } from '../../root'; @@ -125,8 +125,6 @@ import { PipelineUBO } from '../pipeline-ubo'; import { RenderInfo, RenderObject, WebSceneTask, WebSceneTransversal } from './web-scene'; import { WebSceneVisitor } from './web-scene-visitor'; import { RenderAdditiveLightQueue } from '../render-additive-light-queue'; -import { RenderShadowMapBatchedQueue } from '../render-shadow-map-batched-queue'; -import { PlanarShadowQueue } from '../planar-shadow-queue'; import { DefaultVisitor, depthFirstSearch, ReferenceGraphView } from './graph'; import { VectorGraphColorMap } from './effect'; import { @@ -141,6 +139,7 @@ import { import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; import { builtinResMgr } from '../../asset/asset-manager/builtin-res-mgr'; import { Texture2D } from '../../asset/assets/texture-2d'; +import { SceneCulling } from './scene-culling'; class ResourceVisitor implements ResourceGraphVisitor { name: string; @@ -448,7 +447,7 @@ class BlitDesc { const deferredLitsBufView = context.blit.deferredLitsBufView; this._lightBufferData = context.blit.lightBufferData; this._lightBufferData.fill(0); - const binding = isEnableEffect() ? getDescBindingFromName('CCForwardLight') : UBOForwardLight.BINDING; + // const binding = isEnableEffect() ? getDescBindingFromName('CCForwardLight') : UBOForwardLight.BINDING; this._stageDesc.bindBuffer(UBOForwardLight.BINDING, deferredLitsBufView); } this._stageDesc.bindBuffer(UBOLocal.BINDING, context.blit.emptyLocalUBO); @@ -506,7 +505,7 @@ class DeviceRenderQueue { } this.queueId = id; this._devicePass = devicePass; - if (isEnableEffect()) this._phaseID = cclegacy.rendering.getPhaseID(devicePass.passID, context.renderGraph.getLayout(id) || 'default'); + this._phaseID = cclegacy.rendering.getPhaseID(devicePass.passID, context.renderGraph.getLayout(id)); if (!this._sceneVisitor) { this._sceneVisitor = new WebSceneVisitor( context.commandBuffer, @@ -573,39 +572,11 @@ class DeviceRenderQueue { } class SubmitInfo { - public instances = new Set(); - public renderInstanceQueue: InstancedBuffer[] = []; - public opaqueList: RenderInfo[] = []; - public transparentList: RenderInfo[] = []; - public planarQueue: PlanarShadowQueue | null = null; // - public shadowMap: Map = new Map(); public additiveLight: RenderAdditiveLightQueue | null = null; public reflectionProbe: RenderReflectionProbeQueue | null = null; - private _clearInstances (): void { - const it = this.instances.values(); let res = it.next(); - while (!res.done) { - res.value.clear(); - res = it.next(); - } - this.instances.clear(); - } - - private _clearShadowMap (): void { - for (const shadowMap of this.shadowMap) { - shadowMap[1].clear(); - } - this.shadowMap.clear(); - } - reset (): void { - this._clearInstances(); - this.renderInstanceQueue.length = 0; - this.opaqueList.length = 0; - this.transparentList.length = 0; - this.planarQueue = null; - this._clearShadowMap(); this.additiveLight = null; this.reflectionProbe = null; } @@ -961,23 +932,7 @@ class DeviceRenderPass { cmdBuff.endRenderPass(); } - private _clear (): void { - for (const [cam, infoMap] of context.submitMap) { - for (const [id, info] of infoMap) { - info.additiveLight?.clear(); - const it = info.instances.values(); let res = it.next(); - while (!res.done) { - res.value.clear(); - res = it.next(); - } - info.renderInstanceQueue = []; - info.instances.clear(); - } - } - } - postPass (): void { - this._clear(); // this.submitMap.clear(); for (const queue of this._deviceQueues) { queue.postRecord(); @@ -1151,182 +1106,17 @@ class DevicePreSceneTask extends WebSceneTask { public start (): void { if (this.graphScene.blit) { this._currentQueue.createBlitDesc(this.graphScene.blit); - return; - } - if (!this.camera) { - return; } - const devicePass = this._currentQueue.devicePass; - const submitMap = context.submitMap; - let submitInfoMap = submitMap.get(this.camera); - if (submitInfoMap && submitInfoMap.has(this._currentQueue.phaseID)) { - this._submitInfo = submitInfoMap.get(this._currentQueue.phaseID)!; - } else { - if (!submitInfoMap) { - submitInfoMap = new Map(); - submitMap.set(this.camera, submitInfoMap); - } - this._submitInfo = new SubmitInfo(); - submitInfoMap.set(this._currentQueue.phaseID, this._submitInfo); - } - // culling - if ((!isShadowMap(this.graphScene) || (isShadowMap(this.graphScene) && this.graphScene.scene!.light.level === 0)) - && this.camera !== context.cullCamera) { - super.start(); - context.cullCamera = this.camera; - } - - // shadowmap - if (isShadowMap(this.graphScene)) { - const scene = this.graphScene.scene!; - assert(scene.light.light !== null); - let shadowQueue = this._submitInfo.shadowMap.get(this.graphScene.sceneID); - if (!shadowQueue) { - shadowQueue = new RenderShadowMapBatchedQueue(context.pipeline); - this._submitInfo.shadowMap.set(this.graphScene.sceneID, shadowQueue); - } - this.sceneData.shadowFrameBufferMap.set(scene.light.light, devicePass.framebuffer); - shadowQueue.gatherLightPasses(this.camera, scene.light.light, this._cmdBuff, scene.light.level); - return; - } - // reflection probe - if (this.graphScene.scene!.flags & SceneFlags.REFLECTION_PROBE && !this._submitInfo.reflectionProbe) { - this._submitInfo.reflectionProbe = context.pools.addReflectionProbe(); - this._submitInfo.reflectionProbe.clear(); - if (cclegacy.internal.reflectionProbeManager) { - const probes = cclegacy.internal.reflectionProbeManager.getProbes(); - for (let i = 0; i < probes.length; i++) { - if (probes[i].hasFrameBuffer(this._currentQueue.devicePass.framebuffer)) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this._submitInfo.reflectionProbe.gatherRenderObjects(probes[i], this.camera, this._cmdBuff); - break; - } - } - } - return; - } - const sceneFlag = this._graphScene.scene!.flags; - // If it is not empty, it means that it has been added and will not be traversed. - const isEmpty = !this._submitInfo.opaqueList.length - && !this._submitInfo.transparentList.length - && !this._submitInfo.instances.size; - if (isEmpty) { - for (const ro of this.sceneData.renderObjects) { - const subModels = ro.model.subModels; - for (const subModel of subModels) { - const passes = subModel.passes; - for (const p of passes) { - if (((isEnableEffect()) ? p.phaseID : p.phase) !== this._currentQueue.phaseID) continue; - const batchingScheme = p.batchingScheme; - if (batchingScheme === BatchingSchemes.INSTANCING) { - const instancedBuffer = p.getInstancedBuffer(); - instancedBuffer.merge(subModel, passes.indexOf(p)); - this._submitInfo.instances.add(instancedBuffer); - } else { - this._insertRenderList(ro, subModels.indexOf(subModel), passes.indexOf(p)); - this._insertRenderList(ro, subModels.indexOf(subModel), passes.indexOf(p), true); - } - } - } - } - this._instancedSort(); - } - if (sceneFlag & SceneFlags.DEFAULT_LIGHTING) { - this._submitInfo.additiveLight = context.additiveLight; - validPunctualLightsCulling(context.pipeline, this.camera); - this._submitInfo.additiveLight.gatherLightPasses(this.camera, this._cmdBuff, this._currentQueue.devicePass.layoutName); - } - if (sceneFlag & SceneFlags.PLANAR_SHADOW) { - this._submitInfo.planarQueue = context.planarShadow; - this._submitInfo.planarQueue.gatherShadowPasses(this.camera, this._cmdBuff); - } - if (sceneFlag & SceneFlags.OPAQUE_OBJECT) { this._submitInfo.opaqueList.sort(this._opaqueCompareFn); } - if (sceneFlag & SceneFlags.TRANSPARENT_OBJECT) { this._submitInfo.transparentList.sort(this._transparentCompareFn); } - } - - protected _instancedSort (): void { - let it = this._submitInfo!.instances.values(); - let res = it.next(); - while (!res.done) { - if (!(res.value.pass.blendState.targets[0].blend)) { - this._submitInfo!.renderInstanceQueue.push(res.value); - } - res = it.next(); - } - it = this._submitInfo!.renderInstanceQueue.values(); - res = it.next(); - while (!res.done) { - if (res.value.pass.blendState.targets[0].blend) { - this._submitInfo!.renderInstanceQueue.push(res.value); - } - res = it.next(); - } - } - - protected _insertRenderList (ro: RenderObject, subModelIdx: number, passIdx: number, isTransparent = false): void { - const subModel = ro.model.subModels[subModelIdx]; - const pass: Pass = subModel.passes[passIdx]; - const shader = subModel.shaders[passIdx]; - const currTransparent = pass.blendState.targets[0].blend; - const devicePass = this._currentQueue.devicePass; - const passId = devicePass.passID; - const phase = isEnableEffect() ? this._currentQueue.phaseID // | cclegacy.rendering.getPhaseID(passId, 'planarShadow') - : getPhaseID('default') | getPhaseID('planarShadow'); - if (currTransparent !== isTransparent || !(pass.phaseID & (isTransparent ? phase : this._currentQueue.phaseID))) { - return; - } - const hash = (0 << 30) | pass.priority as number << 16 | subModel.priority as number << 8 | passIdx; - const rp = context.pools.addPassInfo(); - rp.priority = ro.model.priority; - rp.hash = hash; - rp.depth = ro.depth || 0; - rp.shaderId = shader.typedID; - rp.subModel = subModel; - rp.passIdx = passIdx; - if (isTransparent) this._submitInfo!.transparentList.push(rp); - else this._submitInfo!.opaqueList.push(rp); - } - - /** - * @en Comparison sorting function. Opaque objects are sorted by priority -> depth front to back -> shader ID. - * @zh 比较排序函数。不透明对象按优先级 -> 深度由前向后 -> Shader ID 顺序排序。 - */ - protected _opaqueCompareFn (a: RenderInfo, b: RenderInfo): number { - return (a.hash - b.hash) || (a.depth - b.depth) || (a.shaderId - b.shaderId); - } - /** - * @en Comparison sorting function. Transparent objects are sorted by priority -> depth back to front -> shader ID. - * @zh 比较排序函数。半透明对象按优先级 -> 深度由后向前 -> Shader ID 顺序排序。 - */ - protected _transparentCompareFn (a: RenderInfo, b: RenderInfo): number { - return (a.priority - b.priority) || (a.hash - b.hash) || (b.depth - a.depth) || (a.shaderId - b.shaderId); - } - - private _uploadInstanceBuffers (): void { - if (this._currentQueue.isUploadInstance) return; - const it = this._submitInfo!.instances.values(); let res = it.next(); - while (!res.done) { - if (res.value.hasPendingModels) res.value.uploadBuffers(this._cmdBuff); - res = it.next(); - } - this._currentQueue.isUploadInstance = true; - } - - protected _updateGlobal (data: RenderData): void { - const devicePass = this._currentQueue.devicePass; - updateGlobalDescBinding(data, isEnableEffect() ? context.renderGraph.getLayout(devicePass.rasterPassInfo.id) : 'default'); - if (!isEnableEffect()) context.pipeline.descriptorSet.update(); } public submit (): void { if (this.graphScene.blit) { this._currentQueue.blitDesc!.update(); - return; - } - if (isShadowMap(this.graphScene)) { - return; } - this._uploadInstanceBuffers(); + // if (isShadowMap(this.graphScene)) { + + // } + // this._uploadInstanceBuffers(); } } @@ -1358,70 +1148,7 @@ class DeviceSceneTask extends WebSceneTask { } get graphScene (): GraphScene { return this._graphScene; } public start (): void {} - protected _recordRenderList (isTransparent: boolean): void { - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - const renderList = isTransparent ? currSubmitInfo.transparentList - : currSubmitInfo.opaqueList; - for (let i = 0; i < renderList.length; ++i) { - const { subModel, passIdx } = renderList[i]; - const inputAssembler: InputAssembler = subModel.inputAssembler; - const pass: Pass = subModel.passes[passIdx]; - const shader: Shader = subModel.shaders[passIdx]; - const descriptorSet: DescriptorSet = subModel.descriptorSet; - const pso = PipelineStateManager.getOrCreatePipelineState( - deviceManager.gfxDevice, - pass, - shader, - this._renderPass, - inputAssembler, - ); - this.visitor.bindPipelineState(pso); - this.visitor.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); - this.visitor.bindDescriptorSet(SetIndex.LOCAL, descriptorSet); - this.visitor.bindInputAssembler(inputAssembler); - this.visitor.draw(inputAssembler); - } - } - protected _recordOpaqueList (): void { - this._recordRenderList(false); - } - protected _recordInstences (): void { - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - const it = currSubmitInfo.renderInstanceQueue.length === 0 - ? currSubmitInfo.instances.values() - : currSubmitInfo.renderInstanceQueue.values(); - let res = it.next(); - while (!res.done) { - const { instances, pass, hasPendingModels } = res.value; - if (hasPendingModels) { - this.visitor.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); - let lastPSO: PipelineState | null = null; - for (let b = 0; b < instances.length; ++b) { - const instance = instances[b]; - if (!instance.count) { continue; } - const shader = instance.shader!; - const pso = PipelineStateManager.getOrCreatePipelineState( - deviceManager.gfxDevice, - pass, - shader, - this._renderPass, - instance.ia, - ); - if (lastPSO !== pso) { - this.visitor.bindPipelineState(pso); - lastPSO = pso; - } - const ia: InputAssembler = instance.ia; - this.visitor.bindDescriptorSet(SetIndex.LOCAL, instance.descriptorSet, res.value.dynamicOffsets); - this.visitor.bindInputAssembler(ia); - this.visitor.draw(ia); - } - } - res = it.next(); - } - } + protected _recordUI (): void { const batches = this.camera!.scene!.batches; for (let i = 0; i < batches.length; i++) { @@ -1436,7 +1163,7 @@ class DeviceSceneTask extends WebSceneTask { const count = batch.shaders.length; for (let j = 0; j < count; j++) { const pass = batch.passes[j]; - if (((isEnableEffect()) ? pass.phaseID : pass.phase) !== this._currentQueue.phaseID) continue; + if (pass.phaseID !== this._currentQueue.phaseID) continue; const shader = batch.shaders[j]; const inputAssembler: InputAssembler = batch.inputAssembler!; const pso = PipelineStateManager.getOrCreatePipelineState(deviceManager.gfxDevice, pass, shader, this._renderPass, inputAssembler); @@ -1449,19 +1176,7 @@ class DeviceSceneTask extends WebSceneTask { } } } - protected _recordTransparentList (): void { - this._recordRenderList(true); - } - protected _recordShadowMap (): void { - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - currSubmitInfo.shadowMap.get(this.graphScene.sceneID)!.recordCommandBuffer( - context.device, - this._renderPass, - context.commandBuffer, - ); - } protected _recordReflectionProbe (): void { const submitMap = context.submitMap; const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; @@ -1513,63 +1228,22 @@ class DeviceSceneTask extends WebSceneTask { this.visitor.bindPipelineState(pso); const layoutStage = devicePass.renderLayout; const layoutDesc = layoutStage!.descriptorSet!; - const extResId: number[] = isEnableEffect() ? [] : mergeSrcToTargetDesc(pass.descriptorSet, layoutDesc); + const extResId: number[] = []; // if (isEnableEffect()) this.visitor.bindDescriptorSet(SetIndex.GLOBAL, layoutDesc); - this.visitor.bindDescriptorSet(SetIndex.MATERIAL, isEnableEffect() ? pass.descriptorSet : layoutDesc); + this.visitor.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); this.visitor.bindDescriptorSet(SetIndex.LOCAL, this._currentQueue.blitDesc!.stageDesc!); this.visitor.bindInputAssembler(screenIa); this.visitor.draw(screenIa); // The desc data obtained from the outside should be cleaned up so that the data can be modified this._clearExtBlitDesc(layoutDesc, extResId); - // if (isEnableEffect()) this.visitor.bindDescriptorSet(SetIndex.GLOBAL, globalDesc); } } - private _recordAdditiveLights (): void { - const devicePass = this._currentQueue.devicePass; - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - currSubmitInfo.additiveLight?.recordCommandBuffer( - context.device, - this._renderPass, - context.commandBuffer, - ); - } - private _recordPlanarShadows (): void { - const devicePass = this._currentQueue.devicePass; - const submitMap = context.submitMap; - const currSubmitInfo = submitMap.get(this.camera!)!.get(this._currentQueue.phaseID)!; - currSubmitInfo.planarQueue?.recordCommandBuffer( - context.device, - this._renderPass, - context.commandBuffer, - ); - } protected _updateGlobal (data: RenderData): void { const devicePass = this._currentQueue.devicePass; - updateGlobalDescBinding(data, isEnableEffect() ? context.renderGraph.getLayout(devicePass.rasterPassInfo.id) : 'default'); - if (!isEnableEffect()) context.pipeline.descriptorSet.update(); - } - protected _setMainLightShadowTex (data: RenderData): void { - const graphScene = this.graphScene; - if (graphScene.scene && graphScene.scene.camera) { - const mainLight = graphScene.scene.camera.scene!.mainLight; - const shadowFrameBufferMap = this.sceneData.shadowFrameBufferMap; - if (mainLight && shadowFrameBufferMap.has(mainLight)) { - const shadowAttrID = context.layoutGraph.attributeIndex.get('cc_shadowMap'); - const defaultTex = builtinResMgr.get('default-texture').getGFXTexture()!; - for (const [key, value] of data.textures) { - if (key === shadowAttrID) { - const tex = data.textures.get(shadowAttrID); - if (tex === defaultTex) { - data.textures.set(key, shadowFrameBufferMap.get(mainLight)!.colorTextures[0]!); - } - return; - } - } - } - } + updateGlobalDescBinding(data, context.renderGraph.getLayout(devicePass.rasterPassInfo.id)); } + protected _updateRenderData (): void { if (this._currentQueue.isUpdateUBO) return; const devicePass = this._currentQueue.devicePass; @@ -1580,19 +1254,16 @@ class DeviceSceneTask extends WebSceneTask { // CCCamera, CCShadow, CCCSM const queueId = this._currentQueue.queueId; const queueRenderData = context.renderGraph.getData(queueId)!; - this._setMainLightShadowTex(queueRenderData); this._updateGlobal(queueRenderData); - if (isEnableEffect()) { - const layoutName = context.renderGraph.getLayout(rasterId); - const descSetData = getDescriptorSetDataFromLayout(layoutName); - mergeSrcToTargetDesc(descSetData!.descriptorSet, context.pipeline.descriptorSet, true); - } + + const layoutName = context.renderGraph.getLayout(rasterId); + const descSetData = getDescriptorSetDataFromLayout(layoutName); + mergeSrcToTargetDesc(descSetData!.descriptorSet, context.pipeline.descriptorSet, true); this._currentQueue.isUpdateUBO = true; } - public submit (): void { - const devicePass = this._currentQueue.devicePass; + + private _applyViewport (): void { const queueViewport = this._currentQueue.viewport; - this._updateRenderData(); if (queueViewport) { this.visitor.setViewport(queueViewport); this.visitor.setScissor(this._currentQueue.scissor!); @@ -1610,41 +1281,29 @@ class DeviceSceneTask extends WebSceneTask { this.visitor.setViewport(sceneViewport); this.visitor.setScissor(area); } + } + + public submit (): void { + const devicePass = this._currentQueue.devicePass; + const sceneCulling = context.culling; + this._updateRenderData(); + this._applyViewport(); // Currently processing blit and camera first if (this.graphScene.blit) { this._recordBlit(); return; } - if (isShadowMap(this.graphScene)) { - this._recordShadowMap(); - return; - } + const renderQueueDesc = sceneCulling.sceneQueryIndex.get(this.graphScene.sceneID)!; + const renderQueue = sceneCulling.renderQueues[renderQueueDesc.renderQueueTarget]; const graphSceneData = this.graphScene.scene!; - if (graphSceneData.flags & SceneFlags.OPAQUE_OBJECT - || graphSceneData.flags & SceneFlags.CUTOUT_OBJECT) { - this._recordOpaqueList(); - } - if (graphSceneData.flags & SceneFlags.DRAW_INSTANCING) { - this._recordInstences(); - } - if (graphSceneData.flags & SceneFlags.DEFAULT_LIGHTING) { - this._recordAdditiveLights(); - } - this.visitor.bindDescriptorSet( - SetIndex.GLOBAL, - context.pipeline.descriptorSet, - ); - if (graphSceneData.flags & SceneFlags.PLANAR_SHADOW) { - this._recordPlanarShadows(); - } - if (graphSceneData.flags & SceneFlags.TRANSPARENT_OBJECT) { - this._recordTransparentList(); - } + renderQueue.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); + renderQueue.opaqueInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); + renderQueue.transparentInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); + renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); if (graphSceneData.flags & SceneFlags.GEOMETRY) { this.camera!.geometryRenderer?.render( devicePass.renderPass, context.commandBuffer, - context.pipeline.pipelineSceneData, ); } @@ -1907,12 +1566,12 @@ class ExecutorContext { this.width = width; this.height = height; this.additiveLight = new RenderAdditiveLightQueue(pipeline); - this.shadowMapBatched = new RenderShadowMapBatchedQueue(pipeline); - this.planarShadow = new PlanarShadowQueue(pipeline); this.pools = new ExecutorPools(this); this.blit = new BlitInfo(this); + this.culling = new SceneCulling(); } reset (): void { + this.culling.clear(); this.pools.reset(); this.cullCamera = null; for (const infoMap of this.submitMap) { @@ -1935,11 +1594,10 @@ class ExecutorContext { readonly root: Root; readonly ubo: PipelineUBO; readonly additiveLight: RenderAdditiveLightQueue; - readonly shadowMapBatched: RenderShadowMapBatchedQueue; - readonly planarShadow: PlanarShadowQueue; readonly submitMap: Map> = new Map>(); readonly pools: ExecutorPools; readonly blit: BlitInfo; + readonly culling: SceneCulling; renderGraph: RenderGraph; width: number; height: number; @@ -1998,8 +1656,10 @@ export class Executor { execute (rg: RenderGraph): void { context.renderGraph = rg; context.reset(); - this._removeDeviceResource(); const cmdBuff = context.commandBuffer; + context.culling.buildRenderQueues(rg, context.layoutGraph, context.pipelineSceneData); + context.culling.uploadInstancing(cmdBuff); + this._removeDeviceResource(); cmdBuff.begin(); if (!this._visitor) this._visitor = new RenderVisitor(); depthFirstSearch(this._visitor.graphView, this._visitor, this._visitor.colorMap); diff --git a/cocos/rendering/custom/scene-culling.ts b/cocos/rendering/custom/scene-culling.ts new file mode 100644 index 00000000000..b337a00f6de --- /dev/null +++ b/cocos/rendering/custom/scene-culling.ts @@ -0,0 +1,416 @@ +import { Vec3, assert } from '../../core'; +import { Frustum, intersect, AABB } from '../../core/geometry'; +import { CommandBuffer } from '../../gfx'; +import { BatchingSchemes, Pass, RenderScene } from '../../render-scene'; +import { CSMLevel, Camera, DirectionalLight, Light, LightType, Model, SKYBOX_FLAG, ShadowType, SpotLight } from '../../render-scene/scene'; +import { Node } from '../../scene-graph'; +import { PipelineSceneData } from '../pipeline-scene-data'; +import { hashCombineStr, getSubpassOrPassID, bool } from './define'; +import { LayoutGraphData } from './layout-graph'; +import { RenderGraph, RenderGraphValue, SceneData } from './render-graph'; +import { SceneFlags } from './types'; +import { RenderQueue, RenderQueueDesc } from './web-pipeline-types'; + +function computeCullingKey (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number): number { + let hashCode = 0; + if (camera) { + // camera + hashCode = hashCombineStr(`u${camera.node.uuid}`, hashCode); + hashCode = hashCombineStr(`p${camera.priority}`, hashCode); + hashCode = hashCombineStr(`v${camera.visibility}`, hashCode); + hashCode = hashCombineStr(`f${camera.clearFlag}`, hashCode); + hashCode = hashCombineStr(`cx${camera.clearColor.x}cy${camera.clearColor.y}cz${camera.clearColor.z}cw${camera.clearColor.w}`, hashCode); + hashCode = hashCombineStr(`cd${camera.clearDepth}cs${camera.clearStencil}`, hashCode); + hashCode = hashCombineStr(`pj${camera.projectionType}`, hashCode); + hashCode = hashCombineStr(`fa${camera.fovAxis}`, hashCode); + hashCode = hashCombineStr(`fov${camera.fov}`, hashCode); + hashCode = hashCombineStr(`n${camera.nearClip}`, hashCode); + hashCode = hashCombineStr(`far${camera.farClip}`, hashCode); + hashCode = hashCombineStr(`apt${camera.aperture}`, hashCode); + hashCode = hashCombineStr(`sht${camera.shutter}`, hashCode); + hashCode = hashCombineStr(`iso${camera.iso}`, hashCode); + hashCode = hashCombineStr(`rx${camera.viewport.x}ry${camera.viewport.y}rw${camera.viewport.width}rh${camera.viewport.height}`, hashCode); + hashCode = hashCombineStr(`upp${camera.usePostProcess}`, hashCode); + } + // light + if (light) { + hashCode = hashCombineStr(`u${light.node!.uuid}`, hashCode); + // hashCode = hashCombineStr(`cx${light.finalColor.x}cy${light.finalColor.y}cz${light.finalColor.z}`, hashCode); + // hashCode = hashCombineStr(`ct${light.useColorTemperature}`, hashCode); + // hashCode = hashCombineStr(`ctv${light.colorTemperature}`, hashCode); + // hashCode = hashCombineStr(`vis${light.visibility}`, hashCode); + // hashCode = hashCombineStr(`tp${light.type}`, hashCode); + // switch (light.type) { + // case LightType.DIRECTIONAL: + // hashCode = hashCombineStr(`${(light as DirectionalLight).illuminance}`, hashCode); + // break; + // default: + // } + } + hashCode = hashCombineStr(`cast${castShadows}`, hashCode); + hashCode = hashCombineStr(`level${lightLevel}`, hashCode); + return hashCode; +} + +class CullingKey { + camera: Camera | null; + light: Light | null; + castShadows = false; + lightLevel = 0xffffffff; + constructor (camera: Camera | null, light: Light | null, castShadows: boolean, lightLevel: number) { + this.camera = camera; + this.light = light; + this.castShadows = castShadows; + this.lightLevel = lightLevel; + } +} + +let pSceneData: PipelineSceneData; + +class CullingQueries { + // key: hash val + culledResultIndex: Map = new Map(); + cullingKeyResult: Map = new Map(); +} + +function isNodeVisible (node: Node, visibility: number): boolean { + return node && ((visibility & node.layer) === node.layer); +} + +function isModelVisible (model: Model, visibility: number): boolean { + return !!(visibility & model.visFlags); +} +const transWorldBounds = new AABB(); +function isFrustumVisible (model: Model, frustum: Readonly, castShadow: boolean): boolean { + const modelWorldBounds = model.worldBounds; + if (!modelWorldBounds) { + return false; + } + transWorldBounds.copy(modelWorldBounds); + const shadows = pSceneData.shadows; + if (shadows.type === ShadowType.Planar && castShadow) { + AABB.transform(transWorldBounds, modelWorldBounds, shadows.matLight); + } + return !intersect.aabbFrustum(transWorldBounds, frustum); +} + +function sceneCulling ( + skyboxModelToSkip: Model | null, + scene: RenderScene, + camera: Camera, + camOrLightFrustum: Readonly, + castShadow: boolean, + models: Array, +): void { + const visibility = camera.visibility; + for (const model of scene.models) { + assert(!!model); + if (!model.enabled || model === skyboxModelToSkip || (castShadow && !model.castShadow)) { + continue; + } + if (scene && scene.isCulledByLod(camera, model)) { + continue; + } + + if (isNodeVisible(model.node, visibility) + || isModelVisible(model, visibility)) { + // frustum culling + if (isFrustumVisible(model, camOrLightFrustum, castShadow)) { + continue; + } + + models.push(model); + } + } +} + +function isBlend (pass: Pass): boolean { + let bBlend = false; + for (const target of pass.blendState.targets) { + if (target.blend) { + bBlend = true; + } + } + return bBlend; +} + +function computeSortingDepth (camera: Camera, model: Model): number { + let depth = 0; + if (model.node) { + const node = model.transform; + const tempVec3 = new Vec3(); + const position = Vec3.subtract(tempVec3, node.worldPosition, camera.position); + depth = position.dot(camera.forward); + } + return depth; +} + +function addRenderObject ( + phaseLayoutId: number, + isDrawOpaqueOrMask: boolean, + isDrawBlend: boolean, + camera: Camera, + model: Model, + queue: RenderQueue, +): void { + const subModels = model.subModels; + const subModelCount = subModels.length; + for (let subModelIdx = 0; subModelIdx < subModelCount; ++subModelIdx) { + const subModel = subModels[subModelIdx]; + const passes = subModel.passes; + const passCount = passes.length; + for (let passIdx = 0; passIdx < passCount; ++passIdx) { + const pass = passes[passIdx]; + // check phase + const phaseAllowed = phaseLayoutId === pass.phaseID; + if (!phaseAllowed) { + continue; + } + // check scene flags + const is_blend = isBlend(pass); + const isOpaqueOrMask = !is_blend; + if (!isDrawBlend && is_blend) { + // skip transparent object + continue; + } + if (!isDrawOpaqueOrMask && isOpaqueOrMask) { + // skip opaque object + continue; + } + + // add object to queue + if (pass.batchingScheme === BatchingSchemes.INSTANCING) { + const instancedBuffer = pass.getInstancedBuffer(); + instancedBuffer.merge(subModel, passIdx); + if (is_blend) { + queue.transparentInstancingQueue.add(instancedBuffer); + } else { + queue.opaqueInstancingQueue.add(instancedBuffer); + } + } else { + const depth = computeSortingDepth(camera, model); + if (is_blend) { + queue.transparentQueue.add(model, depth, subModelIdx, passIdx); + } else { + queue.opaqueQueue.add(model, depth, subModelIdx, passIdx); + } + } + } + } +} + +export class SceneCulling { + sceneQueries: Map = new Map(); + culledResults: Array> = new Array>(); + renderQueues: Array = new Array(); + sceneQueryIndex: Map = new Map(); + // source id + numCullingQueries = 0; + // target id + numRenderQueues = 0; + layoutGraph; + renderGraph; + clear (): void { + this.sceneQueries.clear(); + for (const c of this.culledResults) { + c.length = 0; + } + this.culledResults.length = 0; + for (const q of this.renderQueues) { + q.clear(); + } + this.renderQueues.length = 0; + this.sceneQueryIndex.clear(); + this.numCullingQueries = 0; + this.numRenderQueues = 0; + } + + buildRenderQueues (rg: RenderGraph, lg: LayoutGraphData, pplSceneData: PipelineSceneData): void { + this.layoutGraph = lg; + this.renderGraph = rg; + pSceneData = pplSceneData; + this.collectCullingQueries(rg, lg); + this.batchCulling(pplSceneData); + this.fillRenderQueues(rg, pplSceneData); + } + + private getOrCreateSceneCullingQuery (sceneData: SceneData): number { + const scene = sceneData.scene!; + let queries = this.sceneQueries.get(scene); + if (!queries) { + this.sceneQueries.set(scene, new CullingQueries()); + queries = this.sceneQueries.get(scene); + } + const castShadow = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); + const key = computeCullingKey(sceneData.camera, sceneData.light.light, castShadow, sceneData.light.level); + const cullNum = queries!.culledResultIndex.get(key); + if (cullNum !== undefined) { + return cullNum; + } + const soureceID = this.numCullingQueries++; + if (this.numCullingQueries > this.culledResults.length) { + assert(this.numCullingQueries === (this.culledResults.length + 1)); + this.culledResults.push([]); + } + queries!.culledResultIndex.set(key, soureceID); + queries!.cullingKeyResult.set(key, new CullingKey(sceneData.camera, sceneData.light.light, castShadow, sceneData.light.level)); + return soureceID; + } + + private createRenderQueue (sceneFlags: SceneFlags, subpassOrPassLayoutID: number): number { + const targetID = this.numRenderQueues++; + if (this.numRenderQueues > this.renderQueues.length) { + assert(this.numRenderQueues === (this.renderQueues.length + 1)); + this.renderQueues.push(new RenderQueue()); + } + assert(targetID < this.renderQueues.length); + const rq = this.renderQueues[targetID]; + rq.sceneFlags = sceneFlags; + rq.subpassOrPassLayoutID = subpassOrPassLayoutID; + return targetID; + } + + private collectCullingQueries (rg: RenderGraph, lg: LayoutGraphData): void { + for (const v of rg.vertices()) { + if (!rg.holds(RenderGraphValue.Scene, v) || !rg.getValid(v)) { + continue; + } + const sceneData = rg.getScene(v); + if (!sceneData.scene) { + assert(!!sceneData.scene); + continue; + } + const sourceID = this.getOrCreateSceneCullingQuery(sceneData); + const layoutID = getSubpassOrPassID(v, rg, lg); + const targetID = this.createRenderQueue(sceneData.flags, layoutID); + + const lightType = sceneData.light.light ? sceneData.light.light.type : LightType.UNKNOWN; + // add render queue to query source + this.sceneQueryIndex.set(v, new RenderQueueDesc(sourceID, targetID, lightType)); + } + } + + uploadInstancing (cmdBuffer: CommandBuffer): void { + for (let queueID = 0; queueID !== this.numRenderQueues; ++queueID) { + assert(this.numRenderQueues <= this.renderQueues.length); + const queue = this.renderQueues[queueID]; + queue.opaqueInstancingQueue.uploadBuffers(cmdBuffer); + queue.transparentInstancingQueue.uploadBuffers(cmdBuffer); + } + } + + private batchCulling (pplSceneData: PipelineSceneData): void { + const skybox = pplSceneData.skybox; + const skyboxModelToSkip = skybox ? skybox.model : null; + for (const [scene, queries] of this.sceneQueries) { + assert(!!scene); + for (const [key, sourceID] of queries.culledResultIndex) { + const cullingKey = queries.cullingKeyResult.get(key)!; + assert(!!cullingKey.camera); + assert(cullingKey.camera.scene === scene); + const camera = cullingKey.camera; + const light = cullingKey.light; + const level = cullingKey.lightLevel; + const castShadow = cullingKey.castShadows; + assert(sourceID < this.culledResults.length); + const models = this.culledResults[sourceID]; + if (light) { + switch (light.type) { + case LightType.SPOT: + sceneCulling(skyboxModelToSkip, scene, camera, (light as SpotLight).frustum, castShadow, models); + break; + case LightType.DIRECTIONAL: { + const csmLayers = pplSceneData.csmLayers; + const mainLight: DirectionalLight = light as DirectionalLight; + const csmLevel = mainLight.csmLevel; + let frustum: Readonly; + const shadows = pplSceneData.shadows; + if (shadows.type === ShadowType.Planar) { + frustum = camera.frustum; + } else { + if (shadows.enabled && shadows.type === ShadowType.ShadowMap && mainLight && mainLight.node) { + // pplSceneData.updateShadowUBORange(UBOShadow.SHADOW_COLOR_OFFSET, shadows.shadowColor); + csmLayers.update(pplSceneData, camera); + } + + if (mainLight.shadowFixedArea || csmLevel === CSMLevel.LEVEL_1) { + frustum = csmLayers.specialLayer.validFrustum; + } else { + frustum = csmLayers.layers[level].validFrustum; + } + } + sceneCulling(skyboxModelToSkip, scene, camera, frustum, castShadow, models); + } + break; + default: + } + } else { + sceneCulling(skyboxModelToSkip, scene, camera, camera.frustum, castShadow, models); + } + } + } + } + + private fillRenderQueues (rg: RenderGraph, pplSceneData: PipelineSceneData): void { + const skybox = pplSceneData.skybox; + for (const [sceneId, desc] of this.sceneQueryIndex) { + assert(rg.holds(RenderGraphValue.Scene, sceneId)); + const sourceId = desc.culledSource; + const targetId = desc.renderQueueTarget; + const sceneData = rg.getScene(sceneId); + const isDrawBlend = bool(sceneData.flags & SceneFlags.TRANSPARENT_OBJECT); + const isDrawOpaqueOrMask = bool(sceneData.flags & (SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT)); + const isDrawShadowCaster = bool(sceneData.flags & SceneFlags.SHADOW_CASTER); + if (!isDrawShadowCaster && !isDrawBlend && !isDrawOpaqueOrMask) { + continue; + } + // render queue info + const renderQueueId = rg.getParent(sceneId); + assert(rg.holds(RenderGraphValue.Queue, renderQueueId)); + const graphRenderQueue = rg.getQueue(renderQueueId); + const phaseLayoutId = graphRenderQueue.phaseID; + assert(phaseLayoutId !== this.layoutGraph.nullVertex()); + + // culling source + assert(sourceId < this.culledResults.length); + const sourceModels = this.culledResults[sourceId]; + + // queue target + assert(targetId < this.renderQueues.length); + const renderQueue = this.renderQueues[targetId]; + assert(renderQueue.empty()); + + // skybox + const camera = sceneData.camera; + assert(!!camera); + if (!bool(sceneData.flags & SceneFlags.SHADOW_CASTER) + && skybox && skybox.enabled + && (camera.clearFlag & SKYBOX_FLAG)) { + assert(!!skybox.model); + const model = skybox.model; + const node = model.node; + let depth = 0; + if (node) { + const tempVec3 = new Vec3(); + Vec3.subtract(tempVec3, node.worldPosition, camera.position); + depth = tempVec3.dot(camera.forward); + } + renderQueue.opaqueQueue.add(model, depth, 0, 0); + } + + // fill render queue + for (const model of sourceModels) { + addRenderObject( + phaseLayoutId, + isDrawOpaqueOrMask, + isDrawBlend, + camera, + model, + renderQueue, + ); + } + // post-processing + renderQueue.sort(); + } + } +} diff --git a/cocos/rendering/custom/web-pipeline-types.ts b/cocos/rendering/custom/web-pipeline-types.ts new file mode 100644 index 00000000000..c41128cefd4 --- /dev/null +++ b/cocos/rendering/custom/web-pipeline-types.ts @@ -0,0 +1,234 @@ +import { CommandBuffer, DescriptorSet, Device, PipelineState, RenderPass, deviceManager } from '../../gfx'; +import { RenderScene } from '../../render-scene'; +import { Camera, Light, LightType, Model, SubModel } from '../../render-scene/scene'; +import { SetIndex } from '../define'; +import { InstancedBuffer } from '../instanced-buffer'; +import { PipelineStateManager } from '../pipeline-state-manager'; +import { SceneFlags } from './types'; + +export class DrawInstance { + subModel: SubModel | null; + priority: number; + hash: number; + depth: number; + shaderID: number; + passIndex: number; + + constructor ( + subModel: SubModel | null = null, + priority = 0, + hash = 0, + depth = 0, + shaderID = 0, + passIndex = 0, + ) { + this.subModel = subModel; + this.priority = priority; + this.hash = hash; + this.depth = depth; + this.shaderID = shaderID; + this.passIndex = passIndex; + } +} + +export class RenderDrawQueue { + instances: Array = new Array(); + + add (model: Model, depth: number, subModelIdx: number, passIdx: number): void { + const subModel = model.subModels[subModelIdx]; + const pass = subModel.passes[passIdx]; + const passPriority = pass.priority; + const modelPriority = subModel.priority; + const shaderId = subModel.shaders[passIdx].typedID; + const hash = (0 << 30) | (passPriority as number << 16) | (modelPriority as number << 8) | passIdx; + const priority = model.priority; + + this.instances.push(new DrawInstance(subModel, priority, hash, depth, shaderId, passIdx)); + } + /** + * @en Comparison sorting function. Opaque objects are sorted by priority -> depth front to back -> shader ID. + * @zh 比较排序函数。不透明对象按优先级 -> 深度由前向后 -> Shader ID 顺序排序。 + */ + sortOpaqueOrCutout (): void { + this.instances.sort((lhs: DrawInstance, rhs: DrawInstance) => { + if (lhs.hash !== rhs.hash) { + return lhs.hash - rhs.hash; + } + if (lhs.depth !== rhs.depth) { + return lhs.depth - rhs.depth; + } + return lhs.shaderID - rhs.shaderID; + }); + } + /** + * @en Comparison sorting function. Transparent objects are sorted by priority -> depth back to front -> shader ID. + * @zh 比较排序函数。半透明对象按优先级 -> 深度由后向前 -> Shader ID 顺序排序。 + */ + sortTransparent (): void { + this.instances.sort((lhs: DrawInstance, rhs: DrawInstance) => { + if (lhs.priority !== rhs.priority) { + return lhs.priority - rhs.priority; + } + if (lhs.hash !== rhs.hash) { + return lhs.hash - rhs.hash; + } + if (lhs.depth !== rhs.depth) { + return rhs.depth - lhs.depth; // 注意此处的差值顺序,为了按照降序排列 + } + return lhs.shaderID - rhs.shaderID; + }); + } + + recordCommandBuffer ( + device: Device, + renderPass: RenderPass, + cmdBuffer: CommandBuffer, + ): void { + for (const instance of this.instances) { + const subModel = instance.subModel!; + + const passIdx = instance.passIndex; + const inputAssembler = subModel.inputAssembler; + const pass = subModel.passes[passIdx]; + const shader = subModel.shaders[passIdx]; + const pso = PipelineStateManager.getOrCreatePipelineState(device, pass, shader, renderPass, inputAssembler); + + cmdBuffer.bindPipelineState(pso); + cmdBuffer.bindDescriptorSet(SetIndex.MATERIAL, pass.descriptorSet); + cmdBuffer.bindDescriptorSet(SetIndex.LOCAL, subModel.descriptorSet); + cmdBuffer.bindInputAssembler(inputAssembler); + cmdBuffer.draw(inputAssembler); + } + } +} + +export class RenderInstancingQueue { + batches: Set = new Set(); + sortedBatches: Array = new Array(); + + add (instancedBuffer: InstancedBuffer): void { + this.batches.add(instancedBuffer); + } + + sort (): void { + this.sortedBatches = Array.from(this.batches); + } + + uploadBuffers (cmdBuffer: CommandBuffer): void { + for (const instanceBuffer of this.batches) { + if (instanceBuffer.hasPendingModels) { + instanceBuffer.uploadBuffers(cmdBuffer); + } + } + } + + recordCommandBuffer ( + renderPass: RenderPass, + cmdBuffer: CommandBuffer, + ds: DescriptorSet | null = null, + offset = 0, + dynamicOffsets: number[] | null = null, + ): void { + const renderQueue = this.sortedBatches; + for (const instanceBuffer of renderQueue) { + if (!instanceBuffer.hasPendingModels) { + continue; + } + const instances = instanceBuffer.instances; + const drawPass = instanceBuffer.pass; + cmdBuffer.bindDescriptorSet(SetIndex.MATERIAL, drawPass.descriptorSet); + let lastPSO: PipelineState | null = null; + for (const instance of instances) { + if (!instance.count) { + continue; + } + const pso = PipelineStateManager.getOrCreatePipelineState( + deviceManager.gfxDevice, + drawPass, + instance.shader!, + renderPass, + instance.ia, + ); + if (lastPSO !== pso) { + cmdBuffer.bindPipelineState(pso); + lastPSO = pso; + } + if (ds) { + cmdBuffer.bindDescriptorSet(SetIndex.GLOBAL, ds, [offset]); + } + if (dynamicOffsets) { + cmdBuffer.bindDescriptorSet(SetIndex.LOCAL, instance.descriptorSet, dynamicOffsets); + } else { + cmdBuffer.bindDescriptorSet( + SetIndex.LOCAL, + instance.descriptorSet, + instanceBuffer.dynamicOffsets, + ); + } + cmdBuffer.bindInputAssembler(instance.ia); + cmdBuffer.draw(instance.ia); + } + } + } +} + +export class RenderQueueDesc { + culledSource: number; + renderQueueTarget: number; + lightType: LightType; + + constructor ( + culledSourceIn = 0xFFFFFFFF, + renderQueueTargetIn = 0xFFFFFFFF, + lightTypeIn: LightType = LightType.UNKNOWN, + ) { + this.culledSource = culledSourceIn; + this.renderQueueTarget = renderQueueTargetIn; + this.lightType = lightTypeIn; + } +} + +export class RenderQueue { + opaqueQueue: RenderDrawQueue = new RenderDrawQueue(); + transparentQueue: RenderDrawQueue = new RenderDrawQueue(); + opaqueInstancingQueue: RenderInstancingQueue = new RenderInstancingQueue(); + transparentInstancingQueue: RenderInstancingQueue = new RenderInstancingQueue(); + sceneFlags: SceneFlags = SceneFlags.NONE; + subpassOrPassLayoutID = 0xffffffff; + + sort (): void { + this.opaqueQueue.sortOpaqueOrCutout(); + this.transparentQueue.sortTransparent(); + this.opaqueInstancingQueue.sort(); + this.transparentInstancingQueue.sort(); + } + + private _clearInstances (instances: Set): void { + const it = instances.values(); let res = it.next(); + while (!res.done) { + res.value.clear(); + res = it.next(); + } + instances.clear(); + } + + clear (): void { + this.opaqueQueue.instances.length = 0; + this.transparentQueue.instances.length = 0; + this._clearInstances(this.opaqueInstancingQueue.batches); + this.opaqueInstancingQueue.sortedBatches.length = 0; + this._clearInstances(this.transparentInstancingQueue.batches); + this.transparentInstancingQueue.sortedBatches.length = 0; + this.sceneFlags = SceneFlags.NONE; + this.subpassOrPassLayoutID = 0xFFFFFFFF; + } + + empty (): boolean { + return this.opaqueQueue.instances.length === 0 + && this.transparentQueue.instances.length === 0 + && this.opaqueInstancingQueue.batches.size === 0 + && this.opaqueInstancingQueue.sortedBatches.length === 0 + && this.transparentInstancingQueue.batches.size === 0 + && this.transparentInstancingQueue.sortedBatches.length === 0; + } +} diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index c1bac8ca455..08e171ab45c 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -304,7 +304,11 @@ function setShadowUBOLightView ( const pipeline = (director.root as Root).pipeline; const device = pipeline.device; const sceneData = pipeline.pipelineSceneData; + const shadowInfo = sceneData.shadows; + if (shadowInfo.type === ShadowType.Planar) { + return; + } const csmLayers = sceneData.csmLayers; const packing = supportsR32FloatTexture(device) ? 0.0 : 1.0; const cap = pipeline.device.capabilities; @@ -758,6 +762,7 @@ function setTextureUBOView (setter: WebSetter, camera: Camera | null, cfg: Reado const skybox = cfg.skybox; const director = cclegacy.director; const root = director.root; + const pipeline = root.pipeline as WebPipeline; if (skybox.reflectionMap) { const texture = skybox.reflectionMap.getGFXTexture()!; const sampler: Sampler = root.device.getSampler(skybox.reflectionMap.getSamplerInfo()); @@ -779,18 +784,17 @@ function setTextureUBOView (setter: WebSetter, camera: Camera | null, cfg: Reado setter.setTexture('cc_diffuseMap', texture); setter.setSampler('cc_diffuseMap', sampler); } - const pointSampler: Sampler = root.device.getSampler(_samplerPointInfo); if (!setter.hasSampler('cc_shadowMap')) { - setter.setSampler('cc_shadowMap', pointSampler); + setter.setSampler('cc_shadowMap', pipeline.defaultSampler); } if (!setter.hasTexture('cc_shadowMap')) { - setter.setTexture('cc_shadowMap', builtinResMgr.get('default-texture').getGFXTexture()!); + setter.setTexture('cc_shadowMap', pipeline.defaultTexture); } if (!setter.hasSampler('cc_spotShadowMap')) { - setter.setSampler('cc_spotShadowMap', pointSampler); + setter.setSampler('cc_spotShadowMap', pipeline.defaultSampler); } if (!setter.hasTexture('cc_spotShadowMap')) { - setter.setTexture('cc_spotShadowMap', builtinResMgr.get('default-texture').getGFXTexture()!); + setter.setTexture('cc_spotShadowMap', pipeline.defaultTexture); } } @@ -989,11 +993,12 @@ export class WebRenderSubpassBuilder extends WebSetter implements RenderSubpassB throw new Error('Method not implemented.'); } addQueue (hint: QueueHint = QueueHint.RENDER_OPAQUE, layoutName = 'default'): RenderQueueBuilder { + const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); if (DEBUG) { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); assert(layoutId !== 0xFFFFFFFF); } const queue = new RenderQueue(hint); + queue.phaseID = layoutId; const data = new RenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); return new WebRenderQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); @@ -1129,11 +1134,12 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR return result; } addQueue (hint: QueueHint = QueueHint.RENDER_OPAQUE, layoutName = 'default'): WebRenderQueueBuilder { + const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); if (DEBUG) { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); assert(layoutId !== 0xFFFFFFFF); } const queue = new RenderQueue(hint); + queue.phaseID = layoutId; const data = new RenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); return new WebRenderQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); @@ -1283,11 +1289,12 @@ export class WebComputePassBuilder extends WebSetter implements ComputePassBuild throw new Error('Method not implemented.'); } addQueue (layoutName = 'default'): WebComputeQueueBuilder { + const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); if (DEBUG) { - const layoutId = this._layoutGraph.locateChild(this._layoutID, layoutName); assert(layoutId !== 0xFFFFFFFF); } const queue = new RenderQueue(); + queue.phaseID = layoutId; const data = new RenderData(); const queueID = this._renderGraph.addVertex(RenderGraphValue.Queue, queue, '', layoutName, data, false, this._vertID); return new WebComputeQueueBuilder(data, this._renderGraph, this._layoutGraph, queueID, queue, this._pipeline); @@ -1556,6 +1563,14 @@ export class WebPipeline implements BasicPipeline { return this._globalDescSetData; } + get defaultSampler (): Sampler { + return this._defaultSampler; + } + + get defaultTexture (): Texture { + return builtinResMgr.get('default-texture').getGFXTexture()!; + } + private _compileMaterial (): void { this._copyPassMat.initialize({ effectName: 'pipeline/copy-pass', @@ -1587,7 +1602,9 @@ export class WebPipeline implements BasicPipeline { // 0: SHADOWMAP_LINER_DEPTH_OFF, 1: SHADOWMAP_LINER_DEPTH_ON. const isLinear = this._device.gfxAPI === API.WEBGL ? 1 : 0; this.setMacroInt('CC_SHADOWMAP_USE_LINEAR_DEPTH', isLinear); - + const director: Director = cclegacy.director; + const root: Root = director.root!; + this._defaultSampler = root.device.getSampler(_samplerPointInfo); // 0: UNIFORM_VECTORS_LESS_EQUAL_64, 1: UNIFORM_VECTORS_GREATER_EQUAL_125. this.pipelineSceneData.csmSupported = this.device.capabilities.maxFragmentUniformVectors >= (WebPipeline.CSM_UNIFORM_VECTORS + WebPipeline.GLOBAL_UNIFORM_VECTORS); @@ -1998,6 +2015,7 @@ export class WebPipeline implements BasicPipeline { private _copyPassMat: Material = new Material(); private _device!: Device; private _globalDSManager!: GlobalDSManager; + private _defaultSampler!: Sampler; private _globalDescriptorSet: DescriptorSet | null = null; private _globalDescriptorSetInfo: DescriptorSetInfo | null = null; private _globalDescriptorSetLayout: DescriptorSetLayout | null = null; diff --git a/cocos/rendering/post-process/passes/forward-pass.ts b/cocos/rendering/post-process/passes/forward-pass.ts index ef9f478d28e..e81630d80d2 100644 --- a/cocos/rendering/post-process/passes/forward-pass.ts +++ b/cocos/rendering/post-process/passes/forward-pass.ts @@ -11,7 +11,7 @@ import { ShadowPass } from './shadow-pass'; export class ForwardPass extends BasePass { name = 'ForwardPass'; - outputNames = ['ForwardColor', 'ForwardDS'] + outputNames = ['ForwardColor', 'ForwardDS']; enableInAllEditorCamera = true; depthBufferShadingScale = 1; @@ -70,11 +70,21 @@ export class ForwardPass extends BasePass { } } pass.addQueue(QueueHint.RENDER_OPAQUE) - .addSceneOfCamera(camera, + .addSceneOfCamera( + camera, new LightInfo(), - SceneFlags.OPAQUE_OBJECT | SceneFlags.PLANAR_SHADOW | SceneFlags.CUTOUT_OBJECT - | SceneFlags.DEFAULT_LIGHTING | SceneFlags.DRAW_INSTANCING | SceneFlags.GEOMETRY); - + SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT + | SceneFlags.DEFAULT_LIGHTING | SceneFlags.GEOMETRY, + ); + if (camera.scene?.mainLight) { + pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'planar-shadow') + .addSceneOfCamera( + camera, + new LightInfo(camera.scene?.mainLight), + SceneFlags.TRANSPARENT_OBJECT | SceneFlags.SHADOW_CASTER + | SceneFlags.DEFAULT_LIGHTING | SceneFlags.GEOMETRY, + ); + } passContext.forwardPass = this; } } diff --git a/cocos/rendering/post-process/passes/skin-pass.ts b/cocos/rendering/post-process/passes/skin-pass.ts index bcbc60fdc82..24bdd068a8b 100644 --- a/cocos/rendering/post-process/passes/skin-pass.ts +++ b/cocos/rendering/post-process/passes/skin-pass.ts @@ -120,7 +120,7 @@ export class SSSSBlurData { const o = -range + i * step; const sign = o < 0.0 ? -1.0 : 1.0; // eslint-disable-next-line no-restricted-properties - this._kernel[i].w = range * sign * Math.abs(Math.pow(o, EXPONENT)) / Math.pow(range, EXPONENT); + this._kernel[i].w = range * sign * Math.abs(o ** EXPONENT) / range ** EXPONENT; } // Calculate the weights: @@ -185,9 +185,9 @@ export class SSSSBlurData { } export class SkinPass extends SettingPass { - name = 'SkinPass' + name = 'SkinPass'; effectName = 'pipeline/ssss-blur'; - outputNames = ['SSSSBlur', 'SSSSBlurDS'] + outputNames = ['SSSSBlur', 'SSSSBlurDS']; ssssBlurData = new SSSSBlurData(); private _activate = false; @@ -220,10 +220,12 @@ export class SkinPass extends SettingPass { this._buildSpecularPass(camera, ppl, inputRT!, inputDS); } - private _buildSSSSBlurPass (camera: Camera, + private _buildSSSSBlurPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): void { + inputDS: string, + ): void { const cameraID = getCameraUniqueID(camera); const pipelineSceneData = ppl.pipelineSceneData; @@ -259,8 +261,12 @@ export class SkinPass extends SettingPass { passIdx = SSSS_BLUR_X_PASS_INDEX; const ssssblurXPassLayoutName = 'ssss-blurX'; const ssssblurXPassPassName = `ssss-blurX${cameraID}`; - this.material.setProperty('blurInfo', new Vec4(camera.fov, skin.blurRadius, - boundingBox, skin.sssIntensity), passIdx); + this.material.setProperty('blurInfo', new Vec4( + camera.fov, + skin.blurRadius, + boundingBox, + skin.sssIntensity, + ), passIdx); this.material.setProperty('kernel', this.ssssBlurData.kernel, passIdx); passContext.updatePassViewPort() .addRenderPass(ssssblurXPassLayoutName, ssssblurXPassPassName) @@ -276,8 +282,12 @@ export class SkinPass extends SettingPass { passIdx = SSSS_BLUR_Y_PASS_INDEX; const ssssblurYPassLayoutName = 'ssss-blurY'; const ssssblurYPassPassName = `ssss-blurY${cameraID}`; - this.material.setProperty('blurInfo', new Vec4(camera.fov, skin.blurRadius, - boundingBox, skin.sssIntensity), passIdx); + this.material.setProperty('blurInfo', new Vec4( + camera.fov, + skin.blurRadius, + boundingBox, + skin.sssIntensity, + ), passIdx); this.material.setProperty('kernel', this.ssssBlurData.kernel, passIdx); passContext.updatePassViewPort() .addRenderPass(ssssblurYPassLayoutName, ssssblurYPassPassName) @@ -290,10 +300,12 @@ export class SkinPass extends SettingPass { .version(); } - private _buildSpecularPass (camera: Camera, + private _buildSpecularPass ( + camera: Camera, ppl: BasicPipeline, inputRT: string, - inputDS: string): void { + inputDS: string, + ): void { const cameraID = getCameraUniqueID(camera); const layoutName = 'specular-pass'; const passName = `specular-pass${cameraID}`; @@ -323,13 +335,19 @@ export class SkinPass extends SettingPass { } pass.addQueue(QueueHint.RENDER_OPAQUE, 'default') - .addSceneOfCamera(camera, new LightInfo(), - SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING | SceneFlags.PLANAR_SHADOW - | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING); + .addSceneOfCamera( + camera, + new LightInfo(), + SceneFlags.TRANSPARENT_OBJECT + | SceneFlags.CUTOUT_OBJECT, + ); pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'forward-add') - .addSceneOfCamera(camera, new LightInfo(), - SceneFlags.TRANSPARENT_OBJECT | SceneFlags.DEFAULT_LIGHTING | SceneFlags.PLANAR_SHADOW - | SceneFlags.CUTOUT_OBJECT | SceneFlags.DRAW_INSTANCING); + .addSceneOfCamera( + camera, + new LightInfo(), + SceneFlags.TRANSPARENT_OBJECT + | SceneFlags.CUTOUT_OBJECT, + ); } slotName (camera: Camera, index = 0): string { diff --git a/native/cocos/renderer/gfx-base/GFXDef-common.h b/native/cocos/renderer/gfx-base/GFXDef-common.h index ab5c7bd810f..a8a6e4b22d2 100644 --- a/native/cocos/renderer/gfx-base/GFXDef-common.h +++ b/native/cocos/renderer/gfx-base/GFXDef-common.h @@ -173,9 +173,8 @@ enum class Feature : uint32_t { MULTIPLE_RENDER_TARGETS, BLEND_MINMAX, COMPUTE_SHADER, - // @deprecated - INPUT_ATTACHMENT_BENEFIT, + INPUT_ATTACHMENT_BENEFIT, // @deprecated SUBPASS_COLOR_INPUT, SUBPASS_DEPTH_STENCIL_INPUT, RASTERIZATION_ORDER_NOCOHERENT, @@ -474,11 +473,12 @@ CC_ENUM_BITWISE_OPERATORS(TextureUsageBit); enum class TextureFlagBit : uint32_t { NONE = 0, - GEN_MIPMAP = 0x1, // Generate mipmaps using bilinear filter - GENERAL_LAYOUT = 0x2, // @deprecated, For inout framebuffer attachments - EXTERNAL_OES = 0x4, // External oes texture - EXTERNAL_NORMAL = 0x8, // External normal texture - LAZILY_ALLOCATED = 0x10 // Try lazily allocated mode. + GEN_MIPMAP = 0x1, // Generate mipmaps using bilinear filter + GENERAL_LAYOUT = 0x2, // @deprecated, For inout framebuffer attachments + EXTERNAL_OES = 0x4, // External oes texture + EXTERNAL_NORMAL = 0x8, // External normal texture + LAZILY_ALLOCATED = 0x10, // Try lazily allocated mode. + MUTABLE_VIEW_FORMAT = 0x40, // texture view as different format }; using TextureFlags = TextureFlagBit; CC_ENUM_BITWISE_OPERATORS(TextureFlagBit); @@ -1089,6 +1089,8 @@ struct ALIGNAS(8) TextureViewInfo { uint32_t levelCount{1}; uint32_t baseLayer{0}; uint32_t layerCount{1}; + uint32_t basePlane{0}; + uint32_t planeCount{1}; #if CC_CPU_ARCH == CC_CPU_ARCH_32 uint32_t _padding{0}; #endif diff --git a/native/cocos/renderer/gfx-base/GFXTexture.cpp b/native/cocos/renderer/gfx-base/GFXTexture.cpp index 0f1a7c2c14d..59432996a07 100644 --- a/native/cocos/renderer/gfx-base/GFXTexture.cpp +++ b/native/cocos/renderer/gfx-base/GFXTexture.cpp @@ -144,6 +144,8 @@ void Texture::updateTextureInfo(const SwapchainTextureInfo &info, Texture *out) out->_viewInfo.layerCount = out->_info.layerCount; out->_viewInfo.baseLevel = 0; out->_viewInfo.levelCount = out->_info.levelCount; + out->_viewInfo.basePlane = 0; + out->_viewInfo.planeCount = info.format == gfx::Format::DEPTH_STENCIL ? 2 : 1; } } // namespace gfx diff --git a/native/cocos/renderer/gfx-base/GFXTexture.h b/native/cocos/renderer/gfx-base/GFXTexture.h index b00defb4fc4..0d29fcfc27d 100644 --- a/native/cocos/renderer/gfx-base/GFXTexture.h +++ b/native/cocos/renderer/gfx-base/GFXTexture.h @@ -51,7 +51,7 @@ class CC_DLL Texture : public GFXObject, public RefCounted { inline ccstd::hash_t getHash() const { return _hash; } // convenient getter for common usages - inline Format getFormat() const { return _info.format; } + inline Format getFormat() const { return _isTextureView ? _viewInfo.format : _info.format; } inline uint32_t getWidth() const { return _info.width; } inline uint32_t getHeight() const { return _info.height; } diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp index afddfc2d1a7..231ed1d3b5e 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp @@ -1375,16 +1375,21 @@ void cmdFuncGLES3CreateRenderPass(GLES3Device * /*device*/, GLES3GPURenderPass * auto &attachments = gpuRenderPass->colorAttachments; auto &drawBuffers = gpuRenderPass->drawBuffers; + bool hasDS = (gpuRenderPass->depthStencilAttachment.format != Format::UNKNOWN); gpuRenderPass->drawBuffers.resize(subPasses.size()); - gpuRenderPass->indices.resize(attachments.size(), INVALID_BINDING); + gpuRenderPass->indices.resize(attachments.size() + hasDS, INVALID_BINDING); for (uint32_t i = 0; i < subPasses.size(); ++i) { auto &sub = subPasses[i]; auto &drawBuffer = drawBuffers[i]; - std::vector visited(gpuRenderPass->colorAttachments.size()); + std::vector visited(gpuRenderPass->colorAttachments.size() + hasDS); for (auto &input : sub.inputs) { visited[input] = true; + if(input == gpuRenderPass->colorAttachments.size()) { + // ds input + continue; + } drawBuffer.emplace_back(gpuRenderPass->indices[input]); } @@ -1411,8 +1416,14 @@ void cmdFuncGLES3CreateRenderPass(GLES3Device * /*device*/, GLES3GPURenderPass * } } - gpuRenderPass->depthStencil = sub.depthStencil; - gpuRenderPass->depthStencilResolve = sub.depthStencilResolve; + + if (sub.depthStencil != gfx::INVALID_BINDING) { + gpuRenderPass->depthStencil = sub.depthStencil; + gpuRenderPass->indices.back() = gpuRenderPass->depthStencil; + } + if (sub.depthStencilResolve != gfx::INVALID_BINDING) { + gpuRenderPass->depthStencilResolve = sub.depthStencilResolve; + } } } diff --git a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h index 169767fe082..0005cf0c6b8 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h +++ b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h @@ -156,6 +156,8 @@ struct GLES3GPUTextureView { Format format = Format::UNKNOWN; uint32_t baseLevel = 0U; uint32_t levelCount = 1U; + uint32_t basePlane = 0U; + uint32_t planeCount = 0U; }; using GLES3GPUTextureViewList = ccstd::vector; diff --git a/native/cocos/renderer/gfx-gles3/GLES3PipelineState.cpp b/native/cocos/renderer/gfx-gles3/GLES3PipelineState.cpp index 067c5037471..cd97b6fdf4e 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3PipelineState.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3PipelineState.cpp @@ -61,14 +61,20 @@ void updateGPUShaderSourceByRenderPass(GLES3GPUShader *gpuShader, GLES3GPURender } CC_ASSERT(subpassIndex < renderPass->subpasses.size()); - if (renderPass->subpasses[subpassIndex].inputs.empty()) { + if (renderPass->subpasses.size() <= 1) { return; } - auto &drawBuffers = renderPass->drawBuffers.at(subpassIndex); + bool dsInput{false}; + if (renderPass->depthStencil != INVALID_BINDING && !renderPass->subpasses[subpassIndex].inputs.empty()) { + const auto &inputs = renderPass->subpasses[subpassIndex].inputs; + // depth stencil input should always lies at the end of index list. + dsInput = inputs.back() == renderPass->depthStencil; + } + auto &drawBuffers = renderPass->drawBuffers.at(subpassIndex); ccstd::string::size_type offset = 0; for (uint32_t i = 0; i < drawBuffers.size(); ++i) { - const char* layoutPrefix = "layout(location = "; + const char *layoutPrefix = "layout(location = "; std::stringstream ss1; ss1 << layoutPrefix << i << ") out"; diff --git a/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp b/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp index 286ef62b78f..2026ec3d019 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp @@ -95,6 +95,8 @@ void GLES3Texture::createTextureView() { _gpuTextureView->format = _viewInfo.format; _gpuTextureView->baseLevel = _viewInfo.baseLevel; _gpuTextureView->levelCount = _viewInfo.levelCount; + _gpuTextureView->basePlane = _viewInfo.basePlane; + _gpuTextureView->planeCount = _viewInfo.planeCount; } void GLES3Texture::doDestroy() { diff --git a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm index 84cd6f958e0..eef51f0eef7 100644 --- a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm +++ b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm @@ -219,7 +219,9 @@ of this software and associated engine source code (the "Software"), a limited, for (size_t i = 0; i < subpasses.size(); ++i) { for (size_t j = 0; j < subpasses[i].inputs.size(); ++j) { uint32_t input = subpasses[i].inputs[j]; - if(input >= colorAttachments.size()) { + if(input >= colorAttachments.size() || + colorAttachments[input].format == Format::DEPTH_STENCIL || + colorAttachments[input].format == Format::DEPTH) { continue; // depthStencil as input } if (visited[input]) @@ -237,7 +239,7 @@ of this software and associated engine source code (the "Software"), a limited, if(color >= colorAttachments.size()) { continue; // depthStencil as output } - if (subpasses[i].resolves.size() > j) { + if (!subpasses[i].resolves.empty() && subpasses[i].resolves[j] != INVALID_BINDING) { uint32_t resolve = subpasses[i].resolves[j]; auto *resolveTex = static_cast(colorTextures[resolve]); mtlRenderPassDescriptor.colorAttachments[color].resolveTexture = resolveTex->getMTLTexture(); @@ -245,6 +247,8 @@ of this software and associated engine source code (the "Software"), a limited, mtlRenderPassDescriptor.colorAttachments[color].resolveSlice = 0; mtlRenderPassDescriptor.colorAttachments[color].resolveDepthPlane = 0; mtlRenderPassDescriptor.colorAttachments[color].storeAction = MTLStoreActionMultisampleResolve; + } else { + mtlRenderPassDescriptor.colorAttachments[color].storeAction = mu::isFramebufferFetchSupported() ? mu::toMTLStoreAction(colorAttachments[color].storeOp) : MTLStoreActionStore; } if (visited[color]) continue; @@ -261,7 +265,6 @@ of this software and associated engine source code (the "Software"), a limited, } else { mtlRenderPassDescriptor.colorAttachments[color].loadAction = mu::toMTLLoadAction(colorAttachments[color].loadOp); } - mtlRenderPassDescriptor.colorAttachments[color].storeAction = mu::isFramebufferFetchSupported() ? mu::toMTLStoreAction(colorAttachments[color].storeOp) : MTLStoreActionStore; visited[color] = true; _colorAppearedBefore.set(color); } @@ -386,7 +389,7 @@ of this software and associated engine source code (the "Software"), a limited, } if (subpass.depthStencilResolve != INVALID_BINDING) { - descriptor.depthAttachment.resolveTexture = static_cast(curFBO->getDepthStencilTexture())->getMTLTexture(); + descriptor.depthAttachment.resolveTexture = static_cast(curFBO->getDepthStencilResolveTexture())->getMTLTexture(); descriptor.depthAttachment.resolveLevel = 0; descriptor.depthAttachment.resolveSlice = 0; descriptor.depthAttachment.resolveDepthPlane = 0; diff --git a/native/cocos/renderer/gfx-metal/MTLDevice.mm b/native/cocos/renderer/gfx-metal/MTLDevice.mm index 186a152bcda..097d14dd0b1 100644 --- a/native/cocos/renderer/gfx-metal/MTLDevice.mm +++ b/native/cocos/renderer/gfx-metal/MTLDevice.mm @@ -135,7 +135,7 @@ of this software and associated engine source code (the "Software"), a limited, _features[toNumber(Feature::ELEMENT_INDEX_UINT)] = true; _features[toNumber(Feature::COMPUTE_SHADER)] = true; _features[toNumber(Feature::INPUT_ATTACHMENT_BENEFIT)] = true; - _features[toNumber(Feature::SUBPASS_COLOR_INPUT)] = false; + _features[toNumber(Feature::SUBPASS_COLOR_INPUT)] = true; _features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = false; _features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = true; diff --git a/native/cocos/renderer/gfx-metal/MTLPipelineState.mm b/native/cocos/renderer/gfx-metal/MTLPipelineState.mm index 447ca460e19..5eb009affe0 100644 --- a/native/cocos/renderer/gfx-metal/MTLPipelineState.mm +++ b/native/cocos/renderer/gfx-metal/MTLPipelineState.mm @@ -304,10 +304,11 @@ of this software and associated engine source code (the "Software"), a limited, depthStencilTexIndex = subpass.depthStencil; for (size_t i = 0; i < subpass.inputs.size(); ++i) { uint32_t input = subpass.inputs[i]; + if (inputs.find(input) == inputs.end()) { inputs.insert(input); - if(input >= colorAttachments.size()) { - depthStencilTexIndex = input; + if(_renderPass->getColorAttachments()[input].format == Format::DEPTH || + _renderPass->getColorAttachments()[input].format == Format::DEPTH_STENCIL) { continue; } mtlPixelFormat = mu::toMTLPixelFormat(colorAttachments[input].format); diff --git a/native/cocos/renderer/gfx-metal/MTLRenderPass.mm b/native/cocos/renderer/gfx-metal/MTLRenderPass.mm index 06c177998ea..51b98ea9f3e 100644 --- a/native/cocos/renderer/gfx-metal/MTLRenderPass.mm +++ b/native/cocos/renderer/gfx-metal/MTLRenderPass.mm @@ -93,7 +93,13 @@ of this software and associated engine source code (the "Software"), a limited, auto &drawBuffer = _drawBuffers[i]; for (auto &input : subPass.inputs) { - auto &index = _colorIndices[input]; + auto index = INVALID_BINDING; + if(input < _colorAttachments.size()) { + index = _colorIndices[input]; + } else { + // ds input + index = input; + } CC_ASSERT(index != INVALID_BINDING); // input should not appear before color or depthstencil. readBuffer.emplace_back(index); } diff --git a/native/cocos/renderer/gfx-metal/MTLShader.mm b/native/cocos/renderer/gfx-metal/MTLShader.mm index 3a81909b736..24b7e35b6a4 100644 --- a/native/cocos/renderer/gfx-metal/MTLShader.mm +++ b/native/cocos/renderer/gfx-metal/MTLShader.mm @@ -73,9 +73,9 @@ of this software and associated engine source code (the "Software"), a limited, _specializedFragFuncs = [[NSMutableDictionary alloc] init]; // spirv-cross for input attachment needs RenderPass to build [[color(index)]], // build gpu shader only when there is no subPass input. - if (!checkInputAttachment(info)) { - gpuShader(nullptr, 0); - } +// if (!checkInputAttachment(info)) { +// gpuShader(nullptr, 0); +// } } void CCMTLShader::doDestroy() { @@ -169,7 +169,7 @@ of this software and associated engine source code (the "Software"), a limited, const auto &drawBuffer = renderPass != nullptr ? renderPass->getDrawBuffer(subPass) : emptyBuffer; const auto &readBuffer = renderPass != nullptr ? renderPass->getReadBuffer(subPass) : emptyBuffer; ccstd::string mtlShaderSrc = mu::spirv2MSL(spirv->getOutputData(), spirv->getOutputSize() / unitSize, stage.stage, - _gpuShader, drawBuffer, readBuffer); + _gpuShader, renderPass, subPass); NSString* shader = [NSString stringWithUTF8String:mtlShaderSrc.c_str()]; NSError* error = nil; diff --git a/native/cocos/renderer/gfx-metal/MTLTexture.mm b/native/cocos/renderer/gfx-metal/MTLTexture.mm index 96d7b9a1bc1..2359cd99697 100644 --- a/native/cocos/renderer/gfx-metal/MTLTexture.mm +++ b/native/cocos/renderer/gfx-metal/MTLTexture.mm @@ -162,8 +162,14 @@ of this software and associated engine source code (the "Software"), a limited, } _convertedFormat = mu::convertGFXPixelFormat(_viewInfo.format); auto mtlTextureType = mu::toMTLTextureType(_viewInfo.type); + + MTLPixelFormat format = mu::toMTLPixelFormat(_convertedFormat); + if(_viewInfo.format == Format::DEPTH_STENCIL) { + format = _viewInfo.basePlane == 0 ? mu::toMTLPixelFormat(_viewInfo.texture->getFormat()) : MTLPixelFormatX32_Stencil8; + } + _mtlTextureView = [static_cast(_viewInfo.texture)->_mtlTexture - newTextureViewWithPixelFormat:mu::toMTLPixelFormat(_convertedFormat) + newTextureViewWithPixelFormat:format textureType:mtlTextureType levels:NSMakeRange(_viewInfo.baseLevel, _viewInfo.levelCount) slices:NSMakeRange(_viewInfo.baseLayer, _viewInfo.layerCount)]; @@ -220,6 +226,9 @@ of this software and associated engine source code (the "Software"), a limited, return false; descriptor.usage = mu::toMTLTextureUsage(_info.usage); + if(hasFlag(_info.flags, TextureFlags::MUTABLE_VIEW_FORMAT)) { + descriptor.usage |= MTLTextureUsagePixelFormatView; + } descriptor.sampleCount = mu::toMTLSampleCount(_info.samples); descriptor.textureType = descriptor.sampleCount > 1 ? MTLTextureType2DMultisample : mu::toMTLTextureType(_info.type); descriptor.mipmapLevelCount = _info.levelCount; diff --git a/native/cocos/renderer/gfx-metal/MTLUtils.h b/native/cocos/renderer/gfx-metal/MTLUtils.h index f055f6de261..18f597b3f3b 100644 --- a/native/cocos/renderer/gfx-metal/MTLUtils.h +++ b/native/cocos/renderer/gfx-metal/MTLUtils.h @@ -71,8 +71,7 @@ MTLSamplerAddressMode toMTLSamplerAddressMode(Address); int toMTLSamplerBorderColor(const Color &); MTLSamplerMinMagFilter toMTLSamplerMinMagFilter(Filter); MTLSamplerMipFilter toMTLSamplerMipFilter(Filter); -ccstd::string spirv2MSL(const uint32_t *ir, size_t word_count, ShaderStageFlagBit shaderType, CCMTLGPUShader *gpuShader, - const ccstd::vector &drawBuffer, const ccstd::vector &readBuffer); +ccstd::string spirv2MSL(const uint32_t *ir, size_t word_count, ShaderStageFlagBit shaderType, CCMTLGPUShader *gpuShader, RenderPass* renderpass, uint32_t subpassIndex); const uint8_t *convertRGB8ToRGBA8(const uint8_t *source, uint32_t length); const uint8_t *convertRGB32FToRGBA32F(const uint8_t *source, uint32_t length); NSUInteger highestSupportedFeatureSet(id device); diff --git a/native/cocos/renderer/gfx-metal/MTLUtils.mm b/native/cocos/renderer/gfx-metal/MTLUtils.mm index d2864e9b917..cf4f3fc7a8c 100644 --- a/native/cocos/renderer/gfx-metal/MTLUtils.mm +++ b/native/cocos/renderer/gfx-metal/MTLUtils.mm @@ -35,6 +35,7 @@ of this software and associated engine source code (the "Software"), a limited, #include "spirv_cross/spirv_msl.hpp" #include "TargetConditionals.h" #include "base/Log.h" +#include namespace cc { namespace gfx { @@ -918,8 +919,8 @@ void main() { ccstd::string mu::spirv2MSL(const uint32_t *ir, size_t word_count, ShaderStageFlagBit shaderType, CCMTLGPUShader *gpuShader, - const ccstd::vector &drawBuffer, - const ccstd::vector &readBuffer) { + RenderPass* renderPass, + uint32_t subpassIndex) { CCMTLDevice *device = CCMTLDevice::getInstance(); spirv_cross::CompilerMSL msl(ir, word_count); @@ -1057,18 +1058,24 @@ void main() { } if (executionModel == spv::ExecutionModelFragment) { + auto* ccRenderPass = static_cast(renderPass); + const auto& readBuffer = ccRenderPass ? ccRenderPass->getReadBuffer(subpassIndex) : ccstd::vector{}; if (!resources.subpass_inputs.empty()) { - gpuShader->inputs.resize(resources.subpass_inputs.size()); +// gpuShader->inputs.resize(resources.subpass_inputs.size()); for (size_t i = 0; i < resources.subpass_inputs.size(); i++) { const auto &attachment = resources.subpass_inputs[i]; - gpuShader->inputs[i].name = attachment.name; - auto id = msl.get_decoration(attachment.id, spv::DecorationInputAttachmentIndex); - auto loc = id >= readBuffer.size() ? id : readBuffer[id]; + auto inputIndex = msl.get_decoration(attachment.id, spv::DecorationInputAttachmentIndex); + auto loc = inputIndex >= readBuffer.size() ? inputIndex : readBuffer[inputIndex]; + // depth stencil input not support in metal + CC_ASSERT(loc != renderPass->getColorAttachments().size()); + auto& input = gpuShader->inputs.emplace_back(); + input.name = attachment.name; msl.set_decoration(attachment.id, spv::DecorationInputAttachmentIndex, loc); } } gpuShader->outputs.resize(resources.stage_outputs.size()); + const auto& drawBuffer = renderPass ? ccRenderPass->getDrawBuffer(subpassIndex) : ccstd::vector{}; for (size_t i = 0; i < resources.stage_outputs.size(); i++) { const auto &stageOutput = resources.stage_outputs[i]; auto set = msl.get_decoration(stageOutput.id, spv::DecorationDescriptorSet); @@ -1096,6 +1103,7 @@ void main() { CC_LOG_ERROR("Compile to MSL failed."); CC_LOG_ERROR("%s", output.c_str()); } + return output; } diff --git a/native/cocos/renderer/gfx-vulkan/VKCommands.cpp b/native/cocos/renderer/gfx-vulkan/VKCommands.cpp index cf098298382..0468624dd53 100644 --- a/native/cocos/renderer/gfx-vulkan/VKCommands.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKCommands.cpp @@ -196,15 +196,31 @@ void cmdFuncCCVKCreateTextureView(CCVKDevice *device, CCVKGPUTextureView *gpuTex if (!gpuTextureView->gpuTexture) return; auto createFn = [device, gpuTextureView](VkImage vkImage, VkImageView *pVkImageView) { + auto format = gpuTextureView->format; + auto mapAspect = [](CCVKGPUTextureView *gpuTextureView) { + auto aspectMask = gpuTextureView->gpuTexture->aspectMask; + if (gpuTextureView->gpuTexture->format == Format::DEPTH_STENCIL) { + uint32_t planeIndex = gpuTextureView->basePlane; + uint32_t planeCount = gpuTextureView->planeCount; + aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT << planeIndex; + CC_ASSERT(planeIndex + planeCount <= 2); + CC_ASSERT(planeCount > 0); + while (planeCount && --planeCount) { + aspectMask |= (aspectMask << 1); + } + } + return aspectMask; + }; + VkImageViewCreateInfo createInfo{VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; createInfo.image = vkImage; createInfo.viewType = mapVkImageViewType(gpuTextureView->type); - createInfo.format = mapVkFormat(gpuTextureView->format, device->gpuDevice()); - createInfo.subresourceRange.aspectMask = gpuTextureView->gpuTexture->aspectMask; + createInfo.subresourceRange.aspectMask = mapAspect(gpuTextureView); createInfo.subresourceRange.baseMipLevel = gpuTextureView->baseLevel; createInfo.subresourceRange.levelCount = gpuTextureView->levelCount; createInfo.subresourceRange.baseArrayLayer = gpuTextureView->baseLayer; createInfo.subresourceRange.layerCount = gpuTextureView->layerCount; + createInfo.format = mapVkFormat(format, device->gpuDevice()); VK_CHECK(vkCreateImageView(device->gpuDevice()->vkDevice, &createInfo, nullptr, pVkImageView)); }; @@ -444,13 +460,13 @@ void cmdFuncCCVKCreateRenderPass(CCVKDevice *device, CCVKGPURenderPass *gpuRende for (uint32_t input : subpassInfo.inputs) { bool appearsInOutput = std::find(subpassInfo.colors.begin(), subpassInfo.colors.end(), input) != subpassInfo.colors.end(); + VkImageLayout layout = appearsInOutput ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + VkImageAspectFlags aspectFlag = VK_IMAGE_ASPECT_COLOR_BIT; if (input == gpuRenderPass->colorAttachments.size()) { - VkImageLayout layout = subpassInfo.depthStencil != INVALID_BINDING ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - attachmentReferences.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, input, layout, VK_IMAGE_ASPECT_DEPTH_BIT}); - } else { - VkImageLayout layout = appearsInOutput ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - attachmentReferences.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, input, layout, VK_IMAGE_ASPECT_COLOR_BIT}); + layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; + aspectFlag = VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT; } + attachmentReferences.push_back({VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, nullptr, input, layout, aspectFlag}); } for (uint32_t color : subpassInfo.colors) { const VkAttachmentDescription2 &attachment = attachmentDescriptions[color]; @@ -518,7 +534,6 @@ void cmdFuncCCVKCreateRenderPass(CCVKDevice *device, CCVKGPURenderPass *gpuRende offset += subpassInfo.resolves.size(); } } - if (!subpassInfo.preserves.empty()) { desc.preserveAttachmentCount = utils::toUint(subpassInfo.preserves.size()); desc.pPreserveAttachments = subpassInfo.preserves.data(); diff --git a/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h b/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h index cb386223c67..edb7dfc6f42 100644 --- a/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h +++ b/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h @@ -188,6 +188,8 @@ struct CCVKGPUTextureView : public CCVKGPUDeviceObject { uint32_t levelCount = 1U; uint32_t baseLayer = 0U; uint32_t layerCount = 1U; + uint32_t basePlane = 0U; + uint32_t planeCount = 1U; ccstd::vector swapchainVkImageViews; diff --git a/native/cocos/renderer/gfx-vulkan/VKTexture.cpp b/native/cocos/renderer/gfx-vulkan/VKTexture.cpp index 5f0a3e85b47..c9b74b170ba 100644 --- a/native/cocos/renderer/gfx-vulkan/VKTexture.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKTexture.cpp @@ -43,6 +43,7 @@ CCVKTexture::~CCVKTexture() { void CCVKTexture::doInit(const TextureInfo & /*info*/) { createTexture(_info.width, _info.height, _size); + _viewInfo.planeCount = _info.format == Format::DEPTH_STENCIL ? 2 : 1; createTextureView(); } @@ -71,6 +72,7 @@ void CCVKTexture::createTexture(uint32_t width, uint32_t height, uint32_t size, _gpuTexture->mipLevels = _info.levelCount; _gpuTexture->samples = _info.samples; _gpuTexture->flags = _info.flags; + bool hasExternalFlag = hasFlag(_gpuTexture->flags, TextureFlagBit::EXTERNAL_NORMAL); if (hasExternalFlag) { _gpuTexture->externalVKImage = reinterpret_cast(_info.externalRes); @@ -90,6 +92,8 @@ void CCVKTexture::createTextureView(bool initGPUTextureView) { _gpuTextureView->levelCount = _viewInfo.levelCount; _gpuTextureView->baseLayer = _viewInfo.baseLayer; _gpuTextureView->layerCount = _viewInfo.layerCount; + _gpuTextureView->basePlane = _viewInfo.basePlane; + _gpuTextureView->planeCount = _viewInfo.planeCount; if (initGPUTextureView) { _gpuTextureView->init(); diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherGraphs.h b/native/cocos/renderer/pipeline/custom/FGDispatcherGraphs.h index 4050a7fbb5d..c12b37f57bc 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherGraphs.h +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherGraphs.h @@ -1,824 +1,962 @@ -/**************************************************************************** - Copyright (c) 2021-2023 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 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. -****************************************************************************/ - -/** - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - * The following section is auto-generated. - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - */ -// clang-format off -#pragma once -#include -#include -#include "cocos/renderer/pipeline/custom/FGDispatcherTypes.h" -#include "cocos/renderer/pipeline/custom/details/GraphImpl.h" -#include "cocos/renderer/pipeline/custom/details/Overload.h" -#include "cocos/renderer/pipeline/custom/details/PathUtils.h" - -namespace cc { - -namespace render { - -// IncidenceGraph -inline ResourceAccessGraph::vertex_descriptor -source(const ResourceAccessGraph::edge_descriptor& e, const ResourceAccessGraph& /*g*/) noexcept { - return e.source; -} - -inline ResourceAccessGraph::vertex_descriptor -target(const ResourceAccessGraph::edge_descriptor& e, const ResourceAccessGraph& /*g*/) noexcept { - return e.target; -} - -inline std::pair -out_edges(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - return std::make_pair( - ResourceAccessGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).begin(), u), - ResourceAccessGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).end(), u)); -} - -inline ResourceAccessGraph::degree_size_type -out_degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getOutEdgeList(u).size()); -} - -inline std::pair -edge(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph::vertex_descriptor v, const ResourceAccessGraph& g) noexcept { - const auto& outEdgeList = g.getOutEdgeList(u); - auto iter = std::find(outEdgeList.begin(), outEdgeList.end(), ResourceAccessGraph::OutEdge(v)); - bool hasEdge = (iter != outEdgeList.end()); - return {ResourceAccessGraph::edge_descriptor(u, v), hasEdge}; -} - -// BidirectionalGraph(Directed) -inline std::pair -in_edges(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - return std::make_pair( - ResourceAccessGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).begin(), u), - ResourceAccessGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).end(), u)); -} - -inline ResourceAccessGraph::degree_size_type -in_degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getInEdgeList(u).size()); -} - -inline ResourceAccessGraph::degree_size_type -degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { - return in_degree(u, g) + out_degree(u, g); -} - -// AdjacencyGraph -inline std::pair -adjacent_vertices(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT - auto edges = out_edges(u, g); - return std::make_pair(ResourceAccessGraph::adjacency_iterator(edges.first, &g), ResourceAccessGraph::adjacency_iterator(edges.second, &g)); -} - -// VertexListGraph -inline std::pair -vertices(const ResourceAccessGraph& g) noexcept { - return std::make_pair(const_cast(g).getVertexList().begin(), const_cast(g).getVertexList().end()); -} - -inline ResourceAccessGraph::vertices_size_type -num_vertices(const ResourceAccessGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getVertexList().size()); -} - -// EdgeListGraph -inline std::pair -edges(const ResourceAccessGraph& g0) noexcept { - auto& g = const_cast(g0); - return std::make_pair( - ResourceAccessGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().begin(), g.getVertexList().end(), g), - ResourceAccessGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().end(), g.getVertexList().end(), g)); -} - -inline ResourceAccessGraph::edges_size_type -num_edges(const ResourceAccessGraph& g) noexcept { // NOLINT - ResourceAccessGraph::edges_size_type numEdges = 0; - - auto range = vertices(g); - for (auto iter = range.first; iter != range.second; ++iter) { - numEdges += out_degree(*iter, g); - } - return numEdges; -} - -// MutableGraph(Edge) -inline std::pair -add_edge( // NOLINT - ResourceAccessGraph::vertex_descriptor u, - ResourceAccessGraph::vertex_descriptor v, ResourceAccessGraph& g) { - auto& outEdgeList = g.getOutEdgeList(u); - outEdgeList.emplace_back(v); - - auto& inEdgeList = g.getInEdgeList(v); - inEdgeList.emplace_back(u); - - return std::make_pair(ResourceAccessGraph::edge_descriptor(u, v), true); -} - -inline void remove_edge(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph::vertex_descriptor v, ResourceAccessGraph& g) noexcept { // NOLINT - auto& s = g._vertices[u]; - auto& t = g._vertices[v]; - s.outEdges.erase(std::remove(s.outEdges.begin(), s.outEdges.end(), ResourceAccessGraph::OutEdge(v)), s.outEdges.end()); - t.inEdges.erase(std::remove(t.inEdges.begin(), t.inEdges.end(), ResourceAccessGraph::InEdge(u)), t.inEdges.end()); -} - -inline void remove_edge(ResourceAccessGraph::out_edge_iterator outIter, ResourceAccessGraph& g) noexcept { // NOLINT - auto e = *outIter; - const auto u = source(e, g); - const auto v = target(e, g); - auto& s = g._vertices[u]; - auto& t = g._vertices[v]; - auto inIter = std::find(t.inEdges.begin(), t.inEdges.end(), ResourceAccessGraph::InEdge(u)); - CC_EXPECTS(inIter != t.inEdges.end()); - t.inEdges.erase(inIter); - s.outEdges.erase(outIter.base()); -} - -inline void remove_edge(ResourceAccessGraph::edge_descriptor e, ResourceAccessGraph& g) noexcept { // NOLINT - const auto u = source(e, g); - const auto v = target(e, g); - auto& s = g._vertices[u]; - auto outIter = std::find(s.outEdges.begin(), s.outEdges.end(), ResourceAccessGraph::OutEdge(v)); - CC_EXPECTS(outIter != s.outEdges.end()); - remove_edge(ResourceAccessGraph::out_edge_iterator(outIter, u), g); -} - -// MutableGraph(Vertex) -inline void clear_out_edges(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT - // Bidirectional (OutEdges) - auto& outEdgeList = g.getOutEdgeList(u); - auto outEnd = outEdgeList.end(); - for (auto iter = outEdgeList.begin(); iter != outEnd; ++iter) { - auto& inEdgeList = g.getInEdgeList((*iter).get_target()); - // eraseFromIncidenceList - impl::sequenceEraseIf(inEdgeList, [u](const auto& e) { - return e.get_target() == u; - }); - } - outEdgeList.clear(); -} - -inline void clear_in_edges(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT - // Bidirectional (InEdges) - auto& inEdgeList = g.getInEdgeList(u); - auto inEnd = inEdgeList.end(); - for (auto iter = inEdgeList.begin(); iter != inEnd; ++iter) { - auto& outEdgeList = g.getOutEdgeList((*iter).get_target()); - // eraseFromIncidenceList - impl::sequenceEraseIf(outEdgeList, [u](const auto& e) { - return e.get_target() == u; - }); - } - inEdgeList.clear(); -} - -inline void clear_vertex(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT - clear_out_edges(u, g); - clear_in_edges(u, g); -} - -inline void remove_vertex(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT - { // UuidGraph - const auto& key = g.passID[u]; - auto num = g.passIndex.erase(key); - CC_ENSURES(num == 1); - for (auto&& pair : g.passIndex) { - auto& v = pair.second; - if (v > u) { - --v; - } - } - } - impl::removeVectorVertex(const_cast(g), u, ResourceAccessGraph::directed_category{}); - - // remove components - g.passID.erase(g.passID.begin() + static_cast(u)); - g.access.erase(g.access.begin() + static_cast(u)); -} - -// MutablePropertyGraph(Vertex) -template -inline ResourceAccessGraph::vertex_descriptor -addVertex(Component0&& c0, Component1&& c1, ResourceAccessGraph& g) { - auto v = gsl::narrow_cast(g._vertices.size()); - - g._vertices.emplace_back(); - - { // UuidGraph - const auto& uuid = c0; - auto res = g.passIndex.emplace(uuid, v); - CC_ENSURES(res.second); - } - g.passID.emplace_back(std::forward(c0)); - g.access.emplace_back(std::forward(c1)); - - return v; -} - -template -inline ResourceAccessGraph::vertex_descriptor -addVertex(std::piecewise_construct_t /*tag*/, Component0&& c0, Component1&& c1, ResourceAccessGraph& g) { - auto v = gsl::narrow_cast(g._vertices.size()); - - g._vertices.emplace_back(); - - { // UuidGraph - std::apply( - [&](const auto&... args) { - auto res = g.passIndex.emplace(std::piecewise_construct, std::forward_as_tuple(args...), std::forward_as_tuple(v)); - CC_ENSURES(res.second); - }, - c0); - } - - std::apply( - [&](auto&&... args) { - g.passID.emplace_back(std::forward(args)...); - }, - std::forward(c0)); - - std::apply( - [&](auto&&... args) { - g.access.emplace_back(std::forward(args)...); - }, - std::forward(c1)); - - return v; -} - -// IncidenceGraph -inline RelationGraph::vertex_descriptor -source(const RelationGraph::edge_descriptor& e, const RelationGraph& /*g*/) noexcept { - return e.source; -} - -inline RelationGraph::vertex_descriptor -target(const RelationGraph::edge_descriptor& e, const RelationGraph& /*g*/) noexcept { - return e.target; -} - -inline std::pair -out_edges(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - return std::make_pair( - RelationGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).begin(), u), - RelationGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).end(), u)); -} - -inline RelationGraph::degree_size_type -out_degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getOutEdgeList(u).size()); -} - -inline std::pair -edge(RelationGraph::vertex_descriptor u, RelationGraph::vertex_descriptor v, const RelationGraph& g) noexcept { - const auto& outEdgeList = g.getOutEdgeList(u); - auto iter = std::find(outEdgeList.begin(), outEdgeList.end(), RelationGraph::OutEdge(v)); - bool hasEdge = (iter != outEdgeList.end()); - return {RelationGraph::edge_descriptor(u, v), hasEdge}; -} - -// BidirectionalGraph(Directed) -inline std::pair -in_edges(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - return std::make_pair( - RelationGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).begin(), u), - RelationGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).end(), u)); -} - -inline RelationGraph::degree_size_type -in_degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getInEdgeList(u).size()); -} - -inline RelationGraph::degree_size_type -degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { - return in_degree(u, g) + out_degree(u, g); -} - -// AdjacencyGraph -inline std::pair -adjacent_vertices(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT - auto edges = out_edges(u, g); - return std::make_pair(RelationGraph::adjacency_iterator(edges.first, &g), RelationGraph::adjacency_iterator(edges.second, &g)); -} - -// VertexListGraph -inline std::pair -vertices(const RelationGraph& g) noexcept { - return std::make_pair(const_cast(g).getVertexList().begin(), const_cast(g).getVertexList().end()); -} - -inline RelationGraph::vertices_size_type -num_vertices(const RelationGraph& g) noexcept { // NOLINT - return gsl::narrow_cast(g.getVertexList().size()); -} - -// EdgeListGraph -inline std::pair -edges(const RelationGraph& g0) noexcept { - auto& g = const_cast(g0); - return std::make_pair( - RelationGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().begin(), g.getVertexList().end(), g), - RelationGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().end(), g.getVertexList().end(), g)); -} - -inline RelationGraph::edges_size_type -num_edges(const RelationGraph& g) noexcept { // NOLINT - RelationGraph::edges_size_type numEdges = 0; - - auto range = vertices(g); - for (auto iter = range.first; iter != range.second; ++iter) { - numEdges += out_degree(*iter, g); - } - return numEdges; -} - -// MutableGraph(Edge) -inline std::pair -add_edge( // NOLINT - RelationGraph::vertex_descriptor u, - RelationGraph::vertex_descriptor v, RelationGraph& g) { - auto& outEdgeList = g.getOutEdgeList(u); - outEdgeList.emplace_back(v); - - auto& inEdgeList = g.getInEdgeList(v); - inEdgeList.emplace_back(u); - - return std::make_pair(RelationGraph::edge_descriptor(u, v), true); -} - -inline void remove_edge(RelationGraph::vertex_descriptor u, RelationGraph::vertex_descriptor v, RelationGraph& g) noexcept { // NOLINT - auto& s = g._vertices[u]; - auto& t = g._vertices[v]; - s.outEdges.erase(std::remove(s.outEdges.begin(), s.outEdges.end(), RelationGraph::OutEdge(v)), s.outEdges.end()); - t.inEdges.erase(std::remove(t.inEdges.begin(), t.inEdges.end(), RelationGraph::InEdge(u)), t.inEdges.end()); -} - -inline void remove_edge(RelationGraph::out_edge_iterator outIter, RelationGraph& g) noexcept { // NOLINT - auto e = *outIter; - const auto u = source(e, g); - const auto v = target(e, g); - auto& s = g._vertices[u]; - auto& t = g._vertices[v]; - auto inIter = std::find(t.inEdges.begin(), t.inEdges.end(), RelationGraph::InEdge(u)); - CC_EXPECTS(inIter != t.inEdges.end()); - t.inEdges.erase(inIter); - s.outEdges.erase(outIter.base()); -} - -inline void remove_edge(RelationGraph::edge_descriptor e, RelationGraph& g) noexcept { // NOLINT - const auto u = source(e, g); - const auto v = target(e, g); - auto& s = g._vertices[u]; - auto outIter = std::find(s.outEdges.begin(), s.outEdges.end(), RelationGraph::OutEdge(v)); - CC_EXPECTS(outIter != s.outEdges.end()); - remove_edge(RelationGraph::out_edge_iterator(outIter, u), g); -} - -// MutableGraph(Vertex) -inline void clear_out_edges(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT - // Bidirectional (OutEdges) - auto& outEdgeList = g.getOutEdgeList(u); - auto outEnd = outEdgeList.end(); - for (auto iter = outEdgeList.begin(); iter != outEnd; ++iter) { - auto& inEdgeList = g.getInEdgeList((*iter).get_target()); - // eraseFromIncidenceList - impl::sequenceEraseIf(inEdgeList, [u](const auto& e) { - return e.get_target() == u; - }); - } - outEdgeList.clear(); -} - -inline void clear_in_edges(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT - // Bidirectional (InEdges) - auto& inEdgeList = g.getInEdgeList(u); - auto inEnd = inEdgeList.end(); - for (auto iter = inEdgeList.begin(); iter != inEnd; ++iter) { - auto& outEdgeList = g.getOutEdgeList((*iter).get_target()); - // eraseFromIncidenceList - impl::sequenceEraseIf(outEdgeList, [u](const auto& e) { - return e.get_target() == u; - }); - } - inEdgeList.clear(); -} - -inline void clear_vertex(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT - clear_out_edges(u, g); - clear_in_edges(u, g); -} - -inline void remove_vertex(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT - { // UuidGraph - const auto& key = g.descID[u]; - auto num = g.vertexMap.erase(key); - CC_ENSURES(num == 1); - for (auto&& pair : g.vertexMap) { - auto& v = pair.second; - if (v > u) { - --v; - } - } - } - impl::removeVectorVertex(const_cast(g), u, RelationGraph::directed_category{}); - - // remove components - g.descID.erase(g.descID.begin() + static_cast(u)); -} - -// MutablePropertyGraph(Vertex) -template -inline RelationGraph::vertex_descriptor -addVertex(Component0&& c0, RelationGraph& g) { - auto v = gsl::narrow_cast(g._vertices.size()); - - g._vertices.emplace_back(); - - { // UuidGraph - const auto& uuid = c0; - auto res = g.vertexMap.emplace(uuid, v); - CC_ENSURES(res.second); - } - g.descID.emplace_back(std::forward(c0)); - - return v; -} - -template -inline RelationGraph::vertex_descriptor -addVertex(std::piecewise_construct_t /*tag*/, Component0&& c0, RelationGraph& g) { - auto v = gsl::narrow_cast(g._vertices.size()); - - g._vertices.emplace_back(); - - { // UuidGraph - std::apply( - [&](const auto&... args) { - auto res = g.vertexMap.emplace(std::piecewise_construct, std::forward_as_tuple(args...), std::forward_as_tuple(v)); - CC_ENSURES(res.second); - }, - c0); - } - - std::apply( - [&](auto&&... args) { - g.descID.emplace_back(std::forward(args)...); - }, - std::forward(c0)); - - return v; -} - -} // namespace render - -} // namespace cc - -namespace boost { - -// Vertex Index -template <> -struct property_map { - using const_type = identity_property_map; - using type = identity_property_map; -}; - -// Vertex Component -template <> -struct property_map { - using const_type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - const cc::render::ResourceAccessGraph, - const ccstd::pmr::vector, - cc::render::RenderGraph::vertex_descriptor, - const cc::render::RenderGraph::vertex_descriptor&>; - using type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - cc::render::ResourceAccessGraph, - ccstd::pmr::vector, - cc::render::RenderGraph::vertex_descriptor, - cc::render::RenderGraph::vertex_descriptor&>; -}; - -// Vertex Component -template <> -struct property_map { - using const_type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - const cc::render::ResourceAccessGraph, - const ccstd::pmr::vector, - cc::render::ResourceAccessNode, - const cc::render::ResourceAccessNode&>; - using type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - cc::render::ResourceAccessGraph, - ccstd::pmr::vector, - cc::render::ResourceAccessNode, - cc::render::ResourceAccessNode&>; -}; - -// Vertex ComponentMember -template -struct property_map { - using const_type = cc::render::impl::VectorVertexComponentMemberPropertyMap< - lvalue_property_map_tag, - const cc::render::ResourceAccessGraph, - const ccstd::pmr::vector, - T, - const T&, - T cc::render::ResourceAccessNode::*>; - using type = cc::render::impl::VectorVertexComponentMemberPropertyMap< - lvalue_property_map_tag, - cc::render::ResourceAccessGraph, - ccstd::pmr::vector, - T, - T&, - T cc::render::ResourceAccessNode::*>; -}; - -// Vertex Index -template <> -struct property_map { - using const_type = identity_property_map; - using type = identity_property_map; -}; - -// Vertex Component -template <> -struct property_map { - using const_type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - const cc::render::RelationGraph, - const ccstd::pmr::vector, - cc::render::ResourceAccessGraph::vertex_descriptor, - const cc::render::ResourceAccessGraph::vertex_descriptor&>; - using type = cc::render::impl::VectorVertexComponentPropertyMap< - lvalue_property_map_tag, - cc::render::RelationGraph, - ccstd::pmr::vector, - cc::render::ResourceAccessGraph::vertex_descriptor, - cc::render::ResourceAccessGraph::vertex_descriptor&>; -}; - -} // namespace boost - -namespace cc { - -namespace render { - -// Vertex Index -inline boost::property_map::const_type -get(boost::vertex_index_t /*tag*/, const ResourceAccessGraph& /*g*/) noexcept { - return {}; -} - -inline boost::property_map::type -get(boost::vertex_index_t /*tag*/, ResourceAccessGraph& /*g*/) noexcept { - return {}; -} - -inline impl::ColorMap -get(ccstd::pmr::vector& colors, const ResourceAccessGraph& /*g*/) noexcept { - return {colors}; -} - -// Vertex Component -inline typename boost::property_map::const_type -get(ResourceAccessGraph::PassIDTag /*tag*/, const ResourceAccessGraph& g) noexcept { - return {g.passID}; -} - -inline typename boost::property_map::type -get(ResourceAccessGraph::PassIDTag /*tag*/, ResourceAccessGraph& g) noexcept { - return {g.passID}; -} - -// Vertex Component -inline typename boost::property_map::const_type -get(ResourceAccessGraph::AccessNodeTag /*tag*/, const ResourceAccessGraph& g) noexcept { - return {g.access}; -} - -inline typename boost::property_map::type -get(ResourceAccessGraph::AccessNodeTag /*tag*/, ResourceAccessGraph& g) noexcept { - return {g.access}; -} - -// Vertex ComponentMember -template -inline typename boost::property_map::const_type -get(T ResourceAccessNode::*memberPointer, const ResourceAccessGraph& g) noexcept { - return {g.access, memberPointer}; -} - -template -inline typename boost::property_map::type -get(T ResourceAccessNode::*memberPointer, ResourceAccessGraph& g) noexcept { - return {g.access, memberPointer}; -} - -// Vertex Constant Getter -template -inline decltype(auto) -get(Tag tag, const ResourceAccessGraph& g, ResourceAccessGraph::vertex_descriptor v) noexcept { - return get(get(tag, g), v); -} - -// Vertex Mutable Getter -template -inline decltype(auto) -get(Tag tag, ResourceAccessGraph& g, ResourceAccessGraph::vertex_descriptor v) noexcept { - return get(get(tag, g), v); -} - -// Vertex Setter -template -inline void put( - Tag tag, ResourceAccessGraph& g, - ResourceAccessGraph::vertex_descriptor v, - Args&&... args) { - put(get(tag, g), v, std::forward(args)...); -} - -// UuidGraph -inline ResourceAccessGraph::vertex_descriptor -vertex(const RenderGraph::vertex_descriptor& key, const ResourceAccessGraph& g) { - return g.passIndex.at(key); -} - -template -inline ResourceAccessGraph::vertex_descriptor -vertex(const KeyLike& key, const ResourceAccessGraph& g) { - const auto& index = g.passIndex; - auto iter = index.find(key); - if (iter == index.end()) { - throw std::out_of_range("at(key, ResourceAccessGraph) out of range"); - } - return iter->second; -} - -template -inline ResourceAccessGraph::vertex_descriptor -findVertex(const KeyLike& key, const ResourceAccessGraph& g) noexcept { - const auto& index = g.passIndex; - auto iter = index.find(key); - if (iter == index.end()) { - return ResourceAccessGraph::null_vertex(); - } - return iter->second; -} - -inline bool -contains(const RenderGraph::vertex_descriptor& key, const ResourceAccessGraph& g) noexcept { - auto iter = g.passIndex.find(key); - return iter != g.passIndex.end(); -} - -template -inline bool -contains(const KeyLike& key, const ResourceAccessGraph& g) noexcept { - auto iter = g.passIndex.find(key); - return iter != g.passIndex.end(); -} - -// MutableGraph(Vertex) -inline ResourceAccessGraph::vertex_descriptor -add_vertex(ResourceAccessGraph& g, const RenderGraph::vertex_descriptor& key) { // NOLINT - return addVertex( - std::piecewise_construct, - std::forward_as_tuple(key), // passID - std::forward_as_tuple(), // access - g); -} - -// Vertex Index -inline boost::property_map::const_type -get(boost::vertex_index_t /*tag*/, const RelationGraph& /*g*/) noexcept { - return {}; -} - -inline boost::property_map::type -get(boost::vertex_index_t /*tag*/, RelationGraph& /*g*/) noexcept { - return {}; -} - -inline impl::ColorMap -get(ccstd::pmr::vector& colors, const RelationGraph& /*g*/) noexcept { - return {colors}; -} - -// Vertex Component -inline typename boost::property_map::const_type -get(RelationGraph::DescIDTag /*tag*/, const RelationGraph& g) noexcept { - return {g.descID}; -} - -inline typename boost::property_map::type -get(RelationGraph::DescIDTag /*tag*/, RelationGraph& g) noexcept { - return {g.descID}; -} - -// Vertex Constant Getter -template -inline decltype(auto) -get(Tag tag, const RelationGraph& g, RelationGraph::vertex_descriptor v) noexcept { - return get(get(tag, g), v); -} - -// Vertex Mutable Getter -template -inline decltype(auto) -get(Tag tag, RelationGraph& g, RelationGraph::vertex_descriptor v) noexcept { - return get(get(tag, g), v); -} - -// Vertex Setter -template -inline void put( - Tag tag, RelationGraph& g, - RelationGraph::vertex_descriptor v, - Args&&... args) { - put(get(tag, g), v, std::forward(args)...); -} - -// UuidGraph -inline RelationGraph::vertex_descriptor -vertex(const ResourceAccessGraph::vertex_descriptor& key, const RelationGraph& g) { - return g.vertexMap.at(key); -} - -template -inline RelationGraph::vertex_descriptor -vertex(const KeyLike& key, const RelationGraph& g) { - const auto& index = g.vertexMap; - auto iter = index.find(key); - if (iter == index.end()) { - throw std::out_of_range("at(key, RelationGraph) out of range"); - } - return iter->second; -} - -template -inline RelationGraph::vertex_descriptor -findVertex(const KeyLike& key, const RelationGraph& g) noexcept { - const auto& index = g.vertexMap; - auto iter = index.find(key); - if (iter == index.end()) { - return RelationGraph::null_vertex(); - } - return iter->second; -} - -inline bool -contains(const ResourceAccessGraph::vertex_descriptor& key, const RelationGraph& g) noexcept { - auto iter = g.vertexMap.find(key); - return iter != g.vertexMap.end(); -} - -template -inline bool -contains(const KeyLike& key, const RelationGraph& g) noexcept { - auto iter = g.vertexMap.find(key); - return iter != g.vertexMap.end(); -} - -// MutableGraph(Vertex) -inline RelationGraph::vertex_descriptor -add_vertex(RelationGraph& g, const ResourceAccessGraph::vertex_descriptor& key) { // NOLINT - return addVertex( - std::piecewise_construct, - std::forward_as_tuple(key), // descID - g); -} - -} // namespace render - -} // namespace cc - -// clang-format on +/**************************************************************************** + Copyright (c) 2021-2023 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 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. +****************************************************************************/ + +/** + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + * The following section is auto-generated. + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + */ +// clang-format off +#pragma once +#include +#include +#include "cocos/renderer/pipeline/custom/FGDispatcherTypes.h" +#include "cocos/renderer/pipeline/custom/details/GraphImpl.h" +#include "cocos/renderer/pipeline/custom/details/Overload.h" +#include "cocos/renderer/pipeline/custom/details/PathUtils.h" + +namespace cc { + +namespace render { + +// IncidenceGraph +inline ResourceAccessGraph::vertex_descriptor +source(const ResourceAccessGraph::edge_descriptor& e, const ResourceAccessGraph& /*g*/) noexcept { + return e.source; +} + +inline ResourceAccessGraph::vertex_descriptor +target(const ResourceAccessGraph::edge_descriptor& e, const ResourceAccessGraph& /*g*/) noexcept { + return e.target; +} + +inline std::pair +out_edges(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + return std::make_pair( + ResourceAccessGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).begin(), u), + ResourceAccessGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).end(), u)); +} + +inline ResourceAccessGraph::degree_size_type +out_degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getOutEdgeList(u).size()); +} + +inline std::pair +edge(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph::vertex_descriptor v, const ResourceAccessGraph& g) noexcept { + const auto& outEdgeList = g.getOutEdgeList(u); + auto iter = std::find(outEdgeList.begin(), outEdgeList.end(), ResourceAccessGraph::OutEdge(v)); + bool hasEdge = (iter != outEdgeList.end()); + return {ResourceAccessGraph::edge_descriptor(u, v), hasEdge}; +} + +// BidirectionalGraph(Directed) +inline std::pair +in_edges(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + return std::make_pair( + ResourceAccessGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).begin(), u), + ResourceAccessGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).end(), u)); +} + +inline ResourceAccessGraph::degree_size_type +in_degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getInEdgeList(u).size()); +} + +inline ResourceAccessGraph::degree_size_type +degree(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { + return in_degree(u, g) + out_degree(u, g); +} + +// AdjacencyGraph +inline std::pair +adjacent_vertices(ResourceAccessGraph::vertex_descriptor u, const ResourceAccessGraph& g) noexcept { // NOLINT + auto edges = out_edges(u, g); + return std::make_pair(ResourceAccessGraph::adjacency_iterator(edges.first, &g), ResourceAccessGraph::adjacency_iterator(edges.second, &g)); +} + +// VertexListGraph +inline std::pair +vertices(const ResourceAccessGraph& g) noexcept { + return std::make_pair(const_cast(g).getVertexList().begin(), const_cast(g).getVertexList().end()); +} + +inline ResourceAccessGraph::vertices_size_type +num_vertices(const ResourceAccessGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getVertexList().size()); +} + +// EdgeListGraph +inline std::pair +edges(const ResourceAccessGraph& g0) noexcept { + auto& g = const_cast(g0); + return std::make_pair( + ResourceAccessGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().begin(), g.getVertexList().end(), g), + ResourceAccessGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().end(), g.getVertexList().end(), g)); +} + +inline ResourceAccessGraph::edges_size_type +num_edges(const ResourceAccessGraph& g) noexcept { // NOLINT + ResourceAccessGraph::edges_size_type numEdges = 0; + + auto range = vertices(g); + for (auto iter = range.first; iter != range.second; ++iter) { + numEdges += out_degree(*iter, g); + } + return numEdges; +} + +// MutableGraph(Edge) +inline std::pair +add_edge( // NOLINT + ResourceAccessGraph::vertex_descriptor u, + ResourceAccessGraph::vertex_descriptor v, ResourceAccessGraph& g) { + auto& outEdgeList = g.getOutEdgeList(u); + outEdgeList.emplace_back(v); + + auto& inEdgeList = g.getInEdgeList(v); + inEdgeList.emplace_back(u); + + return std::make_pair(ResourceAccessGraph::edge_descriptor(u, v), true); +} + +inline void remove_edge(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph::vertex_descriptor v, ResourceAccessGraph& g) noexcept { // NOLINT + auto& s = g._vertices[u]; + auto& t = g._vertices[v]; + s.outEdges.erase(std::remove(s.outEdges.begin(), s.outEdges.end(), ResourceAccessGraph::OutEdge(v)), s.outEdges.end()); + t.inEdges.erase(std::remove(t.inEdges.begin(), t.inEdges.end(), ResourceAccessGraph::InEdge(u)), t.inEdges.end()); +} + +inline void remove_edge(ResourceAccessGraph::out_edge_iterator outIter, ResourceAccessGraph& g) noexcept { // NOLINT + auto e = *outIter; + const auto u = source(e, g); + const auto v = target(e, g); + auto& s = g._vertices[u]; + auto& t = g._vertices[v]; + auto inIter = std::find(t.inEdges.begin(), t.inEdges.end(), ResourceAccessGraph::InEdge(u)); + CC_EXPECTS(inIter != t.inEdges.end()); + t.inEdges.erase(inIter); + s.outEdges.erase(outIter.base()); +} + +inline void remove_edge(ResourceAccessGraph::edge_descriptor e, ResourceAccessGraph& g) noexcept { // NOLINT + const auto u = source(e, g); + const auto v = target(e, g); + auto& s = g._vertices[u]; + auto outIter = std::find(s.outEdges.begin(), s.outEdges.end(), ResourceAccessGraph::OutEdge(v)); + CC_EXPECTS(outIter != s.outEdges.end()); + remove_edge(ResourceAccessGraph::out_edge_iterator(outIter, u), g); +} + +// MutableGraph(Vertex) +inline void clear_out_edges(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT + // Bidirectional (OutEdges) + auto& outEdgeList = g.getOutEdgeList(u); + auto outEnd = outEdgeList.end(); + for (auto iter = outEdgeList.begin(); iter != outEnd; ++iter) { + auto& inEdgeList = g.getInEdgeList((*iter).get_target()); + // eraseFromIncidenceList + impl::sequenceEraseIf(inEdgeList, [u](const auto& e) { + return e.get_target() == u; + }); + } + outEdgeList.clear(); +} + +inline void clear_in_edges(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT + // Bidirectional (InEdges) + auto& inEdgeList = g.getInEdgeList(u); + auto inEnd = inEdgeList.end(); + for (auto iter = inEdgeList.begin(); iter != inEnd; ++iter) { + auto& outEdgeList = g.getOutEdgeList((*iter).get_target()); + // eraseFromIncidenceList + impl::sequenceEraseIf(outEdgeList, [u](const auto& e) { + return e.get_target() == u; + }); + } + inEdgeList.clear(); +} + +inline void clear_vertex(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT + clear_out_edges(u, g); + clear_in_edges(u, g); +} + +inline void remove_vertex(ResourceAccessGraph::vertex_descriptor u, ResourceAccessGraph& g) noexcept { // NOLINT + { // UuidGraph + const auto& key = g.passID[u]; + auto num = g.passIndex.erase(key); + CC_ENSURES(num == 1); + for (auto&& pair : g.passIndex) { + auto& v = pair.second; + if (v > u) { + --v; + } + } + } + impl::removeVectorVertex(const_cast(g), u, ResourceAccessGraph::directed_category{}); + + // remove components + g.passID.erase(g.passID.begin() + static_cast(u)); + g.passResource.erase(g.passResource.begin() + static_cast(u)); + g.rpInfo.erase(g.rpInfo.begin() + static_cast(u)); + g.barrier.erase(g.barrier.begin() + static_cast(u)); +} + +// MutablePropertyGraph(Vertex) +template +inline ResourceAccessGraph::vertex_descriptor +addVertex(Component0&& c0, Component1&& c1, Component2&& c2, Component3&& c3, ResourceAccessGraph& g) { + auto v = gsl::narrow_cast(g._vertices.size()); + + g._vertices.emplace_back(); + + { // UuidGraph + const auto& uuid = c0; + auto res = g.passIndex.emplace(uuid, v); + CC_ENSURES(res.second); + } + g.passID.emplace_back(std::forward(c0)); + g.passResource.emplace_back(std::forward(c1)); + g.rpInfo.emplace_back(std::forward(c2)); + g.barrier.emplace_back(std::forward(c3)); + + return v; +} + +template +inline ResourceAccessGraph::vertex_descriptor +addVertex(std::piecewise_construct_t /*tag*/, Component0&& c0, Component1&& c1, Component2&& c2, Component3&& c3, ResourceAccessGraph& g) { + auto v = gsl::narrow_cast(g._vertices.size()); + + g._vertices.emplace_back(); + + { // UuidGraph + std::apply( + [&](const auto&... args) { + auto res = g.passIndex.emplace(std::piecewise_construct, std::forward_as_tuple(args...), std::forward_as_tuple(v)); + CC_ENSURES(res.second); + }, + c0); + } + + std::apply( + [&](auto&&... args) { + g.passID.emplace_back(std::forward(args)...); + }, + std::forward(c0)); + + std::apply( + [&](auto&&... args) { + g.passResource.emplace_back(std::forward(args)...); + }, + std::forward(c1)); + + std::apply( + [&](auto&&... args) { + g.rpInfo.emplace_back(std::forward(args)...); + }, + std::forward(c2)); + + std::apply( + [&](auto&&... args) { + g.barrier.emplace_back(std::forward(args)...); + }, + std::forward(c3)); + + return v; +} + +// IncidenceGraph +inline RelationGraph::vertex_descriptor +source(const RelationGraph::edge_descriptor& e, const RelationGraph& /*g*/) noexcept { + return e.source; +} + +inline RelationGraph::vertex_descriptor +target(const RelationGraph::edge_descriptor& e, const RelationGraph& /*g*/) noexcept { + return e.target; +} + +inline std::pair +out_edges(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + return std::make_pair( + RelationGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).begin(), u), + RelationGraph::out_edge_iterator(const_cast(g).getOutEdgeList(u).end(), u)); +} + +inline RelationGraph::degree_size_type +out_degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getOutEdgeList(u).size()); +} + +inline std::pair +edge(RelationGraph::vertex_descriptor u, RelationGraph::vertex_descriptor v, const RelationGraph& g) noexcept { + const auto& outEdgeList = g.getOutEdgeList(u); + auto iter = std::find(outEdgeList.begin(), outEdgeList.end(), RelationGraph::OutEdge(v)); + bool hasEdge = (iter != outEdgeList.end()); + return {RelationGraph::edge_descriptor(u, v), hasEdge}; +} + +// BidirectionalGraph(Directed) +inline std::pair +in_edges(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + return std::make_pair( + RelationGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).begin(), u), + RelationGraph::in_edge_iterator(const_cast(g).getInEdgeList(u).end(), u)); +} + +inline RelationGraph::degree_size_type +in_degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getInEdgeList(u).size()); +} + +inline RelationGraph::degree_size_type +degree(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { + return in_degree(u, g) + out_degree(u, g); +} + +// AdjacencyGraph +inline std::pair +adjacent_vertices(RelationGraph::vertex_descriptor u, const RelationGraph& g) noexcept { // NOLINT + auto edges = out_edges(u, g); + return std::make_pair(RelationGraph::adjacency_iterator(edges.first, &g), RelationGraph::adjacency_iterator(edges.second, &g)); +} + +// VertexListGraph +inline std::pair +vertices(const RelationGraph& g) noexcept { + return std::make_pair(const_cast(g).getVertexList().begin(), const_cast(g).getVertexList().end()); +} + +inline RelationGraph::vertices_size_type +num_vertices(const RelationGraph& g) noexcept { // NOLINT + return gsl::narrow_cast(g.getVertexList().size()); +} + +// EdgeListGraph +inline std::pair +edges(const RelationGraph& g0) noexcept { + auto& g = const_cast(g0); + return std::make_pair( + RelationGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().begin(), g.getVertexList().end(), g), + RelationGraph::edge_iterator(g.getVertexList().begin(), g.getVertexList().end(), g.getVertexList().end(), g)); +} + +inline RelationGraph::edges_size_type +num_edges(const RelationGraph& g) noexcept { // NOLINT + RelationGraph::edges_size_type numEdges = 0; + + auto range = vertices(g); + for (auto iter = range.first; iter != range.second; ++iter) { + numEdges += out_degree(*iter, g); + } + return numEdges; +} + +// MutableGraph(Edge) +inline std::pair +add_edge( // NOLINT + RelationGraph::vertex_descriptor u, + RelationGraph::vertex_descriptor v, RelationGraph& g) { + auto& outEdgeList = g.getOutEdgeList(u); + outEdgeList.emplace_back(v); + + auto& inEdgeList = g.getInEdgeList(v); + inEdgeList.emplace_back(u); + + return std::make_pair(RelationGraph::edge_descriptor(u, v), true); +} + +inline void remove_edge(RelationGraph::vertex_descriptor u, RelationGraph::vertex_descriptor v, RelationGraph& g) noexcept { // NOLINT + auto& s = g._vertices[u]; + auto& t = g._vertices[v]; + s.outEdges.erase(std::remove(s.outEdges.begin(), s.outEdges.end(), RelationGraph::OutEdge(v)), s.outEdges.end()); + t.inEdges.erase(std::remove(t.inEdges.begin(), t.inEdges.end(), RelationGraph::InEdge(u)), t.inEdges.end()); +} + +inline void remove_edge(RelationGraph::out_edge_iterator outIter, RelationGraph& g) noexcept { // NOLINT + auto e = *outIter; + const auto u = source(e, g); + const auto v = target(e, g); + auto& s = g._vertices[u]; + auto& t = g._vertices[v]; + auto inIter = std::find(t.inEdges.begin(), t.inEdges.end(), RelationGraph::InEdge(u)); + CC_EXPECTS(inIter != t.inEdges.end()); + t.inEdges.erase(inIter); + s.outEdges.erase(outIter.base()); +} + +inline void remove_edge(RelationGraph::edge_descriptor e, RelationGraph& g) noexcept { // NOLINT + const auto u = source(e, g); + const auto v = target(e, g); + auto& s = g._vertices[u]; + auto outIter = std::find(s.outEdges.begin(), s.outEdges.end(), RelationGraph::OutEdge(v)); + CC_EXPECTS(outIter != s.outEdges.end()); + remove_edge(RelationGraph::out_edge_iterator(outIter, u), g); +} + +// MutableGraph(Vertex) +inline void clear_out_edges(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT + // Bidirectional (OutEdges) + auto& outEdgeList = g.getOutEdgeList(u); + auto outEnd = outEdgeList.end(); + for (auto iter = outEdgeList.begin(); iter != outEnd; ++iter) { + auto& inEdgeList = g.getInEdgeList((*iter).get_target()); + // eraseFromIncidenceList + impl::sequenceEraseIf(inEdgeList, [u](const auto& e) { + return e.get_target() == u; + }); + } + outEdgeList.clear(); +} + +inline void clear_in_edges(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT + // Bidirectional (InEdges) + auto& inEdgeList = g.getInEdgeList(u); + auto inEnd = inEdgeList.end(); + for (auto iter = inEdgeList.begin(); iter != inEnd; ++iter) { + auto& outEdgeList = g.getOutEdgeList((*iter).get_target()); + // eraseFromIncidenceList + impl::sequenceEraseIf(outEdgeList, [u](const auto& e) { + return e.get_target() == u; + }); + } + inEdgeList.clear(); +} + +inline void clear_vertex(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT + clear_out_edges(u, g); + clear_in_edges(u, g); +} + +inline void remove_vertex(RelationGraph::vertex_descriptor u, RelationGraph& g) noexcept { // NOLINT + { // UuidGraph + const auto& key = g.descID[u]; + auto num = g.vertexMap.erase(key); + CC_ENSURES(num == 1); + for (auto&& pair : g.vertexMap) { + auto& v = pair.second; + if (v > u) { + --v; + } + } + } + impl::removeVectorVertex(const_cast(g), u, RelationGraph::directed_category{}); + + // remove components + g.descID.erase(g.descID.begin() + static_cast(u)); +} + +// MutablePropertyGraph(Vertex) +template +inline RelationGraph::vertex_descriptor +addVertex(Component0&& c0, RelationGraph& g) { + auto v = gsl::narrow_cast(g._vertices.size()); + + g._vertices.emplace_back(); + + { // UuidGraph + const auto& uuid = c0; + auto res = g.vertexMap.emplace(uuid, v); + CC_ENSURES(res.second); + } + g.descID.emplace_back(std::forward(c0)); + + return v; +} + +template +inline RelationGraph::vertex_descriptor +addVertex(std::piecewise_construct_t /*tag*/, Component0&& c0, RelationGraph& g) { + auto v = gsl::narrow_cast(g._vertices.size()); + + g._vertices.emplace_back(); + + { // UuidGraph + std::apply( + [&](const auto&... args) { + auto res = g.vertexMap.emplace(std::piecewise_construct, std::forward_as_tuple(args...), std::forward_as_tuple(v)); + CC_ENSURES(res.second); + }, + c0); + } + + std::apply( + [&](auto&&... args) { + g.descID.emplace_back(std::forward(args)...); + }, + std::forward(c0)); + + return v; +} + +} // namespace render + +} // namespace cc + +namespace boost { + +// Vertex Index +template <> +struct property_map { + using const_type = identity_property_map; + using type = identity_property_map; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + cc::render::RenderGraph::vertex_descriptor, + const cc::render::RenderGraph::vertex_descriptor&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + cc::render::RenderGraph::vertex_descriptor, + cc::render::RenderGraph::vertex_descriptor&>; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + cc::render::ResourceAccessNode, + const cc::render::ResourceAccessNode&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + cc::render::ResourceAccessNode, + cc::render::ResourceAccessNode&>; +}; + +// Vertex ComponentMember +template +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + T, + const T&, + T cc::render::ResourceAccessNode::*>; + using type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + T, + T&, + T cc::render::ResourceAccessNode::*>; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + cc::render::FGRenderPassInfo, + const cc::render::FGRenderPassInfo&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + cc::render::FGRenderPassInfo, + cc::render::FGRenderPassInfo&>; +}; + +// Vertex ComponentMember +template +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + T, + const T&, + T cc::render::FGRenderPassInfo::*>; + using type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + T, + T&, + T cc::render::FGRenderPassInfo::*>; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + cc::render::BarrierNode, + const cc::render::BarrierNode&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + cc::render::BarrierNode, + cc::render::BarrierNode&>; +}; + +// Vertex ComponentMember +template +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + const cc::render::ResourceAccessGraph, + const ccstd::pmr::vector, + T, + const T&, + T cc::render::BarrierNode::*>; + using type = cc::render::impl::VectorVertexComponentMemberPropertyMap< + lvalue_property_map_tag, + cc::render::ResourceAccessGraph, + ccstd::pmr::vector, + T, + T&, + T cc::render::BarrierNode::*>; +}; + +// Vertex Index +template <> +struct property_map { + using const_type = identity_property_map; + using type = identity_property_map; +}; + +// Vertex Component +template <> +struct property_map { + using const_type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + const cc::render::RelationGraph, + const ccstd::pmr::vector, + cc::render::ResourceAccessGraph::vertex_descriptor, + const cc::render::ResourceAccessGraph::vertex_descriptor&>; + using type = cc::render::impl::VectorVertexComponentPropertyMap< + lvalue_property_map_tag, + cc::render::RelationGraph, + ccstd::pmr::vector, + cc::render::ResourceAccessGraph::vertex_descriptor, + cc::render::ResourceAccessGraph::vertex_descriptor&>; +}; + +} // namespace boost + +namespace cc { + +namespace render { + +// Vertex Index +inline boost::property_map::const_type +get(boost::vertex_index_t /*tag*/, const ResourceAccessGraph& /*g*/) noexcept { + return {}; +} + +inline boost::property_map::type +get(boost::vertex_index_t /*tag*/, ResourceAccessGraph& /*g*/) noexcept { + return {}; +} + +inline impl::ColorMap +get(ccstd::pmr::vector& colors, const ResourceAccessGraph& /*g*/) noexcept { + return {colors}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(ResourceAccessGraph::PassIDTag /*tag*/, const ResourceAccessGraph& g) noexcept { + return {g.passID}; +} + +inline typename boost::property_map::type +get(ResourceAccessGraph::PassIDTag /*tag*/, ResourceAccessGraph& g) noexcept { + return {g.passID}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(ResourceAccessGraph::PassNodeTag /*tag*/, const ResourceAccessGraph& g) noexcept { + return {g.passResource}; +} + +inline typename boost::property_map::type +get(ResourceAccessGraph::PassNodeTag /*tag*/, ResourceAccessGraph& g) noexcept { + return {g.passResource}; +} + +// Vertex ComponentMember +template +inline typename boost::property_map::const_type +get(T ResourceAccessNode::*memberPointer, const ResourceAccessGraph& g) noexcept { + return {g.passResource, memberPointer}; +} + +template +inline typename boost::property_map::type +get(T ResourceAccessNode::*memberPointer, ResourceAccessGraph& g) noexcept { + return {g.passResource, memberPointer}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(ResourceAccessGraph::RenderPassInfoTag /*tag*/, const ResourceAccessGraph& g) noexcept { + return {g.rpInfo}; +} + +inline typename boost::property_map::type +get(ResourceAccessGraph::RenderPassInfoTag /*tag*/, ResourceAccessGraph& g) noexcept { + return {g.rpInfo}; +} + +// Vertex ComponentMember +template +inline typename boost::property_map::const_type +get(T FGRenderPassInfo::*memberPointer, const ResourceAccessGraph& g) noexcept { + return {g.rpInfo, memberPointer}; +} + +template +inline typename boost::property_map::type +get(T FGRenderPassInfo::*memberPointer, ResourceAccessGraph& g) noexcept { + return {g.rpInfo, memberPointer}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(ResourceAccessGraph::BarrierTag /*tag*/, const ResourceAccessGraph& g) noexcept { + return {g.barrier}; +} + +inline typename boost::property_map::type +get(ResourceAccessGraph::BarrierTag /*tag*/, ResourceAccessGraph& g) noexcept { + return {g.barrier}; +} + +// Vertex ComponentMember +template +inline typename boost::property_map::const_type +get(T BarrierNode::*memberPointer, const ResourceAccessGraph& g) noexcept { + return {g.barrier, memberPointer}; +} + +template +inline typename boost::property_map::type +get(T BarrierNode::*memberPointer, ResourceAccessGraph& g) noexcept { + return {g.barrier, memberPointer}; +} + +// Vertex Constant Getter +template +inline decltype(auto) +get(Tag tag, const ResourceAccessGraph& g, ResourceAccessGraph::vertex_descriptor v) noexcept { + return get(get(tag, g), v); +} + +// Vertex Mutable Getter +template +inline decltype(auto) +get(Tag tag, ResourceAccessGraph& g, ResourceAccessGraph::vertex_descriptor v) noexcept { + return get(get(tag, g), v); +} + +// Vertex Setter +template +inline void put( + Tag tag, ResourceAccessGraph& g, + ResourceAccessGraph::vertex_descriptor v, + Args&&... args) { + put(get(tag, g), v, std::forward(args)...); +} + +// UuidGraph +inline ResourceAccessGraph::vertex_descriptor +vertex(const RenderGraph::vertex_descriptor& key, const ResourceAccessGraph& g) { + return g.passIndex.at(key); +} + +template +inline ResourceAccessGraph::vertex_descriptor +vertex(const KeyLike& key, const ResourceAccessGraph& g) { + const auto& index = g.passIndex; + auto iter = index.find(key); + if (iter == index.end()) { + throw std::out_of_range("at(key, ResourceAccessGraph) out of range"); + } + return iter->second; +} + +template +inline ResourceAccessGraph::vertex_descriptor +findVertex(const KeyLike& key, const ResourceAccessGraph& g) noexcept { + const auto& index = g.passIndex; + auto iter = index.find(key); + if (iter == index.end()) { + return ResourceAccessGraph::null_vertex(); + } + return iter->second; +} + +inline bool +contains(const RenderGraph::vertex_descriptor& key, const ResourceAccessGraph& g) noexcept { + auto iter = g.passIndex.find(key); + return iter != g.passIndex.end(); +} + +template +inline bool +contains(const KeyLike& key, const ResourceAccessGraph& g) noexcept { + auto iter = g.passIndex.find(key); + return iter != g.passIndex.end(); +} + +// MutableGraph(Vertex) +inline ResourceAccessGraph::vertex_descriptor +add_vertex(ResourceAccessGraph& g, const RenderGraph::vertex_descriptor& key) { // NOLINT + return addVertex( + std::piecewise_construct, + std::forward_as_tuple(key), // passID + std::forward_as_tuple(), // passResource + std::forward_as_tuple(), // rpInfo + std::forward_as_tuple(), // barrier + g); +} + +// Vertex Index +inline boost::property_map::const_type +get(boost::vertex_index_t /*tag*/, const RelationGraph& /*g*/) noexcept { + return {}; +} + +inline boost::property_map::type +get(boost::vertex_index_t /*tag*/, RelationGraph& /*g*/) noexcept { + return {}; +} + +inline impl::ColorMap +get(ccstd::pmr::vector& colors, const RelationGraph& /*g*/) noexcept { + return {colors}; +} + +// Vertex Component +inline typename boost::property_map::const_type +get(RelationGraph::DescIDTag /*tag*/, const RelationGraph& g) noexcept { + return {g.descID}; +} + +inline typename boost::property_map::type +get(RelationGraph::DescIDTag /*tag*/, RelationGraph& g) noexcept { + return {g.descID}; +} + +// Vertex Constant Getter +template +inline decltype(auto) +get(Tag tag, const RelationGraph& g, RelationGraph::vertex_descriptor v) noexcept { + return get(get(tag, g), v); +} + +// Vertex Mutable Getter +template +inline decltype(auto) +get(Tag tag, RelationGraph& g, RelationGraph::vertex_descriptor v) noexcept { + return get(get(tag, g), v); +} + +// Vertex Setter +template +inline void put( + Tag tag, RelationGraph& g, + RelationGraph::vertex_descriptor v, + Args&&... args) { + put(get(tag, g), v, std::forward(args)...); +} + +// UuidGraph +inline RelationGraph::vertex_descriptor +vertex(const ResourceAccessGraph::vertex_descriptor& key, const RelationGraph& g) { + return g.vertexMap.at(key); +} + +template +inline RelationGraph::vertex_descriptor +vertex(const KeyLike& key, const RelationGraph& g) { + const auto& index = g.vertexMap; + auto iter = index.find(key); + if (iter == index.end()) { + throw std::out_of_range("at(key, RelationGraph) out of range"); + } + return iter->second; +} + +template +inline RelationGraph::vertex_descriptor +findVertex(const KeyLike& key, const RelationGraph& g) noexcept { + const auto& index = g.vertexMap; + auto iter = index.find(key); + if (iter == index.end()) { + return RelationGraph::null_vertex(); + } + return iter->second; +} + +inline bool +contains(const ResourceAccessGraph::vertex_descriptor& key, const RelationGraph& g) noexcept { + auto iter = g.vertexMap.find(key); + return iter != g.vertexMap.end(); +} + +template +inline bool +contains(const KeyLike& key, const RelationGraph& g) noexcept { + auto iter = g.vertexMap.find(key); + return iter != g.vertexMap.end(); +} + +// MutableGraph(Vertex) +inline RelationGraph::vertex_descriptor +add_vertex(RelationGraph& g, const ResourceAccessGraph::vertex_descriptor& key) { // NOLINT + return addVertex( + std::piecewise_construct, + std::forward_as_tuple(key), // descID + g); +} + +} // namespace render + +} // namespace cc + +// clang-format on diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp index 01ba6c84a29..1982760fd0a 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp @@ -1,107 +1,173 @@ -/**************************************************************************** - Copyright (c) 2021-2023 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 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. -****************************************************************************/ - -/** - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - * The following section is auto-generated. - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - */ -// clang-format off -#include "FGDispatcherTypes.h" - -namespace cc { - -namespace render { - -ResourceAccessGraph::ResourceAccessGraph(const allocator_type& alloc) noexcept -: _vertices(alloc), - passID(alloc), - access(alloc), - passIndex(alloc), - resourceNames(alloc), - resourceIndex(alloc), - leafPasses(alloc), - culledPasses(alloc), - accessRecord(alloc), - resourceLifeRecord(alloc), - topologicalOrder(alloc), - rpInfos(alloc), - subpassIndex(alloc) {} - -// ContinuousContainer -void ResourceAccessGraph::reserve(vertices_size_type sz) { - _vertices.reserve(sz); - passID.reserve(sz); - access.reserve(sz); -} - -ResourceAccessGraph::Vertex::Vertex(const allocator_type& alloc) noexcept -: outEdges(alloc), - inEdges(alloc) {} - -ResourceAccessGraph::Vertex::Vertex(Vertex&& rhs, const allocator_type& alloc) -: outEdges(std::move(rhs.outEdges), alloc), - inEdges(std::move(rhs.inEdges), alloc) {} - -ResourceAccessGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) -: outEdges(rhs.outEdges, alloc), - inEdges(rhs.inEdges, alloc) {} - -RelationGraph::RelationGraph(const allocator_type& alloc) noexcept -: _vertices(alloc), - descID(alloc), - vertexMap(alloc) {} - -// ContinuousContainer -void RelationGraph::reserve(vertices_size_type sz) { - _vertices.reserve(sz); - descID.reserve(sz); -} - -RelationGraph::Vertex::Vertex(const allocator_type& alloc) noexcept -: outEdges(alloc), - inEdges(alloc) {} - -RelationGraph::Vertex::Vertex(Vertex&& rhs, const allocator_type& alloc) -: outEdges(std::move(rhs.outEdges), alloc), - inEdges(std::move(rhs.inEdges), alloc) {} - -RelationGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) -: outEdges(rhs.outEdges, alloc), - inEdges(rhs.inEdges, alloc) {} - -FrameGraphDispatcher::FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& graphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept -: resourceAccessGraph(alloc), - resourceGraph(resourceGraphIn), - graph(graphIn), - layoutGraph(layoutGraphIn), - scratch(scratchIn), - externalResMap(alloc), - relationGraph(alloc) {} - -} // namespace render - -} // namespace cc - -// clang-format on +/**************************************************************************** + Copyright (c) 2021-2023 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 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. +****************************************************************************/ + +/** + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + * The following section is auto-generated. + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + */ +// clang-format off +#include "FGDispatcherTypes.h" + +namespace cc { + +namespace render { + +ResourceAccessNode::ResourceAccessNode(const allocator_type& alloc) noexcept +: resourceStatus(alloc) {} + +ResourceAccessNode::ResourceAccessNode(ResourceAccessNode&& rhs, const allocator_type& alloc) +: resourceStatus(std::move(rhs.resourceStatus), alloc) {} + +ResourceAccessNode::ResourceAccessNode(ResourceAccessNode const& rhs, const allocator_type& alloc) +: resourceStatus(rhs.resourceStatus, alloc) {} + +AttachmentInfo::AttachmentInfo(const allocator_type& alloc) noexcept +: parentName(alloc) {} + +AttachmentInfo::AttachmentInfo(AttachmentInfo&& rhs, const allocator_type& alloc) +: parentName(std::move(rhs.parentName), alloc), + attachmentIndex(rhs.attachmentIndex), + isResolveView(rhs.isResolveView) {} + +AttachmentInfo::AttachmentInfo(AttachmentInfo const& rhs, const allocator_type& alloc) +: parentName(rhs.parentName, alloc), + attachmentIndex(rhs.attachmentIndex), + isResolveView(rhs.isResolveView) {} + +FGRenderPassInfo::FGRenderPassInfo(const allocator_type& alloc) noexcept +: orderedViews(alloc), + viewIndex(alloc) {} + +FGRenderPassInfo::FGRenderPassInfo(FGRenderPassInfo&& rhs, const allocator_type& alloc) +: colorAccesses(std::move(rhs.colorAccesses)), + dsAccess(rhs.dsAccess), + dsResolveAccess(rhs.dsResolveAccess), + rpInfo(std::move(rhs.rpInfo)), + orderedViews(std::move(rhs.orderedViews), alloc), + viewIndex(std::move(rhs.viewIndex), alloc), + resolveCount(rhs.resolveCount), + uniqueRasterViewCount(rhs.uniqueRasterViewCount) {} + +FGRenderPassInfo::FGRenderPassInfo(FGRenderPassInfo const& rhs, const allocator_type& alloc) +: colorAccesses(rhs.colorAccesses), + dsAccess(rhs.dsAccess), + dsResolveAccess(rhs.dsResolveAccess), + rpInfo(rhs.rpInfo), + orderedViews(rhs.orderedViews, alloc), + viewIndex(rhs.viewIndex, alloc), + resolveCount(rhs.resolveCount), + uniqueRasterViewCount(rhs.uniqueRasterViewCount) {} + +ResourceAccessGraph::ResourceAccessGraph(const allocator_type& alloc) noexcept +: _vertices(alloc), + passID(alloc), + passResource(alloc), + rpInfo(alloc), + barrier(alloc), + passIndex(alloc), + resourceNames(alloc), + resourceIndex(alloc), + leafPasses(alloc), + culledPasses(alloc), + resourceLifeRecord(alloc), + topologicalOrder(alloc), + resourceAccess(alloc), + movedTarget(alloc), + movedSourceStatus(alloc) {} + +// ContinuousContainer +void ResourceAccessGraph::reserve(vertices_size_type sz) { + _vertices.reserve(sz); + passID.reserve(sz); + passResource.reserve(sz); + rpInfo.reserve(sz); + barrier.reserve(sz); +} + +ResourceAccessGraph::Vertex::Vertex(const allocator_type& alloc) noexcept +: outEdges(alloc), + inEdges(alloc) {} + +ResourceAccessGraph::Vertex::Vertex(Vertex&& rhs, const allocator_type& alloc) +: outEdges(std::move(rhs.outEdges), alloc), + inEdges(std::move(rhs.inEdges), alloc) {} + +ResourceAccessGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) +: outEdges(rhs.outEdges, alloc), + inEdges(rhs.inEdges, alloc) {} + +RelationGraph::RelationGraph(const allocator_type& alloc) noexcept +: _vertices(alloc), + descID(alloc), + vertexMap(alloc) {} + +// ContinuousContainer +void RelationGraph::reserve(vertices_size_type sz) { + _vertices.reserve(sz); + descID.reserve(sz); +} + +RelationGraph::Vertex::Vertex(const allocator_type& alloc) noexcept +: outEdges(alloc), + inEdges(alloc) {} + +RelationGraph::Vertex::Vertex(Vertex&& rhs, const allocator_type& alloc) +: outEdges(std::move(rhs.outEdges), alloc), + inEdges(std::move(rhs.inEdges), alloc) {} + +RelationGraph::Vertex::Vertex(Vertex const& rhs, const allocator_type& alloc) +: outEdges(rhs.outEdges, alloc), + inEdges(rhs.inEdges, alloc) {} + +RenderingInfo::RenderingInfo(const allocator_type& alloc) noexcept +: clearColors(alloc) {} + +RenderingInfo::RenderingInfo(RenderingInfo&& rhs, const allocator_type& alloc) +: renderpassInfo(std::move(rhs.renderpassInfo)), + framebufferInfo(std::move(rhs.framebufferInfo)), + clearColors(std::move(rhs.clearColors), alloc), + clearDepth(rhs.clearDepth), + clearStencil(rhs.clearStencil) {} + +RenderingInfo::RenderingInfo(RenderingInfo const& rhs, const allocator_type& alloc) +: renderpassInfo(rhs.renderpassInfo), + framebufferInfo(rhs.framebufferInfo), + clearColors(rhs.clearColors, alloc), + clearDepth(rhs.clearDepth), + clearStencil(rhs.clearStencil) {} + +FrameGraphDispatcher::FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& renderGraphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept +: resourceAccessGraph(alloc), + resourceGraph(resourceGraphIn), + renderGraph(renderGraphIn), + layoutGraph(layoutGraphIn), + scratch(scratchIn), + relationGraph(alloc) {} + +} // namespace render + +} // namespace cc + +// clang-format on diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h index 0ac3830c647..25816eaf81c 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h @@ -1,451 +1,502 @@ -/**************************************************************************** - Copyright (c) 2021-2023 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 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. -****************************************************************************/ - -/** - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - * The following section is auto-generated. - * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= - */ -// clang-format off -#pragma once -#include -#include -#include -#include -#include -#include "cocos/base/std/container/string.h" -#include "cocos/base/std/container/vector.h" -#include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" -#include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" -#include "cocos/renderer/pipeline/custom/details/GraphTypes.h" -#include "cocos/renderer/pipeline/custom/details/Map.h" -#include "cocos/renderer/pipeline/custom/details/Set.h" -#include "gfx-base/GFXDef-common.h" - -namespace cc { - -namespace render { - -struct NullTag { -}; - -struct ResourceLifeRecord { - uint32_t start{0}; - uint32_t end{0}; -}; - -struct LeafStatus { - bool isExternal{false}; - bool needCulling{false}; -}; - -struct BufferRange { - uint32_t offset{0}; - uint32_t size{0}; -}; - -inline bool operator<(const BufferRange& lhs, const BufferRange& rhs) noexcept { - return std::forward_as_tuple(lhs.offset, lhs.size) < - std::forward_as_tuple(rhs.offset, rhs.size); -} - -struct TextureRange { - uint32_t firstSlice{0}; - uint32_t numSlices{1}; - uint32_t mipLevel{0}; - uint32_t levelCount{1}; -}; - -inline bool operator<(const TextureRange& lhs, const TextureRange& rhs) noexcept { - return std::forward_as_tuple(lhs.firstSlice, lhs.numSlices, lhs.mipLevel, lhs.levelCount) < - std::forward_as_tuple(rhs.firstSlice, rhs.numSlices, rhs.mipLevel, rhs.levelCount); -} - -using Range = ccstd::variant; - -using ResourceUsage = ccstd::variant; - -struct AccessStatus { - uint32_t vertID{0xFFFFFFFF}; - gfx::ShaderStageFlagBit visibility{gfx::ShaderStageFlagBit::NONE}; - gfx::MemoryAccessBit access{gfx::MemoryAccessBit::NONE}; - gfx::PassType passType{gfx::PassType::RASTER}; - gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; - ResourceUsage usage; - Range range; -}; - -struct ResourceTransition { - AccessStatus lastStatus; - AccessStatus currStatus; -}; - -struct ResourceAccessNode { - std::vector attachmentStatus; - struct ResourceAccessNode* nextSubpass{nullptr}; -}; - -struct LayoutAccess { - gfx::AccessFlagBit prevAccess{gfx::AccessFlagBit::NONE}; - gfx::AccessFlagBit nextAccess{gfx::AccessFlagBit::NONE}; -}; - -struct FGRenderPassInfo { - std::vector colorAccesses; - LayoutAccess dsAccess; - LayoutAccess dsResolveAccess; - gfx::RenderPassInfo rpInfo; - std::vector orderedViews; - bool needResolve{false}; -}; - -struct ResourceAccessGraph { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {_vertices.get_allocator().resource()}; - } - - inline boost::container::pmr::memory_resource* resource() const noexcept { - return get_allocator().resource(); - } - - ResourceAccessGraph(const allocator_type& alloc) noexcept; // NOLINT - ResourceAccessGraph(ResourceAccessGraph&& rhs) = delete; - ResourceAccessGraph(ResourceAccessGraph const& rhs) = delete; - ResourceAccessGraph& operator=(ResourceAccessGraph&& rhs) = delete; - ResourceAccessGraph& operator=(ResourceAccessGraph const& rhs) = delete; - - // Graph - using directed_category = boost::bidirectional_tag; - using vertex_descriptor = uint32_t; - using edge_descriptor = impl::EdgeDescriptor; - using edge_parallel_category = boost::allow_parallel_edge_tag; - struct traversal_category // NOLINT - : virtual boost::incidence_graph_tag, - virtual boost::bidirectional_graph_tag, - virtual boost::adjacency_graph_tag, - virtual boost::vertex_list_graph_tag, - virtual boost::edge_list_graph_tag {}; - - constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT - return std::numeric_limits::max(); - } - - // IncidenceGraph - using OutEdge = impl::StoredEdge; - using out_edge_iterator = impl::OutEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - using degree_size_type = uint32_t; - - // BidirectionalGraph - using InEdge = impl::StoredEdge; - using in_edge_iterator = impl::InEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - - // AdjacencyGraph - using adjacency_iterator = boost::adjacency_iterator_generator< - ResourceAccessGraph, vertex_descriptor, out_edge_iterator>::type; - - // VertexListGraph - using vertex_iterator = boost::integer_range::iterator; - using vertices_size_type = uint32_t; - - // VertexList help functions - inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].outEdges; - } - inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].outEdges; - } - - inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].inEdges; - } - inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].inEdges; - } - - inline boost::integer_range getVertexList() const noexcept { - return {0, static_cast(_vertices.size())}; - } - - inline vertex_descriptor getCurrentID() const noexcept { - return static_cast(_vertices.size()); - } - - inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { - return ccstd::pmr::vector(_vertices.size(), mr); - } - - // EdgeListGraph - using edge_iterator = impl::DirectedEdgeIterator; - using edges_size_type = uint32_t; - - ~ResourceAccessGraph() { - for (auto& node : access) { - auto* resNode = node.nextSubpass; - node.nextSubpass = nullptr; - while(resNode) { - auto* oldResNode = resNode; - resNode = resNode->nextSubpass; - oldResNode->nextSubpass = nullptr; - delete oldResNode; - } - } - } - - - // ContinuousContainer - void reserve(vertices_size_type sz); - - // Members - struct Vertex { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {outEdges.get_allocator().resource()}; - } - - Vertex(const allocator_type& alloc) noexcept; // NOLINT - Vertex(Vertex&& rhs, const allocator_type& alloc); - Vertex(Vertex const& rhs, const allocator_type& alloc); - - Vertex(Vertex&& rhs) noexcept = default; - Vertex(Vertex const& rhs) = delete; - Vertex& operator=(Vertex&& rhs) = default; - Vertex& operator=(Vertex const& rhs) = default; - - ccstd::pmr::vector outEdges; - ccstd::pmr::vector inEdges; - }; - - struct PassIDTag {}; - struct AccessNodeTag {}; - - // Vertices - ccstd::pmr::vector _vertices; - // Components - ccstd::pmr::vector passID; - ccstd::pmr::vector access; - // UuidGraph - PmrUnorderedMap passIndex; - // Members - ccstd::pmr::vector resourceNames; - PmrUnorderedStringMap resourceIndex; - vertex_descriptor presentPassID{0xFFFFFFFF}; - PmrFlatMap leafPasses; - PmrFlatSet culledPasses; - PmrFlatMap accessRecord; - PmrFlatMap resourceLifeRecord; - ccstd::pmr::vector topologicalOrder; - PmrFlatMap rpInfos; - PmrFlatMap subpassIndex; -}; - -struct RelationGraph { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {_vertices.get_allocator().resource()}; - } - - inline boost::container::pmr::memory_resource* resource() const noexcept { - return get_allocator().resource(); - } - - RelationGraph(const allocator_type& alloc) noexcept; // NOLINT - RelationGraph(RelationGraph&& rhs) = delete; - RelationGraph(RelationGraph const& rhs) = delete; - RelationGraph& operator=(RelationGraph&& rhs) = delete; - RelationGraph& operator=(RelationGraph const& rhs) = delete; - - // Graph - using directed_category = boost::bidirectional_tag; - using vertex_descriptor = uint32_t; - using edge_descriptor = impl::EdgeDescriptor; - using edge_parallel_category = boost::allow_parallel_edge_tag; - struct traversal_category // NOLINT - : virtual boost::incidence_graph_tag, - virtual boost::bidirectional_graph_tag, - virtual boost::adjacency_graph_tag, - virtual boost::vertex_list_graph_tag, - virtual boost::edge_list_graph_tag {}; - - constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT - return std::numeric_limits::max(); - } - - // IncidenceGraph - using OutEdge = impl::StoredEdge; - using out_edge_iterator = impl::OutEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - using degree_size_type = uint32_t; - - // BidirectionalGraph - using InEdge = impl::StoredEdge; - using in_edge_iterator = impl::InEdgeIter< - ccstd::pmr::vector::iterator, - vertex_descriptor, edge_descriptor, int32_t>; - - // AdjacencyGraph - using adjacency_iterator = boost::adjacency_iterator_generator< - RelationGraph, vertex_descriptor, out_edge_iterator>::type; - - // VertexListGraph - using vertex_iterator = boost::integer_range::iterator; - using vertices_size_type = uint32_t; - - // VertexList help functions - inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].outEdges; - } - inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].outEdges; - } - - inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { - return _vertices[v].inEdges; - } - inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { - return _vertices[v].inEdges; - } - - inline boost::integer_range getVertexList() const noexcept { - return {0, static_cast(_vertices.size())}; - } - - inline vertex_descriptor getCurrentID() const noexcept { - return static_cast(_vertices.size()); - } - - inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { - return ccstd::pmr::vector(_vertices.size(), mr); - } - - // EdgeListGraph - using edge_iterator = impl::DirectedEdgeIterator; - using edges_size_type = uint32_t; - - // ContinuousContainer - void reserve(vertices_size_type sz); - - // Members - struct Vertex { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {outEdges.get_allocator().resource()}; - } - - Vertex(const allocator_type& alloc) noexcept; // NOLINT - Vertex(Vertex&& rhs, const allocator_type& alloc); - Vertex(Vertex const& rhs, const allocator_type& alloc); - - Vertex(Vertex&& rhs) noexcept = default; - Vertex(Vertex const& rhs) = delete; - Vertex& operator=(Vertex&& rhs) = default; - Vertex& operator=(Vertex const& rhs) = default; - - ccstd::pmr::vector outEdges; - ccstd::pmr::vector inEdges; - }; - - struct DescIDTag {}; - - // Vertices - ccstd::pmr::vector _vertices; - // Components - ccstd::pmr::vector descID; - // UuidGraph - PmrUnorderedMap vertexMap; -}; - -struct Barrier { - ResourceGraph::vertex_descriptor resourceID{0xFFFFFFFF}; - gfx::BarrierType type{gfx::BarrierType::FULL}; - gfx::GFXObject* barrier{nullptr}; - AccessStatus beginStatus; - AccessStatus endStatus; -}; - -struct BarrierPair { - std::vector frontBarriers; - std::vector rearBarriers; -}; - -struct BarrierNode { - BarrierPair blockBarrier; - std::vector subpassBarriers; -}; - -struct FrameGraphDispatcher { - using allocator_type = boost::container::pmr::polymorphic_allocator; - allocator_type get_allocator() const noexcept { // NOLINT - return {resourceAccessGraph.get_allocator().resource()}; - } - - FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& graphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept; - FrameGraphDispatcher(FrameGraphDispatcher&& rhs) = delete; - FrameGraphDispatcher(FrameGraphDispatcher const& rhs) = delete; - FrameGraphDispatcher& operator=(FrameGraphDispatcher&& rhs) = delete; - FrameGraphDispatcher& operator=(FrameGraphDispatcher const& rhs) = delete; - - using BarrierMap = PmrMap; - - void enablePassReorder(bool enable); - - // how much paralell-execution weights during pass reorder, - // eg:0.3 means 30% of effort aim to paralellize execution, other 70% aim to decrease memory using. - // 0 by default - void setParalellWeight(float paralellExecWeight); - - void enableMemoryAliasing(bool enable); - - void run(); - - const ResourceAccessNode& getAttachmentStatus(RenderGraph::vertex_descriptor renderGraphVertID) const; - - inline const BarrierMap& getBarriers() const { return barrierMap; } - - BarrierMap barrierMap; - - ResourceAccessGraph resourceAccessGraph; - ResourceGraph& resourceGraph; - const RenderGraph& graph; - const LayoutGraphData& layoutGraph; - boost::container::pmr::memory_resource* scratch{nullptr}; - PmrFlatMap externalResMap; - RelationGraph relationGraph; - bool _enablePassReorder{false}; - bool _enableAutoBarrier{true}; - bool _enableMemoryAliasing{false}; - bool _accessGraphBuilt{false}; - float _paralellExecWeight{0.0F}; -}; - -} // namespace render - -} // namespace cc - -// clang-format on +/**************************************************************************** + Copyright (c) 2021-2023 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 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. +****************************************************************************/ + +/** + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + * The following section is auto-generated. + * ========================= !DO NOT CHANGE THE FOLLOWING SECTION MANUALLY! ========================= + */ +// clang-format off +#pragma once +#include +#include +#include +#include +#include +#include "cocos/base/std/container/string.h" +#include "cocos/base/std/container/vector.h" +#include "cocos/renderer/pipeline/custom/LayoutGraphTypes.h" +#include "cocos/renderer/pipeline/custom/RenderGraphTypes.h" +#include "cocos/renderer/pipeline/custom/details/GraphTypes.h" +#include "cocos/renderer/pipeline/custom/details/Map.h" +#include "cocos/renderer/pipeline/custom/details/Set.h" +#include "gfx-base/GFXDef-common.h" + +namespace cc { + +namespace render { + +struct NullTag { +}; + +struct ResourceLifeRecord { + uint32_t start{0}; + uint32_t end{0}; +}; + +struct LeafStatus { + bool isExternal{false}; + bool needCulling{false}; +}; + +struct ResourceRange { + uint32_t width{0}; + uint32_t height{0}; + uint32_t depthOrArraySize{0}; + uint32_t firstSlice{0}; + uint32_t numSlices{0}; + uint32_t mipLevel{0}; + uint32_t levelCount{0}; + uint32_t basePlane{0}; + uint32_t planeCount{0}; +}; + +struct AccessStatus { + gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; + ResourceRange range; +}; + +struct ResourceAccessNode { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {resourceStatus.get_allocator().resource()}; + } + + ResourceAccessNode(const allocator_type& alloc) noexcept; // NOLINT + ResourceAccessNode(ResourceAccessNode&& rhs, const allocator_type& alloc); + ResourceAccessNode(ResourceAccessNode const& rhs, const allocator_type& alloc); + + ResourceAccessNode(ResourceAccessNode&& rhs) noexcept = default; + ResourceAccessNode(ResourceAccessNode const& rhs) = delete; + ResourceAccessNode& operator=(ResourceAccessNode&& rhs) = default; + ResourceAccessNode& operator=(ResourceAccessNode const& rhs) = default; + + PmrFlatMap resourceStatus; +}; + +struct LayoutAccess { + gfx::AccessFlagBit prevAccess{gfx::AccessFlagBit::NONE}; + gfx::AccessFlagBit nextAccess{gfx::AccessFlagBit::NONE}; +}; + +struct AttachmentInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {parentName.get_allocator().resource()}; + } + + AttachmentInfo(const allocator_type& alloc) noexcept; // NOLINT + AttachmentInfo(AttachmentInfo&& rhs, const allocator_type& alloc); + AttachmentInfo(AttachmentInfo const& rhs, const allocator_type& alloc); + + AttachmentInfo(AttachmentInfo&& rhs) noexcept = default; + AttachmentInfo(AttachmentInfo const& rhs) = delete; + AttachmentInfo& operator=(AttachmentInfo&& rhs) = default; + AttachmentInfo& operator=(AttachmentInfo const& rhs) = default; + + ccstd::pmr::string parentName; + uint32_t attachmentIndex{0}; + uint32_t isResolveView{0}; +}; + +struct FGRenderPassInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {orderedViews.get_allocator().resource()}; + } + + FGRenderPassInfo(const allocator_type& alloc) noexcept; // NOLINT + FGRenderPassInfo(FGRenderPassInfo&& rhs, const allocator_type& alloc); + FGRenderPassInfo(FGRenderPassInfo const& rhs, const allocator_type& alloc); + + FGRenderPassInfo(FGRenderPassInfo&& rhs) noexcept = default; + FGRenderPassInfo(FGRenderPassInfo const& rhs) = delete; + FGRenderPassInfo& operator=(FGRenderPassInfo&& rhs) = default; + FGRenderPassInfo& operator=(FGRenderPassInfo const& rhs) = default; + + std::vector colorAccesses; + LayoutAccess dsAccess; + LayoutAccess dsResolveAccess; + gfx::RenderPassInfo rpInfo; + ccstd::pmr::vector orderedViews; + PmrTransparentMap viewIndex; + uint32_t resolveCount{0}; + uint32_t uniqueRasterViewCount{0}; +}; + +struct Barrier { + ResourceGraph::vertex_descriptor resourceID{0xFFFFFFFF}; + gfx::BarrierType type{gfx::BarrierType::FULL}; + gfx::GFXObject* barrier{nullptr}; + RenderGraph::vertex_descriptor beginVert{0xFFFFFFFF}; + RenderGraph::vertex_descriptor endVert{0xFFFFFFFF}; + AccessStatus beginStatus; + AccessStatus endStatus; +}; + +struct BarrierNode { + std::vector frontBarriers; + std::vector rearBarriers; +}; + +struct ResourceAccessGraph { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {_vertices.get_allocator().resource()}; + } + + inline boost::container::pmr::memory_resource* resource() const noexcept { + return get_allocator().resource(); + } + + ResourceAccessGraph(const allocator_type& alloc) noexcept; // NOLINT + ResourceAccessGraph(ResourceAccessGraph&& rhs) = delete; + ResourceAccessGraph(ResourceAccessGraph const& rhs) = delete; + ResourceAccessGraph& operator=(ResourceAccessGraph&& rhs) = delete; + ResourceAccessGraph& operator=(ResourceAccessGraph const& rhs) = delete; + + // Graph + using directed_category = boost::bidirectional_tag; + using vertex_descriptor = uint32_t; + using edge_descriptor = impl::EdgeDescriptor; + using edge_parallel_category = boost::allow_parallel_edge_tag; + struct traversal_category // NOLINT + : virtual boost::incidence_graph_tag, + virtual boost::bidirectional_graph_tag, + virtual boost::adjacency_graph_tag, + virtual boost::vertex_list_graph_tag, + virtual boost::edge_list_graph_tag {}; + + constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT + return std::numeric_limits::max(); + } + + // IncidenceGraph + using OutEdge = impl::StoredEdge; + using out_edge_iterator = impl::OutEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + using degree_size_type = uint32_t; + + // BidirectionalGraph + using InEdge = impl::StoredEdge; + using in_edge_iterator = impl::InEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + + // AdjacencyGraph + using adjacency_iterator = boost::adjacency_iterator_generator< + ResourceAccessGraph, vertex_descriptor, out_edge_iterator>::type; + + // VertexListGraph + using vertex_iterator = boost::integer_range::iterator; + using vertices_size_type = uint32_t; + + // VertexList help functions + inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].outEdges; + } + inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].outEdges; + } + + inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].inEdges; + } + inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].inEdges; + } + + inline boost::integer_range getVertexList() const noexcept { + return {0, static_cast(_vertices.size())}; + } + + inline vertex_descriptor getCurrentID() const noexcept { + return static_cast(_vertices.size()); + } + + inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { + return ccstd::pmr::vector(_vertices.size(), mr); + } + + // EdgeListGraph + using edge_iterator = impl::DirectedEdgeIterator; + using edges_size_type = uint32_t; + + LayoutAccess getAccess(ccstd::pmr::string, RenderGraph::vertex_descriptor vertID); + + + // ContinuousContainer + void reserve(vertices_size_type sz); + + // Members + struct Vertex { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {outEdges.get_allocator().resource()}; + } + + Vertex(const allocator_type& alloc) noexcept; // NOLINT + Vertex(Vertex&& rhs, const allocator_type& alloc); + Vertex(Vertex const& rhs, const allocator_type& alloc); + + Vertex(Vertex&& rhs) noexcept = default; + Vertex(Vertex const& rhs) = delete; + Vertex& operator=(Vertex&& rhs) = default; + Vertex& operator=(Vertex const& rhs) = default; + + ccstd::pmr::vector outEdges; + ccstd::pmr::vector inEdges; + }; + + struct PassIDTag {}; + struct PassNodeTag {}; + struct RenderPassInfoTag {}; + struct BarrierTag {}; + + // Vertices + ccstd::pmr::vector _vertices; + // Components + ccstd::pmr::vector passID; + ccstd::pmr::vector passResource; + ccstd::pmr::vector rpInfo; + ccstd::pmr::vector barrier; + // UuidGraph + PmrUnorderedMap passIndex; + // Members + ccstd::pmr::vector resourceNames; + PmrUnorderedStringMap resourceIndex; + vertex_descriptor presentPassID{0xFFFFFFFF}; + PmrFlatMap leafPasses; + PmrFlatSet culledPasses; + PmrFlatMap resourceLifeRecord; + ccstd::pmr::vector topologicalOrder; + PmrTransparentMap> resourceAccess; + PmrFlatMap> movedTarget; + PmrFlatMap movedSourceStatus; +}; + +struct RelationGraph { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {_vertices.get_allocator().resource()}; + } + + inline boost::container::pmr::memory_resource* resource() const noexcept { + return get_allocator().resource(); + } + + RelationGraph(const allocator_type& alloc) noexcept; // NOLINT + RelationGraph(RelationGraph&& rhs) = delete; + RelationGraph(RelationGraph const& rhs) = delete; + RelationGraph& operator=(RelationGraph&& rhs) = delete; + RelationGraph& operator=(RelationGraph const& rhs) = delete; + + // Graph + using directed_category = boost::bidirectional_tag; + using vertex_descriptor = uint32_t; + using edge_descriptor = impl::EdgeDescriptor; + using edge_parallel_category = boost::allow_parallel_edge_tag; + struct traversal_category // NOLINT + : virtual boost::incidence_graph_tag, + virtual boost::bidirectional_graph_tag, + virtual boost::adjacency_graph_tag, + virtual boost::vertex_list_graph_tag, + virtual boost::edge_list_graph_tag {}; + + constexpr static vertex_descriptor null_vertex() noexcept { // NOLINT + return std::numeric_limits::max(); + } + + // IncidenceGraph + using OutEdge = impl::StoredEdge; + using out_edge_iterator = impl::OutEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + using degree_size_type = uint32_t; + + // BidirectionalGraph + using InEdge = impl::StoredEdge; + using in_edge_iterator = impl::InEdgeIter< + ccstd::pmr::vector::iterator, + vertex_descriptor, edge_descriptor, int32_t>; + + // AdjacencyGraph + using adjacency_iterator = boost::adjacency_iterator_generator< + RelationGraph, vertex_descriptor, out_edge_iterator>::type; + + // VertexListGraph + using vertex_iterator = boost::integer_range::iterator; + using vertices_size_type = uint32_t; + + // VertexList help functions + inline ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].outEdges; + } + inline const ccstd::pmr::vector& getOutEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].outEdges; + } + + inline ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) noexcept { + return _vertices[v].inEdges; + } + inline const ccstd::pmr::vector& getInEdgeList(vertex_descriptor v) const noexcept { + return _vertices[v].inEdges; + } + + inline boost::integer_range getVertexList() const noexcept { + return {0, static_cast(_vertices.size())}; + } + + inline vertex_descriptor getCurrentID() const noexcept { + return static_cast(_vertices.size()); + } + + inline ccstd::pmr::vector colors(boost::container::pmr::memory_resource* mr) const { + return ccstd::pmr::vector(_vertices.size(), mr); + } + + // EdgeListGraph + using edge_iterator = impl::DirectedEdgeIterator; + using edges_size_type = uint32_t; + + // ContinuousContainer + void reserve(vertices_size_type sz); + + // Members + struct Vertex { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {outEdges.get_allocator().resource()}; + } + + Vertex(const allocator_type& alloc) noexcept; // NOLINT + Vertex(Vertex&& rhs, const allocator_type& alloc); + Vertex(Vertex const& rhs, const allocator_type& alloc); + + Vertex(Vertex&& rhs) noexcept = default; + Vertex(Vertex const& rhs) = delete; + Vertex& operator=(Vertex&& rhs) = default; + Vertex& operator=(Vertex const& rhs) = default; + + ccstd::pmr::vector outEdges; + ccstd::pmr::vector inEdges; + }; + + struct DescIDTag {}; + + // Vertices + ccstd::pmr::vector _vertices; + // Components + ccstd::pmr::vector descID; + // UuidGraph + PmrUnorderedMap vertexMap; +}; + +struct RenderingInfo { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {clearColors.get_allocator().resource()}; + } + + RenderingInfo(const allocator_type& alloc) noexcept; // NOLINT + RenderingInfo(RenderingInfo&& rhs, const allocator_type& alloc); + RenderingInfo(RenderingInfo const& rhs, const allocator_type& alloc); + + RenderingInfo(RenderingInfo&& rhs) noexcept = default; + RenderingInfo(RenderingInfo const& rhs) = delete; + RenderingInfo& operator=(RenderingInfo&& rhs) = default; + RenderingInfo& operator=(RenderingInfo const& rhs) = default; + + gfx::RenderPassInfo renderpassInfo; + gfx::FramebufferInfo framebufferInfo; + ccstd::pmr::vector clearColors; + float clearDepth{0}; + uint8_t clearStencil{0}; +}; + +struct FrameGraphDispatcher { + using allocator_type = boost::container::pmr::polymorphic_allocator; + allocator_type get_allocator() const noexcept { // NOLINT + return {resourceAccessGraph.get_allocator().resource()}; + } + + FrameGraphDispatcher(ResourceGraph& resourceGraphIn, const RenderGraph& renderGraphIn, const LayoutGraphData& layoutGraphIn, boost::container::pmr::memory_resource* scratchIn, const allocator_type& alloc) noexcept; + FrameGraphDispatcher(FrameGraphDispatcher&& rhs) = delete; + FrameGraphDispatcher(FrameGraphDispatcher const& rhs) = delete; + FrameGraphDispatcher& operator=(FrameGraphDispatcher&& rhs) = delete; + FrameGraphDispatcher& operator=(FrameGraphDispatcher const& rhs) = delete; + + + void enablePassReorder(bool enable); + + // how much paralell-execution weights during pass reorder, + // eg:0.3 means 30% of effort aim to paralellize execution, other 70% aim to decrease memory using. + // 0 by default + void setParalellWeight(float paralellExecWeight); + + void enableMemoryAliasing(bool enable); + + void run(); + + const BarrierNode& getBarrier(RenderGraph::vertex_descriptor u) const; + + const ResourceAccessNode& getAccessNode(RenderGraph::vertex_descriptor u) const; + + const gfx::RenderPassInfo& getRenderPassInfo(RenderGraph::vertex_descriptor u) const; + + RenderingInfo getRenderPassAndFrameBuffer(RenderGraph::vertex_descriptor u, const ResourceGraph& resg) const; + + LayoutAccess getResourceAccess(ResourceGraph::vertex_descriptor r, RenderGraph::vertex_descriptor p) const; + + // those resource been moved point to another resID + ResourceGraph::vertex_descriptor realResourceID(const ccstd::pmr::string& name) const; + + PmrFlatMap buildDescriptorIndex( + const PmrTransparentMap>&computeViews, + const PmrTransparentMap& rasterViews, + boost::container::pmr::memory_resource* scratch) const; + + PmrFlatMap buildDescriptorIndex( + const PmrTransparentMap>&computeViews, + boost::container::pmr::memory_resource* scratch) const; + + ResourceAccessGraph resourceAccessGraph; + ResourceGraph& resourceGraph; + const RenderGraph& renderGraph; + const LayoutGraphData& layoutGraph; + boost::container::pmr::memory_resource* scratch{nullptr}; + RelationGraph relationGraph; + bool _enablePassReorder{false}; + bool _enableAutoBarrier{true}; + bool _enableMemoryAliasing{false}; + bool _accessGraphBuilt{false}; + float _paralellExecWeight{0.0F}; +}; + +} // namespace render + +} // namespace cc + +// clang-format on diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index 1a2cffac76a..6cdd864a2b4 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,7 @@ #include "boost/graph/hawick_circuits.hpp" #include "boost/graph/visitors.hpp" #include "boost/lexical_cast.hpp" +#include "details/GraphView.h" #include "details/Range.h" #include "gfx-base/GFXBarrier.h" #include "gfx-base/GFXDef-common.h" @@ -54,11 +56,20 @@ #include "pipeline/custom/RenderCommonFwd.h" #include "pipeline/custom/RenderGraphTypes.h" #include "pipeline/custom/details/GslUtils.h" +#include "NativeRenderGraphUtils.h" #ifndef BRANCH_CULLING #define BRANCH_CULLING 0 #endif +#define ENABLE_FGD_WARNNING 1 + +#ifdef ENABLE_FGD_WARNNING + #define FGD_WARNING(...) printf(##__VA_ARGS__) +#else + #define FGD_WARNING(...) +#endif + namespace cc { namespace render { @@ -91,35 +102,219 @@ void FrameGraphDispatcher::setParalellWeight(float paralellExecWeight) { _paralellExecWeight = clampf(paralellExecWeight, 0.0F, 1.0F); } -const ResourceAccessNode &FrameGraphDispatcher::getAttachmentStatus(RenderGraph::vertex_descriptor renderGraphVertID) const { - auto iter = resourceAccessGraph.subpassIndex.find(renderGraphVertID); - auto ragVertID = resourceAccessGraph.passIndex.at(renderGraphVertID); - const ResourceAccessNode *accessNode = &resourceAccessGraph.access.at(ragVertID); - if (iter != resourceAccessGraph.subpassIndex.end()) { - auto subpassIndex = iter->second; - accessNode = accessNode->nextSubpass; - CC_ASSERT(accessNode); - while (subpassIndex) { - accessNode = accessNode->nextSubpass; - --subpassIndex; - CC_ASSERT(accessNode); +const BarrierNode &FrameGraphDispatcher::getBarrier(RenderGraph::vertex_descriptor u) const { + auto ragVertID = resourceAccessGraph.passIndex.at(u); + return get(ResourceAccessGraph::BarrierTag{}, resourceAccessGraph, ragVertID); +} + +const ResourceAccessNode &FrameGraphDispatcher::getAccessNode(RenderGraph::vertex_descriptor u) const { + auto ragVertID = resourceAccessGraph.passIndex.at(u); + return get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, ragVertID); +} + +const gfx::RenderPassInfo &FrameGraphDispatcher::getRenderPassInfo(RenderGraph::vertex_descriptor u) const { + CC_EXPECTS(holds(u, renderGraph)); + auto ragVertID = resourceAccessGraph.passIndex.at(u); + return get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, ragVertID).rpInfo; +} + +ResourceGraph::vertex_descriptor FrameGraphDispatcher::realResourceID(const ccstd::pmr::string &name) const { + return resourceAccessGraph.resourceIndex.at(name); +} + +ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor resID, const ResourceGraph &resg, std::string_view name) { + auto resName = get(ResourceGraph::NameTag{}, resg, resID); + resName += "/"; + resName += name; + return findVertex(resName, resg); +} + +ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor resID, + const ResourceGraph &resg, + uint32_t basePlane) { + auto ret = resID; + const auto &desc = get(ResourceGraph::DescTag{}, resg, resID); + if (desc.format == gfx::Format::DEPTH_STENCIL) { + ret = basePlane == 0 ? locateSubres(resID, resg, DEPTH_PLANE_NAME) : locateSubres(resID, resg, STENCIL_PLANE_NAME); + } + return ret; +} + +PmrFlatMap FrameGraphDispatcher::buildDescriptorIndex( + const PmrTransparentMap> &computeViews, + boost::container::pmr::memory_resource *scratch) const { + PmrFlatMap resourceIndex(scratch); + resourceIndex.reserve(computeViews.size() * 2); + if (!computeViews.empty()) { + for (const auto &[resName, computeViews] : computeViews) { + auto resID = realResourceID(resName); + for (const auto &computeView : computeViews) { + const auto &name = computeView.name; + CC_EXPECTS(!name.empty()); + const auto nameID = layoutGraph.attributeIndex.at(name); + auto subresID = locateSubres(resID, resourceGraph, computeView.plane); + resourceIndex.emplace(nameID, subresID); + } + } + } + return resourceIndex; +} + +PmrFlatMap FrameGraphDispatcher::buildDescriptorIndex( + const PmrTransparentMap> &computeViews, + const PmrTransparentMap &rasterViews, + boost::container::pmr::memory_resource *scratch) const { + + auto resourceIndex = buildDescriptorIndex(computeViews, scratch); + if (!rasterViews.empty()) { + NameLocalID unused{128}; + // input sort by slot name + ccstd::pmr::map> inputs(scratch); + for (const auto &[resourceName, rasterView] : rasterViews) { + if (rasterView.accessType != AccessType::WRITE) { + if (!defaultAttachment(rasterView.slotName)) { + std::string_view suffix = rasterView.attachmentType == AttachmentType::DEPTH_STENCIL ? DEPTH_PLANE_NAME : ""; + inputs.emplace(std::piecewise_construct, + std::forward_as_tuple(rasterView.slotName), + std::forward_as_tuple(resourceName, suffix)); + } + if (!defaultAttachment(rasterView.slotName1)) { + CC_EXPECTS(rasterView.attachmentType == AttachmentType::DEPTH_STENCIL); + std::string_view suffix = STENCIL_PLANE_NAME; + inputs.emplace(std::piecewise_construct, + std::forward_as_tuple(rasterView.slotName1), + std::forward_as_tuple(resourceName, suffix)); + } + } + } + // build pass resources + for (const auto &[slotName, nameInfo] : inputs) { + auto resID = realResourceID(nameInfo.first.data()); + if (!nameInfo.second.empty()) { + resID = locateSubres(resID, resourceGraph, nameInfo.second); + } + resourceIndex.emplace(unused, resID); + unused.value++; } } - return *accessNode; + + return resourceIndex; +} + +RenderingInfo FrameGraphDispatcher::getRenderPassAndFrameBuffer(RenderGraph::vertex_descriptor u, const ResourceGraph &resg) const { + auto ragVertID = resourceAccessGraph.passIndex.at(u); + const auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, ragVertID); + const auto &orderedViews = fgRenderPassInfo.orderedViews; + const auto &viewIndex = fgRenderPassInfo.viewIndex; + + RenderingInfo renderingInfo(scratch); + renderingInfo.renderpassInfo = getRenderPassInfo(u); + gfx::FramebufferInfo fbInfo{ + nullptr, + }; + + CC_ENSURES(holds(u, renderGraph)); + const RasterPass &pass = get(RasterPassTag{}, u, renderGraph); + + for (const auto &viewName : orderedViews) { + const auto &info = viewIndex.at(viewName); + auto attachmentIndex = info.attachmentIndex; + gfx::Color clearColor{}; + if (!info.isResolveView) { + const auto &rasterView = pass.rasterViews.at(viewName); + clearColor = rasterView.clearColor; + } + if (info.attachmentIndex != gfx::INVALID_BINDING) { + // colorLike + renderingInfo.clearColors.emplace_back(clearColor); + + auto resID = resourceAccessGraph.resourceIndex.at(viewName); + visitObject( + resID, resg, + [&](const ManagedResource &res) { + std::ignore = res; + CC_EXPECTS(false); + }, + [&](const ManagedBuffer &res) { + std::ignore = res; + CC_EXPECTS(false); + }, + [&](const ManagedTexture &tex) { + CC_EXPECTS(tex.texture); + fbInfo.colorTextures.emplace_back(tex.texture); + }, + [&](const IntrusivePtr &res) { + std::ignore = res; + CC_EXPECTS(false); + }, + [&](const IntrusivePtr &tex) { + fbInfo.colorTextures.emplace_back(tex); + }, + [&](const IntrusivePtr &fb) { + CC_EXPECTS(fb->getColorTextures().size() == 1); + CC_EXPECTS(fb->getColorTextures().at(0)); + // render window attaches a depthStencil by default, which may differs from renderpassInfo here. + // data.framebuffer = fb; + }, + [&](const RenderSwapchain &sc) { + fbInfo.colorTextures.emplace_back(sc.swapchain->getColorTexture()); + }, + [&](const FormatView &view) { + // TODO(zhouzhenglong): add ImageView support + std::ignore = view; + CC_EXPECTS(false); + }, + [&](const SubresourceView &view) { + fbInfo.colorTextures.emplace_back(view.textureView); + }); + } else { + // ds or ds resolve + if (!info.isResolveView) { + renderingInfo.clearDepth = clearColor.x; + renderingInfo.clearStencil = static_cast(clearColor.y); + } + + auto &dsAttachment = info.isResolveView ? fbInfo.depthStencilResolveTexture : fbInfo.depthStencilTexture; + + auto resID = resourceAccessGraph.resourceIndex.at(viewName); + visitObject( + resID, resg, + [&](const ManagedTexture &tex) { + CC_EXPECTS(tex.texture); + dsAttachment = tex.texture.get(); + }, + [&](const IntrusivePtr &tex) { + dsAttachment = tex.get(); + }, + [&](const FormatView &view) { + std::ignore = view; + CC_EXPECTS(false); + }, + [&](const SubresourceView &view) { + std::ignore = view; + CC_EXPECTS(false); + }, + [](const auto & /*unused*/) { + CC_EXPECTS(false); + }); + } + } + renderingInfo.framebufferInfo = fbInfo; + + return renderingInfo; +} + +LayoutAccess FrameGraphDispatcher::getResourceAccess(ResourceGraph::vertex_descriptor r, RenderGraph::vertex_descriptor p) const { + auto ragVertID = resourceAccessGraph.passIndex.at(p); + const auto &resName = get(ResourceGraph::NameTag{}, resourceGraph, r); + auto range = resourceAccessGraph.resourceAccess.at(resName).equal_range(ragVertID); + return {range.first->second.accessFlag, range.second->second.accessFlag}; } /////////////////////////////////////////////////////////////////////////////////////INTERNAL⚡IMPLEMENTATION///////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------predefine------------------------------------------------------------------ using PmrString = ccstd::pmr::string; -using RAG = ResourceAccessGraph; -using LGD = LayoutGraphData; -using gfx::PassType; -using BarrierMap = FrameGraphDispatcher::BarrierMap; -using AccessVertex = ResourceAccessGraph::vertex_descriptor; -using InputStatusTuple = std::tuple; -using ResourceHandle = ResourceGraph::vertex_descriptor; -using ResourceNames = PmrFlatSet; using EdgeList = std::pair; using CloseCircuit = std::pair; using CloseCircuits = std::vector; @@ -134,30 +329,23 @@ using ResourceLifeRecordMap = PmrFlatMap; struct Graphs { const RenderGraph &renderGraph; - ResourceGraph &resourceGraph; const LayoutGraphData &layoutGraphData; + ResourceGraph &resourceGraph; ResourceAccessGraph &resourceAccessGraph; RelationGraph &relationGraph; }; struct ViewStatus { - PmrString name; - const PassType passType; + const ccstd::pmr::string &name; + const AccessType access; const gfx::ShaderStageFlagBit visibility; - const gfx::MemoryAccessBit access; const gfx::AccessFlags accessFlag; - const ResourceUsage usage; + const ResourceRange ⦥ }; -auto defaultAccess = gfx::MemoryAccessBit::NONE; -auto defaultVisibility = gfx::ShaderStageFlagBit::NONE; - constexpr uint32_t EXPECT_START_ID = 0; constexpr uint32_t INVALID_ID = 0xFFFFFFFF; -using AccessTable = PmrFlatMap; -using ExternalResMap = PmrFlatMap; - // for scoped enum only template class GfxTypeConverter { @@ -168,39 +356,11 @@ class GfxTypeConverter { } }; -// static auto toGfxAccess = GfxTypeConverter(); -gfx::MemoryAccessBit toGfxAccess(AccessType type) { - switch (type) { - case AccessType::READ: - return gfx::MemoryAccessBit::READ_ONLY; - case AccessType::WRITE: - return gfx::MemoryAccessBit::WRITE_ONLY; - case AccessType::READ_WRITE: - return gfx::MemoryAccessBit::READ_WRITE; - default: - return gfx::MemoryAccessBit::NONE; - } -}; - // TODO(Zeqiang): remove barrier in renderpassinfo gfx::GeneralBarrier *getGeneralBarrier(gfx::Device *device, gfx::AccessFlagBit prevAccess, gfx::AccessFlagBit nextAccess) { return device->getGeneralBarrier({prevAccess, nextAccess}); } -// AccessStatus.vertID : in resourceNode it's resource ID; in barrierNode it's pass ID. -AccessVertex dependencyCheck(RAG &rag, AccessVertex curVertID, const ResourceGraph &rg, const ViewStatus &status); -gfx::ShaderStageFlagBit getVisibilityByDescName(const RenderGraph &renderGraph, const LGD &lgd, uint32_t passID, const PmrString &resName); - -PmrString addAccessStatus(RAG &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status); -void addCopyAccessStatus(RAG &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status, const Range &range); -void processRasterPass(const Graphs &graphs, uint32_t passID, const RasterPass &pass); -void processComputePass(const Graphs &graphs, uint32_t passID, const ComputePass &pass); -void processRasterSubpass(const Graphs &graphs, uint32_t passID, const RasterSubpass &pass); -void processComputeSubpass(const Graphs &graphs, uint32_t passID, const ComputeSubpass &pass); -void processCopyPass(const Graphs &graphs, uint32_t passID, const CopyPass &pass); -void processRaytracePass(const Graphs &graphs, uint32_t passID, const RaytracePass &pass); -auto getResourceStatus(PassType passType, const PmrString &name, gfx::MemoryAccess memAccess, gfx::ShaderStageFlags visibility, const ResourceGraph &resourceGraph, bool rasterized); - // execution order BUT NOT LOGICALLY bool isPassExecAdjecent(uint32_t passLID, uint32_t passRID) { return std::abs(static_cast(passLID) - static_cast(passRID)) <= 1; @@ -235,11 +395,21 @@ inline bool isAttachmentAccess(gfx::AccessFlagBit flag) { gfx::AccessFlagBit::DEPTH_STENCIL_ATTACHMENT_WRITE); } +// SHADING_RATE may be ambiguos inline bool isReadOnlyAccess(gfx::AccessFlagBit flag) { - return flag < gfx::AccessFlagBit::PRESENT || flag == gfx::AccessFlagBit::SHADING_RATE; + return static_cast(flag) < static_cast(gfx::AccessFlagBit::PRESENT) || flag == gfx::AccessFlagBit::SHADING_RATE; +} + +bool accessDependent(const gfx::AccessFlagBit lhs, const gfx::AccessFlagBit &rhs, bool buffer) { + bool dep{false}; + if (buffer) { + dep = !isReadOnlyAccess(lhs) || !isReadOnlyAccess(rhs); + } else { + dep = (!isReadOnlyAccess(lhs) || !isReadOnlyAccess(rhs)) || (lhs != rhs); + } + return dep; } -bool isTransitionStatusDependent(const AccessStatus &lhs, const AccessStatus &rhs); template bool tryAddEdge(uint32_t srcVertex, uint32_t dstVertex, Graph &graph); @@ -249,2362 +419,2006 @@ inline RelationGraph::vertex_descriptor add_vertex(RelationGraph &g) { // NOLINT return add_vertex(g, count++); } -// status of resource access -void buildAccessGraph(const Graphs &graphs) { - // what we need: - // - pass dependency - // - pass attachment access - // AccessTable accessRecord; +bool isResourceView(const ResourceGraph::vertex_descriptor v, const ResourceGraph &resg) { + return resg.isTextureView(v); // || isBufferView +} - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - size_t numPasses = 0; - numPasses += renderGraph.rasterPasses.size(); - numPasses += renderGraph.computePasses.size(); - numPasses += renderGraph.copyPasses.size(); - numPasses += renderGraph.movePasses.size(); - numPasses += renderGraph.raytracePasses.size(); +ResourceRange getResourceRange(const ResourceGraph::vertex_descriptor v, + const ResourceGraph &resg) { + const auto &desc = get(ResourceGraph::DescTag{}, resg, v); + ResourceRange range{ + desc.width, + desc.height, + desc.depthOrArraySize, + }; - resourceAccessGraph.reserve(static_cast(numPasses)); - resourceAccessGraph.resourceNames.reserve(128); - resourceAccessGraph.resourceIndex.reserve(128); + if (isResourceView(v, resg)) { + const auto *const subResView = get_if(v, &resg); + range.firstSlice = subResView->firstArraySlice; + range.numSlices = subResView->numArraySlices; + range.mipLevel = subResView->indexOrFirstMipLevel; + range.levelCount = subResView->numMipLevels; + range.basePlane = subResView->firstPlane; + range.planeCount = subResView->numPlanes; + } else { + range.numSlices = desc.depthOrArraySize; + range.levelCount = desc.mipLevels; + } - resourceAccessGraph.topologicalOrder.reserve(numPasses); - resourceAccessGraph.topologicalOrder.clear(); - resourceAccessGraph.resourceLifeRecord.reserve(resourceGraph.names.size()); + return range; +} - if (!resourceAccessGraph.resourceLifeRecord.empty()) { - resourceAccessGraph.resourceLifeRecord.clear(); +ResourceGraph::vertex_descriptor realID(const ccstd::pmr::string &name, const ResourceGraph &resg) { + auto resID = vertex(name, resg); + while (parent(resID, resg) != ResourceGraph::null_vertex()) { + resID = parent(resID, resg); } + return resID; +} - if (!resourceAccessGraph.leafPasses.empty()) { - resourceAccessGraph.leafPasses.clear(); - } - if (!resourceAccessGraph.culledPasses.empty()) { - resourceAccessGraph.culledPasses.clear(); - } +bool depthStencil(gfx::Format format) { + return format == gfx::Format::DEPTH_STENCIL || format == gfx::Format::DEPTH; +} - // const auto &names = get(RenderGraph::Name, renderGraph); - for (size_t i = 1; i <= numPasses; ++i) { - resourceAccessGraph.leafPasses.emplace(i, LeafStatus{false, true}); +void subResourceFeedback(ResourceGraph &resg, ResourceGraph::vertex_descriptor parentID, gfx::Format subFormat) { + auto &parentDesc = get(ResourceGraph::DescTag{}, resg, parentID); + if (depthStencil(subFormat) || parentDesc.format != subFormat) { + parentDesc.textureFlags |= gfx::TextureFlagBit::MUTABLE_VIEW_FORMAT; } +} - auto startID = add_vertex(resourceAccessGraph, INVALID_ID - 1); - CC_EXPECTS(startID == EXPECT_START_ID); - - add_vertex(relationGraph, startID); +auto dependencyCheck(ResourceAccessGraph &rag, ResourceAccessGraph::vertex_descriptor curVertID, ResourceGraph &resourceGraph, const ViewStatus &viewStatus) { + auto &accessRecord = rag.resourceAccess; + const auto &[name, access, visibility, accessFlag, originRange] = viewStatus; + auto resourceID = rag.resourceIndex.at(name); + const auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, resourceID); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resourceID); - for (const auto passID : makeRange(vertices(renderGraph))) { - visitObject( - passID, renderGraph, - [&](const RasterPass &pass) { - processRasterPass(graphs, passID, pass); - }, - [&](const RasterSubpass &pass) { - processRasterSubpass(graphs, passID, pass); - }, - [&](const ComputeSubpass &pass) { - processComputeSubpass(graphs, passID, pass); - }, - [&](const ComputePass &pass) { - processComputePass(graphs, passID, pass); - }, - [&](const CopyPass &pass) { - processCopyPass(graphs, passID, pass); - }, - [&](const RaytracePass &pass) { - processRaytracePass(graphs, passID, pass); - }, - [&](const auto & /*pass*/) { - // do nothing - }); + auto range = originRange; + if (rag.movedSourceStatus.find(name) != rag.movedSourceStatus.end()) { + range = rag.movedSourceStatus.at(name).range; } - auto &rag = resourceAccessGraph; - auto branchCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) -> void { - CC_EXPECTS(out_degree(vertex, rag) == 0); - using FuncType = void (*)(ResourceAccessGraph::vertex_descriptor, ResourceAccessGraph &); - static FuncType leafCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) { - rag.culledPasses.emplace(vertex); - auto &attachments = get(ResourceAccessGraph::AccessNodeTag{}, rag, vertex); - attachments.attachmentStatus.clear(); - if (attachments.nextSubpass) { - delete attachments.nextSubpass; - attachments.nextSubpass = nullptr; - } - auto inEdges = in_edges(vertex, rag); - for (auto iter = inEdges.first; iter < inEdges.second;) { - auto inEdge = *iter; - auto srcVert = source(inEdge, rag); - remove_edge(inEdge, rag); - if (out_degree(srcVert, rag) == 0) { - leafCulling(srcVert, rag); - } - inEdges = in_edges(vertex, rag); - iter = inEdges.first; - } - }; - leafCulling(vertex, rag); - }; + bool isExternalPass = get(get(ResourceGraph::TraitsTag{}, resourceGraph), resourceID).hasSideEffects(); + auto iter = accessRecord.find(name); + ResourceAccessGraph::vertex_descriptor lastVertID{EXPECT_START_ID}; + gfx::AccessFlagBit lastAccess{gfx::AccessFlagBit::NONE}; - // no present pass found, add a fake node to gather leaf node(s). - if (resourceAccessGraph.presentPassID == 0xFFFFFFFF) { - auto ragEndNode = add_vertex(rag, RenderGraph::null_vertex()); - auto rlgEndNode = add_vertex(relationGraph, ragEndNode); - // keep sync before pass reorder done. - CC_EXPECTS(ragEndNode == rlgEndNode); - resourceAccessGraph.presentPassID = ragEndNode; - auto iter = resourceAccessGraph.leafPasses.find(ragEndNode); - constexpr bool isExternal = true; - constexpr bool needCulling = false; - if (iter == resourceAccessGraph.leafPasses.end()) { - resourceAccessGraph.leafPasses.emplace(ragEndNode, LeafStatus{isExternal, needCulling}); + if (iter == accessRecord.end()) { + accessRecord[name].emplace(curVertID, AccessStatus{accessFlag, range}); + if (isExternalPass) { + rag.leafPasses[curVertID] = LeafStatus{true, isReadOnlyAccess(accessFlag)}; + lastAccess = states.states; + } + + // update parent + auto parentID = realID(name, resourceGraph); + if (parentID != resourceID) { + const auto &realName = get(ResourceGraph::NameTag{}, resourceGraph, parentID); + auto lastIter = accessRecord[realName].rbegin(); + if (lastIter->first == curVertID) { + // in case more than 1 view of same resource in a renderpass + ++lastIter; + } + accessRecord[name].emplace(*lastIter); + accessRecord[realName][curVertID] = AccessStatus{accessFlag, range}; + subResourceFeedback(resourceGraph, parentID, desc.format); } else { - resourceAccessGraph.leafPasses.at(ragEndNode) = LeafStatus{isExternal, needCulling}; + accessRecord[name].emplace(0, AccessStatus{lastAccess, range}); } - } + } else { + auto &transMap = iter->second; + CC_ASSERT(!transMap.empty()); - // make leaf node closed walk for pass reorder - for (auto pass : resourceAccessGraph.leafPasses) { - bool isExternal = pass.second.isExternal; - bool needCulling = pass.second.needCulling; + const auto lastRecordIter = (--transMap.end()); + const auto &lastStatus = lastRecordIter->second; + lastAccess = lastStatus.accessFlag; + bool isBuffer = desc.dimension == ResourceDimension::BUFFER; + bool dependent = accessDependent(lastAccess, accessFlag, isBuffer); - if (pass.first != resourceAccessGraph.presentPassID) { - if (isExternal && !needCulling) { - add_edge(pass.first, resourceAccessGraph.presentPassID, resourceAccessGraph); - } else { - // write into transient resources, culled - if constexpr (ENABLE_BRANCH_CULLING) { - branchCulling(pass.first, resourceAccessGraph); + if (!dependent) { + for (auto recordIter = transMap.rbegin(); recordIter != transMap.rend(); ++recordIter) { + if (accessDependent(recordIter->second.accessFlag, accessFlag, isBuffer)) { + lastVertID = recordIter->first; + break; } } - } - } - for (auto rit = resourceAccessGraph.culledPasses.rbegin(); rit != resourceAccessGraph.culledPasses.rend(); ++rit) { - // remove culled vertices, std::less make this set ascending order, so reverse iterate - remove_vertex(*rit, relationGraph); - } - - for (auto rlgVert : makeRange(vertices(relationGraph))) { - auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, rlgVert); - rag.topologicalOrder.emplace_back(ragVert); - } -} + if (isExternalPass) { + // only external res will be manually record here, leaf pass with transient resource will be culled by default, + // those leaf passes with ALL read access on external(or with transients) res can be culled. + rag.leafPasses[curVertID].needCulling &= (access == AccessType::READ); + lastAccess = states.states; + } + transMap[curVertID] = {accessFlag, range}; + } else { + lastVertID = lastRecordIter->first; + transMap[curVertID] = {accessFlag, range}; -#pragma region BUILD_BARRIERS -struct BarrierVisitor : public boost::bfs_visitor<> { - using Vertex = ResourceAccessGraph::vertex_descriptor; - using Edge = ResourceAccessGraph::edge_descriptor; - using Graph = ResourceAccessGraph; - - explicit BarrierVisitor( - const ResourceGraph &rg, - BarrierMap &barriers, // what we get - ExternalResMap &extMap, // record external res between frames - ResourceNames &resourceNamesIn, // for resource record - const AccessTable &accessRecordIn, // resource last meet - ResourceLifeRecordMap &rescLifeRecord, // resource lifetime - PmrFlatMap &rpInfosIn) - : barrierMap(barriers), resourceGraph(rg), externalMap(extMap), resourceNames(resourceNamesIn), accessRecord(accessRecordIn), resourceLifeRecord(rescLifeRecord), rpInfos(rpInfosIn) {} - - void updateResourceLifeTime(const ResourceAccessNode &node, ResourceAccessGraph::vertex_descriptor u) { - for (const auto &access : node.attachmentStatus) { - auto name = get(ResourceGraph::NameTag{}, resourceGraph, access.vertID); - if (resourceLifeRecord.find(name) == resourceLifeRecord.end()) { - resourceLifeRecord.emplace(name, ResourceLifeRecord{u, u}); - } else { - resourceLifeRecord.at(name).end = u; + if (rag.leafPasses.find(curVertID) != rag.leafPasses.end()) { + // only write into externalRes counts + if (isExternalPass) { + rag.leafPasses[curVertID].needCulling &= (access == AccessType::READ); + } } } - } - - struct AccessNodeInfo { - const std::vector &status; - std::vector &edgeBarriers; // need to barrier front or back - const Vertex &vertID; - uint32_t subpassIndex{INVALID_ID}; - }; - void processVertex(Vertex u, const Graph &g) { - if (in_degree(u, g) == 0 && out_degree(u, g) == 0) { - // culled - return; + if (rag.leafPasses.find(lastVertID) != rag.leafPasses.end()) { + rag.leafPasses.erase(lastVertID); } - const ResourceAccessNode &access = get(ResourceAccessGraph::AccessNodeTag{}, g, u); - updateResourceLifeTime(access, u); - - if (barrierMap.find(u) == barrierMap.end()) { - barrierMap.emplace(u, BarrierNode{{}, {}}); + if(viewStatus.access != AccessType::WRITE) { + subResourceFeedback(resourceGraph, resourceID, desc.format); } + } + auto lastDependentVert = lastVertID; // last dependent vert, WAW/WAR/RAW + auto nearestAccess = lastAccess; // last access, maybe RAR + return std::make_tuple(lastDependentVert, nearestAccess); +} - const auto *srcAccess = &access; - - auto *dstAccess = access.nextSubpass; - auto &blockBarrier = barrierMap[u].blockBarrier; - auto &barriers = barrierMap[u].subpassBarriers; - - uint32_t srcSubpass = 0; - uint32_t dstSubpass = 1; - bool isAdjacent = true; // subpass always adjacent to each other - if (dstAccess) { - if (!dstAccess->nextSubpass) { - return; - } - // subpass at least two passes inside. - // the very first pass becomes attachment status collection of all subpass - CC_ASSERT(dstAccess->nextSubpass); - srcAccess = dstAccess; - dstAccess = dstAccess->nextSubpass; - } - while (srcAccess) { - while (dstAccess) { - // 2 barriers at least when subpass exist - std::vector &srcRearBarriers = barriers[srcSubpass].rearBarriers; - std::vector &dstFrontBarriers = barriers[dstSubpass].frontBarriers; - - AccessNodeInfo from = {srcAccess->attachmentStatus, srcRearBarriers, u, srcSubpass}; - AccessNodeInfo to = {dstAccess->attachmentStatus, dstFrontBarriers, u, dstSubpass}; - std::set noUseSet; - fillBarrier(from, to, isAdjacent, noUseSet); - - dstAccess = dstAccess->nextSubpass; - ++dstSubpass; - } - srcAccess = srcAccess->nextSubpass; - if (srcAccess) { - dstAccess = srcAccess->nextSubpass; - ++srcSubpass; - dstSubpass = srcSubpass + 1; - } +ResourceGraph::vertex_descriptor parentResource(ResourceGraph::vertex_descriptor vert, const ResourceGraph &resg) { + const auto &desc = get(ResourceGraph::DescTag{}, resg, vert); + auto ret = vert; + if (desc.dimension == ResourceDimension::BUFFER) { + // TODO(Zeqaing): bufferview + } else { + auto srcParentID = vert; + while (resg.isTextureView(srcParentID)) { + srcParentID = parent(srcParentID, resg); } + ret = srcParentID; } + return ret; +} - void discover_vertex(Vertex u, const Graph &g) { - processVertex(u, g); - } - - void finish_vertex(Vertex u, const Graph &g) { - auto &rearBarriers = barrierMap[u].blockBarrier.rearBarriers; - auto &frontBarriers = barrierMap[u].blockBarrier.frontBarriers; - Barrier *lastSubpassBarrier = nullptr; - uint32_t subpassIdx{0}; - for (const auto &barriers : barrierMap[u].subpassBarriers) { - if (!barriers.frontBarriers.empty()) { - auto &subpassDependencies = rpInfos.at(u).rpInfo.dependencies; - auto dependency = gfx::SubpassDependency{}; - dependency.srcSubpass = INVALID_ID; - dependency.dstSubpass = subpassIdx; - for (const auto &barrier : barriers.frontBarriers) { - if (barrier.beginStatus.accessFlag == gfx::AccessFlagBit::NONE) { - continue; - } - auto resID = barrier.resourceID; - auto findBarrierByResID = [resID](const Barrier &barrier) { - return barrier.resourceID == resID; - }; - auto resFinalPassID = accessRecord.at(resID).currStatus.vertID; - auto firstMeetIter = std::find_if(frontBarriers.begin(), frontBarriers.end(), findBarrierByResID); - auto innerResIter = std::find_if(rearBarriers.begin(), rearBarriers.end(), findBarrierByResID); - - if (firstMeetIter == frontBarriers.end() && innerResIter == rearBarriers.end() && resFinalPassID >= u) { - auto &collect = frontBarriers.emplace_back(barrier); - collect.beginStatus.vertID = collect.endStatus.vertID = u; - } - if ((barrier.beginStatus.vertID > dependency.srcSubpass) && (barrier.beginStatus.vertID != INVALID_ID)) { - dependency.srcSubpass = barrier.beginStatus.vertID; - } - - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); - if (desc.format == gfx::Format::DEPTH_STENCIL || desc.format == gfx::Format::DEPTH) { - if (g.access.at(u).attachmentStatus.size() > 1) { - auto &dsDep = subpassDependencies.emplace_back(); - dsDep.srcSubpass = dependency.srcSubpass; - dsDep.dstSubpass = dependency.dstSubpass; - dsDep.prevAccesses |= barrier.beginStatus.accessFlag; - dsDep.nextAccesses |= barrier.endStatus.accessFlag; - } - } else { - bool isWriteAccess = !isReadOnlyAccess(barrier.endStatus.accessFlag); - if (isWriteAccess) { - auto &dep = subpassDependencies.emplace_back(); - dep.srcSubpass = dependency.srcSubpass; - dep.dstSubpass = dependency.dstSubpass; - dep.prevAccesses |= barrier.beginStatus.accessFlag; - dep.nextAccesses |= barrier.endStatus.accessFlag; - if (hasReadAccess(barrier.endStatus.accessFlag)) { - auto &selfDep = subpassDependencies.emplace_back(); - selfDep.srcSubpass = dependency.dstSubpass; - selfDep.dstSubpass = dependency.dstSubpass; - selfDep.prevAccesses |= barrier.endStatus.accessFlag; - selfDep.nextAccesses |= barrier.endStatus.accessFlag; - } - } else { - dependency.prevAccesses |= barrier.beginStatus.accessFlag; - dependency.nextAccesses |= barrier.endStatus.accessFlag; - } - } - } - if (dependency.prevAccesses != gfx::AccessFlagBit::NONE) { - subpassDependencies.emplace_back(dependency); - } - } - - if (!barriers.rearBarriers.empty()) { - auto &subpassDependencies = rpInfos.at(u).rpInfo.dependencies; - auto dependency = gfx::SubpassDependency{}; - dependency.srcSubpass = subpassIdx; - dependency.dstSubpass = INVALID_ID; - for (const auto &barrier : barriers.rearBarriers) { - if (barrier.endStatus.vertID < dependency.dstSubpass) { - dependency.dstSubpass = barrier.endStatus.vertID; - } +gfx::ShaderStageFlagBit getVisibility(const RenderGraph &renderGraph, const LayoutGraphData &lgd, uint32_t passID, const PmrString &resName) { // NOLINT + auto iter = lgd.attributeIndex.find(resName); + if (iter == lgd.attributeIndex.end()) { + iter = lgd.constantIndex.find(resName); + if (iter == lgd.constantIndex.end()) { + // resource not in descriptor: eg. input or output attachment. + return gfx::ShaderStageFlagBit::NONE; + } + } + auto slotID = iter->second; - auto resID = barrier.resourceID; - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); - if (desc.format == gfx::Format::DEPTH_STENCIL || desc.format == gfx::Format::DEPTH) { - if (g.access.at(u).attachmentStatus.size() > 1) { - auto &dsDep = subpassDependencies.emplace_back(); - dsDep.srcSubpass = dependency.srcSubpass; - dsDep.dstSubpass = dependency.dstSubpass; - dsDep.prevAccesses |= barrier.beginStatus.accessFlag; - dsDep.nextAccesses |= barrier.endStatus.accessFlag; - } - } else { - bool isWriteAccess = !isReadOnlyAccess(barrier.endStatus.accessFlag); - if (isWriteAccess) { - auto &dep = subpassDependencies.emplace_back(); - dep.srcSubpass = dependency.srcSubpass; - dep.dstSubpass = dependency.dstSubpass; - dep.prevAccesses |= barrier.beginStatus.accessFlag; - dep.nextAccesses |= barrier.endStatus.accessFlag; - if (hasReadAccess(barrier.endStatus.accessFlag)) { - auto &selfDep = subpassDependencies.emplace_back(); - selfDep.srcSubpass = dependency.dstSubpass; - selfDep.dstSubpass = dependency.dstSubpass; - selfDep.prevAccesses |= barrier.endStatus.accessFlag; - selfDep.nextAccesses |= barrier.endStatus.accessFlag; - } - } else { - dependency.prevAccesses |= barrier.beginStatus.accessFlag; - dependency.nextAccesses |= barrier.endStatus.accessFlag; - } - } - } - if (dependency.prevAccesses != gfx::AccessFlagBit::NONE) { - subpassDependencies.emplace_back(dependency); + auto layoutName = get(RenderGraph::LayoutTag{}, renderGraph, passID); + auto layoutID = locate(LayoutGraphData::null_vertex(), layoutName, lgd); + const auto &layout = get(LayoutGraphData::LayoutTag{}, lgd, layoutID); + for (const auto &pair : layout.descriptorSets) { + for (const auto &block : pair.second.descriptorSetLayoutData.descriptorBlocks) { + for (const auto &descriptor : block.descriptors) { + if (descriptor.descriptorID.value == slotID.value) { + return block.visibility; } } - ++subpassIdx; } } + // unreachable + CC_EXPECTS(false); - void fillBarrier(const AccessNodeInfo &from, const AccessNodeInfo &to, bool isAdjacent, std::set &subpassResourceSet) { - const auto &[srcStatus, srcRearBarriers, srcPassVert, srcHasSubpass] = from; - const auto &[dstStatus, dstFrontBarriers, dstPassVert, dstHasSubpass] = to; - auto srcVert = srcPassVert; - auto dstVert = dstPassVert; - bool subToSubDeps = false; - if (srcPassVert == dstPassVert) { - srcVert = srcHasSubpass; - dstVert = dstHasSubpass; - subToSubDeps = true; - } - - bool dstExternalDeps = (srcHasSubpass != INVALID_ID) && (dstHasSubpass == INVALID_ID); - bool srcExternalDeps = (srcHasSubpass == INVALID_ID) && (dstHasSubpass != INVALID_ID); - - std::vector commonResources; - std::set_intersection(srcStatus.begin(), srcStatus.end(), - dstStatus.begin(), dstStatus.end(), - std::back_inserter(commonResources), - [](const AccessStatus &lhs, const AccessStatus &rhs) { - return lhs.vertID < rhs.vertID; - }); - if (!commonResources.empty()) { - // this edge is a logic edge added during pass reorder, - // no real dependency between this two vertices. - - // NOLINTNEXTLINE - for (uint32_t i = 0; i < commonResources.size(); ++i) { - uint32_t resourceID = commonResources[i].vertID; - if (subpassResourceSet.find(resourceID) != subpassResourceSet.end()) { - continue; - } - subpassResourceSet.emplace(resourceID); - auto findAccessByID = [resourceID](const AccessStatus &resAccess) { return resAccess.vertID == resourceID; }; - auto fromIter = std::find_if(srcStatus.begin(), srcStatus.end(), findAccessByID); - auto toIter = std::find_if(dstStatus.begin(), dstStatus.end(), findAccessByID); + return gfx::ShaderStageFlagBit::NONE; +}; - // can't happen - CC_ASSERT(fromIter != srcStatus.end()); - CC_ASSERT(toIter != dstStatus.end()); +gfx::MemoryAccessBit toGfxAccess(AccessType type) { + switch (type) { + case AccessType::READ: + return gfx::MemoryAccessBit::READ_ONLY; + case AccessType::WRITE: + return gfx::MemoryAccessBit::WRITE_ONLY; + case AccessType::READ_WRITE: + return gfx::MemoryAccessBit::READ_WRITE; + default: + return gfx::MemoryAccessBit::NONE; + } +}; - if (!isTransitionStatusDependent(*fromIter, *toIter)) { - continue; - } - - auto findBarrierNodeByResID = [resourceID](const Barrier &barrier) { return resourceID == barrier.resourceID; }; +auto mapTextureFlags(ResourceFlags flags) { + gfx::TextureUsage usage = gfx::TextureUsage::NONE; + if ((flags & ResourceFlags::SAMPLED) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::SAMPLED; + } + if ((flags & ResourceFlags::STORAGE) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::STORAGE; + } + if ((flags & ResourceFlags::SHADING_RATE) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::SHADING_RATE; + } + if ((flags & ResourceFlags::COLOR_ATTACHMENT) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::COLOR_ATTACHMENT; + } + if ((flags & ResourceFlags::DEPTH_STENCIL_ATTACHMENT) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT; + } + if ((flags & ResourceFlags::INPUT_ATTACHMENT) != ResourceFlags::NONE) { + usage |= gfx::TextureUsage::INPUT_ATTACHMENT; + } + return usage; +} - auto srcBarrierIter = srcRearBarriers.empty() ? srcRearBarriers.end() : std::find_if(srcRearBarriers.begin(), srcRearBarriers.end(), findBarrierNodeByResID); - auto dstBarrierIter = dstFrontBarriers.empty() ? dstFrontBarriers.end() : std::find_if(dstFrontBarriers.begin(), dstFrontBarriers.end(), findBarrierNodeByResID); +auto getTextureStatus(std::string_view name, AccessType access, gfx::ShaderStageFlags visibility, const ResourceGraph &resourceGraph, bool rasterized) { + gfx::ShaderStageFlags vis{visibility}; + if (vis == gfx::ShaderStageFlags::NONE) { + // attachment + vis = gfx::ShaderStageFlagBit::FRAGMENT; + } + gfx::AccessFlags accesFlag; + auto vertex = resourceGraph.valueIndex.at(name.data()); - auto dstVertDistribute = [&](uint32_t &vertID, bool depends) { - if (depends) { - vertID = INVALID_ID; - } else if (subToSubDeps) { - vertID = dstVert; - } else { - vertID = isAdjacent ? srcVert : dstVert; - } - }; - if (srcBarrierIter == srcRearBarriers.end()) { - auto srcAccess = (*fromIter); - srcAccess.vertID = dstExternalDeps ? INVALID_ID : srcVert; - auto dstAccess = (*toIter); - dstVertDistribute(dstAccess.vertID, dstExternalDeps); - - srcRearBarriers.emplace_back(Barrier{ - resourceID, - isAdjacent ? gfx::BarrierType::FULL : gfx::BarrierType::SPLIT_BEGIN, - nullptr, // generate later - srcAccess, - dstAccess, - }); - srcBarrierIter = std::prev(srcRearBarriers.end()); - } else { - if (isAdjacent) { - srcBarrierIter->type = gfx::BarrierType::FULL; - auto srcAccess = (*fromIter); - srcAccess.vertID = dstExternalDeps ? INVALID_ID : srcVert; - srcBarrierIter->beginStatus = srcAccess; - auto dstAccess = (*toIter); - dstVertDistribute(dstAccess.vertID, dstExternalDeps); - srcBarrierIter->endStatus = dstAccess; - } else { - auto &blockBarrier = barrierMap.at(srcPassVert).blockBarrier; - auto lastVert = srcBarrierIter->beginStatus.vertID; - auto blockIter = blockBarrier.rearBarriers.end(); - if (subToSubDeps) { - blockIter = std::find_if(blockBarrier.rearBarriers.begin(), blockBarrier.rearBarriers.end(), findBarrierNodeByResID); - lastVert = blockIter->beginStatus.vertID; - } - if (srcVert >= lastVert) { - auto srcAccess = (*fromIter); - srcAccess.vertID = srcVert; - if (blockIter != blockBarrier.rearBarriers.end()) { - blockIter->beginStatus = srcAccess; - } - - uint32_t siblingPass = lastVert; - if (srcVert > lastVert) { - auto &siblingPassBarrier = barrierMap[siblingPass].blockBarrier.rearBarriers; - auto siblingIter = std::find_if(siblingPassBarrier.begin(), siblingPassBarrier.end(), - [resourceID](const Barrier &barrier) { - return resourceID == barrier.resourceID; - }); - CC_ASSERT(siblingIter != siblingPassBarrier.end()); - siblingPassBarrier.erase(siblingIter); - } - } - } - } + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, vertex); - if (srcBarrierIter->type == gfx::BarrierType::SPLIT_BEGIN) { - auto srcAccess = (*fromIter); - srcAccess.vertID = srcExternalDeps ? INVALID_ID : srcVert; - auto dstAccess = (*toIter); - dstVertDistribute(dstAccess.vertID, dstExternalDeps); - if (dstBarrierIter == dstFrontBarriers.end()) { - // if isAdjacent, full barrier already in src rear barriers. - if (!isAdjacent) { - dstFrontBarriers.emplace_back(Barrier{ - resourceID, - gfx::BarrierType::SPLIT_END, - nullptr, - srcAccess, - dstAccess, - }); - } - } else { - if (isAdjacent) { - // adjacent, barrier should be commit at fromPass, and remove this iter from dstBarriers - srcBarrierIter->type = gfx::BarrierType::FULL; - srcBarrierIter->beginStatus = srcAccess; - srcBarrierIter->endStatus = dstAccess; - dstFrontBarriers.erase(dstBarrierIter); - } else { - // logic but not exec adjacent - // and more adjacent(distance from src) than another pass which hold a use of resourceID - // replace previous one - - // 1 --> 2 --> 3 - // ↓ - // 4 --> 5 --> 6 - - // [if] real pass order: 1 - 2 - 4 - 5 - 3 - 6 - - // 2 and 5 read from ResA, 6 writes to ResA - // 5 and 6 logically adjacent but not adjacent in execution order. - // barrier for ResA between 2 - 6 can be totally replaced by 5 - 6 - auto &blockBarrier = barrierMap.at(dstPassVert).blockBarrier; - auto blockIter = blockBarrier.frontBarriers.end(); - auto lastVert = dstBarrierIter->endStatus.vertID; - if (subToSubDeps) { - blockIter = std::find_if(blockBarrier.frontBarriers.begin(), blockBarrier.frontBarriers.end(), findBarrierNodeByResID); - lastVert = blockIter->endStatus.vertID; - } - if (dstVert <= lastVert) { - uint32_t siblingPass = lastVert; - dstBarrierIter->endStatus = dstAccess; - - // remove the further redundant barrier - auto &siblingPassBarrier = barrierMap[siblingPass].blockBarrier.frontBarriers; - auto siblingIter = std::find_if(siblingPassBarrier.begin(), siblingPassBarrier.end(), - [resourceID](const Barrier &barrier) { - return resourceID == barrier.resourceID; - }); - CC_ASSERT(siblingIter != siblingPassBarrier.end()); - siblingPassBarrier.erase(siblingIter); - } - } - } - } - } + // can't find this resource in layoutdata, should be output attachment. + gfx::TextureUsage texUsage = gfx::TextureUsage::NONE; + if (access != AccessType::WRITE) { + if ((desc.flags & ResourceFlags::INPUT_ATTACHMENT) != ResourceFlags::NONE && rasterized) { + texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::COLOR_ATTACHMENT | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT | gfx::TextureUsage::INPUT_ATTACHMENT)); + } else { + texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::SAMPLED | gfx::TextureUsage::STORAGE | gfx::TextureUsage::SHADING_RATE | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT)); } + } - //----------------------------------------------check external---------------------------------------------- - auto barrierExternalRes = [&](const AccessStatus &resourcecAccess, Vertex vert) { - uint32_t rescID = resourcecAccess.vertID; - const auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, rescID); - const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, rescID); - const PmrString &resName = get(ResourceGraph::NameTag{}, resourceGraph, rescID); - auto resIter = externalMap.find(resName); - if (traits.hasSideEffects()) { - // first meet in this frame - if (resIter == externalMap.end()) { - // first meet in this program - if (states.states == gfx::AccessFlagBit::NONE) { - auto lastRescAccess = AccessStatus{ - vert, - gfx::ShaderStageFlagBit::NONE, - gfx::MemoryAccessBit::NONE, - gfx::PassType::RASTER, - gfx::AccessFlagBit::NONE, - gfx::TextureUsageBit::NONE, - TextureRange{}, - }; - auto currRescAccess = resourcecAccess; - - // resource id in access -> pass id in barrier - currRescAccess.vertID = vert; - - lastRescAccess.accessFlag = gfx::AccessFlagBit::NONE; - - externalMap.insert({resName, - ResourceTransition{ - lastRescAccess, - currRescAccess, - }}); - } else { - externalMap[resName].lastStatus = {}; - externalMap[resName].lastStatus.vertID = INVALID_ID; - externalMap[resName].lastStatus.accessFlag = states.states; - // deprecated - externalMap[resName].lastStatus.usage = gfx::TextureUsageBit::NONE; - externalMap[resName].lastStatus.range = TextureRange{}; - - externalMap[resName].currStatus = resourcecAccess; - externalMap[resName].currStatus.vertID = vert; - - const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, rescID); - if (isTransitionStatusDependent(externalMap[resName].lastStatus, externalMap[resName].currStatus)) { - resourceNames.emplace(resName); - } - } - } else { - if (resIter->second.currStatus.vertID < vert) { - //[pass: vert] is later access than in iter. - externalMap[resName].currStatus = resourcecAccess; - externalMap[resName].currStatus.vertID = vert; - if (!isReadOnlyAccess(resourcecAccess.accessFlag)) { - resourceNames.emplace(resName); - } - } - } - } - }; + if (access != AccessType::READ) { + texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::COLOR_ATTACHMENT | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT | gfx::TextureUsage::STORAGE)); + } + accesFlag = gfx::getAccessFlags(texUsage, toGfxAccess(access), vis); - for (const AccessStatus &rescAccess : srcStatus) { - barrierExternalRes(rescAccess, from.vertID); - } + return std::make_tuple(vis, accesFlag); +}; - for (const AccessStatus &rescAccess : dstStatus) { - barrierExternalRes(rescAccess, to.vertID); - } - //--------------------------------------------------------------------------------------------------------- +auto getBufferStatus(const PmrString &name, AccessType access, gfx::ShaderStageFlags visibility, const ResourceGraph &resourceGraph) { + gfx::AccessFlags accesFlag; + auto vertex = resourceGraph.valueIndex.at(name); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, vertex); + + gfx::BufferUsage bufferUsage{gfx::BufferUsage::NONE}; + // copy is not included in this logic because copy can be set TRANSFER_xxx directly. + if (access != AccessType::READ) { + bufferUsage = gfx::BufferUsage::STORAGE; } - void examine_edge(Edge e, const Graph &g) { - Vertex from = source(e, g); - Vertex to = target(e, g); + if (access != AccessType::WRITE) { + bool uniformFlag = (desc.flags & ResourceFlags::UNIFORM) != ResourceFlags::NONE; + bool storageFlag = (desc.flags & ResourceFlags::STORAGE) != ResourceFlags::NONE; - // hasSubpass ? fromAccess is a single node with all attachment status stored in 'attachmentStatus' - // : fromAccess is head of chain of subpasses, which stores all attachment status in 'attachmentStatus' - const ResourceAccessNode &fromAccess = get(ResourceAccessGraph::AccessNodeTag{}, g, from); - const ResourceAccessNode &toAccess = get(ResourceAccessGraph::AccessNodeTag{}, g, to); + // CC_EXPECTS(uniformFlag ^ storageFlag); + // uniform or read-only storage buffer + bufferUsage = uniformFlag ? gfx::BufferUsage::UNIFORM : gfx::BufferUsage::STORAGE; + } - bool isAdjacent = isPassExecAdjecent(from, to); - std::vector commonResources; + // those buffers not found in descriptorlayout but appear here, + // can and only can be VERTEX/INDEX/INDIRECT BUFFER, + // only copy pass is allowed. - const auto *srcHead = &fromAccess; - const auto *dstHead = &toAccess; + auto memAccess = toGfxAccess(access); + accesFlag = gfx::getAccessFlags(bufferUsage, gfx::MemoryUsage::DEVICE, memAccess, visibility); + return std::make_tuple(visibility, accesFlag); +}; - bool srcHasSubpass = srcHead->nextSubpass; - bool dstHasSubpass = dstHead->nextSubpass; - srcHead = srcHasSubpass ? srcHead->nextSubpass : srcHead; +void addAccessStatus(ResourceAccessGraph &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status) { + const auto &[name, access, visibility, accessFlag, range] = status; + uint32_t rescID = rg.valueIndex.at(name); + const auto &resourceDesc = get(ResourceGraph::DescTag{}, rg, rescID); + const auto &traits = get(ResourceGraph::TraitsTag{}, rg, rescID); - std::stack reverseSubpassQ; - while (srcHead) { - reverseSubpassQ.push(srcHead); - srcHead = srcHead->nextSubpass; - } - ccstd::set subpassResourceSet; - while (!reverseSubpassQ.empty()) { - uint32_t srcSubpassIndex = reverseSubpassQ.size() - 1; - srcHead = reverseSubpassQ.top(); - reverseSubpassQ.pop(); - const std::vector &fromStatus = srcHead->attachmentStatus; - std::vector &srcRearBarriers = srcHasSubpass ? barrierMap[from].subpassBarriers[srcSubpassIndex].rearBarriers : barrierMap[from].blockBarrier.rearBarriers; - uint32_t dstSubpassIndex = 0; - dstHead = &toAccess; - bool dstHasSubpass = dstHead->nextSubpass; - dstHead = dstHasSubpass ? toAccess.nextSubpass : &toAccess; - while (dstHead) { - const std::vector &toStatus = dstHead->attachmentStatus; - std::vector &dstFrontBarriers = dstHasSubpass ? barrierMap[to].subpassBarriers[dstSubpassIndex].frontBarriers : barrierMap[to].blockBarrier.frontBarriers; - AccessNodeInfo fromInfo = {fromStatus, srcRearBarriers, from, srcHasSubpass ? static_cast(reverseSubpassQ.size()) : INVALID_ID}; - AccessNodeInfo toInfo = {toStatus, dstFrontBarriers, to, dstHasSubpass ? dstSubpassIndex : INVALID_ID}; - bool isExecAdjacent = isAdjacent && (!srcHead->nextSubpass && !dstSubpassIndex); - fillBarrier(fromInfo, toInfo, isAdjacent, subpassResourceSet); - dstHead = dstHead->nextSubpass; - ++dstSubpassIndex; - } - } + CC_EXPECTS(rg.valueIndex.find(name) != rg.valueIndex.end()); + if (std::find(rag.resourceNames.begin(), rag.resourceNames.end(), name) == rag.resourceNames.end()) { + rag.resourceIndex.emplace(name, rescID); + rag.resourceNames.emplace_back(name); + } - auto &rearBarriers = barrierMap[from].blockBarrier.rearBarriers; - auto &frontBarriers = barrierMap[from].blockBarrier.frontBarriers; - - uint32_t subpassIdx = 0; - for (const auto &barriers : barrierMap[from].subpassBarriers) { - for (const auto &barrier : barriers.rearBarriers) { - auto resID = barrier.resourceID; - auto findBarrierByResID = [resID](const Barrier &barrier) { - return barrier.resourceID == resID; - }; - auto iter = std::find_if(rearBarriers.begin(), rearBarriers.end(), findBarrierByResID); - auto resFinalPassID = accessRecord.at(resID).currStatus.vertID; - - if (resFinalPassID > from) { - const auto *dstHead = dstHasSubpass ? toAccess.nextSubpass : &toAccess; - const AccessStatus *dstAccess{nullptr}; - while (dstHead) { - auto iter = std::find_if(dstHead->attachmentStatus.begin(), dstHead->attachmentStatus.end(), [resID](const AccessStatus &access) { - return access.vertID == resID; - }); - if (iter != dstHead->attachmentStatus.end()) { - dstAccess = &(*iter); - break; - } - dstHead = dstHead->nextSubpass; - } + node.resourceStatus.emplace(name, AccessStatus{ + accessFlag, + range, + }); +} - if (!dstAccess) { - continue; - } +namespace { +const uint32_t ATTACHMENT_TYPE_WEIGHT[] = {0, 2, 1}; - const auto *srcHead = srcHasSubpass ? fromAccess.nextSubpass : &fromAccess; - uint32_t step = 0; - while (step <= subpassIdx) { - srcHead = srcHead->nextSubpass; - ++step; - } +struct AttachmentSortKey { + gfx::SampleCount samples; + AccessType accessType; + uint32_t attachmentWeight; + const ccstd::pmr::string name; +}; - bool laterUse = false; - while (srcHead) { - const auto &attachments = srcHead->attachmentStatus; - laterUse |= std::any_of(attachments.begin(), attachments.end(), [resID](const AccessStatus &access) { - return access.vertID == resID; - }); - srcHead = srcHead->nextSubpass; - } +struct AttachmentComparator { + bool operator()(const AttachmentSortKey &lhs, const AttachmentSortKey &rhs) const { + return std::tie(rhs.samples, lhs.accessType, lhs.attachmentWeight, lhs.name) < std::tie(lhs.samples, rhs.accessType, rhs.attachmentWeight, rhs.name); + } +}; - // laterUse: in case it's a split begin/end. - const auto &srcAccess = laterUse ? barrier.endStatus : barrier.beginStatus; - if (isTransitionStatusDependent(srcAccess, *dstAccess)) { - if (iter == rearBarriers.end()) { - auto &collect = rearBarriers.emplace_back(barrier); - collect.beginStatus.vertID = from; - collect.endStatus.vertID = isAdjacent ? from : to; - } else if (iter->endStatus.vertID >= to) { - (*iter) = barrier; - iter->beginStatus.vertID = from; - iter->endStatus.vertID = isAdjacent ? from : to; - } - } - } - } +struct ViewInfo { + gfx::Format format{gfx::Format::UNKNOWN}; + LayoutAccess access; + gfx::LoadOp loadOp; + gfx::StoreOp storeOp; + AttachmentType attachmentType; +}; - for (const auto &barrier : barriers.frontBarriers) { - auto resID = barrier.resourceID; - auto findBarrierByResID = [resID](const Barrier &barrier) { - return barrier.resourceID == resID; - }; - auto resFinalPassID = accessRecord.at(resID).currStatus.vertID; - auto firstMeetIter = std::find_if(frontBarriers.begin(), frontBarriers.end(), findBarrierByResID); - auto innerResIter = std::find_if(rearBarriers.begin(), rearBarriers.end(), findBarrierByResID); - - if (firstMeetIter == frontBarriers.end() && innerResIter == rearBarriers.end() && resFinalPassID > from) { - frontBarriers.emplace_back(barrier); +using AttachmentMap = ccstd::pmr::map; +} // namespace + +void fillRenderPassInfo(const AttachmentMap &colorMap, + FGRenderPassInfo &fgRenderpassInfo, + const ResourceGraph &resg) { + for (const auto &pair : colorMap) { + const auto &key = pair.first; + const auto &viewInfo = pair.second; + if (viewInfo.attachmentType == AttachmentType::DEPTH_STENCIL) { + // put ds[sample > 1] to ds, ds[sample == 1] to dsResolve, swap them if not a ms pass in endRenderPass. + bool ms = key.samples != gfx::SampleCount::X1; + auto &ds = ms ? fgRenderpassInfo.rpInfo.depthStencilAttachment + : fgRenderpassInfo.rpInfo.depthStencilResolveAttachment; + auto &dsAccess = ms ? fgRenderpassInfo.dsAccess : fgRenderpassInfo.dsResolveAccess; + if (ds.format == gfx::Format::UNKNOWN) { + ds.depthLoadOp = viewInfo.loadOp; + ds.stencilLoadOp = viewInfo.loadOp; + ds.sampleCount = key.samples; + ds.format = viewInfo.format; + dsAccess.prevAccess = viewInfo.access.prevAccess; + } + ds.depthStoreOp = viewInfo.storeOp; + ds.stencilStoreOp = viewInfo.storeOp; + dsAccess.nextAccess = viewInfo.access.nextAccess; + + auto iter = fgRenderpassInfo.viewIndex.find(key.name.c_str()); + if (iter == fgRenderpassInfo.viewIndex.end()) { + auto parentID = realID(key.name, resg); + const auto &parentName = get(ResourceGraph::NameTag{}, resg, parentID); + AttachmentInfo attachmentInfo(fgRenderpassInfo.get_allocator()); + attachmentInfo.parentName = parentName; + attachmentInfo.attachmentIndex = gfx::INVALID_BINDING; + attachmentInfo.isResolveView = fgRenderpassInfo.resolveCount && key.samples == gfx::SampleCount::X1; + fgRenderpassInfo.viewIndex.emplace(key.name, attachmentInfo); + } + } else { + auto iter = fgRenderpassInfo.viewIndex.find(key.name.c_str()); + auto &colors = fgRenderpassInfo.rpInfo.colorAttachments; + if (iter == fgRenderpassInfo.viewIndex.end()) { + auto colorIndex = fgRenderpassInfo.orderedViews.size(); + auto &color = colors.emplace_back(); + color.format = viewInfo.format; + color.sampleCount = key.samples; + color.storeOp = viewInfo.storeOp; + color.loadOp = viewInfo.loadOp; + fgRenderpassInfo.colorAccesses.emplace_back(LayoutAccess{viewInfo.access.prevAccess, viewInfo.access.nextAccess}); + fgRenderpassInfo.colorAccesses[colorIndex].nextAccess = viewInfo.access.nextAccess; + + auto parentID = realID(key.name, resg); + const auto &parentName = get(ResourceGraph::NameTag{}, resg, parentID); + AttachmentInfo attachmentInfo(fgRenderpassInfo.get_allocator()); + attachmentInfo.parentName = parentName; + attachmentInfo.attachmentIndex = static_cast(fgRenderpassInfo.orderedViews.size()); + attachmentInfo.isResolveView = fgRenderpassInfo.resolveCount && key.samples == gfx::SampleCount::X1; + + fgRenderpassInfo.viewIndex.emplace(key.name, attachmentInfo); + fgRenderpassInfo.orderedViews.emplace_back(key.name); + } else { + const auto &attachmentInfo = fgRenderpassInfo.viewIndex.at(key.name); + auto cIndex = attachmentInfo.attachmentIndex; + if (cIndex == gfx::INVALID_BINDING) { + bool ms = key.samples == gfx::SampleCount::X1; + auto &ds = ms ? fgRenderpassInfo.rpInfo.depthStencilAttachment : fgRenderpassInfo.rpInfo.depthStencilResolveAttachment; + ds.depthStoreOp = viewInfo.storeOp; + ds.stencilStoreOp = viewInfo.storeOp; + auto &access = ms ? fgRenderpassInfo.dsAccess : fgRenderpassInfo.dsResolveAccess; + access.nextAccess = viewInfo.access.nextAccess; + } else { + auto &color = fgRenderpassInfo.rpInfo.colorAttachments[cIndex]; + color.storeOp = viewInfo.storeOp; + fgRenderpassInfo.colorAccesses[cIndex].nextAccess = viewInfo.access.nextAccess; } } } - subpassIdx++; } - - const AccessTable &accessRecord; - BarrierMap &barrierMap; - const ResourceGraph &resourceGraph; - ExternalResMap &externalMap; // last frame to curr frame status transition - ResourceNames &resourceNames; // record those which been written - ResourceLifeRecordMap &resourceLifeRecord; - PmrFlatMap &rpInfos; }; -void buildBarriers(FrameGraphDispatcher &fgDispatcher) { - auto *scratch = fgDispatcher.scratch; - const auto &renderGraph = fgDispatcher.graph; - const auto &layoutGraph = fgDispatcher.layoutGraph; - auto &resourceGraph = fgDispatcher.resourceGraph; - auto &relationGraph = fgDispatcher.relationGraph; - auto &externalResMap = fgDispatcher.externalResMap; - auto &rag = fgDispatcher.resourceAccessGraph; +[[nodiscard("concat")]] ccstd::pmr::string concatResName( + std::string_view name0, + std::string_view name1, + boost::container::pmr::memory_resource *scratch) { + ccstd::pmr::string name(name0, scratch); + name += "/"; + name += name1; + return name; +} - // record resource current in-access and out-access for every single node - if (!fgDispatcher._accessGraphBuilt) { - const Graphs graphs{renderGraph, resourceGraph, layoutGraph, rag, relationGraph}; - buildAccessGraph(graphs); - fgDispatcher._accessGraphBuilt = true; +void extractNames(const ccstd::pmr::string &resName, + const RasterView &view, + ccstd::pmr::vector> &names) { + // depth_stencil + if (view.attachmentType == AttachmentType::DEPTH_STENCIL) { + if (!defaultAttachment(view.slotName)) { + if (strstr(resName.c_str(), "/")) { + names.emplace_back(resName, 0); + } else { + auto &subresName = names.emplace_back(); + subresName.first = concatResName(resName, DEPTH_PLANE_NAME, names.get_allocator().resource()); + subresName.second = 0; + } + } + if (!defaultAttachment(view.slotName1)) { + if (strstr(resName.c_str(), "/")) { + names.emplace_back(resName, 1); + } else { + auto &subresName = names.emplace_back(); + subresName.first = concatResName(resName, STENCIL_PLANE_NAME, names.get_allocator().resource()); + subresName.second = 1; + } + } } - // found pass id in this map ? barriers you should commit when run into this pass - // : or no extra barrier needed. - BarrierMap &batchedBarriers = fgDispatcher.barrierMap; + // cube - { - // barrier first meet - // O(N) actually - ccstd::set firstMeet; - for (size_t i = 0; i < rag.access.size(); ++i) { - const auto *status = &rag.access[i]; - for (const auto &attachment : status->attachmentStatus) { - AccessStatus lastStatus{ - static_cast(i), - gfx::ShaderStageFlagBit::NONE, - gfx::MemoryAccessBit::NONE, - gfx::PassType::RASTER, - gfx::AccessFlagBit::NONE, - gfx::TextureUsageBit::NONE, - TextureRange{}, - }; - - AccessStatus currStatus = attachment; - currStatus.vertID = static_cast(i); - - gfx::BarrierType bType = gfx::BarrierType::FULL; - const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, attachment.vertID); - if (traits.hasSideEffects()) { - const auto &accessFlag = get(ResourceGraph::StatesTag{}, resourceGraph, attachment.vertID).states; - if (accessFlag != gfx::AccessFlagBit::NONE) { - lastStatus.accessFlag = accessFlag; - bType = traits.residency == ResourceResidency::BACKBUFFER ? gfx::BarrierType::FULL : gfx::BarrierType::SPLIT_END; - } - if (!isTransitionStatusDependent(lastStatus, currStatus)) { - continue; - } - } - if (firstMeet.find(attachment.vertID) == firstMeet.end()) { - firstMeet.emplace(attachment.vertID); - - if (batchedBarriers.find(i) == batchedBarriers.end()) { - batchedBarriers.emplace(i, BarrierNode{}); - auto &rpInfo = rag.rpInfos[i].rpInfo; - // NOLINTNEXTLINE (readability-container-size-empty) - if (rpInfo.subpasses.size() >= 1) { - batchedBarriers[i].subpassBarriers.resize(rpInfo.subpasses.size()); - } - } + // array + + if (names.empty()) { + names.emplace_back(resName, 0); + } +} - auto &blockFrontBarrier = batchedBarriers.at(i).blockBarrier.frontBarriers; - auto resIter = std::find_if(blockFrontBarrier.begin(), blockFrontBarrier.end(), [&attachment](const Barrier &barrier) { return barrier.resourceID == attachment.vertID; }); - if (resIter == blockFrontBarrier.end()) { - Barrier firstMeetBarrier{ - attachment.vertID, - bType, - nullptr, - lastStatus, - currStatus, - }; - blockFrontBarrier.emplace_back(firstMeetBarrier); - } - auto *nextStatus = status->nextSubpass; - uint32_t index = 0; - while (nextStatus) { - const auto &subpassStatus = nextStatus->attachmentStatus; - auto &subpassBarriers = batchedBarriers.at(i).subpassBarriers; - auto &frontBarriers = subpassBarriers[index].frontBarriers; - auto iter = std::find_if(subpassStatus.begin(), subpassStatus.end(), [&attachment](const AccessStatus &access) { return access.vertID == attachment.vertID; }); - if (iter != subpassStatus.end()) { - lastStatus.vertID = 0xFFFFFFFF; - currStatus.vertID = index; - currStatus.accessFlag = iter->accessFlag; - Barrier firstMeetBarrier{ - attachment.vertID, - bType, - nullptr, - lastStatus, - currStatus, - }; - frontBarriers.emplace_back(firstMeetBarrier); - break; - } - nextStatus = nextStatus->nextSubpass; - index++; - } - } - } - } +[[nodiscard("subresName")]] ccstd::pmr::string getSubresName(const ccstd::pmr::string &resName, + uint32_t planeID, const ResourceGraph& resg, + boost::container::pmr::memory_resource* scratch) { + const auto& desc = get(ResourceGraph::DescTag{}, resg, vertex(resName, resg)); + if(desc.format == gfx::Format::DEPTH_STENCIL) { + auto nameView = planeID == 0 ? DEPTH_PLANE_NAME : STENCIL_PLANE_NAME; + const auto &subresName = concatResName(resName, nameView, scratch); + return subresName; } + - ResourceNames namesSet; - { - // barrier between passes - BarrierVisitor visitor(resourceGraph, batchedBarriers, externalResMap, namesSet, rag.accessRecord, rag.resourceLifeRecord, rag.rpInfos); - auto colors = rag.colors(scratch); - boost::queue q; - - boost::breadth_first_visit( - rag, - EXPECT_START_ID, - q, - visitor, - get(colors, rag)); - } - - // external res barrier for next frame - for (const auto &externalPair : externalResMap) { - const auto &resName = externalPair.first; - const auto &transition = externalPair.second; - auto resID = resourceGraph.valueIndex.at(resName); - const auto &resTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, resID); - auto &rescStates = get(ResourceGraph::StatesTag{}, resourceGraph, resID); - - bool backBuffer = resTraits.residency == ResourceResidency::BACKBUFFER; - // when to dispatch a barrier on persistent: - // 1. resource been written in this frame; - // 2. first meet in this frame (no idea if any writes in next frame) - // 3. backbuffer present - bool needNextBarrier = (namesSet.find(resName) != namesSet.end()) || (rescStates.states == gfx::AccessFlagBit::NONE); - - // persistant resource states cached here - rescStates.states = transition.currStatus.accessFlag; - - if (!backBuffer && !needNextBarrier) { - continue; - } + // cube - auto passID = transition.currStatus.vertID; - if (batchedBarriers.find(passID) == batchedBarriers.end()) { - batchedBarriers.emplace(passID, BarrierNode{}); - } + // array - Barrier nextFrameResBarrier{ - resID, - gfx::BarrierType::SPLIT_BEGIN, - nullptr, - externalResMap[externalPair.first].currStatus, - {}}; - - if (backBuffer) { - nextFrameResBarrier.endStatus = { - INVALID_ID, - gfx::ShaderStageFlagBit::NONE, - gfx::MemoryAccessBit::NONE, - gfx::PassType::PRESENT, - gfx::AccessFlagBit::PRESENT, - gfx::TextureUsageBit::NONE, - TextureRange{}, - }; - nextFrameResBarrier.type = gfx::BarrierType::FULL; - rescStates.states = gfx::AccessFlagBit::PRESENT; - } + // UNREACHABLE + CC_ASSERT(false); + return ""; +} - bool hasSubpass = !(batchedBarriers[passID].subpassBarriers.size() <= 1); - if (hasSubpass) { - // rpinfo instead - auto &fgRenderPassInfo = rag.rpInfos.at(passID); - auto iter = std::find(fgRenderPassInfo.orderedViews.begin(), fgRenderPassInfo.orderedViews.end(), resName.c_str()); - CC_ASSERT(iter != fgRenderPassInfo.orderedViews.end()); - auto index = std::distance(fgRenderPassInfo.orderedViews.begin(), iter); - index -= fgRenderPassInfo.rpInfo.depthStencilAttachment.format != gfx::Format::UNKNOWN; - fgRenderPassInfo.colorAccesses[index].nextAccess = nextFrameResBarrier.endStatus.accessFlag; - } else { - auto &rearBarriers = batchedBarriers[passID].blockBarrier.rearBarriers; - rearBarriers.emplace_back(nextFrameResBarrier); - } +auto checkRasterViews(const Graphs &graphs, + ResourceAccessGraph::vertex_descriptor ragVertID, + ResourceAccessNode &node, + const RasterViewsMap &rasterViews, + AttachmentMap &colorMap) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + const auto passID = get(ResourceAccessGraph::PassIDTag{}, resourceAccessGraph, ragVertID); + bool dependent = false; + bool hasDS = false; + + auto explicitVis = gfx::ShaderStageFlagBit::NONE; + if (holds(passID, renderGraph)) { + explicitVis |= gfx::ShaderStageFlagBit::COMPUTE; } - { - const auto &resDescs = get(ResourceGraph::DescTag{}, resourceGraph); - auto genGFXBarrier = [&resDescs](std::vector &barriers) { - for (auto &passBarrier : barriers) { - const auto &desc = get(resDescs, passBarrier.resourceID); - if (desc.dimension == ResourceDimension::BUFFER) { - gfx::BufferBarrierInfo info; - info.prevAccesses = passBarrier.beginStatus.accessFlag; - info.nextAccesses = passBarrier.endStatus.accessFlag; - const auto &range = ccstd::get(passBarrier.endStatus.range); - info.offset = range.offset; - info.size = range.size; - info.type = passBarrier.type; - passBarrier.barrier = gfx::Device::getInstance()->getBufferBarrier(info); - } else { - gfx::TextureBarrierInfo info; - info.prevAccesses = passBarrier.beginStatus.accessFlag; - info.nextAccesses = passBarrier.endStatus.accessFlag; - const auto &range = ccstd::get(passBarrier.beginStatus.range); - info.baseMipLevel = range.mipLevel; - info.levelCount = range.levelCount; - info.baseSlice = range.firstSlice; - info.sliceCount = range.numSlices; - info.type = passBarrier.type; - passBarrier.barrier = gfx::Device::getInstance()->getTextureBarrier(info); - } - } - }; + for (const auto &pair : rasterViews) { + const auto &rasterView = pair.second; + const auto &resName = pair.first; + const auto resID = vertex(resName, resourceGraph); + auto access = rasterView.accessType; + gfx::ShaderStageFlagBit originVis = getVisibility(renderGraph, layoutGraphData, passID, pair.second.slotName) | explicitVis | pair.second.shaderStageFlags; + const auto &[vis, accessFlag] = getTextureStatus(resName.data(), access, originVis, resourceGraph, true); + auto range = getResourceRange(resID, resourceGraph); + + ViewStatus viewStatus{resName, access, vis, accessFlag, range}; + addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); - constexpr static bool USING_RENDERPASS_DEP_INSTEAD_OF_BARRIER{true}; - if constexpr (USING_RENDERPASS_DEP_INSTEAD_OF_BARRIER) { - auto prune = [&rag, &renderGraph, &resourceGraph](std::vector &barriers) { - barriers.erase(std::remove_if(barriers.begin(), barriers.end(), [&rag, &renderGraph, &resourceGraph](Barrier &barrier) { - bool fromAttachment = isAttachmentAccess(barrier.beginStatus.accessFlag) || barrier.beginStatus.accessFlag == gfx::AccessFlagBit::NONE; - bool toAttachment = isAttachmentAccess(barrier.endStatus.accessFlag); - return toAttachment; - }), - barriers.end()); - }; - for (auto &passBarrierInfo : batchedBarriers) { - auto &passBarrierNode = passBarrierInfo.second; - prune(passBarrierNode.blockBarrier.frontBarriers); - prune(passBarrierNode.blockBarrier.rearBarriers); - } - } + const auto &[lastVertId, lastAccess] = dependencyCheck(resourceAccessGraph, ragVertID, resourceGraph, viewStatus); + tryAddEdge(lastVertId, ragVertID, resourceAccessGraph); + tryAddEdge(lastVertId, ragVertID, relationGraph); + dependent |= (lastVertId != EXPECT_START_ID); + + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + colorMap.emplace(AttachmentSortKey{desc.sampleCount, + rasterView.accessType, + ATTACHMENT_TYPE_WEIGHT[static_cast(rasterView.attachmentType)], + resName}, + ViewInfo{desc.format, + LayoutAccess{lastAccess, accessFlag}, + rasterView.loadOp, + rasterView.storeOp, + rasterView.attachmentType}); + hasDS |= rasterView.attachmentType == AttachmentType::DEPTH_STENCIL; + + ccstd::pmr::vector> names(resourceAccessGraph.get_allocator()); + extractNames(resName, rasterView, names); + for (const auto& [subresFullName, plane] : names) { + resourceAccessGraph.resourceIndex.emplace(subresFullName, vertex(subresFullName, resourceGraph)); + } + } + return std::make_tuple(dependent, hasDS); +} - // generate gfx barrier - for (auto &passBarrierInfo : batchedBarriers) { - auto &passBarrierNode = passBarrierInfo.second; - genGFXBarrier(passBarrierNode.blockBarrier.frontBarriers); - genGFXBarrier(passBarrierNode.blockBarrier.rearBarriers); - for (auto &subpassBarrier : passBarrierNode.subpassBarriers) { - genGFXBarrier(subpassBarrier.frontBarriers); - genGFXBarrier(subpassBarrier.rearBarriers); - } - } - } +bool checkComputeViews(const Graphs &graphs, ResourceAccessGraph::vertex_descriptor ragVertID, ResourceAccessNode &node, const ComputeViewsMap &computeViews) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + const auto passID = get(ResourceAccessGraph::PassIDTag{}, resourceAccessGraph, ragVertID); + bool dependent = false; - { - for (auto &[vert, fgRenderpassInfo] : rag.rpInfos) { - auto &colorAttachments = fgRenderpassInfo.rpInfo.colorAttachments; - for (uint32_t i = 0; i < colorAttachments.size(); ++i) { - const auto &colorAccess = fgRenderpassInfo.colorAccesses[i]; - colorAttachments[i].barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), colorAccess.prevAccess, colorAccess.nextAccess); + for (const auto &pair : computeViews) { + const auto &values = pair.second; + const auto &resName = pair.first; + const auto resID = vertex(resName, resourceGraph); + auto range = getResourceRange(vertex(resName, resourceGraph), resourceGraph); + for (const auto &computeView : values) { + gfx::ShaderStageFlagBit vis = gfx::ShaderStageFlagBit::NONE; + for (const auto &view : pair.second) { + vis |= getVisibility(renderGraph, layoutGraphData, passID, view.name); + vis |= view.shaderStageFlags; } - auto &dsAttachment = fgRenderpassInfo.rpInfo.depthStencilAttachment; - if (dsAttachment.format != gfx::Format::UNKNOWN) { - const auto &dsAccess = fgRenderpassInfo.dsAccess; - dsAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), dsAccess.prevAccess, dsAccess.nextAccess); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; + if (desc.dimension == ResourceDimension::BUFFER) { + const auto &[ignore0, access] = getBufferStatus(pair.first, computeView.accessType, vis, resourceGraph); + accessFlag = access; + } else { + const auto &[ignore0, access] = getTextureStatus(pair.first, computeView.accessType, vis, resourceGraph, false); + accessFlag = access; } - auto &dsResolveAttachment = fgRenderpassInfo.rpInfo.depthStencilResolveAttachment; - if (dsResolveAttachment.format != gfx::Format::UNKNOWN) { - const auto &dsAccess = fgRenderpassInfo.dsResolveAccess; - dsResolveAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), dsAccess.prevAccess, dsAccess.nextAccess); + range.firstSlice = computeView.plane; + range.numSlices = 1; + ViewStatus viewStatus{pair.first, computeView.accessType, vis, accessFlag, range}; + addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); + auto [lastVertId, neareastAccess] = dependencyCheck(resourceAccessGraph, ragVertID, resourceGraph, viewStatus); + + tryAddEdge(lastVertId, ragVertID, resourceAccessGraph); + tryAddEdge(lastVertId, ragVertID, relationGraph); + dependent = lastVertId != EXPECT_START_ID; + + if(out_degree(resID, resourceGraph)) { + const auto& subresFullName = getSubresName(resName, computeView.plane, resourceGraph, resourceAccessGraph.resource()); + resourceAccessGraph.resourceIndex.emplace(subresFullName, vertex(subresFullName, resourceGraph)); } } } + + return dependent; } -#pragma endregion BUILD_BARRIERS -#pragma region PASS_REORDER +bool checkResolveResource(const Graphs &graphs, + uint32_t ragVertID, + ResourceAccessNode &node, + const ccstd::pmr::vector &resolves, + AttachmentMap &colorMap) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + const auto passID = get(ResourceAccessGraph::PassIDTag{}, resourceAccessGraph, ragVertID); + bool dependent = false; -struct PassVisitor : boost::dfs_visitor<> { - using RLGVertex = RelationGraph::vertex_descriptor; - using RLGEdge = RelationGraph::edge_descriptor; - using InEdgeRange = std::pair; - using OutEdgeRange = std::pair; + for (const auto &pair : resolves) { + const auto &resolveTargetName = pair.target; - PassVisitor(RelationGraph &tcIn, CloseCircuits &circuitsIn) : _relationGraph(tcIn), _circuits(circuitsIn) {} + const auto &resID = vertex(resolveTargetName, resourceGraph); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); - void start_vertex(RLGVertex u, const RelationGraph &g) {} + bool isDS = desc.format == gfx::Format::DEPTH_STENCIL; + auto accessFlag = isDS ? gfx::AccessFlagBit::DEPTH_STENCIL_ATTACHMENT_WRITE : gfx::AccessFlagBit::COLOR_ATTACHMENT_WRITE; - void discover_vertex(RLGVertex u, const RelationGraph &g) {} + gfx::ShaderStageFlagBit vis = gfx::ShaderStageFlagBit::FRAGMENT; + auto range = getResourceRange(resID, resourceGraph); - void examine_edge(RLGEdge e, const RelationGraph &g) { + ViewStatus viewStatus{resolveTargetName, AccessType::WRITE, vis, accessFlag, range}; + addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); + + const auto &[lastVertId, lastAccess] = dependencyCheck(resourceAccessGraph, ragVertID, resourceGraph, viewStatus); + tryAddEdge(lastVertId, ragVertID, resourceAccessGraph); + tryAddEdge(lastVertId, ragVertID, relationGraph); + dependent = lastVertId != EXPECT_START_ID; + + AttachmentType attachmentType = isDS ? AttachmentType::DEPTH_STENCIL : AttachmentType::RENDER_TARGET; + colorMap.emplace(AttachmentSortKey{desc.sampleCount, + AccessType::WRITE, + ATTACHMENT_TYPE_WEIGHT[static_cast(attachmentType)], + resolveTargetName}, + ViewInfo{desc.format, + LayoutAccess{lastAccess, accessFlag}, + gfx::LoadOp::DISCARD, + gfx::StoreOp::STORE, + attachmentType}); } + return dependent; +} - void tree_edge(RLGEdge e, const RelationGraph &g) {} +uint32_t record(uint32_t index) { + uint32_t res = 1 << index; + return res; +} - void back_edge(RLGEdge e, const RelationGraph &g) {} +uint32_t record(const ccstd::vector &indices) { + uint32_t res = 0; + for (auto attachmentIndex : indices) { + res |= 1 << attachmentIndex; + } + return res; +} - void forward_or_cross_edge(RLGEdge e, const RelationGraph &g) { - // the vertex which: - // 1. is ancestor of targetID; - // 2. sourceID is reachable at this specific vert; - // is where the closed-path started. - // note that `reachable` may results to multiple paths, choose the shortest one. - auto sourceID = source(e, g); - auto targetID = target(e, g); +void extract(uint32_t val, ccstd::vector &preserves) { + uint32_t index = 0; + while (val) { + if (val & 0x1) { + preserves.emplace_back(index); + } + val = val >> 1; + ++index; + } +} - using RhsRangePair = std::pair; +void getPreserves(gfx::RenderPassInfo &rpInfo) { + std::stack stack; + for (auto &info : rpInfo.subpasses) { + stack.push(&info); + } - bool foundIntersect = false; - std::queue vertQ; - auto iterPair = in_edges(targetID, g); - vertQ.emplace(RhsRangePair{iterPair.first, iterPair}); + auto dsIndex = record(rpInfo.colorAttachments.size()); + auto dsMask = record(rpInfo.colorAttachments.size()) | record(rpInfo.colorAttachments.size() + 1); - // from source vertex on this edge back to branch point - EdgeList rhsPath; - bool rootEdge = true; - while (!foundIntersect && !vertQ.empty()) { - auto rangePair = vertQ.front(); - vertQ.pop(); - auto range = rangePair.second; - for (auto iter = range.first; iter != range.second; ++iter) { - auto srcID = source((*iter), g); - if (sourceID == srcID) { - continue; - } - auto e = edge(srcID, sourceID, _relationGraph); - auto recordIter = rootEdge ? iter : rangePair.first; - if (!e.second) { - vertQ.emplace(RhsRangePair{recordIter, in_edges(srcID, g)}); - } else { - rhsPath = {(*iter), *recordIter}; - foundIntersect = true; - break; - } - } - rootEdge = false; + uint32_t laterRead{0}; + while (!stack.empty()) { + auto *tail = stack.top(); + stack.pop(); + + auto readRecord = record(tail->inputs); + auto writeRecord = record(tail->colors); + auto resolveRecord = record(tail->resolves); + + uint32_t dsRecord = 0; + if (tail->depthStencil != INVALID_ID) { + dsRecord |= record(tail->depthStencil); } - assert(foundIntersect); + if (tail->depthStencilResolve != INVALID_ID) { + dsRecord |= record(tail->depthStencilResolve); + } + auto shown = readRecord | writeRecord | resolveRecord | dsRecord; + auto needPreserve = (shown | laterRead) ^ shown; + needPreserve = (needPreserve & dsMask) == dsMask ? (needPreserve & ~dsMask) | dsIndex : (needPreserve & ~dsMask); + extract(needPreserve, tail->preserves); + laterRead |= readRecord; + } +} - using LhsRangePair = std::pair; - auto branchVert = source(rhsPath.first, g); - bool found = false; - std::queue forwardVertQ; - auto forwardIterPair = out_edges(branchVert, g); - forwardVertQ.emplace(LhsRangePair{forwardIterPair.first, forwardIterPair}); - EdgeList lhsPath; - rootEdge = true; - while (!found && !forwardVertQ.empty()) { - auto rangePair = forwardVertQ.front(); - forwardVertQ.pop(); - auto range = rangePair.second; - for (auto iter = range.first; iter != range.second; ++iter) { - if ((*iter) == rhsPath.first) { - continue; - } - auto dstID = target((*iter), g); - auto e = edge(dstID, sourceID, _relationGraph); - auto recordIter = rootEdge ? iter : rangePair.first; - if (!e.second) { - forwardVertQ.emplace(LhsRangePair{recordIter, out_edges(dstID, g)}); - } else { - found = true; - lhsPath = {*recordIter, (*iter)}; - break; - } - } - rootEdge = true; - } - assert(found); - lhsPath.second = e; - - _circuits.emplace_back(CloseCircuit{lhsPath, rhsPath}); - }; +uint32_t getDepthStencilSlot(uint32_t uniqueResourceCount, uint32_t resolveCount, bool hasDS) { + auto dsSlot = uniqueResourceCount - hasDS + resolveCount; + return dsSlot; +} -private: - RelationGraph &_relationGraph; - CloseCircuits &_circuits; -}; +void startRenderPass(const Graphs &graphs, uint32_t passID, const RasterPass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; -// forward (vertex ascending): -// -- true: how much resource this pass writes to, which has an effect of later passes; -// -- false: how much resource this pass reads from, which is dependent from former passes. -auto evaluateHeaviness(const RAG &rag, const ResourceGraph &rescGraph, ResourceAccessGraph::vertex_descriptor vert, bool forward) { - const ResourceAccessNode &accessNode = get(RAG::AccessNodeTag{}, rag, vert); - int64_t score = 0; - bool forceAdjacent = false; - for (const auto &resc : accessNode.attachmentStatus) { - int64_t eval = 0; - auto rescID = resc.vertID; - const ResourceDesc &desc = get(ResourceGraph::DescTag{}, rescGraph, rescID); - const ResourceTraits &traits = get(ResourceGraph::TraitsTag{}, rescGraph, rescID); + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - gfx::MemoryAccessBit substractFilter = forward ? gfx::MemoryAccessBit::READ_ONLY : gfx::MemoryAccessBit::WRITE_ONLY; - if (resc.access == substractFilter) { - // forward calculate write(s), backward calculate read(s). - continue; - } + auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, vertID); + if (pass.subpassGraph.subpasses.empty()) { + AttachmentMap colorMap(resourceAccessGraph.get_allocator()); + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, vertID); + std::ignore = checkRasterViews(graphs, rlgVertID, accessNode, pass.rasterViews, colorMap); + std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); + fillRenderPassInfo(colorMap, fgRenderPassInfo, resourceGraph); + } else { + const auto &subpasses = pass.subpassGraph.subpasses; + uint32_t initVal{0}; + fgRenderPassInfo.resolveCount = std::accumulate(subpasses.begin(), subpasses.end(), initVal, [](uint32_t ct, const Subpass &subpass) { + return ct + subpass.resolvePairs.size(); + }); + } - switch (desc.dimension) { - case ResourceDimension::BUFFER: - eval = desc.width; - break; - case ResourceDimension::TEXTURE1D: - case ResourceDimension::TEXTURE2D: - case ResourceDimension::TEXTURE3D: - eval = gfx::formatSize(desc.format, desc.width, desc.height, desc.depthOrArraySize); - break; + const auto &subpasses = pass.subpassGraph.subpasses; + uint32_t initVal{0}; + ccstd::pmr::set resSet{resourceAccessGraph.get_allocator()}; + for (const auto &subpass : subpasses) { + for (const auto &view : subpass.rasterViews) { + resSet.emplace(realID(view.first, resourceGraph)); } - - if (traits.residency == ResourceResidency::MEMORYLESS) { - forceAdjacent = true; - score = forward ? std::numeric_limits::lowest() : std::numeric_limits::max(); - break; + auto &dsResolveAttachment = fgRenderPassInfo.rpInfo.depthStencilResolveAttachment; + if (dsResolveAttachment.format != gfx::Format::UNKNOWN) { + const auto &dsAccess = fgRenderPassInfo.dsResolveAccess; + dsResolveAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), dsAccess.prevAccess, dsAccess.nextAccess); } } - return std::make_tuple(forceAdjacent, score); -}; - -void evaluateAndTryMerge(const RAG &rag, const ResourceGraph &rescGraph, RelationGraph &relationGraph, const RelationGraph &relationGraphTc, const RelationVerts &lhsVerts, const RelationVerts &rhsVerts) { - assert(lhsVerts.size() >= 2); - assert(rhsVerts.size() >= 2); + fgRenderPassInfo.uniqueRasterViewCount = resSet.size(); +} - auto evaluate = [&rag, &rescGraph, &relationGraph](RelationVert vert, bool forward) { - auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, vert); - return evaluateHeaviness(rag, rescGraph, ragVert, forward); - }; +void endRenderPass(const Graphs &graphs, uint32_t passID, const RasterPass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - if (lhsVerts.size() == 2 || rhsVerts.size() == 2) { - /* - 1 ----------- 2 - \ __--/ - 3 --`` - no extra choice, only 1 - 3 - 2 - */ - const RelationVerts *shorterPath = lhsVerts.size() == 2 ? &lhsVerts : &rhsVerts; - remove_edge((*shorterPath)[0], (*shorterPath)[1], relationGraph); - } else { - // fist and last joint pass in this circuit don't get involved in reorder. - auto firstLhsNode = lhsVerts[1]; - auto lastLhsNode = lhsVerts[lhsVerts.size() - 2]; + auto vertID = resourceAccessGraph.passIndex.at(passID); + auto rlgVertID = relationGraph.vertexMap.at(vertID); - const auto &lhsBackwardStatus = evaluate(firstLhsNode, false); - bool lhsAdjacentToStart = std::get<0>(lhsBackwardStatus); - const auto &lhsForwardStatus = evaluate(lastLhsNode, true); - bool lhsAdjacentToEnd = std::get<0>(lhsForwardStatus); + auto &node = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, vertID); + auto &fgRenderpassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, vertID); - auto firstRhsNode = rhsVerts[1]; - auto lastRhsNode = rhsVerts[rhsVerts.size() - 2]; + bool filledDS{fgRenderpassInfo.dsAccess.nextAccess != gfx::AccessFlags::NONE}; + bool filledDSResolve{fgRenderpassInfo.dsResolveAccess.nextAccess != gfx::AccessFlags::NONE}; + if (filledDSResolve && !filledDS) { + CC_ASSERT(fgRenderpassInfo.rpInfo.depthStencilAttachment.format == gfx::Format::UNKNOWN); + std::swap(fgRenderpassInfo.rpInfo.depthStencilAttachment, fgRenderpassInfo.rpInfo.depthStencilResolveAttachment); + std::swap(fgRenderpassInfo.dsAccess, fgRenderpassInfo.dsResolveAccess); + } - const auto &rhsBackwardStatus = evaluate(firstRhsNode, true); - bool rhsAdjacentToStart = std::get<0>(rhsBackwardStatus); - const auto &rhsForwardStatus = evaluate(lastRhsNode, false); - bool rhsAdjacentToEnd = std::get<0>(rhsForwardStatus); + auto colorSize = fgRenderpassInfo.orderedViews.size(); + for (auto dsIter = fgRenderpassInfo.viewIndex.begin(); dsIter != fgRenderpassInfo.viewIndex.end(); ++dsIter) { + const auto &resName = dsIter->first; + const auto &parentName = dsIter->second.parentName; + if ((dsIter->second.attachmentIndex == gfx::INVALID_BINDING) && (resName == parentName)) { + fgRenderpassInfo.orderedViews.emplace_back(dsIter->first); + } + } - if (lhsAdjacentToStart || rhsAdjacentToEnd || lhsAdjacentToEnd || rhsAdjacentToStart) { - const RelationVerts *formerPath = &lhsVerts; - const RelationVerts *latterPath = &rhsVerts; - if (rhsAdjacentToStart || lhsAdjacentToEnd) { - swap(formerPath, latterPath); - } + if (!pass.subpassGraph.subpasses.empty()) { + // for (auto &subpassInfo : fgRenderpassInfo.rpInfo.subpasses) { + // if (subpassInfo.depthStencil != gfx::INVALID_BINDING) { + // if (subpassInfo.depthStencil != gfx::INVALID_BINDING) { + // subpassInfo.depthStencil = colorSize; + // } + // if (subpassInfo.depthStencilResolve != gfx::INVALID_BINDING) { + // subpassInfo.depthStencilResolve = colorSize + 1; + // } + // } + // } + getPreserves(fgRenderpassInfo.rpInfo); + } +} - remove_edge((*latterPath)[0], (*latterPath)[1], relationGraph); - remove_edge((*formerPath)[formerPath->size() - 2], (*formerPath)[formerPath->size() - 1], relationGraph); +void startRenderSubpass(const Graphs &graphs, uint32_t passID, const RasterSubpass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - tryAddEdge((*formerPath)[formerPath->size() - 2], (*latterPath)[1], relationGraph); - } + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - assert(lhsVerts.size() >= 3 && rhsVerts.size() >= 3); - constexpr int64_t score = std::numeric_limits::lowest(); - ccstd::vector> candidateSections; - std::queue lhsSection; - for (size_t i = 1; i < lhsVerts.size(); ++i) { - auto tryE = edge(lhsVerts[i], lhsVerts[i - 1], relationGraphTc); - auto tryRE = edge(lhsVerts[i - 1], lhsVerts[i], relationGraphTc); - // check if original reachable - if (!tryE.second && !tryRE.second) { - remove_edge(lhsVerts[i - 1], lhsVerts[i], relationGraph); - candidateSections.emplace_back(lhsSection); - std::queue clearQ; - lhsSection.swap(clearQ); + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + + auto parentID = parent(passID, renderGraph); + auto parentRagVertID = resourceAccessGraph.passIndex.at(parentID); + auto &fgRenderpassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, parentRagVertID); + AttachmentMap colorMap(resourceAccessGraph.get_allocator()); + + auto [hasDep, hasDS] = checkRasterViews(graphs, rlgVertID, accessNode, pass.rasterViews, colorMap); + hasDep |= checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); + hasDep |= checkResolveResource(graphs, rlgVertID, accessNode, pass.resolvePairs, colorMap); + fillRenderPassInfo(colorMap, fgRenderpassInfo, resourceGraph); + + auto &subpassInfo = fgRenderpassInfo.rpInfo.subpasses.emplace_back(); + auto &dependencies = fgRenderpassInfo.rpInfo.dependencies; + + // subpass info & subpass dependencies + for (const auto &pair : colorMap) { + const auto &sortKey = pair.first; + const std::string_view name = sortKey.name; + auto resID = vertex(sortKey.name, resourceGraph); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + const auto &[ignored, cIndex, isResolveView] = fgRenderpassInfo.viewIndex.at(name.data()); + if (isResolveView) { + auto resolveIter = std::find_if(pass.resolvePairs.begin(), pass.resolvePairs.end(), [&name](const ResolvePair &resolve) { + return strcmp(resolve.target.c_str(), name.data()) == 0; + }); + if (desc.format == gfx::Format::DEPTH_STENCIL) { + subpassInfo.depthStencilResolve = getDepthStencilSlot(fgRenderpassInfo.uniqueRasterViewCount, fgRenderpassInfo.resolveCount, hasDS) + 1; + if (resolveIter->mode != gfx::ResolveMode::NONE) { + subpassInfo.depthResolveMode = resolveIter->mode; + } + if (resolveIter->mode1 != gfx::ResolveMode::NONE) { + subpassInfo.stencilResolveMode = resolveIter->mode1; + } + } else { + if (subpassInfo.resolves.empty()) { + subpassInfo.resolves.resize(pass.rasterViews.size() - hasDS, gfx::INVALID_BINDING); + } + const auto &resolveSrc = resolveIter->source; + const auto &resourceSrcInfo = fgRenderpassInfo.viewIndex.at(resolveSrc); + subpassInfo.resolves[resourceSrcInfo.attachmentIndex] = cIndex; } - auto e = edge(lhsVerts[i], lhsVerts[i - 1], relationGraph); - // verts comes in order, so either real edge exist or logic edge is added. - CC_ASSERT(e.second); - - lhsSection.emplace(e.first); - } - if (candidateSections.empty()) { - // if this one is a tight edge(no logic edge, dependent from one to its next), - // keep this whole chain as a candidate. - remove_edge(lhsVerts[0], lhsVerts[1], relationGraph); - remove_edge(lhsVerts[lhsVerts.size() - 2], lhsVerts[lhsVerts.size() - 1], relationGraph); - candidateSections.emplace_back(std::move(lhsSection)); - } + } else { + if (desc.format == gfx::Format::DEPTH_STENCIL) { + auto dsSlot = getDepthStencilSlot(fgRenderpassInfo.uniqueRasterViewCount, fgRenderpassInfo.resolveCount, hasDS); + if (sortKey.accessType != AccessType::WRITE) { + subpassInfo.inputs.emplace_back(dsSlot); + } + if (sortKey.accessType != AccessType::READ) { + subpassInfo.depthStencil = dsSlot; + } + } else { + if (sortKey.accessType != AccessType::WRITE) { + subpassInfo.inputs.emplace_back(cIndex); + } + if (sortKey.accessType != AccessType::READ) { + subpassInfo.colors.emplace_back(cIndex); + } - std::queue rhsSection; - for (size_t i = 1; i < rhsVerts.size(); ++i) { - auto tryE = edge(rhsVerts[i], rhsVerts[i - 1], relationGraphTc); - auto tryRE = edge(rhsVerts[i - 1], rhsVerts[i], relationGraphTc); - if (!tryE.second && !tryRE.second) { - remove_edge(rhsVerts[i - 1], rhsVerts[i], relationGraph); - candidateSections.emplace_back(rhsSection); - std::queue clearQ; - rhsSection.swap(clearQ); + if (sortKey.accessType == AccessType::READ_WRITE) { + auto &selfDependency = dependencies.emplace_back(); + selfDependency.srcSubpass = pass.subpassID; + selfDependency.dstSubpass = pass.subpassID; + selfDependency.prevAccesses = pair.second.access.nextAccess; + selfDependency.nextAccesses = pair.second.access.nextAccess; + } } - auto e = edge(rhsVerts[i], rhsVerts[i - 1], relationGraph); - // verts comes in order, so either real edge exist or logic edge is added. - CC_ASSERT(e.second); - rhsSection.emplace(e.first); } - // lhs verts already put in. - if (candidateSections.size() == 1) { - remove_edge(rhsVerts[0], rhsVerts[1], relationGraph); - remove_edge(rhsVerts[rhsVerts.size() - 2], rhsVerts[rhsVerts.size() - 1], relationGraph); - candidateSections.emplace_back(std::move(rhsSection)); - } - - assert(candidateSections.size() >= 2); - - ScoreMap scMap; - auto tailVert = lhsVerts[0]; - while (!candidateSections.empty()) { - int64_t lightest = std::numeric_limits::max(); - uint32_t index = 0; - for (size_t i = 0; i < candidateSections.size(); ++i) { - auto e = candidateSections[i].front(); - auto srcVert = source(e, relationGraph); - auto dstVert = target(e, relationGraph); - int64_t srcBackwardScore = 0; - int64_t dstForwardScore = 0; - if (scMap.find(srcVert) == scMap.end()) { - auto res = evaluate(srcVert, false); - srcBackwardScore = std::get<1>(res); - res = evaluate(srcVert, true); - auto srcForwardScore = std::get<1>(res); - scMap.emplace(srcVert, std::pair(srcBackwardScore, srcForwardScore)); - } else { - srcBackwardScore = std::get<0>(scMap.at(srcVert)); - } - if (scMap.find(dstVert) == scMap.end()) { - auto res = evaluate(dstVert, false); - dstForwardScore = std::get<1>(res); - res = evaluate(dstVert, true); - auto dstBackwardScore = std::get<1>(res); - scMap.emplace(dstVert, std::pair(dstBackwardScore, dstForwardScore)); - } else { - dstForwardScore = std::get<1>(scMap.at(dstVert)); + if (hasDep) { + auto &dependency = dependencies.emplace_back(); + auto lastIter = ++resourceAccessGraph.resourceAccess[name.data()].rbegin(); + bool isBuffer = desc.dimension == ResourceDimension::BUFFER; + if (accessDependent(lastIter->second.accessFlag, accessNode.resourceStatus.at(name.data()).accessFlag, isBuffer) && lastIter->second.accessFlag != gfx::AccessFlagBit::NONE) { + auto lastVert = lastIter->first; + auto lastPassID = get(ResourceAccessGraph::PassIDTag{}, resourceAccessGraph, lastVert); + auto lastPassIndex = INVALID_ID; + if (holds(lastPassID, renderGraph) && (parent(lastPassID, renderGraph) == parentID)) { + const auto *lastPass = get_if(lastPassID, &renderGraph); + lastPassIndex = lastPass->subpassID; } - // we are in a simple path, so all the "input(this path)" resource of this path come from the first vertex, - // all the "output(this path)" come to the last vertex, other resources are "internally(this path)" produced and destroyed. - // so only input of first vertex and output of last vertex are taken into account. - // [simple path]: path without diverged edges. - auto score = dstForwardScore - srcBackwardScore; - if (lightest > score) { - lightest = score; - index = i; - } - } - auto e = candidateSections[index].front(); - candidateSections[index].pop(); - if (candidateSections[index].empty()) { - auto iter = candidateSections.begin(); - std::advance(iter, index); - candidateSections.erase(iter); + auto &dependency = dependencies.emplace_back(); + dependency.srcSubpass = lastPassIndex; + dependency.dstSubpass = pass.subpassID; + dependency.prevAccesses = lastIter->second.accessFlag; + dependency.nextAccesses = pair.second.access.nextAccess; } - auto srcVert = source(e, relationGraph); - auto dstVert = target(e, relationGraph); - tryAddEdge(tailVert, srcVert, relationGraph); - tailVert = dstVert; } - - tryAddEdge(tailVert, lhsVerts.back(), relationGraph); } } -// return : can be further reduced? -bool reduce(const RAG &rag, const ResourceGraph &rescGraph, RelationGraph &relationGraph, RelationGraph &relationGraphTc, const CloseCircuit &circuit) { - auto checkPath = [&relationGraph](std::stack &vertices, RelationGraph::vertex_descriptor endVert, RelationVerts &stackTrace) { - bool simpleGraph = true; - while (!vertices.empty()) { - auto vert = vertices.top(); - vertices.pop(); - stackTrace.emplace_back(vert); +void startComputeSubpass(const Graphs &graphs, uint32_t passID, const ComputeSubpass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - if (endVert == vert) { - break; - } + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - if (out_degree(vert, relationGraph) > 1) { - simpleGraph = false; - break; - } - auto r = out_edges(vert, relationGraph); - for (auto rIter = r.first; rIter != r.second; ++rIter) { - auto dstID = target(*rIter, relationGraph); - vertices.push(dstID); - } - if (r.first == r.second) { - stackTrace.pop_back(); - } - } - return simpleGraph; - }; + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + AttachmentMap colorMap(resourceAccessGraph.get_allocator()); - // check if there is a sub branch on lhs - auto lhsEdges = circuit.first; - auto startVert = target(lhsEdges.first, relationGraph); - auto endVert = source(lhsEdges.second, relationGraph); - - std::stack vertices; - vertices.emplace(startVert); + auto parentID = parent(passID, renderGraph); + auto parentRagVertID = resourceAccessGraph.passIndex.at(parentID); + auto &fgRenderpassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, resourceAccessGraph, parentRagVertID); - RelationVerts lhsVisited; - auto branchStartVert = source(lhsEdges.first, relationGraph); - auto branchEndVert = target(lhsEdges.second, relationGraph); - lhsVisited.push_back(branchStartVert); - // check if there is a branch on lhs path - if (!checkPath(vertices, endVert, lhsVisited)) { - return false; - } - lhsVisited.push_back(branchEndVert); - // if it's a simple graph, lhs path must can be dfs to the end at the first time. - assert(vertices.empty()); + std::ignore = checkRasterViews(graphs, rlgVertID, accessNode, pass.rasterViews, colorMap); + std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); - auto rhsEdges = circuit.second; - startVert = target(rhsEdges.first, relationGraph); - endVert = source(rhsEdges.second, relationGraph); - vertices.emplace(startVert); + fillRenderPassInfo(colorMap, fgRenderpassInfo, resourceGraph); +} - RelationVerts rhsVisited; - rhsVisited.push_back(branchStartVert); - if (!checkPath(vertices, endVert, rhsVisited)) { - return false; - } - rhsVisited.push_back(branchEndVert); +void startComputePass(const Graphs &graphs, uint32_t passID, const ComputePass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - // merge this circuit - // from - /* 2 - 3 - 4 - / \ - 1 8 - \ / - 5 - 6 - 7 + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - to - 1 - A - B - 8 or 1 - B - A -8 depends on algorithm + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); +} - ${A} : 2 - 3 - 4 - ${B} : 5 - 6 - 7 - */ +void startCopyPass(const Graphs &graphs, uint32_t passID, const CopyPass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - evaluateAndTryMerge(rag, rescGraph, relationGraph, relationGraphTc, lhsVisited, rhsVisited); + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); - return true; -} + auto &resg = resourceGraph; + auto &rag = resourceAccessGraph; + auto &rlg = relationGraph; + auto checkCopy = [&](const ccstd::pmr::string &resName, + uint32_t firstSlice, + uint32_t firstMip, + uint32_t firstPlane, + uint32_t sliceCount, + uint32_t mipCount, + bool read) { + auto srcID = vertex(resName, resg); + auto srcRange = getResourceRange(srcID, resg); + srcRange.firstSlice = firstSlice; + srcRange.mipLevel = firstMip; + srcRange.basePlane = firstPlane; + srcRange.numSlices = sliceCount; + srcRange.levelCount = mipCount; + + AccessType access = read ? AccessType::READ : AccessType::WRITE; + gfx::AccessFlags accessFlag = read ? gfx::AccessFlags::TRANSFER_READ : gfx::AccessFlags::TRANSFER_WRITE; + ViewStatus srcViewStatus{resName, access, gfx::ShaderStageFlagBit::NONE, accessFlag, srcRange}; + addAccessStatus(rag, resg, accessNode, srcViewStatus); + const auto &[lastVertSrc, ignore1] = dependencyCheck(rag, vertID, resg, srcViewStatus); + tryAddEdge(lastVertSrc, vertID, rag); + tryAddEdge(lastVertSrc, rlgVertID, rlg); + }; -template -void applyRelation(RelationGraph &relationGraph, const TargetGraph &targetGraph) { - CC_EXPECTS(relationGraph.vertices.size() == targetGraph.vertices.size()); + for (const auto © : pass.copyPairs) { + checkCopy(copy.source, + copy.sourceFirstSlice, copy.sourceMostDetailedMip, copy.sourcePlaneSlice, + copy.numSlices, copy.mipLevels, true); - // remove all edges - for (auto vert : targetGraph.vertices) { - clear_in_edges(vert, targetGraph); - clear_out_edges(vert, targetGraph); + checkCopy(copy.target, + copy.targetFirstSlice, copy.targetMostDetailedMip, copy.targetPlaneSlice, + copy.numSlices, copy.mipLevels, false); } - for (auto vert : relationGraph.vertices) { - auto inEdges = in_edges(vert, relationGraph); - for (auto e : makeRange(inEdges)) { - auto srcVert = source(e, relationGraph); - // auto checkEdge = edge(srcVert, vert, targetGraph); - add_edge(srcVert, vert, targetGraph); - } + for (const auto &upload : pass.uploadPairs) { + checkCopy(upload.target, + upload.targetFirstSlice, upload.targetMostDetailedMip, upload.targetPlaneSlice, + upload.numSlices, upload.mipLevels, false); } } -void passReorder(FrameGraphDispatcher &fgDispatcher) { - auto *scratch = fgDispatcher.scratch; - const auto &renderGraph = fgDispatcher.graph; - const auto &layoutGraph = fgDispatcher.layoutGraph; - auto &resourceGraph = fgDispatcher.resourceGraph; - auto &relationGraph = fgDispatcher.relationGraph; - auto &rag = fgDispatcher.resourceAccessGraph; +void startRaytracePass(const Graphs &graphs, uint32_t passID, const RaytracePass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - if (!fgDispatcher._accessGraphBuilt) { - const Graphs graphs{renderGraph, resourceGraph, layoutGraph, rag, relationGraph}; - buildAccessGraph(graphs); - fgDispatcher._accessGraphBuilt = true; - } + auto vertID = add_vertex(resourceAccessGraph, passID); + auto rlgVertID = add_vertex(relationGraph, vertID); + CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - { - // determine do mem saving how many times - RelationGraph relationGraphTc(fgDispatcher.get_allocator()); - boost::transitive_closure(relationGraph, relationGraphTc); + auto &accessNode = get(ResourceAccessGraph::PassNodeTag{}, resourceAccessGraph, rlgVertID); + std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); +} - CloseCircuits circuits; - std::vector crossEdges; - PassVisitor visitor(relationGraphTc, circuits); - auto colors = relationGraph.colors(scratch); - boost::depth_first_search(relationGraph, visitor, get(colors, relationGraph)); +namespace { +struct SliceNode { + bool full{false}; + ccstd::pmr::vector mips; +}; - float percent = 0.0F; - uint32_t count = 0; - auto total = circuits.size(); +struct TextureNode { + bool full{false}; + ccstd::pmr::vector slices; +}; - float memsavePercent = 1.0F - fgDispatcher._paralellExecWeight; - for (auto iter = circuits.begin(); (iter != circuits.end()) && (percent < memsavePercent);) { - bool reduced = reduce(rag, resourceGraph, relationGraph, relationGraphTc, (*iter)); - if (reduced) { - ++count; - iter = circuits.erase(iter); - percent = count / static_cast(total); - } else { - ++iter; +struct ResourceNode { + ccstd::pmr::vector planes; +}; +} // namespace + +bool rangeCheck(ccstd::pmr::map &status, + const ResourceDesc &desc, + const PmrString &targetName, + uint32_t firstSlice, uint32_t numSlices, + uint32_t firstMip, uint32_t mipLevels, + uint32_t planeIndex) { + if (status.find(targetName) == status.end()) { + status.emplace(targetName, ResourceNode{}); + } + + if (planeIndex >= status[targetName].planes.size()) { + status[targetName].planes.resize(planeIndex + 1); + status[targetName].planes[planeIndex].slices.resize(desc.depthOrArraySize); + for (auto &slice : status[targetName].planes[planeIndex].slices) { + slice.mips.resize(desc.mipLevels, std::numeric_limits::max()); + } + } + + // no spare space in target + bool check = !status[targetName].planes[planeIndex].full; + for (auto slice = firstSlice; slice < firstSlice + numSlices; ++slice) { + auto &slices = status[targetName].planes[planeIndex].slices; + // no spare space in this slice + check &= !slices[slice].full; + for (auto mip = firstMip; mip < firstMip + mipLevels; ++mip) { + auto &mips = slices[slice].mips; + // this mip has been taken + check &= mips[mip] == std::numeric_limits::max(); + mips[mip] = mip; + auto maxIter = std::max_element(mips.begin(), mips.end()); + if ((*maxIter) != std::numeric_limits::max()) { + // linear increasing + check &= (*maxIter) == mips.size() - 1; + slices[slice].full = true; } } + if (std::all_of(slices.begin(), slices.end(), [](const SliceNode &sliceNode) { return sliceNode.full; })) { + status[targetName].planes[planeIndex].full = true; + } + } + return check; +} - // topological sort - rag.topologicalOrder.clear(); - bool empty = relationGraph._vertices.empty(); - ScoreMap scoreMap; - RelationVerts candidates; - candidates.push_back(EXPECT_START_ID); - - std::vector candidateBuffer; - uint32_t coloredVerts = 0; - while (coloredVerts < relationGraph._vertices.size()) { - // decreasing order, pop back from vector, push into queue, then it's ascending order. - std::sort(candidates.begin(), candidates.end(), [&](RelationVert lhsVert, RelationVert rhsVert) { - int64_t lhsForwardScore{0}; - int64_t rhsForwardScore{0}; - int64_t lhsBackwardScore{0}; - int64_t rhsBackwardScore{0}; - if (scoreMap.find(lhsVert) == scoreMap.end()) { - auto lhsRagVert = get(RelationGraph::DescIDTag{}, relationGraph, lhsVert); - const auto &lhsForwardStatus = evaluateHeaviness(rag, resourceGraph, lhsRagVert, true); - lhsForwardScore = get<1>(lhsForwardStatus); - const auto &lhsBackwardStatus = evaluateHeaviness(rag, resourceGraph, lhsRagVert, false); - lhsBackwardScore = get<1>(lhsBackwardStatus); - scoreMap.emplace(lhsVert, std::pair{lhsBackwardScore, lhsForwardScore}); - } else { - lhsBackwardScore = scoreMap[lhsVert].first; - lhsForwardScore = scoreMap[lhsVert].second; +bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const ResourceGraph& resourceGraph) { + bool check = true; + // ccstd::pmr::map sourceCheck; + ccstd::pmr::map targetCheck; + for (const auto &movePair : pass.movePairs) { + const auto &fromResName = movePair.source; + const auto fromResID = resourceGraph.valueIndex.at(fromResName); + const auto &fromResDesc = get(ResourceGraph::DescTag{}, resourceGraph, fromResID); + + const auto &toResName = movePair.target; + const auto toResID = resourceGraph.valueIndex.at(toResName); + const auto &toResDesc = get(ResourceGraph::DescTag{}, resourceGraph, toResID); + + const auto &fromResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, fromResID); + const auto &toResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, toResID); + auto commonUsage = fromResDesc.flags | toResDesc.flags; + + // bool sourceRangeValid = rangeCheck(targetCheck, toResDesc, fromResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); + bool targetRangeValid = rangeCheck(targetCheck, toResDesc, toResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); + + uint32_t validConditions[] = { + !fromResTraits.hasSideEffects(), + rag.movedSourceStatus.find(toResName) == rag.movedSourceStatus.end(), + rag.movedSourceStatus.find(fromResName) == rag.movedSourceStatus.end(), + targetRangeValid, + fromResTraits.residency != ResourceResidency::MEMORYLESS && toResTraits.residency != ResourceResidency::MEMORYLESS, + fromResDesc.dimension == toResDesc.dimension, + fromResDesc.width == toResDesc.width, + fromResDesc.height == toResDesc.height, + fromResDesc.format == toResDesc.format, + fromResDesc.sampleCount == toResDesc.sampleCount, + (fromResDesc.depthOrArraySize == toResDesc.depthOrArraySize) || (toResDesc.dimension != ResourceDimension::BUFFER), // full move if resource is buffer + }; + bool val = std::min_element(std::begin(validConditions), std::end(validConditions)); + check &= val; + } + + // full destination + check &= std::all_of(targetCheck.begin(), targetCheck.end(), [](const auto &pair) { + const ResourceNode &resNode = pair.second; + return std::all_of(resNode.planes.begin(), resNode.planes.end(), [](const auto &textureNode) { + return textureNode.full; + }); + }); + + return check; + } + +void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass) { + const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; + + if(moveValidation(pass, resourceAccessGraph, resourceGraph)) { + for(const auto& pair : pass.movePairs) { + auto srcResourceRange = getResourceRange(vertex(pair.source, resourceGraph), resourceGraph); + srcResourceRange.firstSlice = pair.targetFirstSlice; + srcResourceRange.mipLevel = pair.targetMostDetailedMip; + srcResourceRange.basePlane = pair.targetPlaneSlice; + + auto lastStatusIter = resourceAccessGraph.resourceAccess.at(pair.source).rbegin(); + resourceAccessGraph.movedSourceStatus.emplace(pair.source, AccessStatus{lastStatusIter->second.accessFlag, srcResourceRange}); + resourceAccessGraph.movedTarget[pair.target].emplace_back(pair.source); + resourceAccessGraph.resourceAccess[pair.target] = resourceAccessGraph.resourceAccess[pair.source]; + + auto targetResID = findVertex(pair.target, resourceGraph); + resourceAccessGraph.resourceIndex[pair.target] = targetResID; + + auto &rag = resourceAccessGraph; + std::function feedBack = [&](const ccstd::pmr::string &source, ResourceGraph::vertex_descriptor v) { + rag.resourceIndex[source] = v; + if (rag.movedTarget.find(source) != rag.movedTarget.end()) { + for (const auto &prt : rag.movedTarget[source]) { + feedBack(prt, v); + } } + }; + feedBack(pair.source, targetResID); + } + } else { + for(const auto& pair : pass.movePairs) { + CopyPass copyPass(resourceAccessGraph.get_allocator()); + copyPass.copyPairs.emplace_back(CopyPair( + pair.source, + pair.target, + pair.mipLevels, pair.numSlices, + 0, 0, 0, + pair.targetMostDetailedMip, pair.targetFirstSlice, pair.targetPlaneSlice)); + startCopyPass(graphs, passID, copyPass); + } + } +} - if (scoreMap.find(rhsVert) == scoreMap.end()) { - auto rhsRagVert = get(RelationGraph::DescIDTag{}, relationGraph, rhsVert); - const auto &rhsForwardStatus = evaluateHeaviness(rag, resourceGraph, rhsRagVert, true); - rhsForwardScore = get<1>(rhsForwardStatus); - const auto &rhsBackwardStatus = evaluateHeaviness(rag, resourceGraph, rhsRagVert, false); - rhsBackwardScore = get<1>(rhsBackwardStatus); - scoreMap.emplace(rhsVert, std::pair{rhsBackwardScore, rhsForwardScore}); - } else { - rhsBackwardScore = scoreMap[rhsVert].first; - rhsForwardScore = scoreMap[rhsVert].second; - } - return lhsBackwardScore - lhsForwardScore > rhsBackwardScore - rhsForwardScore; +struct DependencyVisitor : boost::dfs_visitor<> { + void discover_vertex(RenderGraph::vertex_descriptor passID, + const AddressableView &gv) const { + visitObject( + passID, gv.mGraph, + [&](const RasterPass &pass) { + startRenderPass(graphs, passID, pass); + }, + [&](const RasterSubpass &pass) { + startRenderSubpass(graphs, passID, pass); + }, + [&](const ComputeSubpass &pass) { + startComputeSubpass(graphs, passID, pass); + }, + [&](const ComputePass &pass) { + startComputePass(graphs, passID, pass); + }, + [&](const CopyPass &pass) { + startCopyPass(graphs, passID, pass); + }, + [&](const MovePass &pass) { + startMovePass(graphs, passID, pass); + }, + [&](const RaytracePass &pass) { + startRaytracePass(graphs, passID, pass); + }, + [&](const auto & /*pass*/) { + // do nothing }); + } - const auto vert = candidates.back(); - candidates.pop_back(); + void finish_vertex(RenderGraph::vertex_descriptor passID, + const AddressableView &gv) const { + visitObject( + passID, gv.mGraph, + [&](const RasterPass &pass) { + endRenderPass(graphs, passID, pass); + }, + [&](const auto & /*pass*/) { + // do nothing + }); + } - auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, vert); - rag.topologicalOrder.emplace_back(ragVert); - if (!candidateBuffer.empty()) { - candidates.insert(candidates.end(), candidateBuffer.begin(), candidateBuffer.end()); - candidateBuffer.clear(); - } + const Graphs &graphs; +}; - for (const auto nextGeneration : makeRange(out_edges(vert, relationGraph))) { - auto targetID = target(nextGeneration, relationGraph); - if (in_degree(targetID, relationGraph) == 1) { - candidateBuffer.emplace_back(targetID); - } - } +// status of resource access +void buildAccessGraph(const Graphs &graphs) { + // what we need: + // - pass dependency + // - pass attachment access + // AccessTable accessRecord; - auto deprecatedEdges = out_edges(vert, relationGraph); - for (auto iter = deprecatedEdges.first; iter < deprecatedEdges.second;) { - remove_edge(*iter, relationGraph); - deprecatedEdges = out_edges(vert, relationGraph); - iter = deprecatedEdges.first; - } + const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; + size_t numPasses = 0; + numPasses += renderGraph.rasterPasses.size(); + numPasses += renderGraph.computePasses.size(); + numPasses += renderGraph.copyPasses.size(); + numPasses += renderGraph.movePasses.size(); + numPasses += renderGraph.raytracePasses.size(); - if (candidates.empty()) { - candidates.insert(candidates.end(), candidateBuffer.begin(), candidateBuffer.end()); - candidateBuffer.clear(); - } + resourceAccessGraph.reserve(static_cast(numPasses)); + resourceAccessGraph.resourceNames.reserve(128); + resourceAccessGraph.resourceIndex.reserve(128); - coloredVerts++; - } + resourceAccessGraph.topologicalOrder.reserve(numPasses); + resourceAccessGraph.topologicalOrder.clear(); + resourceAccessGraph.resourceLifeRecord.reserve(resourceGraph.names.size()); - // remove all edges - for (auto vert : makeRange(vertices(rag))) { - clear_in_edges(vert, rag); - clear_out_edges(vert, rag); - } + if (!resourceAccessGraph.resourceLifeRecord.empty()) { + resourceAccessGraph.resourceLifeRecord.clear(); + } - // apply relation - for (auto rlgVert : makeRange(vertices(relationGraph))) { - auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, rlgVert); - auto inEdges = in_edges(rlgVert, relationGraph); - for (auto e : makeRange(inEdges)) { - auto srcRlgVert = source(e, relationGraph); - auto srcRagVert = get(RelationGraph::DescIDTag{}, relationGraph, srcRlgVert); - add_edge(srcRagVert, ragVert, rag); - } - } + if (!resourceAccessGraph.leafPasses.empty()) { + resourceAccessGraph.leafPasses.clear(); + } + if (!resourceAccessGraph.culledPasses.empty()) { + resourceAccessGraph.culledPasses.clear(); } -} -#pragma endregion PASS_REORDER + // const auto &names = get(RenderGraph::Name, renderGraph); + for (size_t i = 1; i <= numPasses; ++i) { + resourceAccessGraph.leafPasses.emplace(i, LeafStatus{false, true}); + } -void memoryAliasing(FrameGraphDispatcher &fgDispatcher) { -} + auto startID = add_vertex(resourceAccessGraph, INVALID_ID - 1); + CC_EXPECTS(startID == EXPECT_START_ID); -#pragma region assisstantFuncDefinition -template -bool tryAddEdge(uint32_t srcVertex, uint32_t dstVertex, Graph &graph) { - auto e = edge(srcVertex, dstVertex, graph); - if (!e.second) { - auto res = add_edge(srcVertex, dstVertex, graph); - CC_ENSURES(res.second); - return true; - } - return false; -} - -bool isTransitionStatusDependent(const AccessStatus &lhs, const AccessStatus &rhs) { - return !(isReadOnlyAccess(lhs.accessFlag) && isReadOnlyAccess(rhs.accessFlag)); -} - -auto mapTextureFlags(ResourceFlags flags) { - gfx::TextureUsage usage = gfx::TextureUsage::NONE; - if ((flags & ResourceFlags::SAMPLED) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::SAMPLED; - } - if ((flags & ResourceFlags::STORAGE) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::STORAGE; - } - if ((flags & ResourceFlags::SHADING_RATE) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::SHADING_RATE; - } - if ((flags & ResourceFlags::COLOR_ATTACHMENT) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::COLOR_ATTACHMENT; - } - if ((flags & ResourceFlags::DEPTH_STENCIL_ATTACHMENT) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT; - } - if ((flags & ResourceFlags::INPUT_ATTACHMENT) != ResourceFlags::NONE) { - usage |= gfx::TextureUsage::INPUT_ATTACHMENT; - } - return usage; -} + add_vertex(relationGraph, startID); -auto getResourceStatus(PassType passType, const PmrString &name, gfx::MemoryAccess memAccess, gfx::ShaderStageFlags visibility, const ResourceGraph &resourceGraph, bool rasterized) { - ResourceUsage usage; - gfx::ShaderStageFlags vis{gfx::ShaderStageFlags::NONE}; - vis |= visibility; - gfx::AccessFlags accesFlag; - auto vertex = resourceGraph.valueIndex.at(name); - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, vertex); - if (desc.dimension == ResourceDimension::BUFFER) { - gfx::BufferUsage bufferUsage{gfx::BufferUsage::NONE}; - // copy is not included in this logic because copy can be set TRANSFER_xxx directly. - if (gfx::hasFlag(memAccess, gfx::MemoryAccessBit::WRITE_ONLY)) { - bufferUsage = gfx::BufferUsage::STORAGE; + DependencyVisitor visitor{{}, graphs}; + auto colors = renderGraph.colors(renderGraph.resource()); + AddressableView gv{renderGraph}; + for (const auto passID : renderGraph.sortedVertices) { + if (!holds(passID, renderGraph) && !holds(passID, renderGraph)) { + boost::depth_first_visit(gv, passID, visitor, get(colors, renderGraph)); } + } - if (gfx::hasFlag(memAccess, gfx::MemoryAccessBit::READ_ONLY)) { - bool uniformFlag = (desc.flags & ResourceFlags::UNIFORM) != ResourceFlags::NONE; - bool storageFlag = (desc.flags & ResourceFlags::STORAGE) != ResourceFlags::NONE; - - // CC_EXPECTS(uniformFlag ^ storageFlag); - // uniform or read-only storage buffer - bufferUsage = uniformFlag ? gfx::BufferUsage::UNIFORM : gfx::BufferUsage::STORAGE; - } + auto &rag = resourceAccessGraph; + auto branchCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) -> void { + CC_EXPECTS(out_degree(vertex, rag) == 0); + using FuncType = void (*)(ResourceAccessGraph::vertex_descriptor, ResourceAccessGraph &); + static FuncType leafCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) { + rag.culledPasses.emplace(vertex); + auto &attachments = get(ResourceAccessGraph::PassNodeTag{}, rag, vertex); + attachments.resourceStatus.clear(); + auto inEdges = in_edges(vertex, rag); + for (auto iter = inEdges.first; iter < inEdges.second;) { + auto inEdge = *iter; + auto srcVert = source(inEdge, rag); + remove_edge(inEdge, rag); + if (out_degree(srcVert, rag) == 0) { + leafCulling(srcVert, rag); + } + inEdges = in_edges(vertex, rag); + iter = inEdges.first; + } + }; + leafCulling(vertex, rag); + }; - if (passType == PassType::COMPUTE) { - vis |= gfx::ShaderStageFlagBit::COMPUTE; + // no present pass found, add a fake node to gather leaf node(s). + if (resourceAccessGraph.presentPassID == 0xFFFFFFFF) { + auto ragEndNode = add_vertex(rag, RenderGraph::null_vertex()); + auto rlgEndNode = add_vertex(relationGraph, ragEndNode); + // keep sync before pass reorder done. + CC_EXPECTS(ragEndNode == rlgEndNode); + resourceAccessGraph.presentPassID = ragEndNode; + auto iter = resourceAccessGraph.leafPasses.find(ragEndNode); + constexpr bool isExternal = true; + constexpr bool needCulling = false; + if (iter == resourceAccessGraph.leafPasses.end()) { + resourceAccessGraph.leafPasses.emplace(ragEndNode, LeafStatus{isExternal, needCulling}); + } else { + resourceAccessGraph.leafPasses.at(ragEndNode) = LeafStatus{isExternal, needCulling}; } + } - // those buffers not found in descriptorlayout but appear here, - // can and only can be VERTEX/INDEX/INDIRECT BUFFER, - // only copy pass is allowed. - if (vis == gfx::ShaderStageFlags::NONE) { - CC_EXPECTS(passType == PassType::COPY); - } - usage = bufferUsage; - accesFlag = gfx::getAccessFlags(bufferUsage, gfx::MemoryUsage::DEVICE, memAccess, vis); - } else { - // can't find this resource in layoutdata, not in descriptor so either input or output attachment. - gfx::TextureUsage texUsage = gfx::TextureUsage::NONE; + // make leaf node closed walk for pass reorder + for (auto pass : resourceAccessGraph.leafPasses) { + bool isExternal = pass.second.isExternal; + bool needCulling = pass.second.needCulling; - // TODO(Zeqiang): visbility of slot name "_" not found - if (hasFlag(memAccess, gfx::MemoryAccess::READ_ONLY)) { - if ((desc.flags & ResourceFlags::INPUT_ATTACHMENT) != ResourceFlags::NONE && rasterized) { - texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::COLOR_ATTACHMENT | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT | gfx::TextureUsage::INPUT_ATTACHMENT)); + if (pass.first != resourceAccessGraph.presentPassID) { + if (isExternal && !needCulling) { + add_edge(pass.first, resourceAccessGraph.presentPassID, resourceAccessGraph); } else { - texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::SAMPLED | gfx::TextureUsage::STORAGE | gfx::TextureUsage::SHADING_RATE | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT)); + // write into transient resources, culled + if constexpr (ENABLE_BRANCH_CULLING) { + branchCulling(pass.first, resourceAccessGraph); + } } } - - if (hasFlag(memAccess, gfx::MemoryAccess::WRITE_ONLY)) { - texUsage |= (mapTextureFlags(desc.flags) & (gfx::TextureUsage::COLOR_ATTACHMENT | gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT | gfx::TextureUsage::STORAGE)); - } - - if (vis == gfx::ShaderStageFlags::NONE) { - vis = passType == gfx::PassType::RASTER ? gfx::ShaderStageFlags::FRAGMENT : gfx::ShaderStageFlags::COMPUTE; - } - - usage = texUsage; - accesFlag = gfx::getAccessFlags(texUsage, memAccess, vis); } - - return std::make_tuple(vis, usage, accesFlag); -} - -void addCopyAccessStatus(RAG &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status, const Range &range) { - const auto &[name, passType, visibility, access, accessFlag, usage] = status; - CC_EXPECTS(hasAnyFlags(accessFlag, gfx::AccessFlags::TRANSFER_READ | gfx::AccessFlags::TRANSFER_WRITE)); - - uint32_t rescID = rg.valueIndex.at(name); - - CC_EXPECTS(rg.valueIndex.find(name) != rg.valueIndex.end()); - if (std::find(rag.resourceNames.begin(), rag.resourceNames.end(), name) == rag.resourceNames.end()) { - rag.resourceIndex.emplace(name, rescID); - rag.resourceNames.emplace_back(name); + for (auto rit = resourceAccessGraph.culledPasses.rbegin(); rit != resourceAccessGraph.culledPasses.rend(); ++rit) { + // remove culled vertices, std::less make this set ascending order, so reverse iterate + remove_vertex(*rit, relationGraph); } - node.attachmentStatus.emplace_back(AccessStatus{ - rescID, - visibility, - access, - passType, - accessFlag, - usage, - range, - }); + for (auto rlgVert : makeRange(vertices(relationGraph))) { + auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, rlgVert); + rag.topologicalOrder.emplace_back(ragVert); + } } -PmrString addAccessStatus(RAG &rag, const ResourceGraph &rg, ResourceAccessNode &node, const ViewStatus &status) { - const auto &[name, passType, visibility, access, accessFlag, usage] = status; - uint32_t rescID = rg.valueIndex.at(name); - const auto &resourceDesc = get(ResourceGraph::DescTag{}, rg, rescID); - const auto &traits = get(ResourceGraph::TraitsTag{}, rg, rescID); - // const PmrString *resName = &name; - - Range range; - if (resourceDesc.dimension == ResourceDimension::BUFFER) { - range = BufferRange{0, resourceDesc.width}; - } else { - range = TextureRange{0, 1, 0, resourceDesc.mipLevels}; - } +#pragma region BUILD_BARRIERS +void buildBarriers(FrameGraphDispatcher &fgDispatcher) { + auto *scratch = fgDispatcher.scratch; + const auto &renderGraph = fgDispatcher.renderGraph; + const auto &layoutGraph = fgDispatcher.layoutGraph; + auto &resourceGraph = fgDispatcher.resourceGraph; + auto &relationGraph = fgDispatcher.relationGraph; + auto &rag = fgDispatcher.resourceAccessGraph; - CC_EXPECTS(rg.valueIndex.find(name) != rg.valueIndex.end()); - if (std::find(rag.resourceNames.begin(), rag.resourceNames.end(), name) == rag.resourceNames.end()) { - rag.resourceIndex.emplace(name, rescID); - rag.resourceNames.emplace_back(name); + // record resource current in-access and out-access for every single node + if (!fgDispatcher._accessGraphBuilt) { + const Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; + buildAccessGraph(graphs); + fgDispatcher._accessGraphBuilt = true; } - node.attachmentStatus.emplace_back(AccessStatus{ - rescID, - visibility, - access, - passType, - accessFlag, - usage, - range, - }); - return name; -} - -AccessVertex dependencyCheck(RAG &rag, AccessVertex curVertID, const ResourceGraph &rg, const ViewStatus &viewStatus) { - const auto &[name, passType, visibility, access, accessFlag, usage] = viewStatus; - auto &accessRecord = rag.accessRecord; - - bool readOnly = isReadOnlyAccess(accessFlag); + auto getGFXBarrier = [&resourceGraph](const Barrier &barrier) { + gfx::GFXObject *gfxBarrier{nullptr}; + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, barrier.resourceID); + if (desc.dimension == ResourceDimension::BUFFER) { + gfx::BufferBarrierInfo info; + info.prevAccesses = barrier.beginStatus.accessFlag; + info.nextAccesses = barrier.endStatus.accessFlag; + const auto &range = barrier.endStatus.range; + info.offset = 0; + info.size = range.depthOrArraySize; + info.type = barrier.type; + gfxBarrier = gfx::Device::getInstance()->getBufferBarrier(info); + } else { + gfx::TextureBarrierInfo info; + info.prevAccesses = barrier.beginStatus.accessFlag; + info.nextAccesses = barrier.endStatus.accessFlag; + const auto &range = barrier.beginStatus.range; + info.baseMipLevel = range.mipLevel; + info.levelCount = range.levelCount; + info.baseSlice = range.firstSlice; + info.sliceCount = range.numSlices; + info.type = barrier.type; + gfxBarrier = gfx::Device::getInstance()->getTextureBarrier(info); + } + return gfxBarrier; + }; - AccessVertex lastVertID = INVALID_ID; - CC_EXPECTS(rag.resourceIndex.find(name) != rag.resourceIndex.end()); - auto resourceID = rag.resourceIndex[name]; - bool isExternalPass = get(get(ResourceGraph::TraitsTag{}, rg), resourceID).hasSideEffects(); - auto iter = accessRecord.find(resourceID); - if (iter == accessRecord.end()) { - accessRecord.emplace( - resourceID, - ResourceTransition{ - {}, - {curVertID, visibility, access, passType, accessFlag, usage, Range{}}}); - if (isExternalPass) { - rag.leafPasses[curVertID] = LeafStatus{true, access == gfx::MemoryAccessBit::READ_ONLY}; + // found pass id in this map ? barriers you should commit when run into this pass + // : or no extra barrier needed. + for (auto &accessPair : rag.resourceAccess) { + const auto &resName = accessPair.first; + if (rag.movedSourceStatus.find(resName) != rag.movedSourceStatus.end()) { + // moved, history of this resource access will be copied to moved target. + continue; } - } else { - ResourceTransition &trans = iter->second; - auto &currAccessStatus = trans.currStatus; - auto lastReadOnly = isReadOnlyAccess(currAccessStatus.accessFlag) && (currAccessStatus.access == gfx::MemoryAccessBit::READ_ONLY); - if (readOnly && lastReadOnly) { - if (isExternalPass) { - // only external res will be manually record here, leaf pass with transient resource will be culled by default, - // those leaf passes with ALL read access on external(or with transients) res can be culled. - rag.leafPasses[curVertID].needCulling &= (access == gfx::MemoryAccessBit::READ_ONLY); - - // current READ, no WRITE before in this frame, it's expected to be external. - bool dirtyExternalRes = trans.lastStatus.vertID == INVALID_ID; - if (!dirtyExternalRes) { - tryAddEdge(EXPECT_START_ID, curVertID, rag); - if (rag.leafPasses.find(EXPECT_START_ID) != rag.leafPasses.end()) { - rag.leafPasses.erase(EXPECT_START_ID); - } - } - } else { - tryAddEdge(trans.lastStatus.vertID, curVertID, rag); - if (rag.leafPasses.find(trans.lastStatus.vertID) != rag.leafPasses.end()) { - rag.leafPasses.erase(trans.lastStatus.vertID); + + const auto &resID = findVertex(resName, resourceGraph); + const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + bool isBuffer = desc.dimension == ResourceDimension::BUFFER; + + const auto &accessRecord = accessPair.second; + auto iter = accessRecord.begin(); + auto nextIter = iter; + std::advance(nextIter, 1); + for (; nextIter != accessRecord.end(); ++iter, ++nextIter) { + auto srcRagVertID = iter->first; + auto dstRagVertID = nextIter->first; + auto srcPassID = get(ResourceAccessGraph::PassIDTag{}, rag, srcRagVertID); + auto dstPassID = get(ResourceAccessGraph::PassIDTag{}, rag, dstRagVertID); + + if (holds(dstPassID, renderGraph) || holds(dstPassID, renderGraph)) { + const auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, rag, dstRagVertID); + if (fgRenderPassInfo.viewIndex.find(resName) != fgRenderPassInfo.viewIndex.end()) { + // renderpass info instead + continue; } } - trans.currStatus = {curVertID, visibility, access, passType, accessFlag, usage, Range{}}; - lastVertID = trans.lastStatus.vertID; - } else { - // avoid subpass self depends - if (trans.currStatus.vertID != curVertID) { - lastVertID = trans.currStatus.vertID; - trans.lastStatus = trans.currStatus; - trans.currStatus = {curVertID, visibility, access, passType, accessFlag, usage, Range{}}; - if (rag.leafPasses.find(trans.lastStatus.vertID) != rag.leafPasses.end()) { - rag.leafPasses.erase(trans.lastStatus.vertID); + + // subpass layout transition + if ((srcRagVertID != 0) && (holds(srcPassID, renderGraph) || holds(srcPassID, renderGraph))) { + auto ragVertID = srcRagVertID; + if (holds(srcPassID, renderGraph)) { + auto parentID = parent(srcPassID, renderGraph); + ragVertID = rag.passIndex.at(parentID); } - if (rag.leafPasses.find(curVertID) != rag.leafPasses.end()) { - // only write into externalRes counts - if (isExternalPass) { - // same as above - rag.leafPasses[curVertID].needCulling &= (access == gfx::MemoryAccessBit::READ_ONLY); - } + // RenderPass Info + auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, rag, ragVertID); + std::string_view resName = get(ResourceGraph::NameTag{}, resourceGraph, resID); + auto colorIter = std::find(fgRenderPassInfo.orderedViews.begin(), fgRenderPassInfo.orderedViews.end(), resName); + auto colorIndex = std::distance(fgRenderPassInfo.orderedViews.begin(), colorIter); + if (colorIndex < fgRenderPassInfo.colorAccesses.size()) { + fgRenderPassInfo.colorAccesses[colorIndex].nextAccess = nextIter->second.accessFlag; + } else if (colorIndex == fgRenderPassInfo.colorAccesses.size()) { + fgRenderPassInfo.dsAccess.nextAccess = nextIter->second.accessFlag; + } else if (colorIndex == fgRenderPassInfo.colorAccesses.size() + 1) { + fgRenderPassInfo.dsResolveAccess.nextAccess = nextIter->second.accessFlag; } - } else { - trans.currStatus = {curVertID, visibility, trans.currStatus.access | access, passType, accessFlag, usage, Range{}}; - } - } - } - return lastVertID; -} -gfx::ShaderStageFlagBit getVisibilityByDescName(const RenderGraph &renderGraph, const LGD &lgd, uint32_t passID, const PmrString &resName) { - auto iter = lgd.attributeIndex.find(resName); - if (iter == lgd.attributeIndex.end()) { - iter = lgd.constantIndex.find(resName); - if (iter == lgd.constantIndex.end()) { - // resource not in descriptor: eg. input or output attachment. - return gfx::ShaderStageFlagBit::NONE; - } - } - auto slotID = iter->second; + if (holds(srcPassID, renderGraph) && + accessDependent(iter->second.accessFlag, nextIter->second.accessFlag, isBuffer)) { + const auto *subpass = get_if(srcPassID, &renderGraph); + CC_ASSERT(subpass); + auto subpassID = subpass->subpassID; + auto &dependency = fgRenderPassInfo.rpInfo.dependencies.emplace_back(); + dependency.srcSubpass = subpass->subpassID; + dependency.dstSubpass = INVALID_ID; + dependency.prevAccesses = iter->second.accessFlag; + dependency.nextAccesses = nextIter->second.accessFlag; + } + continue; + } - auto layoutName = get(RenderGraph::LayoutTag{}, renderGraph, passID); - auto layoutID = locate(LayoutGraphData::null_vertex(), layoutName, lgd); - const auto &layout = get(LayoutGraphData::LayoutTag{}, lgd, layoutID); - for (const auto &pair : layout.descriptorSets) { - for (const auto &block : pair.second.descriptorSetLayoutData.descriptorBlocks) { - for (const auto &descriptor : block.descriptors) { - if (descriptor.descriptorID.value == slotID.value) { - return block.visibility; + // undefined access + if (iter == accessRecord.begin()) { + auto &dstBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, dstRagVertID); + auto &firstMeetBarrier = dstBarrierNode.frontBarriers.emplace_back(); + firstMeetBarrier.resourceID = resID; + firstMeetBarrier.type = gfx::BarrierType::FULL; + firstMeetBarrier.beginVert = dstPassID; + firstMeetBarrier.endVert = dstPassID; + firstMeetBarrier.beginStatus = iter->second; + firstMeetBarrier.endStatus = nextIter->second; + firstMeetBarrier.barrier = getGFXBarrier(firstMeetBarrier); + } else if (accessDependent(iter->second.accessFlag, nextIter->second.accessFlag, isBuffer)) { + auto &srcBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, srcRagVertID); + auto &beginBarrier = srcBarrierNode.rearBarriers.emplace_back(); + beginBarrier.resourceID = resID; + beginBarrier.beginVert = srcPassID; + beginBarrier.endVert = dstPassID; + beginBarrier.beginStatus = iter->second; + beginBarrier.endStatus = nextIter->second; + if (isPassExecAdjecent(iter->first, nextIter->first)) { + beginBarrier.type = gfx::BarrierType::FULL; + } else { + beginBarrier.type = gfx::BarrierType::SPLIT_BEGIN; + + auto &dstBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, dstRagVertID); + auto &endBarrier = dstBarrierNode.frontBarriers.emplace_back(); + endBarrier.resourceID = resID; + endBarrier.type = gfx::BarrierType::SPLIT_END; + endBarrier.beginVert = srcPassID; + endBarrier.endVert = dstPassID; + endBarrier.beginStatus = iter->second; + endBarrier.endStatus = nextIter->second; + endBarrier.barrier = getGFXBarrier(endBarrier); } + beginBarrier.barrier = getGFXBarrier(beginBarrier); } } - } - - // unreachable - CC_EXPECTS(false); - return gfx::ShaderStageFlagBit::NONE; -}; - -bool checkRasterViews(const Graphs &graphs, uint32_t vertID, uint32_t passID, PassType passType, ResourceAccessNode &node, const RasterViewsMap &rasterViews) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - bool dependent = false; - - for (const auto &pair : rasterViews) { - const auto &rasterView = pair.second; - auto access = toGfxAccess(rasterView.accessType); - gfx::ShaderStageFlagBit tryGotVis = getVisibilityByDescName(renderGraph, layoutGraphData, passID, pair.second.slotName); - tryGotVis |= pair.second.shaderStageFlags; - const auto &[vis, usage, accessFlag] = getResourceStatus(passType, pair.first, access, tryGotVis, resourceGraph, true); - ViewStatus viewStatus{pair.first, passType, vis, access, accessFlag, usage}; - addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); - auto lastVertId = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, viewStatus); - if (lastVertId != INVALID_ID && lastVertId != vertID) { - tryAddEdge(lastVertId, vertID, resourceAccessGraph); - tryAddEdge(lastVertId, vertID, relationGraph); - dependent = true; + const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, resID); + auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, resID); + if (traits.hasSideEffects()) { + states.states = iter->second.accessFlag; + if (traits.residency == ResourceResidency::BACKBUFFER) { + auto lastAccessPassID = get(ResourceAccessGraph::PassIDTag{}, rag, iter->first); + auto &barrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, iter->first); + auto &presentBarrier = barrierNode.rearBarriers.emplace_back(); + presentBarrier.resourceID = resID; + presentBarrier.type = gfx::BarrierType::FULL; + presentBarrier.beginVert = lastAccessPassID; + presentBarrier.endVert = lastAccessPassID; + presentBarrier.beginStatus = iter->second; + presentBarrier.endStatus = {gfx::AccessFlagBit::PRESENT, iter->second.range}; + presentBarrier.barrier = getGFXBarrier(presentBarrier); + + states.states = gfx::AccessFlagBit::NONE; + } } } - // sort for vector intersection - std::sort(node.attachmentStatus.begin(), node.attachmentStatus.end(), [](const AccessStatus &lhs, const AccessStatus &rhs) { return lhs.vertID < rhs.vertID; }); - - return dependent; -} - -bool checkComputeViews(const Graphs &graphs, uint32_t vertID, uint32_t passID, PassType passType, ResourceAccessNode &node, const ComputeViewsMap &computeViews) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - bool dependent = false; - - for (const auto &pair : computeViews) { - const auto &values = pair.second; - for (const auto &computeView : values) { - auto access = toGfxAccess(computeView.accessType); - gfx::ShaderStageFlagBit tryGotVis = gfx::ShaderStageFlagBit::NONE; - for (const auto &view : pair.second) { - tryGotVis |= getVisibilityByDescName(renderGraph, layoutGraphData, passID, view.name); - tryGotVis |= view.shaderStageFlags; + { + for (auto &fgRenderpassInfo : rag.rpInfo) { + auto &colorAttachments = fgRenderpassInfo.rpInfo.colorAttachments; + uint32_t count{0}; + for (auto &color : colorAttachments) { + const auto &colorAccess = fgRenderpassInfo.colorAccesses[count]; + color.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), + colorAccess.prevAccess, + colorAccess.nextAccess); + ++count; } - const auto &[vis, usage, accessFlag] = getResourceStatus(passType, pair.first, access, tryGotVis, resourceGraph, false); - ViewStatus viewStatus{pair.first, passType, vis, access, accessFlag, usage}; - addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); - auto lastVertId = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, viewStatus); - if (lastVertId != INVALID_ID) { - tryAddEdge(lastVertId, vertID, resourceAccessGraph); - tryAddEdge(lastVertId, vertID, relationGraph); - dependent = true; + auto &dsAttachment = fgRenderpassInfo.rpInfo.depthStencilAttachment; + if (dsAttachment.format != gfx::Format::UNKNOWN) { + const auto &dsAccess = fgRenderpassInfo.dsAccess; + dsAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), + dsAccess.prevAccess, + dsAccess.nextAccess); + } + auto &dsResolveAttachment = fgRenderpassInfo.rpInfo.depthStencilResolveAttachment; + if (dsResolveAttachment.format != gfx::Format::UNKNOWN) { + const auto &dsResolveAccess = fgRenderpassInfo.dsResolveAccess; + dsResolveAttachment.barrier = getGeneralBarrier(cc::gfx::Device::getInstance(), + dsResolveAccess.prevAccess, + dsResolveAccess.nextAccess); } } } +} +#pragma endregion BUILD_BARRIERS - // sort for vector intersection - std::sort(node.attachmentStatus.begin(), node.attachmentStatus.end(), [](const AccessStatus &lhs, const AccessStatus &rhs) { return lhs.vertID < rhs.vertID; }); +#pragma region PASS_REORDER - return dependent; -} +struct PassVisitor : boost::dfs_visitor<> { + using RLGVertex = RelationGraph::vertex_descriptor; + using RLGEdge = RelationGraph::edge_descriptor; + using InEdgeRange = std::pair; + using OutEdgeRange = std::pair; -bool checkResolveResource(const Graphs &graphs, uint32_t vertID, uint32_t /*passID*/, ResourceAccessNode &node, const ccstd::pmr::vector &resolves) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - bool dependent = false; - for (const auto &pair : resolves) { - const auto &resolveTargetName = pair.target; - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, vertex(resolveTargetName, resourceGraph)); - gfx::AccessFlags accessFlag = gfx::AccessFlags::COLOR_ATTACHMENT_WRITE; - gfx::TextureUsage usage = gfx::TextureUsage::COLOR_ATTACHMENT; - if (desc.format == gfx::Format::DEPTH_STENCIL) { - accessFlag = gfx::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE; - usage = gfx::TextureUsage::DEPTH_STENCIL_ATTACHMENT; - } - ViewStatus viewStatus{resolveTargetName, - PassType::RASTER, - gfx::ShaderStageFlags::FRAGMENT, - gfx::MemoryAccess::WRITE_ONLY, - accessFlag, usage}; - addAccessStatus(resourceAccessGraph, resourceGraph, node, viewStatus); - auto lastVertId = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, viewStatus); - if (lastVertId != INVALID_ID) { - tryAddEdge(lastVertId, vertID, resourceAccessGraph); - tryAddEdge(lastVertId, vertID, relationGraph); - dependent = true; - } - } - // sort for vector intersection - std::sort(node.attachmentStatus.begin(), node.attachmentStatus.end(), [](const AccessStatus &lhs, const AccessStatus &rhs) { return lhs.vertID < rhs.vertID; }); + PassVisitor(RelationGraph &tcIn, CloseCircuits &circuitsIn) : _relationGraph(tcIn), _circuits(circuitsIn) {} - return dependent; -} + void start_vertex(RLGVertex u, const RelationGraph &g) {} -void fillRenderPassInfo(gfx::LoadOp loadOp, gfx::StoreOp storeOp, AttachmentType attachmentType, gfx::RenderPassInfo &rpInfo, uint32_t index, const ResourceDesc &viewDesc, bool resolve) { - if (attachmentType != AttachmentType::DEPTH_STENCIL) { - auto &colorAttachment = rpInfo.colorAttachments[index]; - if (colorAttachment.format == gfx::Format::UNKNOWN) { - colorAttachment.format = viewDesc.format; - colorAttachment.loadOp = loadOp; - colorAttachment.storeOp = storeOp; - colorAttachment.sampleCount = viewDesc.sampleCount; - } else { - colorAttachment.storeOp = storeOp; - } + void discover_vertex(RLGVertex u, const RelationGraph &g) {} - } else { - auto &depthStencilAttachment = resolve ? - rpInfo.depthStencilResolveAttachment : - rpInfo.depthStencilAttachment; - if (depthStencilAttachment.format == gfx::Format::UNKNOWN) { - depthStencilAttachment.format = viewDesc.format; - depthStencilAttachment.depthLoadOp = loadOp; - depthStencilAttachment.depthStoreOp = storeOp; - depthStencilAttachment.stencilLoadOp = loadOp; - depthStencilAttachment.stencilStoreOp = storeOp; - depthStencilAttachment.sampleCount = viewDesc.sampleCount; - } else { - // TODO(Zeqiang): separate ds - depthStencilAttachment.depthStoreOp = storeOp; - depthStencilAttachment.stencilStoreOp = storeOp; - } + void examine_edge(RLGEdge e, const RelationGraph &g) { } -} -void processRasterPass(const Graphs &graphs, uint32_t passID, const RasterPass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; + void tree_edge(RLGEdge e, const RelationGraph &g) {} - auto vertID = add_vertex(resourceAccessGraph, passID); - auto rlgVertID = add_vertex(relationGraph, vertID); - CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, vertID); - const auto &subpasses = pass.subpassGraph.subpasses; - bool hasSubpass = !subpasses.empty(); - auto &fgRenderpassInfo = resourceAccessGraph.rpInfos.emplace(vertID, FGRenderPassInfo{}).first->second; - auto &rpInfo = fgRenderpassInfo.rpInfo; - if (!hasSubpass) { - auto &rag = resourceAccessGraph; - auto size = std::count_if(pass.rasterViews.begin(), pass.rasterViews.end(), [](const auto &pair) { - return pair.second.attachmentType != AttachmentType::DEPTH_STENCIL; - }); - rpInfo.colorAttachments.resize(size); - fgRenderpassInfo.colorAccesses.resize(size); - PmrFlatMap> viewIndex(rag.get_allocator()); - for (const auto &[name, view] : pass.rasterViews) { - auto resIter = rag.resourceIndex.find(name); - gfx::AccessFlags prevAccess = resIter == rag.resourceIndex.end() ? gfx::AccessFlags::NONE : rag.accessRecord.at(resIter->second).currStatus.accessFlag; - viewIndex.emplace(std::piecewise_construct, std::forward_as_tuple(view.slotID), std::forward_as_tuple(name, prevAccess)); - } + void back_edge(RLGEdge e, const RelationGraph &g) {} - bool dependent = false; - dependent |= checkRasterViews(graphs, vertID, passID, PassType::RASTER, node, pass.rasterViews); - dependent |= checkComputeViews(graphs, vertID, passID, PassType::RASTER, node, pass.computeViews); + void forward_or_cross_edge(RLGEdge e, const RelationGraph &g) { + // the vertex which: + // 1. is ancestor of targetID; + // 2. sourceID is reachable at this specific vert; + // is where the closed-path started. + // note that `reachable` may results to multiple paths, choose the shortest one. + auto sourceID = source(e, g); + auto targetID = target(e, g); - if (!dependent) { - tryAddEdge(EXPECT_START_ID, vertID, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, rlgVertID, relationGraph); + using RhsRangePair = std::pair; + + bool foundIntersect = false; + std::queue vertQ; + auto iterPair = in_edges(targetID, g); + vertQ.emplace(RhsRangePair{iterPair.first, iterPair}); + + // from source vertex on this edge back to branch point + EdgeList rhsPath; + bool rootEdge = true; + while (!foundIntersect && !vertQ.empty()) { + auto rangePair = vertQ.front(); + vertQ.pop(); + auto range = rangePair.second; + for (auto iter = range.first; iter != range.second; ++iter) { + auto srcID = source((*iter), g); + if (sourceID == srcID) { + continue; + } + auto e = edge(srcID, sourceID, _relationGraph); + auto recordIter = rootEdge ? iter : rangePair.first; + if (!e.second) { + vertQ.emplace(RhsRangePair{recordIter, in_edges(srcID, g)}); + } else { + rhsPath = {(*iter), *recordIter}; + foundIntersect = true; + break; + } + } + rootEdge = false; + } + assert(foundIntersect); + + using LhsRangePair = std::pair; + auto branchVert = source(rhsPath.first, g); + bool found = false; + std::queue forwardVertQ; + auto forwardIterPair = out_edges(branchVert, g); + forwardVertQ.emplace(LhsRangePair{forwardIterPair.first, forwardIterPair}); + EdgeList lhsPath; + rootEdge = true; + while (!found && !forwardVertQ.empty()) { + auto rangePair = forwardVertQ.front(); + forwardVertQ.pop(); + auto range = rangePair.second; + for (auto iter = range.first; iter != range.second; ++iter) { + if ((*iter) == rhsPath.first) { + continue; + } + auto dstID = target((*iter), g); + auto e = edge(dstID, sourceID, _relationGraph); + auto recordIter = rootEdge ? iter : rangePair.first; + if (!e.second) { + forwardVertQ.emplace(LhsRangePair{recordIter, out_edges(dstID, g)}); + } else { + found = true; + lhsPath = {*recordIter, (*iter)}; + break; + } + } + rootEdge = true; + } + assert(found); + lhsPath.second = e; + + _circuits.emplace_back(CloseCircuit{lhsPath, rhsPath}); + }; + +private: + RelationGraph &_relationGraph; + CloseCircuits &_circuits; +}; + +// forward (vertex ascending): +// -- true: how much resource this pass writes to, which has an effect of later passes; +// -- false: how much resource this pass reads from, which is dependent from former passes. +auto evaluateHeaviness(const ResourceAccessGraph &rag, const ResourceGraph &rescGraph, ResourceAccessGraph::vertex_descriptor vert, bool forward) { + const ResourceAccessNode &accessNode = get(ResourceAccessGraph::PassNodeTag{}, rag, vert); + int64_t score = 0; + bool forceAdjacent = false; + for (const auto &pair : accessNode.resourceStatus) { + int64_t eval = 0; + auto rescID = rag.resourceIndex.at(pair.first); + const ResourceDesc &desc = get(ResourceGraph::DescTag{}, rescGraph, rescID); + const ResourceTraits &traits = get(ResourceGraph::TraitsTag{}, rescGraph, rescID); + + const auto &resc = pair.second; + if (!(isReadOnlyAccess(resc.accessFlag) ^ forward)) { + // forward calculate write(s), backward calculate read(s). + continue; + } + + switch (desc.dimension) { + case ResourceDimension::BUFFER: + eval = desc.width; + break; + case ResourceDimension::TEXTURE1D: + case ResourceDimension::TEXTURE2D: + case ResourceDimension::TEXTURE3D: + eval = gfx::formatSize(desc.format, desc.width, desc.height, desc.depthOrArraySize); + break; + } + + if (traits.residency == ResourceResidency::MEMORYLESS) { + forceAdjacent = true; + score = forward ? std::numeric_limits::lowest() : std::numeric_limits::max(); + break; } + } + return std::make_tuple(forceAdjacent, score); +}; + +void evaluateAndTryMerge(const ResourceAccessGraph &rag, const ResourceGraph &rescGraph, RelationGraph &relationGraph, const RelationGraph &relationGraphTc, const RelationVerts &lhsVerts, const RelationVerts &rhsVerts) { + assert(lhsVerts.size() >= 2); + assert(rhsVerts.size() >= 2); + + auto evaluate = [&rag, &rescGraph, &relationGraph](RelationVert vert, bool forward) { + auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, vert); + return evaluateHeaviness(rag, rescGraph, ragVert, forward); + }; + + if (lhsVerts.size() == 2 || rhsVerts.size() == 2) { + /* + 1 ----------- 2 + \ __--/ + 3 --`` + no extra choice, only 1 - 3 - 2 + */ + const RelationVerts *shorterPath = lhsVerts.size() == 2 ? &lhsVerts : &rhsVerts; + remove_edge((*shorterPath)[0], (*shorterPath)[1], relationGraph); + } else { + // fist and last joint pass in this circuit don't get involved in reorder. + auto firstLhsNode = lhsVerts[1]; + auto lastLhsNode = lhsVerts[lhsVerts.size() - 2]; + + const auto &lhsBackwardStatus = evaluate(firstLhsNode, false); + bool lhsAdjacentToStart = std::get<0>(lhsBackwardStatus); + const auto &lhsForwardStatus = evaluate(lastLhsNode, true); + bool lhsAdjacentToEnd = std::get<0>(lhsForwardStatus); + + auto firstRhsNode = rhsVerts[1]; + auto lastRhsNode = rhsVerts[rhsVerts.size() - 2]; + + const auto &rhsBackwardStatus = evaluate(firstRhsNode, true); + bool rhsAdjacentToStart = std::get<0>(rhsBackwardStatus); + const auto &rhsForwardStatus = evaluate(lastRhsNode, false); + bool rhsAdjacentToEnd = std::get<0>(rhsForwardStatus); + + if (lhsAdjacentToStart || rhsAdjacentToEnd || lhsAdjacentToEnd || rhsAdjacentToStart) { + const RelationVerts *formerPath = &lhsVerts; + const RelationVerts *latterPath = &rhsVerts; + if (rhsAdjacentToStart || lhsAdjacentToEnd) { + swap(formerPath, latterPath); + } + + remove_edge((*latterPath)[0], (*latterPath)[1], relationGraph); + remove_edge((*formerPath)[formerPath->size() - 2], (*formerPath)[formerPath->size() - 1], relationGraph); + + tryAddEdge((*formerPath)[formerPath->size() - 2], (*latterPath)[1], relationGraph); + } + + assert(lhsVerts.size() >= 3 && rhsVerts.size() >= 3); + constexpr int64_t score = std::numeric_limits::lowest(); + ccstd::vector> candidateSections; + std::queue lhsSection; + for (size_t i = 1; i < lhsVerts.size(); ++i) { + auto tryE = edge(lhsVerts[i], lhsVerts[i - 1], relationGraphTc); + auto tryRE = edge(lhsVerts[i - 1], lhsVerts[i], relationGraphTc); + // check if original reachable + if (!tryE.second && !tryRE.second) { + remove_edge(lhsVerts[i - 1], lhsVerts[i], relationGraph); + candidateSections.emplace_back(lhsSection); + std::queue clearQ; + lhsSection.swap(clearQ); + } + auto e = edge(lhsVerts[i], lhsVerts[i - 1], relationGraph); + // verts comes in order, so either real edge exist or logic edge is added. + CC_ASSERT(e.second); + + lhsSection.emplace(e.first); + } + if (candidateSections.empty()) { + // if this one is a tight edge(no logic edge, dependent from one to its next), + // keep this whole chain as a candidate. + remove_edge(lhsVerts[0], lhsVerts[1], relationGraph); + remove_edge(lhsVerts[lhsVerts.size() - 2], lhsVerts[lhsVerts.size() - 1], relationGraph); + candidateSections.emplace_back(std::move(lhsSection)); + } + + std::queue rhsSection; + for (size_t i = 1; i < rhsVerts.size(); ++i) { + auto tryE = edge(rhsVerts[i], rhsVerts[i - 1], relationGraphTc); + auto tryRE = edge(rhsVerts[i - 1], rhsVerts[i], relationGraphTc); + if (!tryE.second && !tryRE.second) { + remove_edge(rhsVerts[i - 1], rhsVerts[i], relationGraph); + candidateSections.emplace_back(rhsSection); + std::queue clearQ; + rhsSection.swap(clearQ); + } + auto e = edge(rhsVerts[i], rhsVerts[i - 1], relationGraph); + // verts comes in order, so either real edge exist or logic edge is added. + CC_ASSERT(e.second); + rhsSection.emplace(e.first); + } + + // lhs verts already put in. + if (candidateSections.size() == 1) { + remove_edge(rhsVerts[0], rhsVerts[1], relationGraph); + remove_edge(rhsVerts[rhsVerts.size() - 2], rhsVerts[rhsVerts.size() - 1], relationGraph); + candidateSections.emplace_back(std::move(rhsSection)); + } + + assert(candidateSections.size() >= 2); + + ScoreMap scMap; + auto tailVert = lhsVerts[0]; + while (!candidateSections.empty()) { + int64_t lightest = std::numeric_limits::max(); + uint32_t index = 0; + for (size_t i = 0; i < candidateSections.size(); ++i) { + auto e = candidateSections[i].front(); + auto srcVert = source(e, relationGraph); + auto dstVert = target(e, relationGraph); + int64_t srcBackwardScore = 0; + int64_t dstForwardScore = 0; + if (scMap.find(srcVert) == scMap.end()) { + auto res = evaluate(srcVert, false); + srcBackwardScore = std::get<1>(res); + res = evaluate(srcVert, true); + auto srcForwardScore = std::get<1>(res); + scMap.emplace(srcVert, std::pair(srcBackwardScore, srcForwardScore)); + } else { + srcBackwardScore = std::get<0>(scMap.at(srcVert)); + } + if (scMap.find(dstVert) == scMap.end()) { + auto res = evaluate(dstVert, false); + dstForwardScore = std::get<1>(res); + res = evaluate(dstVert, true); + auto dstBackwardScore = std::get<1>(res); + scMap.emplace(dstVert, std::pair(dstBackwardScore, dstForwardScore)); + } else { + dstForwardScore = std::get<1>(scMap.at(dstVert)); + } + + // we are in a simple path, so all the "input(this path)" resource of this path come from the first vertex, + // all the "output(this path)" come to the last vertex, other resources are "internally(this path)" produced and destroyed. + // so only input of first vertex and output of last vertex are taken into account. + // [simple path]: path without diverged edges. + auto score = dstForwardScore - srcBackwardScore; + if (lightest > score) { + lightest = score; + index = i; + } + } + auto e = candidateSections[index].front(); + candidateSections[index].pop(); + if (candidateSections[index].empty()) { + auto iter = candidateSections.begin(); + std::advance(iter, index); + candidateSections.erase(iter); + } + auto srcVert = source(e, relationGraph); + auto dstVert = target(e, relationGraph); + tryAddEdge(tailVert, srcVert, relationGraph); + tailVert = dstVert; + } + + tryAddEdge(tailVert, lhsVerts.back(), relationGraph); + } +} + +// return : can be further reduced? +bool reduce(const ResourceAccessGraph &rag, const ResourceGraph &rescGraph, RelationGraph &relationGraph, RelationGraph &relationGraphTc, const CloseCircuit &circuit) { + auto checkPath = [&relationGraph](std::stack &vertices, RelationGraph::vertex_descriptor endVert, RelationVerts &stackTrace) { + bool simpleGraph = true; + while (!vertices.empty()) { + auto vert = vertices.top(); + vertices.pop(); + stackTrace.emplace_back(vert); + + if (endVert == vert) { + break; + } + + if (out_degree(vert, relationGraph) > 1) { + simpleGraph = false; + break; + } + auto r = out_edges(vert, relationGraph); + for (auto rIter = r.first; rIter != r.second; ++rIter) { + auto dstID = target(*rIter, relationGraph); + vertices.push(dstID); + } + if (r.first == r.second) { + stackTrace.pop_back(); + } + } + return simpleGraph; + }; + + // check if there is a sub branch on lhs + auto lhsEdges = circuit.first; + auto startVert = target(lhsEdges.first, relationGraph); + auto endVert = source(lhsEdges.second, relationGraph); + + std::stack vertices; + vertices.emplace(startVert); + + RelationVerts lhsVisited; + auto branchStartVert = source(lhsEdges.first, relationGraph); + auto branchEndVert = target(lhsEdges.second, relationGraph); + lhsVisited.push_back(branchStartVert); + // check if there is a branch on lhs path + if (!checkPath(vertices, endVert, lhsVisited)) { + return false; + } + lhsVisited.push_back(branchEndVert); + // if it's a simple graph, lhs path must can be dfs to the end at the first time. + assert(vertices.empty()); - // initial layout(accessrecord.laststatus) and final layout(accessrecord.currstatus) can be filled here - for (const auto &[slotID, pair] : viewIndex) { - const auto &name = pair.first; - const auto resID = rag.resourceIndex.at(name); - const auto &view = pass.rasterViews.at(name); - const auto &viewDesc = get(ResourceGraph::DescTag{}, resourceGraph, resID); - auto prevAccess = pair.second; - // TD:remove find - auto nodeIter = std::find_if(node.attachmentStatus.begin(), node.attachmentStatus.end(), [resID](const AccessStatus &status) { - return status.vertID == resID; - }); - auto nextAccess = nodeIter->accessFlag; + auto rhsEdges = circuit.second; + startVert = target(rhsEdges.first, relationGraph); + endVert = source(rhsEdges.second, relationGraph); + vertices.emplace(startVert); - if (rpInfo.subpasses.empty()) { - rpInfo.subpasses.emplace_back(); - } - auto &subpassInfo = rpInfo.subpasses.front(); - if (view.attachmentType != AttachmentType::DEPTH_STENCIL) { - if (view.attachmentType == AttachmentType::SHADING_RATE) { - subpassInfo.shadingRate = slotID; - } else { - if (view.accessType != AccessType::READ) { - subpassInfo.colors.emplace_back(slotID); - } - if (view.accessType != AccessType::WRITE) { - subpassInfo.inputs.emplace_back(slotID); - } - } - fgRenderpassInfo.colorAccesses[slotID].prevAccess = prevAccess; - fgRenderpassInfo.colorAccesses[slotID].nextAccess = nextAccess; - } else { - subpassInfo.depthStencil = pass.rasterViews.size() - 1; - fgRenderpassInfo.dsAccess.prevAccess = prevAccess; - fgRenderpassInfo.dsAccess.nextAccess = nextAccess; - } - fillRenderPassInfo(view.loadOp, view.storeOp, view.attachmentType, rpInfo, slotID, viewDesc, false); - fgRenderpassInfo.orderedViews.emplace_back(name); - } - } else { - auto colorSize = pass.rasterViews.size(); - bool hasDS = std::any_of(pass.rasterViews.begin(), pass.rasterViews.end(), [](const auto &pair) { - return pair.second.attachmentType == AttachmentType::DEPTH_STENCIL; - }); - colorSize -= hasDS; - const auto &subpasses = pass.subpassGraph.subpasses; - uint32_t count = 0; - const auto &resg = resourceGraph; - auto resolveNum = std::accumulate(subpasses.begin(), subpasses.end(), 0, [&resg](uint32_t initVal, const Subpass &subpass) { - auto iter = std::find_if(subpass.resolvePairs.begin(), subpass.resolvePairs.end(), [&resg](const auto &pair) { - auto resID = vertex(pair.target, resg); - const auto& desc = get(ResourceGraph::DescTag{}, resg, resID); - return desc.format == gfx::Format::DEPTH_STENCIL || desc.format == gfx::Format::DEPTH; - }); - return initVal + subpass.resolvePairs.size() - (iter != subpass.resolvePairs.end()); - }); - colorSize += resolveNum; - rpInfo.colorAttachments.resize(colorSize); - fgRenderpassInfo.colorAccesses.resize(colorSize); + RelationVerts rhsVisited; + rhsVisited.push_back(branchStartVert); + if (!checkPath(vertices, endVert, rhsVisited)) { + return false; } -} + rhsVisited.push_back(branchEndVert); -void processComputePass(const Graphs &graphs, uint32_t passID, const ComputePass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - auto vertID = add_vertex(resourceAccessGraph, passID); - auto rlgVertID = add_vertex(relationGraph, vertID); - CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); + // merge this circuit + // from + /* 2 - 3 - 4 + / \ + 1 8 + \ / + 5 - 6 - 7 - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, vertID); - bool dependent = checkComputeViews(graphs, vertID, passID, PassType::COMPUTE, node, pass.computeViews); + to + 1 - A - B - 8 or 1 - B - A -8 depends on algorithm - if (!dependent) { - tryAddEdge(EXPECT_START_ID, vertID, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, rlgVertID, relationGraph); - } -} + ${A} : 2 - 3 - 4 + ${B} : 5 - 6 - 7 + */ -uint32_t record(const ccstd::vector &indices) { - uint32_t res = 0; - for (auto attachmentIndex : indices) { - res |= 1 << attachmentIndex; - } - return res; -} + evaluateAndTryMerge(rag, rescGraph, relationGraph, relationGraphTc, lhsVisited, rhsVisited); -void extract(uint32_t val, ccstd::vector &preserves) { - uint32_t index = 0; - while (val) { - if (val & 0x1) { - preserves.emplace_back(index); - } - val = val >> 1; - ++index; - } + return true; } -void getPreserves(gfx::RenderPassInfo &rpInfo) { - std::stack stack; - for (auto &info : rpInfo.subpasses) { - stack.push(&info); - } +template +void applyRelation(RelationGraph &relationGraph, const TargetGraph &targetGraph) { + CC_EXPECTS(relationGraph.vertices.size() == targetGraph.vertices.size()); - uint32_t laterRead{0}; - while (!stack.empty()) { - auto *tail = stack.top(); - stack.pop(); + // remove all edges + for (auto vert : targetGraph.vertices) { + clear_in_edges(vert, targetGraph); + clear_out_edges(vert, targetGraph); + } - auto readRecord = record(tail->inputs); - auto writeRecord = record(tail->colors); - auto resolveRecord = record(tail->resolves); - auto shown = readRecord | writeRecord | resolveRecord; - auto needPreserve = (shown | laterRead) ^ shown; - extract(needPreserve, tail->preserves); - laterRead |= readRecord; + for (auto vert : relationGraph.vertices) { + auto inEdges = in_edges(vert, relationGraph); + for (auto e : makeRange(inEdges)) { + auto srcVert = source(e, relationGraph); + // auto checkEdge = edge(srcVert, vert, targetGraph); + add_edge(srcVert, vert, targetGraph); + } } } -void processRasterSubpass(const Graphs &graphs, uint32_t passID, const RasterSubpass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - const auto &obj = renderGraph.objects.at(passID); - const auto parentID = obj.parents.front().target; - const auto parentRagVert = resourceAccessGraph.passIndex.at(parentID); - const auto *parentPass = get_if(parentID, &renderGraph); - CC_EXPECTS(parentPass); - const auto &rag = resourceAccessGraph; - const auto &resg = resourceGraph; - const auto &uberPass = *parentPass; - - resourceAccessGraph.passIndex[passID] = parentRagVert; - - static const uint32_t ACCESS_TYPE_WEIGHT[] = {0, 1, 2}; - static const uint32_t ATTACHMENT_TYPE_WEIGHT[] = {0, 2, 1}; - - struct SubpassRasterViewSortKey { - uint32_t accessType; - uint32_t attachmentType; - std::string_view slotName; - uint32_t samplesReverseWeight; - }; - using RasterViewSortKey = std::tuple; - struct SubpassRasterViewData { - SubpassRasterViewSortKey sortKey; - std::string_view name; - gfx::AccessFlags access; - }; +void passReorder(FrameGraphDispatcher &fgDispatcher) { + auto *scratch = fgDispatcher.scratch; + const auto &renderGraph = fgDispatcher.renderGraph; + const auto &layoutGraph = fgDispatcher.layoutGraph; + auto &resourceGraph = fgDispatcher.resourceGraph; + auto &relationGraph = fgDispatcher.relationGraph; + auto &rag = fgDispatcher.resourceAccessGraph; - bool hasDS{false}; - ccstd::vector viewIndex; - for (const auto &[name, view] : pass.rasterViews) { - auto resIter = rag.resourceIndex.find(name); - const auto &resID = vertex(name, resourceGraph); - const auto &desc = get(ResourceGraph::DescTag{}, resg, resID); - gfx::AccessFlags prevAccess = resIter == rag.resourceIndex.end() ? gfx::AccessFlags::NONE : rag.accessRecord.at(resIter->second).currStatus.accessFlag; - viewIndex.emplace_back(SubpassRasterViewData{ - {ACCESS_TYPE_WEIGHT[static_cast(view.accessType)], ATTACHMENT_TYPE_WEIGHT[static_cast(view.attachmentType)], view.slotName, static_cast(desc.sampleCount)}, - name, - prevAccess, - }); - hasDS |= view.attachmentType == AttachmentType::DEPTH_STENCIL; + if (!fgDispatcher._accessGraphBuilt) { + const Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; + buildAccessGraph(graphs); + fgDispatcher._accessGraphBuilt = true; } - for (const auto &resolve : pass.resolvePairs) { - auto resIter = rag.resourceIndex.find(resolve.target); - gfx::AccessFlags prevAccess = resIter == rag.resourceIndex.end() ? gfx::AccessFlags::NONE : rag.accessRecord.at(resIter->second).currStatus.accessFlag; - viewIndex.emplace_back(SubpassRasterViewData{ - {ACCESS_TYPE_WEIGHT[static_cast(AccessType::WRITE)], ATTACHMENT_TYPE_WEIGHT[static_cast(AttachmentType::RENDER_TARGET)], "_", 0xFFFFFFFF}, - resolve.target, - prevAccess, - }); - } + { + // determine do mem saving how many times + RelationGraph relationGraphTc(fgDispatcher.get_allocator()); + boost::transitive_closure(relationGraph, relationGraphTc); - std::sort(viewIndex.begin(), viewIndex.end(), [](const SubpassRasterViewData &lhs, const SubpassRasterViewData &rhs) { - if (lhs.sortKey.samplesReverseWeight != rhs.sortKey.samplesReverseWeight) { - return lhs.sortKey.samplesReverseWeight < rhs.sortKey.samplesReverseWeight; - } - if (lhs.sortKey.accessType != rhs.sortKey.accessType) { - return lhs.sortKey.accessType < rhs.sortKey.accessType; - } - if (lhs.sortKey.attachmentType != rhs.sortKey.attachmentType) { - return lhs.sortKey.attachmentType < rhs.sortKey.attachmentType; - } - return lhs.sortKey.slotName < rhs.sortKey.slotName; - }); - - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, parentRagVert); - auto &fgRenderpassInfo = resourceAccessGraph.rpInfos.at(parentRagVert); - auto &rpInfo = fgRenderpassInfo.rpInfo; - auto &subpassInfo = rpInfo.subpasses.emplace_back(); - auto *lastNode = &node; - uint32_t subpassIndex = 0; - while (lastNode->nextSubpass) { - lastNode = lastNode->nextSubpass; - ++subpassIndex; - } - lastNode->nextSubpass = new ResourceAccessNode; - resourceAccessGraph.subpassIndex.emplace(passID, subpassIndex); - auto *head = lastNode->nextSubpass; - bool dependent{false}; - dependent |= checkRasterViews(graphs, parentRagVert, passID, PassType::RASTER, *head, pass.rasterViews); - dependent |= checkComputeViews(graphs, parentRagVert, passID, PassType::RASTER, *head, pass.computeViews); - dependent |= checkResolveResource(graphs, parentRagVert, passID, *head, pass.resolvePairs); - - if (!dependent) { - tryAddEdge(EXPECT_START_ID, parentRagVert, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, parentRagVert, relationGraph); - } - - if (!pass.resolvePairs.empty()) { - // ds resolve stores in depthStencilResolve - subpassInfo.resolves.resize(pass.rasterViews.size() - hasDS, gfx::INVALID_BINDING); - } - - uint32_t localSlot = 0; - bool dsAppeared{false}; - for (const auto &[sortKey, name, access] : viewIndex) { - const auto *const resName = name.data(); - auto findByResID = [&](const AccessStatus &status) { - return status.vertID == rag.resourceIndex.at(resName); - }; - auto iter = std::find_if(node.attachmentStatus.begin(), node.attachmentStatus.end(), findByResID); - - // TODO(Zeqiang): remove find - const auto &targetName = name; - auto resID = rag.resourceIndex.at(resName); - const auto &viewDesc = get(ResourceGraph::DescTag{}, resg, rag.resourceIndex.at(resName)); - - AttachmentType attachmentType{AttachmentType::RENDER_TARGET}; - AccessType accessType{AccessType::WRITE}; - gfx::LoadOp loadOp{gfx::LoadOp::DISCARD}; - gfx::StoreOp storeOp{gfx::StoreOp::STORE}; - - uint32_t slot = dsAppeared ? localSlot - 1 : localSlot; - // std::distance(uberPass.rasterViews.begin(), uberPass.rasterViews.find(resName)); - // slot = dsAppeared ? slot - 1 : slot; - /*if (attachmentType != AttachmentType::DEPTH_STENCIL) { - CC_ASSERT(uberPass.attachmentIndexMap.count(resName)); - slot = uberPass.attachmentIndexMap.at(resName); - }*/ - - // TD:remove find - auto nodeIter = std::find_if(head->attachmentStatus.begin(), head->attachmentStatus.end(), [resID](const AccessStatus &status) { - return status.vertID == resID; - }); - auto nextAccess = nodeIter->accessFlag; + CloseCircuits circuits; + std::vector crossEdges; + PassVisitor visitor(relationGraphTc, circuits); + auto colors = relationGraph.colors(scratch); + boost::depth_first_search(relationGraph, visitor, get(colors, relationGraph)); - auto resolveIter = std::find_if(pass.resolvePairs.begin(), pass.resolvePairs.end(), [&targetName](const ResolvePair &resolve) { - return strcmp(resolve.target.c_str(), targetName.data()) == 0; - }); - bool resolveView = resolveIter != pass.resolvePairs.end(); - if (resolveView) { - attachmentType = viewDesc.format == gfx::Format::DEPTH_STENCIL ? AttachmentType::DEPTH_STENCIL : AttachmentType::RENDER_TARGET; - if (attachmentType == AttachmentType::DEPTH_STENCIL) { - subpassInfo.depthStencilResolve = slot; - subpassInfo.depthResolveMode = gfx::ResolveMode::SAMPLE_ZERO; // resolveiter->mode; - subpassInfo.stencilResolveMode = gfx::ResolveMode::SAMPLE_ZERO; // resolveiter->mode1; - fgRenderpassInfo.dsResolveAccess.nextAccess = nextAccess; - } else { - auto indexIter = std::find(fgRenderpassInfo.orderedViews.begin(), fgRenderpassInfo.orderedViews.end(), resolveIter->source.c_str()); - auto srcIndex = indexIter == fgRenderpassInfo.orderedViews.end() ? fgRenderpassInfo.orderedViews.size() - : std::distance(fgRenderpassInfo.orderedViews.begin(), indexIter); - subpassInfo.resolves[srcIndex] = slot; - fgRenderpassInfo.colorAccesses[slot].nextAccess = nextAccess; - } - accessType = AccessType::WRITE; - } else { - const auto &view = pass.rasterViews.at(resName); - attachmentType = view.attachmentType; - accessType = view.accessType; - loadOp = view.loadOp; - storeOp = view.storeOp; - - if (attachmentType != AttachmentType::DEPTH_STENCIL) { - if (attachmentType == AttachmentType::SHADING_RATE) { - subpassInfo.shadingRate = slot; - } else { - if (accessType != AccessType::READ) { - subpassInfo.colors.emplace_back(slot); - } - if (accessType != AccessType::WRITE) { - subpassInfo.inputs.emplace_back(slot); - } - } - fgRenderpassInfo.colorAccesses[slot].nextAccess = nextAccess; + float percent = 0.0F; + uint32_t count = 0; + auto total = circuits.size(); + + float memsavePercent = 1.0F - fgDispatcher._paralellExecWeight; + for (auto iter = circuits.begin(); (iter != circuits.end()) && (percent < memsavePercent);) { + bool reduced = reduce(rag, resourceGraph, relationGraph, relationGraphTc, (*iter)); + if (reduced) { + ++count; + iter = circuits.erase(iter); + percent = count / static_cast(total); } else { - fgRenderpassInfo.dsAccess.nextAccess = nextAccess; - subpassInfo.depthStencil = rpInfo.colorAttachments.size(); - dsAppeared = true; + ++iter; } } - if (iter == node.attachmentStatus.end()) { - auto curIter = std::find_if(head->attachmentStatus.begin(), head->attachmentStatus.end(), findByResID); - node.attachmentStatus.emplace_back(*curIter); - auto prevAccess = access; - CC_ASSERT(head->attachmentStatus.size() > localSlot); - auto nextAccess = head->attachmentStatus[localSlot].accessFlag; + // topological sort + rag.topologicalOrder.clear(); + bool empty = relationGraph._vertices.empty(); + ScoreMap scoreMap; + RelationVerts candidates; + candidates.push_back(EXPECT_START_ID); - if (attachmentType == AttachmentType::DEPTH_STENCIL) { - if (resolveView) { - fgRenderpassInfo.dsResolveAccess.prevAccess = prevAccess; + std::vector candidateBuffer; + uint32_t coloredVerts = 0; + while (coloredVerts < relationGraph._vertices.size()) { + // decreasing order, pop back from vector, push into queue, then it's ascending order. + std::sort(candidates.begin(), candidates.end(), [&](RelationVert lhsVert, RelationVert rhsVert) { + int64_t lhsForwardScore{0}; + int64_t rhsForwardScore{0}; + int64_t lhsBackwardScore{0}; + int64_t rhsBackwardScore{0}; + if (scoreMap.find(lhsVert) == scoreMap.end()) { + auto lhsRagVert = get(RelationGraph::DescIDTag{}, relationGraph, lhsVert); + const auto &lhsForwardStatus = evaluateHeaviness(rag, resourceGraph, lhsRagVert, true); + lhsForwardScore = get<1>(lhsForwardStatus); + const auto &lhsBackwardStatus = evaluateHeaviness(rag, resourceGraph, lhsRagVert, false); + lhsBackwardScore = get<1>(lhsBackwardStatus); + scoreMap.emplace(lhsVert, std::pair{lhsBackwardScore, lhsForwardScore}); } else { - fgRenderpassInfo.dsAccess.prevAccess = prevAccess; + lhsBackwardScore = scoreMap[lhsVert].first; + lhsForwardScore = scoreMap[lhsVert].second; } - } else { - fgRenderpassInfo.colorAccesses[slot].prevAccess = prevAccess; - } - fgRenderpassInfo.orderedViews.emplace_back(resName); - } - fillRenderPassInfo(loadOp, storeOp, attachmentType, rpInfo, slot, viewDesc, resolveView); - fgRenderpassInfo.needResolve |= resolveView; - ++localSlot; - } - if (pass.subpassID == uberPass.subpassGraph.subpasses.size() - 1) { - getPreserves(rpInfo); - } -} - -void processComputeSubpass(const Graphs &graphs, uint32_t passID, const ComputeSubpass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - const auto &obj = renderGraph.objects.at(passID); - const auto parentID = obj.parents.front().target; - const auto parentRagVert = resourceAccessGraph.passIndex.at(parentID); - const auto *parentPass = get_if(parentID, &renderGraph); - CC_EXPECTS(parentPass); - const auto &rag = resourceAccessGraph; - const auto &resg = resourceGraph; - const auto &uberPass = *parentPass; - - resourceAccessGraph.passIndex[passID] = parentRagVert; + if (scoreMap.find(rhsVert) == scoreMap.end()) { + auto rhsRagVert = get(RelationGraph::DescIDTag{}, relationGraph, rhsVert); + const auto &rhsForwardStatus = evaluateHeaviness(rag, resourceGraph, rhsRagVert, true); + rhsForwardScore = get<1>(rhsForwardStatus); + const auto &rhsBackwardStatus = evaluateHeaviness(rag, resourceGraph, rhsRagVert, false); + rhsBackwardScore = get<1>(rhsBackwardStatus); + scoreMap.emplace(rhsVert, std::pair{rhsBackwardScore, rhsForwardScore}); + } else { + rhsBackwardScore = scoreMap[rhsVert].first; + rhsForwardScore = scoreMap[rhsVert].second; + } + return lhsBackwardScore - lhsForwardScore > rhsBackwardScore - rhsForwardScore; + }); - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, parentRagVert); + const auto vert = candidates.back(); + candidates.pop_back(); - auto *lastNode = &node; - while (lastNode->nextSubpass) { - lastNode = lastNode->nextSubpass; - } - lastNode->nextSubpass = new ResourceAccessNode; - auto *head = lastNode->nextSubpass; + auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, vert); + rag.topologicalOrder.emplace_back(ragVert); + if (!candidateBuffer.empty()) { + candidates.insert(candidates.end(), candidateBuffer.begin(), candidateBuffer.end()); + candidateBuffer.clear(); + } - bool dependent = checkComputeViews(graphs, parentRagVert, passID, PassType::COMPUTE, *head, pass.computeViews); + for (const auto nextGeneration : makeRange(out_edges(vert, relationGraph))) { + auto targetID = target(nextGeneration, relationGraph); + if (in_degree(targetID, relationGraph) == 1) { + candidateBuffer.emplace_back(targetID); + } + } - if (!dependent) { - tryAddEdge(EXPECT_START_ID, parentRagVert, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, parentRagVert, relationGraph); - } -} + auto deprecatedEdges = out_edges(vert, relationGraph); + for (auto iter = deprecatedEdges.first; iter < deprecatedEdges.second;) { + remove_edge(*iter, relationGraph); + deprecatedEdges = out_edges(vert, relationGraph); + iter = deprecatedEdges.first; + } -void processCopyPass(const Graphs &graphs, uint32_t passID, const CopyPass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; + if (candidates.empty()) { + candidates.insert(candidates.end(), candidateBuffer.begin(), candidateBuffer.end()); + candidateBuffer.clear(); + } - auto vertID = add_vertex(resourceAccessGraph, passID); - auto rlgVertID = add_vertex(relationGraph, vertID); - CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); + coloredVerts++; + } - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, vertID); - bool dependent = false; - for (const auto &pair : pass.copyPairs) { - auto sourceRange = Range{ - TextureRange{ - pair.sourceFirstSlice, - pair.sourcePlaneSlice, - pair.mipLevels, - pair.numSlices, - }}; - auto targetRange = Range{ - TextureRange{ - pair.targetFirstSlice, - pair.targetPlaneSlice, - pair.mipLevels, - pair.numSlices, - }}; - ResourceUsage srcUsage = gfx::TextureUsage::TRANSFER_SRC; - ViewStatus srcViewStatus{pair.source, PassType::COPY, defaultVisibility, gfx::MemoryAccessBit::READ_ONLY, gfx::AccessFlags::TRANSFER_READ, srcUsage}; - addCopyAccessStatus(resourceAccessGraph, resourceGraph, node, srcViewStatus, sourceRange); - ResourceUsage dstUsage = gfx::TextureUsage::TRANSFER_DST; - ViewStatus dstViewStatus{pair.target, PassType::COPY, defaultVisibility, gfx::MemoryAccessBit::WRITE_ONLY, gfx::AccessFlags::TRANSFER_WRITE, dstUsage}; - addCopyAccessStatus(resourceAccessGraph, resourceGraph, node, dstViewStatus, targetRange); - - uint32_t lastVertSrc = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, srcViewStatus); - if (lastVertSrc != INVALID_ID) { - tryAddEdge(lastVertSrc, vertID, resourceAccessGraph); - tryAddEdge(lastVertSrc, rlgVertID, relationGraph); - dependent = true; + // remove all edges + for (auto vert : makeRange(vertices(rag))) { + clear_in_edges(vert, rag); + clear_out_edges(vert, rag); } - uint32_t lastVertDst = dependencyCheck(resourceAccessGraph, vertID, resourceGraph, dstViewStatus); - if (lastVertDst != INVALID_ID) { - tryAddEdge(lastVertDst, vertID, resourceAccessGraph); - tryAddEdge(lastVertDst, rlgVertID, relationGraph); - dependent = true; + + // apply relation + for (auto rlgVert : makeRange(vertices(relationGraph))) { + auto ragVert = get(RelationGraph::DescIDTag{}, relationGraph, rlgVert); + auto inEdges = in_edges(rlgVert, relationGraph); + for (auto e : makeRange(inEdges)) { + auto srcRlgVert = source(e, relationGraph); + auto srcRagVert = get(RelationGraph::DescIDTag{}, relationGraph, srcRlgVert); + add_edge(srcRagVert, ragVert, rag); + } } } - if (!dependent) { - tryAddEdge(EXPECT_START_ID, vertID, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, rlgVertID, relationGraph); - } - std::sort(node.attachmentStatus.begin(), node.attachmentStatus.end(), [](const AccessStatus &lhs, const AccessStatus &rhs) { return lhs.vertID < rhs.vertID; }); } -void processRaytracePass(const Graphs &graphs, uint32_t passID, const RaytracePass &pass) { - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; - - auto vertID = add_vertex(resourceAccessGraph, passID); - auto rlgVertID = add_vertex(relationGraph, vertID); - CC_EXPECTS(static_cast(rlgVertID) == static_cast(vertID)); +#pragma endregion PASS_REORDER - auto &node = get(RAG::AccessNodeTag{}, resourceAccessGraph, vertID); - bool dependent = checkComputeViews(graphs, vertID, passID, PassType::RAYTRACE, node, pass.computeViews); +void memoryAliasing(FrameGraphDispatcher &fgDispatcher) { +} - if (!dependent) { - tryAddEdge(EXPECT_START_ID, vertID, resourceAccessGraph); - tryAddEdge(EXPECT_START_ID, rlgVertID, relationGraph); +#pragma region assisstantFuncDefinition +template +bool tryAddEdge(uint32_t srcVertex, uint32_t dstVertex, Graph &graph) { + auto e = edge(srcVertex, dstVertex, graph); + if (!e.second) { + auto res = add_edge(srcVertex, dstVertex, graph); + CC_ENSURES(res.second); + return true; } + return false; +} + +bool isTransitionStatusDependent(const AccessStatus &lhs, const AccessStatus &rhs) { + return !(isReadOnlyAccess(lhs.accessFlag) && isReadOnlyAccess(rhs.accessFlag)); } #pragma endregion assisstantFuncDefinition diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index 23fdda466bc..c52a13d114c 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -35,6 +35,7 @@ #include "RenderGraphGraphs.h" #include "RenderGraphTypes.h" #include "RenderingModule.h" +#include "NativeRenderGraphUtils.h" #include "cocos/renderer/gfx-base/GFXBarrier.h" #include "cocos/renderer/gfx-base/GFXDef-common.h" #include "cocos/renderer/gfx-base/GFXDescriptorSetLayout.h" @@ -70,7 +71,6 @@ struct RenderGraphVisitorContext { const RenderGraph& g; ResourceGraph& resourceGraph; const FrameGraphDispatcher& fgd; - const FrameGraphDispatcher::BarrierMap& barrierMap; const ccstd::pmr::vector& validPasses; gfx::Device* device = nullptr; gfx::CommandBuffer* cmdBuff = nullptr; @@ -164,145 +164,24 @@ gfx::GeneralBarrier* getGeneralBarrier(gfx::Device* device, const RasterView& vi return nullptr; } +ResourceGraph::vertex_descriptor getResourceID(const ccstd::pmr::string& name, const FrameGraphDispatcher& fgd) { + return fgd.realResourceID(name); +} + PersistentRenderPassAndFramebuffer createPersistentRenderPassAndFramebuffer( RenderGraphVisitorContext& ctx, const RasterPass& pass, - boost::container::pmr::memory_resource* scratch) { + boost::container::pmr::memory_resource* /*scratch*/) { auto& resg = ctx.resourceGraph; PersistentRenderPassAndFramebuffer data(pass.get_allocator()); - gfx::RenderPassInfo rpInfo{}; - - gfx::FramebufferInfo fbInfo{ - data.renderPass, - }; - fbInfo.colorTextures.reserve(pass.rasterViews.size()); - - PmrFlatSet set(scratch); - auto fillFrameBufferInfo = [&](const ccstd::vector& passViews, bool hasResolve) { - std::ignore = hasResolve; - const auto& uberPass = pass; - auto numTotalAttachments = static_cast(passViews.size()); - - // uint32_t dsvCount = 0; - uint32_t index = 0; - for (const auto& nameIn : passViews) { - const char* name = nameIn.c_str(); - bool colorLikeView{true}; - bool dsResolveAttachment{false}; - auto clearColor = gfx::Color{}; - auto iter = pass.rasterViews.find(name); - if(iter != pass.rasterViews.end()) { - const auto& view = iter->second; - colorLikeView = view.attachmentType == AttachmentType::RENDER_TARGET || view.attachmentType == AttachmentType::SHADING_RATE; - clearColor = view.clearColor; - } else { - // resolves - const auto resID = vertex(name, ctx.resourceGraph); - const auto& desc = get(ResourceGraph::DescTag{}, ctx.resourceGraph, resID); - CC_ASSERT(hasResolve && desc.sampleCount == gfx::SampleCount::X1); - colorLikeView = desc.format != gfx::Format::DEPTH_STENCIL && desc.format != gfx::Format::DEPTH; - dsResolveAttachment = !colorLikeView; - } - - if (colorLikeView) { // RenderTarget - data.clearColors.emplace_back(clearColor); - - auto resID = findVertex(name, resg); - visitObject( - resID, resg, - [&](const ManagedResource& res) { - std::ignore = res; - CC_EXPECTS(false); - }, - [&](const ManagedBuffer& res) { - std::ignore = res; - CC_EXPECTS(false); - }, - [&](const ManagedTexture& tex) { - CC_EXPECTS(tex.texture); - fbInfo.colorTextures.emplace_back(tex.texture); - }, - [&](const IntrusivePtr& res) { - std::ignore = res; - CC_EXPECTS(false); - }, - [&](const IntrusivePtr& tex) { - fbInfo.colorTextures.emplace_back(tex); - }, - [&](const IntrusivePtr& fb) { - CC_EXPECTS(fb->getColorTextures().size() == 1); - CC_EXPECTS(fb->getColorTextures().at(0)); - fbInfo.colorTextures.emplace_back(fb->getColorTextures()[index]); - // render window attaches a depthStencil by default, which may differs from renderpassInfo here. - // data.framebuffer = fb; - }, - [&](const RenderSwapchain& sc) { - fbInfo.colorTextures.emplace_back(sc.swapchain->getColorTexture()); - }, - [&](const FormatView& view) { - // TODO(zhouzhenglong): add ImageView support - std::ignore = view; - CC_EXPECTS(false); - }, - [&](const SubresourceView& view) { - // TODO(zhouzhenglong): add ImageView support - std::ignore = view; - CC_EXPECTS(false); - }); - } else { // DepthStencil - if (!dsResolveAttachment) { - data.clearDepth = clearColor.x; - data.clearStencil = static_cast(clearColor.y); - } - - auto &dsAttachment = dsResolveAttachment ? fbInfo.depthStencilResolveTexture : fbInfo.depthStencilTexture; - - auto resID = findVertex(name, resg); - visitObject( - resID, resg, - [&](const ManagedTexture& tex) { - CC_EXPECTS(tex.texture); - dsAttachment = tex.texture.get(); - }, - [&](const IntrusivePtr& tex) { - dsAttachment = tex.get(); - }, - [&](const FormatView& view) { - std::ignore = view; - CC_EXPECTS(false); - }, - [&](const SubresourceView& view) { - std::ignore = view; - CC_EXPECTS(false); - }, - [](const auto& /*unused*/) { - CC_EXPECTS(false); - }); - } - ++index; - } - }; - - const auto passID = ctx.currentInFlightPassID; - const auto ragVertID = ctx.fgd.resourceAccessGraph.passIndex.at(passID); - if (pass.subpassGraph.subpasses.empty()) { - const auto numInputs = getRasterPassInputCount(pass); - const auto numColors = getRasterPassOutputCount(pass); + auto [rpInfo, fbInfo, clearColors, clearDepth, clearStencil] = ctx.fgd.getRenderPassAndFrameBuffer(ctx.currentInFlightPassID, resg); - // persistent cache - data.clearColors.reserve(numColors); - const auto& fgdRpInfo = ctx.fgd.resourceAccessGraph.rpInfos.at(ragVertID); - rpInfo = fgdRpInfo.rpInfo; - fillFrameBufferInfo(fgdRpInfo.orderedViews, false); - - } else { - const auto& fgdRpInfo = ctx.fgd.resourceAccessGraph.rpInfos.at(ragVertID); - rpInfo = fgdRpInfo.rpInfo; - fillFrameBufferInfo(fgdRpInfo.orderedViews, fgdRpInfo.needResolve); - } - CC_ENSURES(rpInfo.colorAttachments.size() == data.clearColors.size()); + // CC_ENSURES(rpInfo.colorAttachments.size() == data.clearColors.size()); CC_ENSURES(rpInfo.colorAttachments.size() == fbInfo.colorTextures.size()); + data.clearColors = std::move(clearColors); + data.clearDepth = clearDepth; + data.clearStencil = clearStencil; data.renderPass = ctx.device->createRenderPass(rpInfo); fbInfo.renderPass = data.renderPass; data.framebuffer = ctx.device->createFramebuffer(fbInfo); @@ -660,28 +539,23 @@ gfx::DescriptorSet* initDescriptorSet( } break; case DescriptorTypeOrder::INPUT_ATTACHMENT: { - for (auto d : block.descriptors) { - CC_EXPECTS(d.count == 1); - auto iter = resourceIndex.find(d.descriptorID); - if (iter != resourceIndex.end()) { - // render graph textures - auto* texture = resg.getTexture(iter->second); - gfx::AccessFlags access = gfx::AccessFlagBit::NONE; - if (accessNode != nullptr) { - auto accIter = std::find_if( - accessNode->attachmentStatus.begin(), accessNode->attachmentStatus.end(), - [iter](const AccessStatus& status) { - return status.vertID == iter->second; - }); - access = accIter != accessNode->attachmentStatus.end() ? accIter->accessFlag : gfx::AccessFlagBit::NONE; - } - - CC_ENSURES(texture); - newSet->bindTexture(bindID, texture, 0, access); + for (const auto& [descID, resID] : resourceIndex) { + std::ignore = descID; + // render graph textures + auto* texture = resg.getTexture(resID); + gfx::AccessFlags access = gfx::AccessFlagBit::NONE; + if (accessNode != nullptr) { + // whole access only now. + auto parentID = parent(resID, resg); + parentID = parentID == ResourceGraph::null_vertex() ? resID : parentID; + const auto& resName = get(ResourceGraph::NameTag{}, resg, parentID); + access = accessNode->resourceStatus.at(resName).accessFlag; } - bindID += d.count; - } + CC_ENSURES(texture); + newSet->bindTexture(bindID, texture, 0, access); + bindID += 1; + } }; break; default: @@ -908,26 +782,6 @@ void submitProfilerCommands( cmdBuff->draw(ia); } -PmrFlatMap -buildResourceIndex( - const ResourceGraph& resg, - const LayoutGraphData& lg, - const PmrTransparentMap>& computeViews, - boost::container::pmr::memory_resource* scratch) { - PmrFlatMap resourceIndex(scratch); - resourceIndex.reserve(computeViews.size() * 2); - for (const auto& [resName, computeViews] : computeViews) { - const auto resID = vertex(resName, resg); - for (const auto& computeView : computeViews) { - const auto& name = computeView.name; - CC_EXPECTS(!name.empty()); - const auto nameID = lg.attributeIndex.at(name); - resourceIndex.emplace(nameID, resID); - } - } - return resourceIndex; -} - const PmrTransparentMap>& getComputeViews(RenderGraph::vertex_descriptor passID, const RenderGraph& rg) { if (holds(passID, rg)) { @@ -1073,8 +927,7 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { } // build pass resources - const auto& resourceIndex = buildResourceIndex( - ctx.resourceGraph, ctx.lg, computeViews, ctx.scratch); + const auto& resourceIndex = ctx.fgd.buildDescriptorIndex(computeViews, ctx.scratch); // populate set auto& set = iter->second; @@ -1106,8 +959,7 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { } // build pass resources - const auto& resourceIndex = buildResourceIndex( - ctx.resourceGraph, ctx.lg, computeViews, ctx.scratch); + const auto& resourceIndex = ctx.fgd.buildDescriptorIndex(computeViews, ctx.scratch); // find scene resource const auto* const sceneResource = getFirstSceneResource(vertID); @@ -1148,7 +1000,6 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { const auto& subpass = get(RasterSubpassTag{}, vertID, ctx.g); // render pass const auto& layoutName = get(RenderGraph::LayoutTag{}, ctx.g, vertID); - auto parentLayoutID = ctx.currentPassLayoutID; auto layoutID = parentLayoutID; if (!layoutName.empty()) { @@ -1169,35 +1020,12 @@ struct RenderGraphUploadVisitor : boost::dfs_visitor<> { return; } - // build pass resources - /* const auto& resourceIndex = buildResourceIndex( - ctx.resourceGraph, ctx.lg, subpass.computeViews, ctx.scratch);*/ - PmrFlatMap resourceIndex(ctx.scratch); - - resourceIndex.reserve(subpass.rasterViews.size() * 2); - for (const auto& [resName, rasterView] : subpass.rasterViews) { - const auto resID = vertex(resName, ctx.resourceGraph); - auto ragId = ctx.fgd.resourceAccessGraph.passIndex.at(vertID); - const auto& attachments = ctx.fgd.resourceAccessGraph.access[ragId].attachmentStatus; - auto resIter = std::find_if(attachments.begin(), attachments.end(), [resID](const AccessStatus& status) { - return status.vertID == resID; - }); - - auto slotName = rasterView.slotName; - if (rasterView.accessType == AccessType::READ || rasterView.accessType == AccessType::READ_WRITE) { - slotName.insert(0, "__in"); - } - auto iter = ctx.lg.attributeIndex.find(slotName); - if (iter != ctx.lg.attributeIndex.end()) { - resourceIndex.emplace(iter->second, resID); - } - } - + const auto& resourceIndex = ctx.fgd.buildDescriptorIndex(subpass.computeViews, subpass.rasterViews, ctx.scratch); // populate set auto& set = iter->second; const auto& user = get(RenderGraph::DataTag{}, ctx.g, vertID); auto& node = ctx.context.layoutGraphResources.at(layoutID); - const auto& accessNode = ctx.fgd.getAttachmentStatus(vertID); + const auto& accessNode = ctx.fgd.getAccessNode(vertID); auto* perPassSet = initDescriptorSet( ctx.resourceGraph, @@ -1258,25 +1086,15 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { textureBarriers.data(), textures.data(), static_cast(textureBarriers.size())); } void frontBarriers(RenderGraph::vertex_descriptor vertID) const { - auto iter = ctx.fgd.resourceAccessGraph.passIndex.find(vertID); - if (iter == ctx.fgd.resourceAccessGraph.passIndex.end()) { - return; - } - const auto& nodeID = iter->second; - auto iter2 = ctx.barrierMap.find(nodeID); - if (iter2 != ctx.barrierMap.end()) { - submitBarriers(iter2->second.blockBarrier.frontBarriers); + const auto& barrier = ctx.fgd.getBarrier(vertID); + if (!barrier.frontBarriers.empty()) { + submitBarriers(barrier.frontBarriers); } } void rearBarriers(RenderGraph::vertex_descriptor vertID) const { - auto iter = ctx.fgd.resourceAccessGraph.passIndex.find(vertID); - if (iter == ctx.fgd.resourceAccessGraph.passIndex.end()) { - return; - } - const auto& nodeID = iter->second; - auto iter2 = ctx.barrierMap.find(nodeID); - if (iter2 != ctx.barrierMap.end()) { - submitBarriers(iter2->second.blockBarrier.rearBarriers); + const auto& barrier = ctx.fgd.getBarrier(vertID); + if (!barrier.rearBarriers.empty()) { + submitBarriers(barrier.rearBarriers); } } void tryBindPerPassDescriptorSet(RenderGraph::vertex_descriptor vertID) const { @@ -1352,6 +1170,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { if (subpass.subpassID) { ctx.cmdBuff->nextSubpass(); } + //ctx.cmdBuff->setViewport(subpass); tryBindPerPassDescriptorSet(vertID); ctx.subpassIndex = subpass.subpassID; // noop @@ -1546,32 +1365,14 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { const auto* scene = camera->getScene(); const auto& queueDesc = ctx.context.sceneCulling.sceneQueryIndex.at(sceneID); const auto& queue = ctx.context.sceneCulling.renderQueues[queueDesc.renderQueueTarget]; - bool bDraw = any(sceneData.flags & SceneFlags::DRAW_NON_INSTANCING); - bool bDrawInstancing = any(sceneData.flags & SceneFlags::DRAW_INSTANCING); - if (!bDraw && !bDrawInstancing) { - bDraw = true; - bDrawInstancing = true; - } - const bool bDrawBlend = any(sceneData.flags & SceneFlags::TRANSPARENT_OBJECT); - const bool bDrawOpaqueOrMask = any(sceneData.flags & (SceneFlags::OPAQUE_OBJECT | SceneFlags::CUTOUT_OBJECT)); - const bool bDrawShadowCaster = any(sceneData.flags & SceneFlags::SHADOW_CASTER); - - if (bDrawShadowCaster || bDrawOpaqueOrMask) { - queue.opaqueQueue.recordCommandBuffer( - ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); - if (bDrawInstancing) { - queue.opaqueInstancingQueue.recordCommandBuffer( - ctx.currentPass, ctx.cmdBuff); - } - } - if (bDrawBlend) { - queue.transparentQueue.recordCommandBuffer( - ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); - if (bDrawInstancing) { - queue.transparentInstancingQueue.recordCommandBuffer( - ctx.currentPass, ctx.cmdBuff); - } - } + queue.opaqueQueue.recordCommandBuffer( + ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); + queue.opaqueInstancingQueue.recordCommandBuffer( + ctx.currentPass, ctx.cmdBuff); + queue.transparentQueue.recordCommandBuffer( + ctx.device, camera, ctx.currentPass, ctx.cmdBuff, 0); + queue.transparentInstancingQueue.recordCommandBuffer( + ctx.currentPass, ctx.cmdBuff); if (any(sceneData.flags & SceneFlags::UI)) { submitUICommands(ctx.currentPass, ctx.currentPassLayoutID, camera, ctx.cmdBuff); @@ -1750,41 +1551,41 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { } void end(const gfx::Viewport& pass, RenderGraph::vertex_descriptor vertID) const { } + + void mountResource(const ccstd::pmr::string& name) const { // NOLINT(misc-no-recursion) + auto resIter = ctx.fgd.resourceAccessGraph.resourceIndex.find(name); + if (resIter != ctx.fgd.resourceAccessGraph.resourceIndex.end()) { + auto resID = resIter->second; + auto& resg = ctx.resourceGraph; + resg.mount(ctx.device, resID); + for (const auto& subres : makeRange(children(resID, resg))) { + const auto& subresName = get(ResourceGraph::NameTag{}, resg, subres.target); + mountResource(subresName); + } + } + } void mountResources(const Subpass& pass) const { - auto& resg = ctx.resourceGraph; // mount managed resources for (const auto& [name, view] : pass.rasterViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } for (const auto& resolve : pass.resolvePairs) { - auto resID = findVertex(resolve.target, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(resolve.target); } } void mountResources(const RasterPass& pass) const { - auto& resg = ctx.resourceGraph; // mount managed resources for (const auto& [name, view] : pass.rasterViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } - for (const auto& subpass : pass.subpassGraph.subpasses) { mountResources(subpass); } @@ -1794,9 +1595,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } } @@ -1804,9 +1603,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } } @@ -1814,9 +1611,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& [name, views] : pass.computeViews) { - auto resID = findVertex(name, resg); - CC_EXPECTS(resID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, resID); + mountResource(name); } } @@ -1824,12 +1619,8 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& pair : pass.resolvePairs) { - const auto& srcID = findVertex(pair.source, resg); - CC_EXPECTS(srcID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, srcID); - const auto& dstID = findVertex(pair.target, resg); - CC_EXPECTS(dstID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, dstID); + mountResource(pair.source); + mountResource(pair.target); } } @@ -1837,17 +1628,11 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& resg = ctx.resourceGraph; PmrFlatSet mounted(ctx.scratch); for (const auto& pair : pass.copyPairs) { - const auto& srcID = findVertex(pair.source, resg); - CC_EXPECTS(srcID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, srcID); - const auto& dstID = findVertex(pair.target, resg); - CC_EXPECTS(dstID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, dstID); + mountResource(pair.source); + mountResource(pair.target); } for (const auto& pair : pass.uploadPairs) { - const auto& dstID = findVertex(pair.target, resg); - CC_EXPECTS(dstID != ResourceGraph::null_vertex()); - resg.mount(ctx.device, dstID); + mountResource(pair.target); } } @@ -2223,7 +2008,7 @@ void NativePipeline::executeRenderGraph(const RenderGraph& rg) { RenderGraphVisitorContext ctx{ ppl.nativeContext, lg, rg, ppl.resourceGraph, - fgd, fgd.barrierMap, + fgd, validPasses, ppl.device, submit.primaryCommandBuffer, &ppl, diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index ff89a8cd6dc..f747e151f36 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -42,6 +42,50 @@ namespace cc { namespace render { +template +void addSubresourceNode(ResourceGraph::vertex_descriptor v, const ccstd::string &name, ResourceGraph &resg); + +template <> +void addSubresourceNode(ResourceGraph::vertex_descriptor v, const ccstd::string &name, ResourceGraph &resg) { + SubresourceView view{ + nullptr, + gfx::Format::DEPTH_STENCIL, + 0, 1, 0, 1, 0, 1}; + + auto desc = get(ResourceGraph::DescTag{}, resg, v); + auto traits = get(ResourceGraph::TraitsTag{}, resg, v); + auto samplerInfo = get(ResourceGraph::SamplerTag{}, resg, v); + + ccstd::string depthName{name}; + depthName += "/"; + depthName += DEPTH_PLANE_NAME; + auto depthID = addVertex( + SubresourceViewTag{}, + std::forward_as_tuple(depthName.c_str()), + std::forward_as_tuple(desc), + std::forward_as_tuple(traits.residency), + std::forward_as_tuple(), + std::forward_as_tuple(samplerInfo), + std::forward_as_tuple(view), + resg, + v); + + view.firstPlane = 1; + ccstd::string stencilName{name}; + stencilName += "/"; + stencilName += STENCIL_PLANE_NAME; + auto stencilID = addVertex( + SubresourceViewTag{}, + std::forward_as_tuple(stencilName.c_str()), + std::forward_as_tuple(desc), + std::forward_as_tuple(traits.residency), + std::forward_as_tuple(), + std::forward_as_tuple(samplerInfo), + std::forward_as_tuple(view), + resg, + v); +} + NativePipeline::NativePipeline(const allocator_type &alloc) noexcept : device(gfx::Device::getInstance()), globalDSManager(std::make_unique()), @@ -194,7 +238,8 @@ uint32_t NativePipeline::addDepthStencil(const ccstd::string &name, gfx::Format samplerInfo.magFilter = gfx::Filter::POINT; samplerInfo.minFilter = gfx::Filter::POINT; samplerInfo.mipFilter = gfx::Filter::NONE; - return addVertex( + + auto resID = addVertex( ManagedTextureTag{}, std::forward_as_tuple(name.c_str()), std::forward_as_tuple(desc), @@ -203,6 +248,9 @@ uint32_t NativePipeline::addDepthStencil(const ccstd::string &name, gfx::Format std::forward_as_tuple(samplerInfo), std::forward_as_tuple(), resourceGraph); + + addSubresourceNode(resID, name, resourceGraph); + return resID; } uint32_t NativePipeline::addResource(const ccstd::string& name, ResourceDimension dimension, diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 528c95d5ce7..91c9dcf73b4 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -298,6 +298,21 @@ void addRasterViewImpl( auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); const auto slotID = getSlotID(pass, name, attachmentType); CC_EXPECTS(subpass.rasterViews.size() == subpassData.rasterViews.size()); + auto nameIter = subpassData.rasterViews.find(name); + + if (nameIter != subpassData.rasterViews.end()) { + auto &view = subpass.rasterViews.at(name.data()); + if (!defaultAttachment(slotName)) { + nameIter->second.slotName = slotName; + view.slotName = slotName; + } + if (!defaultAttachment(slotName1)) { + nameIter->second.slotName1 = slotName1; + view.slotName1 = slotName1; + } + return; + } + { auto res = subpassData.rasterViews.emplace( std::piecewise_construct, @@ -321,6 +336,7 @@ void addRasterViewImpl( std::forward_as_tuple(name), std::forward_as_tuple( ccstd::pmr::string(slotName, subpassData.get_allocator()), + ccstd::pmr::string(slotName1, subpassData.get_allocator()), accessType, attachmentType, loadOp, @@ -533,18 +549,18 @@ void NativeRenderSubpassBuilderImpl::setShowStatistics(bool enable) { void NativeMultisampleRenderSubpassBuilder::resolveRenderTarget( const ccstd::string &source, const ccstd::string &target) { // NOLINT(bugprone-easily-swappable-parameters) auto &subpass = get(RasterSubpassTag{}, nodeID, *renderGraph); - + auto parentID = parent(nodeID, *renderGraph); auto &pass = get(RasterPassTag{}, parentID, *renderGraph); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); - + subpass.resolvePairs.emplace_back( ccstd::pmr::string(source.data(), renderGraph->get_allocator()), ccstd::pmr::string(target.data(), renderGraph->get_allocator()), ResolveFlags::COLOR, gfx::ResolveMode::AVERAGE, gfx::ResolveMode::NONE); - + subpassData.resolvePairs.emplace_back(subpass.resolvePairs.back()); } @@ -559,7 +575,7 @@ void NativeMultisampleRenderSubpassBuilder::resolveDepthStencil( if (stencilMode != gfx::ResolveMode::NONE) { flags |= ResolveFlags::STENCIL; } - + auto parentID = parent(nodeID, *renderGraph); auto &pass = get(RasterPassTag{}, parentID, *renderGraph); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); @@ -570,7 +586,7 @@ void NativeMultisampleRenderSubpassBuilder::resolveDepthStencil( flags, depthMode, stencilMode); - + subpassData.resolvePairs.emplace_back(subpass.resolvePairs.back()); } @@ -1137,17 +1153,17 @@ void NativeMultisampleRenderPassBuilder::setShowStatistics(bool enable) { void NativeMultisampleRenderPassBuilder::resolveRenderTarget( const ccstd::string &source, const ccstd::string &target) { // NOLINT(bugprone-easily-swappable-parameters) auto &subpass = get(RasterSubpassTag{}, subpassID, *renderGraph); - + auto &pass = get(RasterPassTag{}, nodeID, *renderGraph); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); - + subpass.resolvePairs.emplace_back( ccstd::pmr::string(source.data(), renderGraph->get_allocator()), ccstd::pmr::string(target.data(), renderGraph->get_allocator()), ResolveFlags::COLOR, gfx::ResolveMode::AVERAGE, gfx::ResolveMode::NONE); - + subpassData.resolvePairs.emplace_back(subpass.resolvePairs.back()); } @@ -1162,7 +1178,7 @@ void NativeMultisampleRenderPassBuilder::resolveDepthStencil( if (stencilMode != gfx::ResolveMode::NONE) { flags |= ResolveFlags::STENCIL; } - + auto &pass = get(RasterPassTag{}, nodeID, *renderGraph); auto &subpassData = get(SubpassGraph::SubpassTag{}, pass.subpassGraph, subpass.subpassID); @@ -1172,7 +1188,7 @@ void NativeMultisampleRenderPassBuilder::resolveDepthStencil( flags, depthMode, stencilMode); - + subpassData.resolvePairs.emplace_back(subpass.resolvePairs.back()); } diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h b/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h index 18858869210..bf1ff547408 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h @@ -211,6 +211,19 @@ void addSubpassComputeViewImpl( subpassData.computeViews.find(std::string_view{name})->second.size()); } +inline bool defaultAttachment(std::string_view slotName) { + return slotName.empty() || slotName == "_"; +} + +static constexpr std::string_view DEPTH_PLANE_NAME = "depth"; +static constexpr std::string_view STENCIL_PLANE_NAME = "stencil"; +static constexpr std::string_view CUBE_TOP_NAME = "Top"; +static constexpr std::string_view CUBE_BOTTOM_NAME = "Bottom"; +static constexpr std::string_view CUBE_FRONT_NAME = "Front"; +static constexpr std::string_view CUBE_REAR_NAME = "Rear"; +static constexpr std::string_view CUBE_LEFT_NAME = "Left"; +static constexpr std::string_view CUBE_RIGHT_NAME = "Right"; + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp index 984e215a9ad..5c8ce3ee84f 100644 --- a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp @@ -22,10 +22,12 @@ THE SOFTWARE. ****************************************************************************/ +#include #include "NativePipelineTypes.h" #include "RenderGraphGraphs.h" #include "RenderGraphTypes.h" #include "cocos/renderer/gfx-base/GFXDevice.h" +#include "details/GraphView.h" #include "details/Range.h" #include "gfx-base/GFXDef-common.h" #include "pipeline/custom/RenderCommonFwd.h" @@ -168,6 +170,23 @@ gfx::TextureInfo getTextureInfo(const ResourceDesc& desc, bool bCube = false) { }; } +gfx::TextureViewInfo getTextureViewInfo(const SubresourceView& subresView, const ResourceDesc& desc, bool bCube = false) { + using namespace gfx; // NOLINT(google-build-using-namespace) + + const auto& textureInfo = getTextureInfo(desc, bCube); + + return { + nullptr, + textureInfo.type, + subresView.format, + subresView.indexOrFirstMipLevel, + subresView.numMipLevels, + subresView.firstArraySlice, + subresView.numArraySlices, + subresView.firstPlane, + subresView.numPlanes, + }; +} } // namespace bool ManagedTexture::checkResource(const ResourceDesc& desc) const { @@ -243,10 +262,9 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_EXPECTS(parentID != resg.null_vertex()); CC_EXPECTS(resg.isTexture(parentID)); CC_ENSURES(!resg.isTextureView(parentID)); - mount(device, parentID); + mount(device, parentID); // NOLINT(misc-no-recursion) }, - [&](const SubresourceView& view) { // NOLINT(misc-no-recursion) - std::ignore = view; + [&](SubresourceView& view) { // NOLINT(misc-no-recursion) auto parentID = parent(vertID, resg); CC_EXPECTS(parentID != resg.null_vertex()); while (resg.isTextureView(parentID)) { @@ -255,7 +273,13 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_EXPECTS(parentID != resg.null_vertex()); CC_EXPECTS(resg.isTexture(parentID)); CC_ENSURES(!resg.isTextureView(parentID)); - mount(device, parentID); + auto* parentTexture = resg.getTexture(parentID); + const auto& desc = get(ResourceGraph::DescTag{}, resg, vertID); + if (!view.textureView) { + auto textureViewInfo = getTextureViewInfo(view, desc); + textureViewInfo.texture = parentTexture; + view.textureView = device->createTexture(textureViewInfo); + } }); } @@ -362,8 +386,7 @@ gfx::Texture* ResourceGraph::getTexture(vertex_descriptor resID) { }, [&](const SubresourceView& view) { // TODO(zhouzhenglong): add ImageView support - std::ignore = view; - CC_EXPECTS(false); + texture = view.textureView; }, [&](const auto& buffer) { std::ignore = buffer; diff --git a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp index f2cfd0111b0..0b9a2865259 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSceneCulling.cpp @@ -104,7 +104,7 @@ void SceneCulling::collectCullingQueries( } namespace { - +const pipeline::PipelineSceneData* pSceneData = nullptr; bool isNodeVisible(const Node* node, uint32_t visibility) { return node && ((visibility & node->getLayer()) == node->getLayer()); } @@ -113,9 +113,18 @@ uint32_t isModelVisible(const scene::Model& model, uint32_t visibility) { return visibility & static_cast(model.getVisFlags()); } -bool isFrustumVisible(const scene::Model& model, const geometry::Frustum& frustum) { +bool isFrustumVisible(const scene::Model& model, const geometry::Frustum& frustum, bool castShadow) { const auto* const modelWorldBounds = model.getWorldBounds(); - return !modelWorldBounds || modelWorldBounds->aabbFrustum(frustum); + if (!modelWorldBounds) { + return true; + } + geometry::AABB transWorldBounds{}; + transWorldBounds.set(modelWorldBounds->getCenter(), modelWorldBounds->getHalfExtents()); + const scene::Shadows& shadows = *pSceneData->getShadows(); + if (shadows.getType() == scene::ShadowType::PLANAR && castShadow) { + modelWorldBounds->transform(shadows.getMatLight(), &transWorldBounds); + } + return transWorldBounds.aabbFrustum(frustum); } void octreeCulling( @@ -183,7 +192,7 @@ void bruteForceCulling( // filter model by view visibility if (isNodeVisible(model.getNode(), visibility) || isModelVisible(model, visibility)) { // frustum culling - if (!isFrustumVisible(model, cameraOrLightFrustum)) { + if (!isFrustumVisible(model, cameraOrLightFrustum, bCastShadow)) { continue; } // is skybox, skip @@ -248,14 +257,23 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) models); break; case scene::LightType::DIRECTIONAL: { - const auto& csmLayers = *pplSceneData.getCSMLayers(); + auto& csmLayers = *pplSceneData.getCSMLayers(); const auto* mainLight = dynamic_cast(light); const auto& csmLevel = mainLight->getCSMLevel(); const geometry::Frustum* frustum = nullptr; - if (mainLight->isShadowFixedArea() || csmLevel == scene::CSMLevel::LEVEL_1) { - frustum = &csmLayers.getSpecialLayer()->getValidFrustum(); + const auto& shadows = *pplSceneData.getShadows(); + if (shadows.getType() == scene::ShadowType::PLANAR) { + frustum = &camera.getFrustum(); } else { - frustum = &csmLayers.getLayers()[level]->getValidFrustum(); + if (shadows.isEnabled() && shadows.getType() == scene::ShadowType::SHADOW_MAP && mainLight && mainLight->getNode()) { + csmLayers.update(&pplSceneData, &camera); + } + // const + if (mainLight->isShadowFixedArea() || csmLevel == scene::CSMLevel::LEVEL_1) { + frustum = &csmLayers.getSpecialLayer()->getValidFrustum(); + } else { + frustum = &csmLayers.getLayers()[level]->getValidFrustum(); + } } sceneCulling( skyboxModelToSkip, @@ -281,7 +299,6 @@ void SceneCulling::batchCulling(const pipeline::PipelineSceneData& pplSceneData) } namespace { - bool isBlend(const scene::Pass& pass) { bool bBlend = false; for (const auto& target : pass.getBlendState()->targets) { @@ -307,7 +324,6 @@ void addRenderObject( LayoutGraphData::vertex_descriptor phaseLayoutID, const bool bDrawOpaqueOrMask, const bool bDrawBlend, - const bool bDrawShadowCaster, const scene::Camera& camera, const scene::Model& model, NativeRenderQueue& queue) { @@ -328,15 +344,13 @@ void addRenderObject( // check scene flags const bool bBlend = isBlend(pass); const bool bOpaqueOrMask = !bBlend; - if (!bDrawShadowCaster) { - if (!bDrawBlend && bBlend) { - // skip transparent object - continue; - } - if (!bDrawOpaqueOrMask && bOpaqueOrMask) { - // skip opaque object - continue; - } + if (!bDrawBlend && bBlend) { + // skip transparent object + continue; + } + if (!bDrawOpaqueOrMask && bOpaqueOrMask) { + // skip opaque object + continue; } // add object to queue @@ -417,7 +431,7 @@ void SceneCulling::fillRenderQueues( // fill native queue for (const auto* const model : sourceModels) { addRenderObject( - phaseLayoutID, bDrawOpaqueOrMask, bDrawBlend, bDrawShadowCaster, + phaseLayoutID, bDrawOpaqueOrMask, bDrawBlend, *sceneData.camera, *model, nativeQueue); } @@ -429,6 +443,7 @@ void SceneCulling::fillRenderQueues( void SceneCulling::buildRenderQueues( const RenderGraph& rg, const LayoutGraphData& lg, const pipeline::PipelineSceneData& pplSceneData) { + pSceneData = &pplSceneData; collectCullingQueries(rg, lg); batchCulling(pplSceneData); fillRenderQueues(rg, pplSceneData); diff --git a/native/cocos/renderer/pipeline/custom/test/test.h b/native/cocos/renderer/pipeline/custom/test/test.h index ed8f44f5eec..f329ac731f4 100644 --- a/native/cocos/renderer/pipeline/custom/test/test.h +++ b/native/cocos/renderer/pipeline/custom/test/test.h @@ -60,7 +60,6 @@ using framegraph::PassBarrierPair; using framegraph::ResourceBarrier; using RasterViews = PmrTransparentMap; using ComputeViews = PmrTransparentMap>; -using BarrierMap = FrameGraphDispatcher::BarrierMap; static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescInfo, const LayoutInfo &layoutInfo, RenderGraph &renderGraph, ResourceGraph &rescGraph, LayoutGraphData &layoutGraphData) { for (const auto &resc : rescInfo) { @@ -104,6 +103,7 @@ static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescIn auto addRasterNode = [&](const vector>> &subpasses, uint32_t count, uint32_t passID) { const ccstd::string name = "pass" + std::to_string(passID); const auto vertexID = add_vertex(renderGraph, RasterPassTag{}, name.c_str()); + renderGraph.sortedVertices.emplace_back(vertexID); auto &raster = get(RasterPassTag{}, vertexID, renderGraph); auto &subpassGraph = raster.subpassGraph; @@ -195,6 +195,7 @@ static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescIn const ccstd::string name = "pass" + std::to_string(passCount++); const auto vertexID = add_vertex(renderGraph, ComputeTag{}, name.c_str()); + renderGraph.sortedVertices.emplace_back(vertexID); assert(subpasses.back().size() == 2); // inputs and outputs auto &computePass = get(ComputeTag{}, vertexID, renderGraph); @@ -231,6 +232,7 @@ static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescIn const ccstd::string name = "pass" + std::to_string(passCount++); const auto vertexID = add_vertex(renderGraph, CopyTag{}, name.c_str()); + renderGraph.sortedVertices.emplace_back(vertexID); assert(subpasses.back().size() == 2); // inputs and outputs auto ©Pass = get(CopyTag{}, vertexID, renderGraph); const auto &inputsAndOutputs = subpasses.back(); @@ -260,302 +262,6 @@ static void fillTestGraph(const ViewInfo &rasterData, const ResourceInfo &rescIn fgDispatcher.run(); */ } -static void fillBarriers(const ResourceGraph &resourceGraph, const BarrierPair &barrierInfo, framegraph::PassNodeBuilder &builder, PassBarrierPair &barriers) { - auto doFill = [&builder, &resourceGraph](const std::vector &edgeInfo, std::vector &edgeBarriers) { - for (const auto &resBarrier : edgeInfo) { - const auto &name = get(ResourceGraph::NameTag{}, resourceGraph, resBarrier.resourceID); - const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resBarrier.resourceID); - auto type = desc.dimension == ResourceDimension::BUFFER ? cc::framegraph::ResourceType::BUFFER : cc::framegraph::ResourceType::TEXTURE; - framegraph::Range layerRange; - framegraph::Range mipRange; - if (type == framegraph::ResourceType::BUFFER) { - auto bufferRange = ccstd::get(resBarrier.beginStatus.range); - layerRange = {0, 0}; - mipRange = {bufferRange.offset, bufferRange.size}; - } else { - auto textureRange = ccstd::get(resBarrier.beginStatus.range); - layerRange = {textureRange.firstSlice, textureRange.numSlices}; - mipRange = {textureRange.mipLevel, textureRange.levelCount}; - } - - edgeBarriers.emplace_back(cc::framegraph::ResourceBarrier{ - type, - resBarrier.type, - builder.readFromBlackboard(framegraph::FrameGraph::stringToHandle(name.c_str())), - {resBarrier.beginStatus.passType, - resBarrier.beginStatus.visibility, - resBarrier.beginStatus.access}, - {resBarrier.endStatus.passType, - resBarrier.endStatus.visibility, - resBarrier.endStatus.access}, - layerRange, - mipRange, - }); - } - }; - - doFill(barrierInfo.frontBarriers, barriers.frontBarriers); - doFill(barrierInfo.rearBarriers, barriers.rearBarriers); -} - -struct TestRenderData { - ccstd::vector> outputTexes; -}; - -struct FrameGraphPassInfo { - framegraph::FrameGraph &frameGraph; - const RenderGraph &renderGraph; - const ResourceGraph &resourceGraph; - const RasterViews &rasterViews; - const ComputeViews &computeViews; - const BarrierMap &barrierMap; - uint32_t passID{0}; - bool isSubpass{false}; - bool subpassEnd{false}; -}; - -static void addPassToFrameGraph(const FrameGraphPassInfo &info) { - const auto &rasterViews = info.rasterViews; - const auto &passID = info.passID; - const auto &barrierMap = info.barrierMap; - const auto &renderGraph = info.renderGraph; - const auto &resourceGraph = info.resourceGraph; - auto &frameGraph = info.frameGraph; - bool isSupass = info.isSubpass; - bool subpassEnd = info.subpassEnd; - - auto forwardSetup = [&](framegraph::PassNodeBuilder &builder, TestRenderData &data) { - if (isSupass) { - builder.subpass(subpassEnd); - } - - auto goThroughRasterViews = [&](const RasterViews &views) { - for (const auto &view : views) { - const auto handle = framegraph::FrameGraph::stringToHandle(view.second.slotName.c_str()); - auto typedHandle = builder.readFromBlackboard(handle); - data.outputTexes.emplace_back(); - auto &lastTex = data.outputTexes.back(); - framegraph::Texture::Descriptor colorTexInfo; - colorTexInfo.format = gfx::Format::RGBA8; - - // if (rasterView.second.accessType == AccessType::READ) { - colorTexInfo.usage = gfx::TextureUsage::INPUT_ATTACHMENT | gfx::TextureUsage::COLOR_ATTACHMENT; - //} - lastTex.first = view.second.accessType; - lastTex.second = static_cast(typedHandle); - - if (framegraph::Handle::IndexType(typedHandle) == framegraph::Handle::UNINITIALIZED) { - colorTexInfo.width = 960; - colorTexInfo.height = 640; - - lastTex.second = builder.create(handle, colorTexInfo); - } - - framegraph::RenderTargetAttachment::Descriptor colorAttachmentInfo; - colorAttachmentInfo.usage = view.second.attachmentType == AttachmentType::RENDER_TARGET ? framegraph::RenderTargetAttachment::Usage::COLOR : framegraph::RenderTargetAttachment::Usage::DEPTH_STENCIL; - colorAttachmentInfo.clearColor = view.second.clearColor; - colorAttachmentInfo.loadOp = view.second.loadOp; - if (view.second.accessType == AccessType::WRITE) { - lastTex.second = builder.write(lastTex.second, colorAttachmentInfo); - builder.writeToBlackboard(handle, lastTex.second); - colorAttachmentInfo.beginAccesses = colorAttachmentInfo.endAccesses = gfx::AccessFlagBit::COLOR_ATTACHMENT_WRITE; - } else { - colorAttachmentInfo.beginAccesses = colorAttachmentInfo.endAccesses = gfx::AccessFlagBit::COLOR_ATTACHMENT_READ; - auto res = builder.read(framegraph::TextureHandle(builder.readFromBlackboard(handle))); - builder.writeToBlackboard(handle, res); - } - } - }; - - auto goThroughComputeViews = [&](const ComputeViews &views) { - for (const auto &pair : views) { - for (const auto &view : pair.second) { - const auto handle = framegraph::FrameGraph::stringToHandle(view.name.c_str()); - auto typedHandle = builder.readFromBlackboard(handle); - data.outputTexes.emplace_back(); - auto &lastTex = data.outputTexes.back(); - framegraph::Texture::Descriptor colorTexInfo; - colorTexInfo.format = gfx::Format::RGBA8; - - // if (rasterView.second.accessType == AccessType::READ) { - colorTexInfo.usage = gfx::TextureUsage::INPUT_ATTACHMENT | gfx::TextureUsage::COLOR_ATTACHMENT; - //} - lastTex.first = view.accessType; - lastTex.second = static_cast(typedHandle); - - if (framegraph::Handle::IndexType(typedHandle) == framegraph::Handle::UNINITIALIZED) { - colorTexInfo.width = 960; - colorTexInfo.height = 640; - - lastTex.second = builder.create(handle, colorTexInfo); - } - - framegraph::RenderTargetAttachment::Descriptor colorAttachmentInfo; - - if (view.accessType == AccessType::WRITE) { - lastTex.second = builder.write(lastTex.second); - builder.writeToBlackboard(handle, lastTex.second); - } else { - auto res = builder.read(framegraph::TextureHandle(builder.readFromBlackboard(handle))); - builder.writeToBlackboard(handle, res); - } - } - } - }; - - goThroughRasterViews(info.rasterViews); - goThroughComputeViews(info.computeViews); - - builder.setViewport({0U, 640U, 0U, 960U, 0.0F, 1.0F}, {0U, 0U, 960U, 640U}); - - if (barrierMap.find(passID + 1) == barrierMap.end()) { - return; - } - const auto &barrier = barrierMap.at(passID + 1); - PassBarrierPair barrierPairs; - fillBarriers(resourceGraph, barrier.blockBarrier, builder, barrierPairs); - builder.setBarrier(barrierPairs); - }; - - auto forwardExec = [](const TestRenderData &data, - const framegraph::DevicePassResourceTable &table) { - /*for(const auto& pair: data.outputTexes) { - if(pair.first == AccessType::WRITE) { - table.getWrite(pair.second); - } - if(pair.first == AccessType::READ) { - table.getRead(pair.second); - } - if(pair.first == AccessType::READ_WRITE) { - table.getRead(pair.second); - table.getWrite(pair.second); - } - }*/ - }; - - auto passHandle = framegraph::FrameGraph::stringToHandle(get(RenderGraph::NameTag{}, renderGraph, passID).c_str()); - - string presentHandle; - - for (const auto &view : rasterViews) { - // write or read_write - if (view.second.accessType != AccessType::READ) { - presentHandle = view.first; - break; - } - } - - frameGraph.addPass(static_cast(ForwardInsertPoint::IP_FORWARD), passHandle, forwardSetup, forwardExec); -} - -static void runTestGraph(const RenderGraph &renderGraph, const ResourceGraph &resourceGraph, const LayoutGraphData &layoutGraphData, const FrameGraphDispatcher &fgDispatcher) { - const auto &barriers = fgDispatcher.getBarriers(); - - framegraph::FrameGraph framegraph; - - auto *device = gfx::Device::getInstance(); - if (!device) { - device = gfx::DeviceManager::create(); - } - - for (const auto passID : makeRange(vertices(renderGraph))) { - visitObject( - passID, renderGraph, - [&](const RasterPass &pass) { - // TestRenderData tmpData; - const auto &subpasses = get(SubpassGraph::SubpassTag{}, pass.subpassGraph); - uint32_t count = 0; - for (const auto &subpass : *subpasses.container) { - FrameGraphPassInfo info = { - framegraph, - renderGraph, - resourceGraph, - subpass.rasterViews, - subpass.computeViews, - fgDispatcher.getBarriers(), - passID, - true, - count < subpasses.container->size() - 1}; - addPassToFrameGraph(info); - ++count; - }; - if ((*subpasses.container).empty()) { - FrameGraphPassInfo info = { - framegraph, - renderGraph, - resourceGraph, - pass.rasterViews, - pass.computeViews, - fgDispatcher.getBarriers(), - passID, - false, - false}; - addPassToFrameGraph(info); - ++count; - } - }, - [&](const ComputePass &pass) { - // TestRenderData tmpData; - FrameGraphPassInfo info = { - framegraph, - renderGraph, - resourceGraph, - {}, - pass.computeViews, - fgDispatcher.getBarriers(), - passID, - false, - false}; - addPassToFrameGraph(info); - }, - [&](const CopyPass &pass) { - auto forwardSetup = [&](framegraph::PassNodeBuilder &builder, TestRenderData &data) { - for (const auto &pair : pass.copyPairs) { - for (size_t i = 0; i < 2; ++i) { - bool write = (i % 2 == 0); - const auto handle = framegraph::FrameGraph::stringToHandle(write ? pair.target.c_str() : pair.source.c_str()); - auto typedHandle = builder.readFromBlackboard(handle); - data.outputTexes.emplace_back(); - auto &lastTex = data.outputTexes.back(); - framegraph::Texture::Descriptor colorTexInfo; - colorTexInfo.format = gfx::Format::RGBA8; - colorTexInfo.usage = write ? gfx::TextureUsage::TRANSFER_DST : gfx::TextureUsage::TRANSFER_SRC; - - lastTex.second = static_cast(typedHandle); - - if (framegraph::Handle::IndexType(typedHandle) == framegraph::Handle::UNINITIALIZED) { - colorTexInfo.width = 960; - colorTexInfo.height = 640; - - lastTex.second = builder.create(handle, colorTexInfo); - } - - if (write) { - lastTex.second = builder.write(lastTex.second); - builder.writeToBlackboard(handle, lastTex.second); - } else { - auto res = builder.read(framegraph::TextureHandle(builder.readFromBlackboard(handle))); - builder.writeToBlackboard(handle, res); - } - } - } - }; - - auto forwardExec = [](const TestRenderData &data, - const framegraph::DevicePassResourceTable &table) { - }; - - auto passHandle = framegraph::FrameGraph::stringToHandle(get(RenderGraph::NameTag{}, renderGraph, passID).c_str()); - framegraph.addPass(static_cast(ForwardInsertPoint::IP_FORWARD), passHandle, forwardSetup, forwardExec); - }, - [&](const RaytracePass &pass) {}, - [&](const auto & /*pass*/) {}); - } - framegraph.compile(); - framegraph.execute(); - framegraph.reset(); -} - #define TEST_CASE_DEFINE \ using namespace cc::render; \ using cc::gfx::AccessFlagBit; \ diff --git a/native/tests/unit-test/src/complicated_barrier_case.cpp b/native/tests/unit-test/src/complicated_barrier_case.cpp index 3fdb5ae8a40..a837a4867a1 100644 --- a/native/tests/unit-test/src/complicated_barrier_case.cpp +++ b/native/tests/unit-test/src/complicated_barrier_case.cpp @@ -46,202 +46,67 @@ TEST(complicatedBarrierTest, test12) { }); }; - const auto& barrierMap = fgDispatcher.getBarriers(); + const auto& barrierMap = fgDispatcher.resourceAccessGraph.barrier; const auto& rag = fgDispatcher.resourceAccessGraph; - ExpectEq(rag._vertices.size() == 17, true); + ExpectEq(rag._vertices.size() == 23, true); // head const auto& head = barrierMap.at(0); - ExpectEq(head.blockBarrier.frontBarriers.empty(), true); - ExpectEq(head.blockBarrier.rearBarriers.empty(), true); - ExpectEq(head.subpassBarriers.empty(), true); + ExpectEq(head.frontBarriers.empty(), true); + ExpectEq(head.rearBarriers.empty(), true); // 1st node const auto& node1 = barrierMap.at(1); // block barrier: replace by rnderpass info, same below //ExpectEq(node1.blockBarrier.frontBarriers.size() == 2, true); //ExpectEq(node1.blockBarrier.rearBarriers.size() == 1, true); - ExpectEq(node1.subpassBarriers.empty(), false); - - //ExpectEq(node1.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].resourceID == 1, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].beginStatus.vertID == 1, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].endStatus.vertID == 1, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].endStatus.access == MemoryAccessBit::READ_ONLY, true); - - //subpass barrier: like normal pass - const auto& node1subpass = node1.subpassBarriers; - ExpectEq(node1subpass[0].frontBarriers.empty(), false); - ExpectEq(node1subpass[0].rearBarriers.size() == 1, true); - - // undefined external depends - const auto& node1subpassres0 = node1subpass[0].rearBarriers[0]; - ExpectEq(node1subpassres0.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(node1subpassres0.resourceID == 0, true); - // vertid in subpass:subpass index, same below - ExpectEq(node1subpassres0.beginStatus.vertID == 0, true); - ExpectEq(node1subpassres0.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node1subpassres0.beginStatus.passType == PassType::RASTER, true); - ExpectEq(node1subpassres0.endStatus.vertID == 1, true); - ; - ExpectEq(node1subpassres0.endStatus.access == MemoryAccessBit::READ_ONLY, true); - ExpectEq(node1subpassres0.endStatus.passType == PassType::RASTER, true); - - ExpectEq(node1subpass[1].frontBarriers.size() == 1, true); - const auto& node1subpassres1 = node1subpass[1].rearBarriers[0]; - ExpectEq(node1subpassres1.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(node1subpassres1.resourceID == 1, true); - ExpectEq(node1subpassres1.beginStatus.vertID == 1, true); - ExpectEq(node1subpassres1.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node1subpassres1.beginStatus.passType == PassType::RASTER, true); - ExpectEq(node1subpassres1.endStatus.vertID == 1, true); - ; - ExpectEq(node1subpassres1.endStatus.access == MemoryAccessBit::READ_ONLY, true); - ExpectEq(node1subpassres1.endStatus.passType == PassType::RASTER, true); - - //node2 - const auto& node2 = barrierMap.at(2); - //ExpectEq(node2.blockBarrier.frontBarriers.size() == 2, true); - //ExpectEq(node2.blockBarrier.rearBarriers.size() == 1, true); - ExpectEq(node2.subpassBarriers.size() == 2, true); - - //const auto& node2blockRear = node2.blockBarrier.rearBarriers; - //auto iter3in2 = findBarrierByResID(node2blockRear, 3); - //const auto& res3in2 = (*iter3in2); - //ExpectEq(res3in2.resourceID == 3, true); - //ExpectEq(res3in2.type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(res3in2.beginStatus.vertID == 2, true); - //ExpectEq(res3in2.beginStatus.passType == PassType::RASTER, true); - //ExpectEq(res3in2.endStatus.vertID == 2, true); - //ExpectEq(res3in2.endStatus.passType == PassType::RASTER, true); - - const auto& node2subpass = node2.subpassBarriers; - ExpectEq(node2subpass.empty(), false); - // subpass dependency instead of extra barrier - ExpectEq(node2subpass[0].frontBarriers.size() == 1, true); - ExpectEq(node2subpass[0].rearBarriers.empty(), false); - - const auto& node2subpassRes2 = node2subpass[0].rearBarriers[0]; - ExpectEq(node2subpassRes2.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(node2subpassRes2.resourceID == 2, true); - ExpectEq(node2subpassRes2.beginStatus.vertID == 0, true); - ExpectEq(node2subpassRes2.beginStatus.passType == PassType::RASTER, true); - ExpectEq(node2subpassRes2.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node2subpassRes2.endStatus.vertID == 1, true); - ExpectEq(node2subpassRes2.endStatus.access == MemoryAccessBit::READ_ONLY, true); //node3 // renderpass info layout instead - const auto& node3 = barrierMap.at(3); - ExpectEq(node3.blockBarrier.frontBarriers.empty(), true); - ExpectEq(node3.blockBarrier.rearBarriers.empty(), true); - - // subpass barrier size is the same as renderpass subpassinfo, though maybe empty. - ExpectEq(node3.subpassBarriers.size() == 1, true); - ExpectEq(node3.subpassBarriers.front().frontBarriers.empty(), true); - ExpectEq(node3.subpassBarriers.front().rearBarriers.empty(), true); - - //node4 - const auto& node4 = barrierMap.at(4); - //ExpectEq(node4.blockBarrier.frontBarriers.size() == 2, true); - //ExpectEq(node4.blockBarrier.rearBarriers.size() == 1, true); - ExpectEq(node4.subpassBarriers.empty(), false); - - //const auto& node4block = node4.blockBarrier; - //auto iter5in4 = findBarrierByResID(node4block.rearBarriers, 5); - //ExpectEq(iter5in4 == node4block.rearBarriers.end(), true); - - //auto iter6in4 = findBarrierByResID(node4block.rearBarriers, 6); - //ExpectEq(iter6in4 != node4block.rearBarriers.end(), true); - //ExpectEq((*iter6in4).type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq((*iter6in4).resourceID == 6, true); - //ExpectEq((*iter6in4).beginStatus.vertID == 4, true); - //ExpectEq((*iter6in4).endStatus.vertID == 14, true); - - const auto& node4subpass0 = node4.subpassBarriers[0]; - // subpass undefined external depends - ExpectEq(node4subpass0.frontBarriers.empty(), false); - ExpectEq(node4subpass0.rearBarriers.size() == 1, true); - ExpectEq(node4subpass0.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - ExpectEq(node4subpass0.rearBarriers[0].resourceID == 5, true); - ExpectEq(node4subpass0.rearBarriers[0].beginStatus.vertID == 0, true); - ExpectEq(node4subpass0.rearBarriers[0].beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node4subpass0.rearBarriers[0].endStatus.vertID == 1, true); - ExpectEq(node4subpass0.rearBarriers[0].endStatus.access == MemoryAccessBit::READ_ONLY, true); - - const auto& node4subpass1 = node4.subpassBarriers[1]; - ExpectEq(node4subpass1.frontBarriers.empty(), false); - ExpectEq(node4subpass1.rearBarriers.size() == 1, true); - ExpectEq(node4subpass1.rearBarriers[0].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - ExpectEq(node4subpass1.rearBarriers[0].resourceID == 6, true); - // external subpass depends - ExpectEq(node4subpass1.rearBarriers[0].beginStatus.vertID == 0xFFFFFFFF, true); - ExpectEq(node4subpass1.rearBarriers[0].beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - // external subpass depends - ExpectEq(node4subpass1.rearBarriers[0].endStatus.vertID == 0xFFFFFFFF, true); - ExpectEq(node4subpass1.rearBarriers[0].endStatus.access == MemoryAccessBit::READ_ONLY, true); - - const auto& node5 = barrierMap.at(5); - ExpectEq(node5.blockBarrier.frontBarriers.size() == 1, true); - ExpectEq(node5.blockBarrier.rearBarriers.size() == 1, true); - // not raster pass - ExpectEq(node5.subpassBarriers.empty(), true); - - auto iter7in5 = findBarrierByResID(node5.blockBarrier.rearBarriers, 7); - const auto& res7in5 = (*iter7in5); - ExpectEq(res7in5.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(res7in5.resourceID == 7, true); - ExpectEq(res7in5.beginStatus.vertID == 5, true); - ExpectEq(res7in5.endStatus.vertID == 5, true); - ExpectEq(res7in5.beginStatus.passType == PassType::COPY, true); - ExpectEq(res7in5.endStatus.passType == PassType::COPY, true); - ExpectEq(res7in5.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(res7in5.endStatus.access == MemoryAccessBit::READ_ONLY, true); - - const auto& node6 = barrierMap.at(6); - ExpectEq(node6.blockBarrier.frontBarriers.size() == 1, true); + const auto& node3 = barrierMap.at(7); + ExpectEq(node3.frontBarriers.empty(), true); + ExpectEq(node3.rearBarriers.empty(), true); + + const auto& node11 = barrierMap.at(11); + ExpectEq(node11.frontBarriers.size() == 1, true); + ExpectEq(node11.rearBarriers.size() == 1, true); + + auto iter7in11 = findBarrierByResID(node11.rearBarriers, 7); + const auto& res7in11 = (*iter7in11); + ExpectEq(res7in11.type == cc::gfx::BarrierType::FULL, true); + ExpectEq(res7in11.resourceID == 7, true); + ExpectEq(res7in11.beginStatus.accessFlag == AccessFlagBit::TRANSFER_WRITE, true); + ExpectEq(res7in11.endStatus.accessFlag == AccessFlagBit::TRANSFER_READ, true); + + const auto& node12 = barrierMap.at(12); + ExpectEq(node12.frontBarriers.size() == 1, true); // resource later used by raster pass, so that layout can be transferred automatically. - ExpectEq(node6.blockBarrier.rearBarriers.empty(), true); - // not a raster pass - ExpectEq(node6.subpassBarriers.empty(), true); + ExpectEq(node12.rearBarriers.empty(), true); // node7 - const auto& node7 = barrierMap.at(7); + const auto& node13 = barrierMap.at(13); // undefined layout already in initial layout - ExpectEq(node7.blockBarrier.frontBarriers.empty(), true); - ExpectEq(node7.blockBarrier.rearBarriers.empty(), true); - ExpectEq(node7.subpassBarriers.empty(), false); - - ExpectEq(node7.blockBarrier.rearBarriers.size(), 0); - - //node8: almost the same as node7 - //node9: almost the same as node8 - //node10: ditto - //node11: ditto - //node12: ditto + ExpectEq(node13.frontBarriers.empty(), true); + ExpectEq(node13.rearBarriers.empty(), true); //node13 - const auto& node13 = barrierMap.at(13); - ExpectEq(node13.blockBarrier.frontBarriers.size(), 0); - ExpectEq(node13.blockBarrier.rearBarriers.size(), 0); - ExpectEq(node13.subpassBarriers.empty(), false); + const auto& node19 = barrierMap.at(19); + ExpectEq(node19.frontBarriers.size(), 0); + ExpectEq(node19.rearBarriers.size(), 0); //node14: almost the same as 13 //node15: ditto - const auto& node15 = barrierMap.at(15); - const auto& theone = node15.blockBarrier.rearBarriers.front(); + const auto& node21 = barrierMap.at(21); + const auto& theone = node21.rearBarriers.front(); ExpectEq(theone.resourceID == 22, true); ExpectEq(theone.type == cc::gfx::BarrierType::FULL, true); - ExpectEq(theone.endStatus.vertID == 0xFFFFFFFF, true); + ExpectEq(theone.endStatus.accessFlag == AccessFlagBit::PRESENT, true); //node16 const auto& node16 = barrierMap.at(16); - ExpectEq(node16.blockBarrier.frontBarriers.empty(), true); - ExpectEq(node16.blockBarrier.rearBarriers.empty(), true); - // not raster pass - ExpectEq(node16.subpassBarriers.empty(), true); + ExpectEq(node16.frontBarriers.empty(), true); + ExpectEq(node16.rearBarriers.empty(), true); //runTestGraph(renderGraph, rescGraph, layoutGraphData, fgDispatcher); } diff --git a/native/tests/unit-test/src/simple_barrier_test.cpp b/native/tests/unit-test/src/simple_barrier_test.cpp index d6c7dc7b5fc..108418e7ced 100644 --- a/native/tests/unit-test/src/simple_barrier_test.cpp +++ b/native/tests/unit-test/src/simple_barrier_test.cpp @@ -40,44 +40,22 @@ TEST(barrierTest, test10) { FrameGraphDispatcher fgDispatcher(rescGraph, renderGraph, layoutGraphData, resource, resource); fgDispatcher.run(); - const auto& barrierMap = fgDispatcher.getBarriers(); + const auto& barrierMap = fgDispatcher.resourceAccessGraph.barrier; const auto& rag = fgDispatcher.resourceAccessGraph; - ExpectEq(rag._vertices.size() == 4, true); + ExpectEq(rag._vertices.size() == 6, true); // head const auto& head = barrierMap.at(0); - ExpectEq(head.blockBarrier.frontBarriers.empty(), true); - ExpectEq(head.blockBarrier.rearBarriers.empty(), true); - - // 1st node - const auto& node1 = barrierMap.at(1); - //ExpectEq(node1.blockBarrier.frontBarriers.size() == 4, true); - //ExpectEq(node1.blockBarrier.rearBarriers.size() == 1, true); - - // undefined external - ExpectEq(node1.subpassBarriers[0].frontBarriers.size() == 3, true); - ExpectEq(node1.subpassBarriers[0].rearBarriers.size() == 3, true); - - // undefined external - ExpectEq(node1.subpassBarriers[1].frontBarriers.size() == 1, true); - ExpectEq(node1.subpassBarriers[1].rearBarriers.size() == 1, true); - - //const auto& barrier = node1.blockBarrier.rearBarriers[0]; - //ExpectEq(barrier.type == BarrierType::FULL, true); - //ExpectEq(barrier.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ////resID 3 - //ExpectEq(barrier.beginStatus.visibility == std::get<2>(layoutInfo[0][3]), true); + ExpectEq(head.frontBarriers.empty(), true); + ExpectEq(head.rearBarriers.empty(), true); //// 2nd node - const auto& node2 = barrierMap.at(2); - ExpectEq(node2.blockBarrier.frontBarriers.size(), 0); - ExpectEq(node2.blockBarrier.rearBarriers.size() == 1, true); + const auto& node4 = barrierMap.at(4); + ExpectEq(node4.frontBarriers.size(), 0); + ExpectEq(node4.rearBarriers.size() == 1, true); - const auto& node2RearBarrier0 = node2.blockBarrier.rearBarriers.back(); - ExpectEq(node2RearBarrier0.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - ExpectEq(node2RearBarrier0.beginStatus.visibility == ShaderStageFlagBit::FRAGMENT, true); - ExpectEq(node2RearBarrier0.endStatus.accessFlag == AccessFlagBit::PRESENT, true); - //endstatus: whatever it was, it's COLOR_ATTACHMENT_OPTIMAL + const auto& node4RearBarrier0 = node4.rearBarriers.back(); + ExpectEq(node4RearBarrier0.endStatus.accessFlag == AccessFlagBit::PRESENT, true); //runTestGraph(renderGraph, rescGraph, layoutGraphData, fgDispatcher); } diff --git a/native/tests/unit-test/src/simple_closed_barrier_test.cpp b/native/tests/unit-test/src/simple_closed_barrier_test.cpp index 644132e90fb..095cc345508 100644 --- a/native/tests/unit-test/src/simple_closed_barrier_test.cpp +++ b/native/tests/unit-test/src/simple_closed_barrier_test.cpp @@ -40,148 +40,29 @@ TEST(simpleClosedBarrierTest, test11) { FrameGraphDispatcher fgDispatcher(rescGraph, renderGraph, layoutGraphData, resource, resource); fgDispatcher.run(); - const auto& barrierMap = fgDispatcher.getBarriers(); + const auto& barrierMap = fgDispatcher.resourceAccessGraph.barrier; const auto& rag = fgDispatcher.resourceAccessGraph; ExpectEq(rag._vertices.size() == 10, true); // head const auto& head = barrierMap.at(0); - ExpectEq(head.blockBarrier.frontBarriers.empty(), true); - ExpectEq(head.blockBarrier.rearBarriers.empty(), true); - ExpectEq(head.subpassBarriers.empty(), true); + ExpectEq(head.frontBarriers.empty(), true); + ExpectEq(head.rearBarriers.empty(), true); // 1st node const auto& node1 = barrierMap.at(1); - ExpectEq(node1.blockBarrier.frontBarriers.size(), 0); - ExpectEq(node1.blockBarrier.rearBarriers.size(), 0); - ExpectEq(node1.subpassBarriers.size() == 1, true); - ExpectEq(node1.subpassBarriers.front().frontBarriers.empty(), true); - ExpectEq(node1.subpassBarriers.front().rearBarriers.empty(), true); - - // transitioned by renderpass info - //ExpectEq(node1.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node1.blockBarrier.rearBarriers[0].endStatus.vertID == 1, true); - //ExpectEq(node1.blockBarrier.rearBarriers[1].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node1.blockBarrier.rearBarriers[1].endStatus.vertID == 3, true); + ExpectEq(node1.frontBarriers.size(), 0); + ExpectEq(node1.rearBarriers.size(), 0); const auto& node2 = barrierMap.at(2); - ExpectEq(node2.blockBarrier.frontBarriers.size(), 0); - ExpectEq(node2.blockBarrier.rearBarriers.size(), 0); - ExpectEq(node2.subpassBarriers.size() == 1, true); - ExpectEq(node2.subpassBarriers.front().frontBarriers.empty(), true); - ExpectEq(node2.subpassBarriers.front().rearBarriers.empty(), true); - - // ditto - //// res3 - //ExpectEq(node2.blockBarrier.rearBarriers[1].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node2.blockBarrier.rearBarriers[1].beginStatus.vertID == 2, true); - //ExpectEq(node2.blockBarrier.rearBarriers[1].endStatus.vertID == 5, true); - //// res2 - //ExpectEq(node2.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node2.blockBarrier.rearBarriers[0].beginStatus.vertID == 2, true); - //ExpectEq(node2.blockBarrier.rearBarriers[0].endStatus.vertID == 4, true); - - //const auto& node3 = barrierMap.at(3); - //ExpectEq(node3.blockBarrier.frontBarriers.size() == 3, true); - //ExpectEq(node3.blockBarrier.rearBarriers.size() == 2, true); - //ExpectEq(node3.subpassBarriers.empty(), true); - - //const auto& res1Index = std::find_if(node3.blockBarrier.frontBarriers.begin(), node3.blockBarrier.frontBarriers.end(), [](const Barrier& barrier) { return barrier.resourceID == 1; }); - //ExpectEq(res1Index != node3.blockBarrier.frontBarriers.end(), true); - //ExpectEq(res1Index->type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(res1Index->beginStatus.vertID == 1, true); - //ExpectEq(res1Index->endStatus.vertID == 3, true); - //// res 5 - //ExpectEq(node3.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node3.blockBarrier.rearBarriers[0].beginStatus.vertID == 3, true); - //ExpectEq(node3.blockBarrier.rearBarriers[0].endStatus.vertID == 3, true); - //// res 4 - //ExpectEq(node3.blockBarrier.rearBarriers[1].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node3.blockBarrier.rearBarriers[1].beginStatus.vertID == 3, true); - //ExpectEq(node3.blockBarrier.rearBarriers[1].endStatus.vertID == 5, true); - - //const auto& node4 = barrierMap.at(4); - //ExpectEq(node4.blockBarrier.frontBarriers.size() == 2, true); - //ExpectEq(node4.blockBarrier.rearBarriers.size() == 1, true); - //ExpectEq(node4.subpassBarriers.empty(), true); - - //const auto& res3Index = std::find_if(node4.blockBarrier.frontBarriers.begin(), node4.blockBarrier.frontBarriers.end(), [](const Barrier& barrier) { return barrier.resourceID == 3; }); - //ExpectEq(res3Index != node4.blockBarrier.frontBarriers.end(), true); - //ExpectEq(res3Index->type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(res3Index->beginStatus.vertID == 2, true); - //ExpectEq(res3Index->endStatus.vertID == 4, true); - - //ExpectEq(node4.blockBarrier.rearBarriers[0].resourceID == 6, true); - //ExpectEq(node4.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node4.blockBarrier.rearBarriers[0].beginStatus.vertID == 4, true); - //ExpectEq(node4.blockBarrier.rearBarriers[0].endStatus.vertID == 4, true); - - //const auto& node5 = barrierMap.at(5); - //ExpectEq(node5.blockBarrier.frontBarriers.size() == 3, true); - //ExpectEq(node5.blockBarrier.rearBarriers.size() == 1, true); - //ExpectEq(node5.subpassBarriers.empty(), true); - - //const auto& res2Index = std::find_if(node5.blockBarrier.frontBarriers.begin(), node5.blockBarrier.frontBarriers.end(), [](const Barrier& barrier) { return barrier.resourceID == 2; }); - //ExpectEq(res2Index != node5.blockBarrier.frontBarriers.end(), true); - //ExpectEq(res2Index->type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(res2Index->beginStatus.vertID == 2, true); - //ExpectEq(res2Index->endStatus.vertID == 5, true); - //const auto& res4Index = std::find_if(node5.blockBarrier.frontBarriers.begin(), node5.blockBarrier.frontBarriers.end(), [](const Barrier& barrier) { return barrier.resourceID == 4; }); - //ExpectEq(res4Index != node5.blockBarrier.frontBarriers.end(), true); - //ExpectEq(res4Index->type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(res4Index->beginStatus.vertID == 3, true); - //ExpectEq(res4Index->endStatus.vertID == 5, true); - - //ExpectEq(node5.blockBarrier.rearBarriers[0].resourceID == 7, true); - //ExpectEq(node5.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::SPLIT_BEGIN, true); - //ExpectEq(node5.blockBarrier.rearBarriers[0].beginStatus.vertID == 5, true); - //ExpectEq(node5.blockBarrier.rearBarriers[0].endStatus.vertID == 8, true); - - //const auto& node6 = barrierMap.at(6); - //ExpectEq(node6.blockBarrier.frontBarriers.size() == 1, true); - //ExpectEq(node6.blockBarrier.rearBarriers.size() == 1, true); - //ExpectEq(node6.subpassBarriers.empty(), true); - - //ExpectEq(node6.blockBarrier.rearBarriers[0].resourceID == 8, true); - //ExpectEq(node6.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node6.blockBarrier.rearBarriers[0].beginStatus.vertID == 6, true); - //ExpectEq(node6.blockBarrier.rearBarriers[0].endStatus.vertID == 6, true); - - //const auto& node7 = barrierMap.at(7); - //ExpectEq(node7.subpassBarriers.empty(), true); - //ExpectEq(node7.blockBarrier.frontBarriers.size() == 1, true); - //ExpectEq(node7.blockBarrier.rearBarriers.size() == 1, true); - - //ExpectEq(node7.blockBarrier.rearBarriers[0].resourceID == 9, true); - //ExpectEq(node7.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node7.blockBarrier.rearBarriers[0].beginStatus.vertID == 7, true); - //ExpectEq(node7.blockBarrier.rearBarriers[0].endStatus.vertID == 7, true); - - //const auto& node8 = barrierMap.at(8); - //ExpectEq(node8.subpassBarriers.empty(), true); - //ExpectEq(node8.blockBarrier.frontBarriers.empty(), false); // size == 1 - //ExpectEq(node8.blockBarrier.rearBarriers.size() == 1, true); - - //ExpectEq(node8.blockBarrier.frontBarriers[1].resourceID == 7, true); - //ExpectEq(node8.blockBarrier.frontBarriers[1].type == cc::gfx::BarrierType::SPLIT_END, true); - //ExpectEq(node8.blockBarrier.frontBarriers[1].beginStatus.vertID == 5, true); - //ExpectEq(node8.blockBarrier.frontBarriers[1].endStatus.vertID == 8, true); - - //ExpectEq(node8.blockBarrier.rearBarriers[0].resourceID == 22, true); - //ExpectEq(node8.blockBarrier.rearBarriers[0].type == cc::gfx::BarrierType::FULL, true); - //ExpectEq(node8.blockBarrier.rearBarriers[0].beginStatus.vertID == 8, true); - //ExpectEq(node8.blockBarrier.rearBarriers[0].endStatus.vertID == 0xFFFFFFFF, true); + ExpectEq(node2.frontBarriers.size(), 0); + ExpectEq(node2.rearBarriers.size(), 0); // TODO: validate renderpassInfo instead const auto& node9 = barrierMap.at(9); - ExpectEq(node9.subpassBarriers.empty(), true); - ExpectEq(node9.blockBarrier.frontBarriers.empty(), true); - ExpectEq(node9.blockBarrier.rearBarriers.empty(), true); - // const auto& node2RearBarrier0 = node2.blockBarrier.rearBarriers.back(); - // ExpectEq(node2RearBarrier0.beginStatus.access == MemoryAccessBit::WRITE_ONLY, true); - // ExpectEq(node2RearBarrier0.beginStatus.visibility == ShaderStageFlagBit::VERTEX, true); - // ExpectEq(node2RearBarrier0.endStatus.access == MemoryAccessBit::READ_ONLY, true); + ExpectEq(node9.frontBarriers.empty(), true); + ExpectEq(node9.rearBarriers.empty(), true); //endstatus: whatever it was, it's COLOR_ATTACHMENT_OPTIMAL //runTestGraph(renderGraph, rescGraph, layoutGraphData, fgDispatcher); From 46a59abe0c5cbf0b1270333f304eb495eb5f1d42 Mon Sep 17 00:00:00 2001 From: dogeFu <609075410@qq.com> Date: Wed, 9 Aug 2023 16:04:27 +0800 Subject: [PATCH 071/184] refactor : prefab code optimization and protection (#15845) * refactor : prefab code optimization and protection * remove extra if * remove extra param * replace class with interface * Update cocos/scene-graph/prefab/utils.ts Co-authored-by: PP * remove command and protect access * add prefab getter in node.jsb.ts --------- Co-authored-by: PP --- cocos/scene-graph/node.jsb.ts | 32 +++++++++-- cocos/scene-graph/node.ts | 6 +- cocos/scene-graph/prefab/prefab-info.ts | 4 +- cocos/scene-graph/prefab/utils.ts | 73 +++++++++++-------------- 4 files changed, 67 insertions(+), 48 deletions(-) diff --git a/cocos/scene-graph/node.jsb.ts b/cocos/scene-graph/node.jsb.ts index 3f4308293ce..ed2e4274521 100644 --- a/cocos/scene-graph/node.jsb.ts +++ b/cocos/scene-graph/node.jsb.ts @@ -1016,6 +1016,14 @@ Object.defineProperty(nodeProto, '_siblingIndex', { }, }); +Object.defineProperty(nodeProto, 'prefab', { + configurable: true, + enumerable: true, + get() { + return this._prefab; + }, +}); + // External classes need to access it through getter/setter Object.defineProperty(nodeProto, 'siblingIndex', { configurable: true, @@ -1214,11 +1222,25 @@ nodeProto[serializeTag] = function (serializationOutput: SerializationOutput, co // discard props disallow to synchronize const isRoot = this._prefab?.root === this; if (isRoot) { - serializationOutput.writeProperty('_objFlags', this._objFlags); - serializationOutput.writeProperty('_parent', this._parent); - serializationOutput.writeProperty('_prefab', this._prefab); - if (context.customArguments.keepNodeUuid) { - serializationOutput.writeProperty('_id', this._id); + // if B prefab is in A prefab,B can be referenced by component.We should discard it.because B is not the root of prefab + let isNestedPrefab = false; + let parent = this.getParent(); + while (parent) { + const nestedRoots = parent._prefab?.nestedPrefabInstanceRoots; + if (nestedRoots && nestedRoots.length > 0) { + // if this node is not in nestedPrefabInstanceRoots,it means this node is not the root of prefab,so it should be discarded. + isNestedPrefab = !nestedRoots.some((root) => root === this); + break; + } + parent = parent.getParent(); + } + if (!isNestedPrefab) { + serializationOutput.writeProperty('_objFlags', this._objFlags); + serializationOutput.writeProperty('_parent', this._parent); + serializationOutput.writeProperty('_prefab', this._prefab); + if (context.customArguments.keepNodeUuid) { + serializationOutput.writeProperty('_id', this._id); + } } // TODO: editorExtrasTag may be a symbol in the future serializationOutput.writeProperty(editorExtrasTag, this[editorExtrasTag]); diff --git a/cocos/scene-graph/node.ts b/cocos/scene-graph/node.ts index aa7607d4aa1..c1724a27da3 100644 --- a/cocos/scene-graph/node.ts +++ b/cocos/scene-graph/node.ts @@ -363,6 +363,10 @@ export class Node extends CCObject implements ISchedulable, CustomSerializable { */ @serializable protected _prefab: PrefabInfo | null = null; + /** + * @engineInternal + */ + public get prefab (): PrefabInfo | null { return this._prefab; } protected _scene: Scene = null!; @@ -1806,7 +1810,7 @@ export class Node extends CCObject implements ISchedulable, CustomSerializable { let isNestedPrefab = false; let parent = this.getParent(); while (parent) { - const nestedRoots = parent?._prefab?.nestedPrefabInstanceRoots; + const nestedRoots = parent._prefab?.nestedPrefabInstanceRoots; if (nestedRoots && nestedRoots.length > 0) { // if this node is not in nestedPrefabInstanceRoots,it means this node is not the root of prefab,so it should be discarded. isNestedPrefab = !nestedRoots.some((root) => root === this); diff --git a/cocos/scene-graph/prefab/prefab-info.ts b/cocos/scene-graph/prefab/prefab-info.ts index f4427d7a04c..dac885a21aa 100644 --- a/cocos/scene-graph/prefab/prefab-info.ts +++ b/cocos/scene-graph/prefab/prefab-info.ts @@ -167,7 +167,7 @@ export class PrefabInstance { @type([TargetInfo]) public removedComponents: TargetInfo[] = []; - public targetMap: Record = {}; + public targetMap: TargetMap = {}; /** * make sure prefab instance expand only once @@ -201,6 +201,8 @@ export class PrefabInstance { } } +export interface TargetMap { [k: string]: TargetMap | Node | Component } + @ccclass('cc.PrefabInfo') export class PrefabInfo { // the most top node of this prefab in the scene diff --git a/cocos/scene-graph/prefab/utils.ts b/cocos/scene-graph/prefab/utils.ts index 8e59d819bab..94c31c8b6b4 100644 --- a/cocos/scene-graph/prefab/utils.ts +++ b/cocos/scene-graph/prefab/utils.ts @@ -27,15 +27,20 @@ import { EDITOR, SUPPORT_JIT } from 'internal:constants'; import { cclegacy, errorID, warn, editorExtrasTag } from '../../core'; import { Node } from '../node'; import { Component } from '../component'; -import { MountedChildrenInfo, PropertyOverrideInfo, MountedComponentsInfo, TargetInfo } from './prefab-info'; +import { + MountedChildrenInfo, + PropertyOverrideInfo, + MountedComponentsInfo, + TargetInfo, TargetMap, + PrefabInstance, + TargetOverrideInfo, +} from './prefab-info'; import { ValueType } from '../../core/value-types'; export * from './prefab-info'; export function createNodeWithPrefab (node: Node): void { - // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. - // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - const prefabInfo = (node as any)._prefab; + const prefabInfo = node?.prefab; if (!prefabInfo) { return; } @@ -63,7 +68,6 @@ export function createNodeWithPrefab (node: Node): void { const _id = node.uuid; // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - const _prefab = (node as any)._prefab; const editorExtras = node[editorExtrasTag]; // instantiate prefab @@ -90,16 +94,14 @@ export function createNodeWithPrefab (node: Node): void { node[editorExtrasTag] = editorExtras; } - // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. - // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - if ((node as any)._prefab) { + if (node.prefab) { // just keep the instance - (node as any)._prefab.instance = _prefab?.instance; + node.prefab.instance = prefabInfo.instance; } } // TODO: more efficient id->Node/Component map -export function generateTargetMap (node: Node, targetMap: any, isRoot: boolean): void { +export function generateTargetMap (node: Node, targetMap: TargetMap, isRoot: boolean): void { if (!targetMap) { return; } @@ -110,17 +112,13 @@ export function generateTargetMap (node: Node, targetMap: any, isRoot: boolean): let curTargetMap = targetMap; - // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. - // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - const prefabInstance = (node as any)._prefab?.instance; + const prefabInstance = node.prefab?.instance; if (!isRoot && prefabInstance) { targetMap[prefabInstance.fileId] = {}; - curTargetMap = targetMap[prefabInstance.fileId]; + curTargetMap = targetMap[prefabInstance.fileId] as TargetMap; } - // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. - // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - const prefabInfo = (node as any)._prefab; + const prefabInfo = node.prefab; if (prefabInfo) { curTargetMap[prefabInfo.fileId] = node; } @@ -158,7 +156,7 @@ export function getTarget (localID: string[], targetMap: any): Node | Component return target; } -export function applyMountedChildren (node: Node, mountedChildren: MountedChildrenInfo[], targetMap: Record): void { +export function applyMountedChildren (node: Node, mountedChildren: MountedChildrenInfo[], targetMap: TargetMap): void { if (!mountedChildren) { return; } @@ -175,7 +173,7 @@ export function applyMountedChildren (node: Node, mountedChildren: MountedChildr const localID = childInfo.targetInfo.localID; if (localID.length > 0) { for (let i = 0; i < localID.length - 1; i++) { - curTargetMap = curTargetMap[localID[i]]; + curTargetMap = curTargetMap[localID[i]] as TargetMap; } } if (childInfo.nodes) { @@ -205,7 +203,7 @@ export function applyMountedChildren (node: Node, mountedChildren: MountedChildr } } -export function applyMountedComponents (node: Node, mountedComponents: MountedComponentsInfo[], targetMap: Record): void { +export function applyMountedComponents (node: Node, mountedComponents: MountedComponentsInfo[], targetMap: TargetMap): void { if (!mountedComponents) { return; } @@ -240,7 +238,7 @@ export function applyMountedComponents (node: Node, mountedComponents: MountedCo } } -export function applyRemovedComponents (node: Node, removedComponents: TargetInfo[], targetMap: Record): void { +export function applyRemovedComponents (node: Node, removedComponents: TargetInfo[], targetMap: TargetMap): void { if (!removedComponents) { return; } @@ -261,7 +259,7 @@ export function applyRemovedComponents (node: Node, removedComponents: TargetInf } } -export function applyPropertyOverrides (node: Node, propertyOverrides: PropertyOverrideInfo[], targetMap: Record): void { +export function applyPropertyOverrides (node: Node, propertyOverrides: PropertyOverrideInfo[], targetMap: TargetMap): void { if (propertyOverrides.length <= 0) { return; } @@ -320,9 +318,7 @@ export function applyPropertyOverrides (node: Node, propertyOverrides: PropertyO } export function applyTargetOverrides (node: Node): void { - // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. - // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - const targetOverrides = (node as any)._prefab?.targetOverrides; + const targetOverrides = node.prefab?.targetOverrides as TargetOverrideInfo[]; if (targetOverrides) { for (let i = 0; i < targetOverrides.length; i++) { const targetOverride = targetOverrides[i]; @@ -330,8 +326,8 @@ export function applyTargetOverrides (node: Node): void { let source: Node | Component | null = targetOverride.source; const sourceInfo = targetOverride.sourceInfo; if (sourceInfo) { - // TODO: targetOverride.source is type of `Node | Component`, while `_prefab` does not exist on type 'Component'. - const sourceInstance = targetOverride.source?._prefab?.instance; + const src = targetOverride.source as Node; + const sourceInstance = src?.prefab?.instance; if (sourceInstance && sourceInstance.targetMap) { source = getTarget(sourceInfo.localID, sourceInstance.targetMap); } @@ -347,8 +343,8 @@ export function applyTargetOverrides (node: Node): void { if (!targetInfo) { continue; } - - const targetInstance = targetOverride.target?._prefab?.instance; + const targetAsNode = targetOverride.target as Node; + const targetInstance = targetAsNode?.prefab?.instance; if (!targetInstance || !targetInstance.targetMap) { continue; } @@ -385,10 +381,7 @@ export function applyTargetOverrides (node: Node): void { } export function expandPrefabInstanceNode (node: Node, recursively = false): void { - // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. - // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - const prefabInfo = (node as any)._prefab; - const prefabInstance = prefabInfo?.instance; + const prefabInstance = node?.prefab?.instance as PrefabInstance; if (prefabInstance && !prefabInstance.expanded) { createNodeWithPrefab(node); // nested prefab should expand before parent(property override order) @@ -400,7 +393,7 @@ export function expandPrefabInstanceNode (node: Node, recursively = false): void } } - const targetMap: Record = {}; + const targetMap = {}; prefabInstance.targetMap = targetMap; generateTargetMap(node, targetMap, true); applyMountedChildren(node, prefabInstance.mountedChildren, targetMap); @@ -418,17 +411,15 @@ export function expandPrefabInstanceNode (node: Node, recursively = false): void } export function expandNestedPrefabInstanceNode (node: Node): void { - // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. - // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - const prefabInfo = (node as any)._prefab; + const prefabInfo = node.prefab; if (prefabInfo && prefabInfo.nestedPrefabInstanceRoots) { prefabInfo.nestedPrefabInstanceRoots.forEach((instanceNode: Node) => { expandPrefabInstanceNode(instanceNode); // when expanding the prefab,it's children will be change,so need to apply after expanded - if (!EDITOR) { - applyNodeAndComponentId(instanceNode, (instanceNode as any)._prefab?.instance?.fileId ?? ''); - } + // if (!EDITOR) { + // applyNodeAndComponentId(instanceNode, (instanceNode as any)._prefab?.instance?.fileId ?? ''); + // } }); } } @@ -445,7 +436,7 @@ export function applyNodeAndComponentId (prefabInstanceNode: Node, rootId: strin const child = children[i]; // TODO(PP_Pro): after we support editorOnly tag, we could remove this any type assertion. // Tracking issue: https://github.com/cocos/cocos-engine/issues/14613 - const prefabInfo = (child as any)._prefab!; + const prefabInfo = child.prefab!; const fileId = prefabInfo?.instance ? prefabInfo.instance.fileId : prefabInfo?.fileId; if (!fileId) continue; child.id = `${rootId}${fileId}`; From e00bf293260e68e76b479d77688dab8b88dfa6fb Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Thu, 10 Aug 2023 10:25:17 +0800 Subject: [PATCH 072/184] fix glass effect and planar shadow bias (#15881) --- .../post-process/components/post-process.ts | 8 +- .../post-process/post-process-builder.ts | 13 ++- .../chunks/common/lighting/functions.chunk | 16 ++-- .../render-planar-shadow/vs.chunk | 2 +- editor/assets/effects/advanced/glass.effect | 83 ++++++++++++------- 5 files changed, 76 insertions(+), 46 deletions(-) diff --git a/cocos/rendering/post-process/components/post-process.ts b/cocos/rendering/post-process/components/post-process.ts index 86de77d06f1..ac5454530ad 100644 --- a/cocos/rendering/post-process/components/post-process.ts +++ b/cocos/rendering/post-process/components/post-process.ts @@ -10,17 +10,17 @@ import { PostProcessSetting } from './post-process-setting'; @disallowMultiple @executeInEditMode export class PostProcess extends Component { - static all: PostProcess[] = [] + static all: PostProcess[] = []; @tooltip('i18n:postprocess.global') @property global = true; @property - _shadingScale = 1 + _shadingScale = 1; @tooltip('i18n:postprocess.shadingScale') @slide - @range([0.01, 1, 0.01]) + @range([0.01, 4, 0.01]) @property get shadingScale (): number { return this._shadingScale; @@ -38,7 +38,7 @@ export class PostProcess extends Component { @property enableShadingScaleInEditor = false; - settings: Map = new Map() + settings: Map = new Map(); addSetting (setting: PostProcessSetting): void { this.settings.set(setting.constructor as typeof PostProcessSetting, setting); diff --git a/cocos/rendering/post-process/post-process-builder.ts b/cocos/rendering/post-process/post-process-builder.ts index b240de3a8d7..bfe9b18377a 100644 --- a/cocos/rendering/post-process/post-process-builder.ts +++ b/cocos/rendering/post-process/post-process-builder.ts @@ -43,15 +43,20 @@ export class PostProcessBuilder implements PipelineBuilder { // rendering dependent data generation this.addPass(shadowPass); - // forward pipeline + // opaque objects forward lighting this.addPass(forward); - this.addPass(new SkinPass()); - this.addPass(new ForwardTransparencyPass()); - // pipeline related + // depth-based shading this.addPass(new HBAOPass()); + + // hdr this.addPass(new ToneMappingPass()); + // simple fog with LDR after tone-mapping, atmosphere with HDR before tone-mapping + // this.addPass(new FogPass()); + + // transparency should after hdr and depth-based shading + this.addPass(new ForwardTransparencyPass()); // user post-processing this.addPass(new TAAPass()); diff --git a/editor/assets/chunks/common/lighting/functions.chunk b/editor/assets/chunks/common/lighting/functions.chunk index 4d7375b06bc..cc744e5f7ab 100644 --- a/editor/assets/chunks/common/lighting/functions.chunk +++ b/editor/assets/chunks/common/lighting/functions.chunk @@ -86,14 +86,18 @@ vec4 CalculatePlanarShadowPos(vec3 meshWorldPos, vec3 cameraPos, vec3 lightDir, vec3 P = meshWorldPos; vec3 L = lightDir; vec3 N = plane.xyz; - float d = plane.w + 0.001; + float d = plane.w + EPSILON_LOWP; float dist = (-d - dot(P, N)) / (dot(L, N) + EPSILON_LOWP); vec3 shadowPos = P + L * dist; - // avoid z-fighting with shadow plane - vec3 view = normalize(cameraPos.xyz - shadowPos); - float viewLength = length(cameraPos.xyz - shadowPos); - shadowPos += view * min(1.0, 0.005 * viewLength); - return vec4(shadowPos, dist); } +// calculate planar clip pos from world pos +vec4 CalculatePlanarShadowClipPos(vec4 shadowPos, vec3 cameraPos, mat4 matView, mat4 matProj, vec4 nearFar) { + vec4 camPos = matView * vec4(shadowPos.xyz, 1.0); + // avoid z-fighting with shadow receive plane, add camera bias with perspective correction + // notice that near plane should not be too small, assume near 1, far 1000 + float lerpCoef = saturate((nearFar.z < 0.0 ? -camPos.z : camPos.z) / (nearFar.y - nearFar.x)); + camPos.z += mix(nearFar.x * 0.01, nearFar.y * EPSILON_LOWP, lerpCoef); + return matProj * camPos; +} diff --git a/editor/assets/chunks/shading-entries/main-functions/render-planar-shadow/vs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-planar-shadow/vs.chunk index f2b34e3506a..75f3708624b 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-planar-shadow/vs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-planar-shadow/vs.chunk @@ -22,7 +22,7 @@ void main() In.worldPos = shadowPos.xyz; // Clip Space - In.clipPos = cc_matProj * cc_matView * vec4(In.worldPos, 1.0); + In.clipPos = CalculatePlanarShadowClipPos(shadowPos, cc_cameraPos.xyz, cc_matView, cc_matProj, cc_nearFar); In.clipPos = SurfacesVertexModifyClipPos(In); // Other Surfaces Function diff --git a/editor/assets/effects/advanced/glass.effect b/editor/assets/effects/advanced/glass.effect index e16bf1878c1..b1d7fce571a 100644 --- a/editor/assets/effects/advanced/glass.effect +++ b/editor/assets/effects/advanced/glass.effect @@ -2,18 +2,28 @@ CCEffect %{ techniques: - - name: opaque + - name: single-sided passes: - vert: standard-vs frag: standard-fs + embeddedMacros: { CC_FORCE_FORWARD_SHADING: true } + rasterizerState: + cullMode: Back + depthStencilState: &d1 + depthTest: true + depthWrite: false + blendState: &b1 + targets: + - blend: true + blendSrc: one + blendDst: src_alpha properties: &props tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } mainColor: { value: [0.05, 0.05, 0.05, 1.0], target: albedo, linear: true, editor: { displayName: Albedo, type: color } } albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } roughness: { value: 0.0, target: pbrParams.y, editor: { slide: true, range: [0, 1.0], step: 0.001 } } - metallic: { value: 0.0, target: pbrParams.z, editor: { slide: true, range: [0, 1.0], step: 0.001 } } - specularIntensity: { value: 0.2, target: pbrParams.w, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } - F0: { value: 0.7, target: emissiveScaleParam.x, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + specularIntensity: { value: 0.5, target: pbrParams.w, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + F0: { value: 0.5, target: emissiveScaleParam.x, editor: { slide: true, range: [0, 1.0], step: 0.001 } } F90: { value: 0.9, target: emissiveScaleParam.y, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } gradientColor: { value: [0.0, 0.05, 0.0, 1.0], linear: true, editor: { parent: USE_GRADIENT_COLOR, type: color } } gradientIntensity: { value: 0.2, target: emissiveScaleParam.z, editor: { parent: USE_GRADIENT_COLOR, slide: true, range: [0, 1.0], step: 0.001 } } @@ -82,31 +92,37 @@ CCEffect %{ phase: gbuffer embeddedMacros: { CC_PIPELINE_TYPE: 1 } propertyIndex: 0 - - name: transparent + - name: two-sided passes: - vert: standard-vs frag: standard-fs - embeddedMacros: { CC_FORCE_FORWARD_SHADING: true } + embeddedMacros: { CC_FORCE_FORWARD_SHADING: true, TECHNIQUE_TWO_SIDE: true } rasterizerState: cullMode: Front - depthStencilState: &d1 - depthTest: true - depthWrite: false - blendState: &b1 - targets: - - blend: true - blendSrc: src_alpha - blendDst: one_minus_src_alpha - blendDstAlpha: one_minus_src_alpha - properties: *props + properties: &props + tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } + mainColor: { value: [0.05, 0.05, 0.05, 1.0], target: albedo, linear: true, editor: { displayName: Albedo, type: color } } + albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } + roughness: { value: 0.0, target: pbrParams.y, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + specularIntensity: { value: 0.5, target: pbrParams.w, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + F0: { value: 0.5, target: emissiveScaleParam.x, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + F90: { value: 0.9, target: emissiveScaleParam.y, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + gradientColor: { value: [0.0, 0.05, 0.0, 1.0], linear: true, editor: { parent: USE_GRADIENT_COLOR, type: color } } + gradientIntensity: { value: 0.2, target: emissiveScaleParam.z, editor: { parent: USE_GRADIENT_COLOR, slide: true, range: [0, 1.0], step: 0.001 } } + normalStrength: { value: 1.0, target: emissiveScaleParam.w, editor: { parent: USE_NORMAL_MAP, slide: true, range: [0, 5.0], step: 0.001 } } + mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } + normalMap: { value: normal } + pbrMap: { value: grey } + depthStencilState: *d1 + blendState: *b1 - vert: standard-vs frag: standard-fs - embeddedMacros: { CC_FORCE_FORWARD_SHADING: true } + embeddedMacros: { CC_FORCE_FORWARD_SHADING: true, TECHNIQUE_TWO_SIDE: true } rasterizerState: cullMode: Back + propertyIndex: 0 depthStencilState: *d1 blendState: *b1 - properties: *props - *forward-add - *shadow-caster - *planar-shadow @@ -133,11 +149,9 @@ CCProgram shared-ubos %{ CCProgram macro-remapping %{ // ui displayed macros - #pragma define-meta USE_TWOSIDE #pragma define-meta USE_VERTEX_COLOR #pragma define-meta USE_PROBE_REFRACTION editor({ tooltip: 'Use transparency technique when disabled, otherwise use opaque technique' }) - #define CC_SURFACES_USE_TWO_SIDED USE_TWOSIDE #define CC_SURFACES_USE_VERTEX_COLOR USE_VERTEX_COLOR #define CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR USE_PROBE_REFRACTION #define CC_SURFACES_LIGHTING_USE_FRESNEL USE_PROBE_REFRACTION @@ -145,6 +159,10 @@ CCProgram macro-remapping %{ // depend on UI macros #if USE_NORMAL_MAP #define CC_SURFACES_USE_TANGENT_SPACE 1 +#endif + // depend on technique macros +#if TECHNIQUE_TWO_SIDE + #define CC_SURFACES_USE_TWO_SIDED 1 #endif }% @@ -210,9 +228,10 @@ CCProgram surface-fragment %{ { vec4 pbr = pbrParams; pbr.x = 1.0; + pbr.z = 1.0; #if USE_PBR_MAP vec4 res = texture(pbrMap, DEFAULT_UV); - pbr.yzw *= res.yzw; + pbr.yw *= res.yw; #endif return pbr; @@ -227,9 +246,12 @@ CCProgram surface-fragment %{ float NoVSat = saturate(dot(surfaceData.worldNormal, viewDir)); #if !USE_PROBE_REFRACTION - // fresnel for alpha blend + // final color = srcColor * F + dstColor * (1-F) * glassColor + // srcAlpha = (1-F) * glassColorBright (use bright instead for one channel) + // srcBlend = 1, dstBlend = srcAlpha float F0 = emissiveScaleParam.x, F90 = emissiveScaleParam.y; - surfaceData.baseColor.a = CalculateFresnelCoefficient(min(F0, F90), F90, NoVSat); + float fresnel = CalculateFresnelCoefficient(min(F0, F90), F90, NoVSat); + surfaceData.baseColor.a = (1.0 - fresnel) * length(surfaceData.baseColor.rgb); #endif #if USE_GRADIENT_COLOR @@ -241,14 +263,13 @@ CCProgram surface-fragment %{ #define CC_SURFACES_LIGHTING_MODIFY_FINAL_RESULT void SurfacesLightingModifyFinalResult(inout LightingResult result, in LightingIntermediateData lightingData, in SurfacesMaterialData surfaceData, in LightingMiscData miscData) { - #if USE_PROBE_REFRACTION - // fresnel for refraction - vec3 viewDir = normalize(cc_cameraPos.xyz - surfaceData.worldPos); - float NoVSat = saturate(dot(surfaceData.worldNormal, viewDir)); - float F0 = emissiveScaleParam.x, F90 = emissiveScaleParam.y; - float fresnel = CalculateFresnelCoefficient(min(F0, F90), F90, NoVSat); - result.fresnel = vec3(fresnel); - #else + vec3 viewDir = normalize(cc_cameraPos.xyz - surfaceData.worldPos); + float NoVSat = saturate(dot(surfaceData.worldNormal, viewDir)); + float F0 = emissiveScaleParam.x, F90 = emissiveScaleParam.y; + float fresnel = CalculateFresnelCoefficient(min(F0, F90), F90, NoVSat); + result.fresnel = vec3(fresnel); + + #if !USE_PROBE_REFRACTION // simply fix single blend source issue for bright color alpha blending float threshold = 0.5, bright = dot(result.environmentSpecular, vec3(0.33333)); if (bright > threshold) From e69ae568a090614a05f1871477f7b58a04e3c692 Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Thu, 10 Aug 2023 10:29:08 +0800 Subject: [PATCH 073/184] remove ia pool. (#15880) * remove ia pool. * fix vb / ib leaks in ui mesh && renderDrawInfo --- native/cocos/2d/renderer/Batcher2d.cpp | 17 ++++-- native/cocos/2d/renderer/RenderDrawInfo.cpp | 61 ++++++------------- native/cocos/2d/renderer/RenderDrawInfo.h | 10 +-- native/cocos/2d/renderer/UIMeshBuffer.cpp | 48 +++++---------- native/cocos/2d/renderer/UIMeshBuffer.h | 9 ++- .../renderer/pipeline/InstancedBuffer.cpp | 17 +++--- .../cocos/renderer/pipeline/InstancedBuffer.h | 2 +- .../pipeline/RenderInstancedQueue.cpp | 2 +- native/cocos/renderer/pipeline/UIPhase.cpp | 2 +- .../pipeline/custom/NativeExecutor.cpp | 2 +- .../pipeline/custom/NativeRenderQueue.cpp | 4 +- native/cocos/scene/DrawBatch2D.cpp | 5 ++ native/cocos/scene/DrawBatch2D.h | 6 +- 13 files changed, 81 insertions(+), 104 deletions(-) diff --git a/native/cocos/2d/renderer/Batcher2d.cpp b/native/cocos/2d/renderer/Batcher2d.cpp index c1ffb4d9e9f..8e05a432868 100644 --- a/native/cocos/2d/renderer/Batcher2d.cpp +++ b/native/cocos/2d/renderer/Batcher2d.cpp @@ -332,9 +332,14 @@ void Batcher2d::generateBatch(RenderEntity* entity, RenderDrawInfo* drawInfo) { return; } gfx::InputAssembler* ia = nullptr; + + uint32_t indexOffset = 0; + uint32_t indexCount = 0; if (drawInfo->getIsMeshBuffer()) { // Todo MeshBuffer RenderData ia = drawInfo->requestIA(getDevice()); + indexOffset = drawInfo->getIndexOffset(); + indexCount = drawInfo->getIbCount(); _meshRenderDrawInfo.emplace_back(drawInfo); } else { UIMeshBuffer* currMeshBuffer = drawInfo->getMeshBuffer(); @@ -342,13 +347,11 @@ void Batcher2d::generateBatch(RenderEntity* entity, RenderDrawInfo* drawInfo) { currMeshBuffer->setDirty(true); ia = currMeshBuffer->requireFreeIA(getDevice()); - uint32_t indexCount = currMeshBuffer->getIndexOffset() - _indexStart; + indexCount = currMeshBuffer->getIndexOffset() - _indexStart; if (ia == nullptr) { return; } - - ia->setFirstIndex(_indexStart); - ia->setIndexCount(indexCount); + indexOffset = _indexStart; _indexStart = currMeshBuffer->getIndexOffset(); } @@ -364,6 +367,8 @@ void Batcher2d::generateBatch(RenderEntity* entity, RenderDrawInfo* drawInfo) { auto* curdrawBatch = _drawBatchPool.alloc(); curdrawBatch->setVisFlags(_currLayer); curdrawBatch->setInputAssembler(ia); + curdrawBatch->setFirstIndex(indexOffset); + curdrawBatch->setIndexCount(indexCount); curdrawBatch->fillPass(_currMaterial, depthStencil, dssHash); const auto& pass = curdrawBatch->getPasses().at(0); @@ -392,8 +397,6 @@ void Batcher2d::generateBatchForMiddleware(RenderEntity* entity, RenderDrawInfo* meshBuffer->setDirty(true); gfx::InputAssembler* ia = meshBuffer->requireFreeIA(getDevice()); - ia->setFirstIndex(drawInfo->getIndexOffset()); - ia->setIndexCount(drawInfo->getIbCount()); // stencilstage auto stencilStage = _stencilManager->getStencilStage(); @@ -403,6 +406,8 @@ void Batcher2d::generateBatchForMiddleware(RenderEntity* entity, RenderDrawInfo* auto* curdrawBatch = _drawBatchPool.alloc(); curdrawBatch->setVisFlags(_currLayer); curdrawBatch->setInputAssembler(ia); + curdrawBatch->setFirstIndex(drawInfo->getIndexOffset()); + curdrawBatch->setIndexCount(drawInfo->getIbCount()); curdrawBatch->fillPass(material, depthStencil, dssHash); const auto& pass = curdrawBatch->getPasses().at(0); if (entity->getUseLocal()) { diff --git a/native/cocos/2d/renderer/RenderDrawInfo.cpp b/native/cocos/2d/renderer/RenderDrawInfo.cpp index f376de0f979..94397e3c382 100644 --- a/native/cocos/2d/renderer/RenderDrawInfo.cpp +++ b/native/cocos/2d/renderer/RenderDrawInfo.cpp @@ -51,56 +51,30 @@ void RenderDrawInfo::changeMeshBuffer() { gfx::InputAssembler* RenderDrawInfo::requestIA(gfx::Device* device) { CC_ASSERT(_drawInfoAttrs._isMeshBuffer && _drawInfoAttrs._drawInfoType == RenderDrawInfoType::COMP); - if (!_iaPool) { - _iaPool = ccnew ccstd::vector; - } - if (_nextFreeIAHandle >= _iaPool->size()) { - initIAInfo(device); - } - auto* ia = (*_iaPool)[_nextFreeIAHandle++]; - ia->setFirstIndex(getIndexOffset()); - ia->setIndexCount(getIbCount()); - return ia; + return initIAInfo(device); } void RenderDrawInfo::uploadBuffers() { CC_ASSERT(_drawInfoAttrs._isMeshBuffer && _drawInfoAttrs._drawInfoType == RenderDrawInfoType::COMP); if (_drawInfoAttrs._vbCount == 0 || _drawInfoAttrs._ibCount == 0) return; uint32_t size = _drawInfoAttrs._vbCount * 9 * sizeof(float); // magic Number - gfx::Buffer* vBuffer = _iaInfo->vertexBuffers[0]; + gfx::Buffer* vBuffer = _ia->getVertexBuffers()[0]; vBuffer->resize(size); vBuffer->update(_vDataBuffer); - gfx::Buffer* iBuffer = _iaInfo->indexBuffer; + gfx::Buffer* iBuffer = _ia->getIndexBuffer(); uint32_t iSize = _drawInfoAttrs._ibCount * 2; iBuffer->resize(iSize); iBuffer->update(_iDataBuffer); } -void RenderDrawInfo::resetMeshIA() { +void RenderDrawInfo::resetMeshIA() { // NOLINT(readability-make-member-function-const) CC_ASSERT(_drawInfoAttrs._isMeshBuffer && _drawInfoAttrs._drawInfoType == RenderDrawInfoType::COMP); - _nextFreeIAHandle = 0; } void RenderDrawInfo::destroy() { - _nextFreeIAHandle = 0; - if (_iaInfo) { - CC_SAFE_DELETE(_iaInfo->indexBuffer); - if (!_iaInfo->vertexBuffers.empty()) { - // only one vb - CC_SAFE_DELETE(_iaInfo->vertexBuffers[0]); - _iaInfo->vertexBuffers.clear(); - } - CC_SAFE_DELETE(_iaInfo); - } - - if (_iaPool) { - for (auto* ia : *_iaPool) { - CC_SAFE_DELETE(ia); - } - _iaPool->clear(); - CC_SAFE_DELETE(_iaPool); - } - + _vb = nullptr; + _ib = nullptr; + _ia = nullptr; if (_localDSBF) { CC_SAFE_DELETE(_localDSBF->ds); CC_SAFE_DELETE(_localDSBF->uboBuf); @@ -109,31 +83,30 @@ void RenderDrawInfo::destroy() { } gfx::InputAssembler* RenderDrawInfo::initIAInfo(gfx::Device* device) { - if (_iaPool->empty()) { - _iaInfo = ccnew gfx::InputAssemblerInfo(); + if (!_ia) { + gfx::InputAssemblerInfo iaInfo = {}; uint32_t vbStride = 9 * sizeof(float); // magic Number uint32_t ibStride = sizeof(uint16_t); - auto* vertexBuffer = device->createBuffer({ + _vb = device->createBuffer({ gfx::BufferUsageBit::VERTEX | gfx::BufferUsageBit::TRANSFER_DST, gfx::MemoryUsageBit::DEVICE | gfx::MemoryUsageBit::HOST, vbStride * 3, vbStride, }); - auto* indexBuffer = device->createBuffer({ + _ib = device->createBuffer({ gfx::BufferUsageBit::INDEX | gfx::BufferUsageBit::TRANSFER_DST, gfx::MemoryUsageBit::DEVICE | gfx::MemoryUsageBit::HOST, ibStride * 3, ibStride, }); - _iaInfo->attributes = *(Root::getInstance()->getBatcher2D()->getDefaultAttribute()); - _iaInfo->vertexBuffers.emplace_back(vertexBuffer); - _iaInfo->indexBuffer = indexBuffer; - } - auto* ia = device->createInputAssembler(*_iaInfo); - _iaPool->emplace_back(ia); + iaInfo.attributes = *(Root::getInstance()->getBatcher2D()->getDefaultAttribute()); + iaInfo.vertexBuffers.emplace_back(_vb); + iaInfo.indexBuffer = _ib; - return ia; + _ia = device->createInputAssembler(iaInfo); + } + return _ia; } void RenderDrawInfo::updateLocalDescriptorSet(Node* transform, const gfx::DescriptorSetLayout* dsLayout) { diff --git a/native/cocos/2d/renderer/RenderDrawInfo.h b/native/cocos/2d/renderer/RenderDrawInfo.h index ee4ab7b2b47..a06266be5c5 100644 --- a/native/cocos/2d/renderer/RenderDrawInfo.h +++ b/native/cocos/2d/renderer/RenderDrawInfo.h @@ -24,6 +24,7 @@ #pragma once #include "2d/renderer/UIMeshBuffer.h" +#include "base/Ptr.h" #include "base/Macros.h" #include "base/TypeDef.h" #include "bindings/utils/BindingUtils.h" @@ -266,8 +267,6 @@ class RenderDrawInfo final { ccstd::hash_t _dataHash{0}; } _drawInfoAttrs{}; - uint16_t _nextFreeIAHandle{0}; - bindings::NativeMemorySharedToScriptActor _attrSharedBufferActor; // weak reference Material* _material{nullptr}; @@ -291,8 +290,11 @@ class RenderDrawInfo final { scene::Model* _model; uint8_t* _sharedBuffer; }; - gfx::InputAssemblerInfo* _iaInfo{nullptr}; - ccstd::vector* _iaPool{nullptr}; LocalDSBF* _localDSBF{nullptr}; + + // ia + IntrusivePtr _ia; + IntrusivePtr _vb; + IntrusivePtr _ib; }; } // namespace cc diff --git a/native/cocos/2d/renderer/UIMeshBuffer.cpp b/native/cocos/2d/renderer/UIMeshBuffer.cpp index 6f539c46e2d..bf8f307f2cd 100644 --- a/native/cocos/2d/renderer/UIMeshBuffer.cpp +++ b/native/cocos/2d/renderer/UIMeshBuffer.cpp @@ -59,25 +59,17 @@ void UIMeshBuffer::initialize(ccstd::vector&& attrs, bool needCr void UIMeshBuffer::reset() { setIndexOffset(0); - _nextFreeIAHandle = 0; _dirty = false; } void UIMeshBuffer::resetIA() { - for (auto* ia : _iaPool) { - ia->setFirstIndex(0); - ia->setIndexCount(0); - } } void UIMeshBuffer::destroy() { reset(); _attributes.clear(); - for (auto* vb : _iaInfo.vertexBuffers) { - delete vb; - } - _iaInfo.vertexBuffers.clear(); - CC_SAFE_DELETE(_iaInfo.indexBuffer); + _vb = nullptr; + _ib = nullptr; if (_needDeleteVData) { delete _vData; delete _iData; @@ -85,11 +77,7 @@ void UIMeshBuffer::destroy() { _vData = nullptr; _iData = nullptr; // Destroy InputAssemblers - for (auto* ia : _iaPool) { - ia->destroy(); - delete ia; - } - _iaPool.clear(); + _ia = nullptr; if (_needDeleteLayout) { CC_SAFE_DELETE(_meshBufferLayout); } @@ -100,24 +88,20 @@ void UIMeshBuffer::setDirty() { } gfx::InputAssembler* UIMeshBuffer::requireFreeIA(gfx::Device* device) { - if (_nextFreeIAHandle >= _iaPool.size()) { - createNewIA(device); - } - return _iaPool[_nextFreeIAHandle++]; + return createNewIA(device); } void UIMeshBuffer::uploadBuffers() { uint32_t byteOffset = getByteOffset(); bool dirty = getDirty(); - if (_meshBufferLayout == nullptr || byteOffset == 0 || !dirty || _iaPool.empty()) { + if (_meshBufferLayout == nullptr || byteOffset == 0 || !dirty || !_ia) { return; } uint32_t indexCount = getIndexOffset(); uint32_t byteCount = getByteOffset(); - gfx::InputAssembler* ia = _iaPool[0]; - gfx::BufferList vBuffers = ia->getVertexBuffers(); + gfx::BufferList vBuffers = _ia->getVertexBuffers(); if (!vBuffers.empty()) { gfx::Buffer* vBuffer = vBuffers[0]; if (byteCount > vBuffer->getSize()) { @@ -125,7 +109,7 @@ void UIMeshBuffer::uploadBuffers() { } vBuffer->update(_vData); } - gfx::Buffer* iBuffer = ia->getIndexBuffer(); + gfx::Buffer* iBuffer = _ia->getIndexBuffer(); if (indexCount * 2 > iBuffer->getSize()) { iBuffer->resize(indexCount * 2); } @@ -139,31 +123,31 @@ void UIMeshBuffer::recycleIA(gfx::InputAssembler* ia) { } gfx::InputAssembler* UIMeshBuffer::createNewIA(gfx::Device* device) { - if (_iaPool.empty()) { + if (!_ia) { uint32_t vbStride = _vertexFormatBytes; uint32_t ibStride = sizeof(uint16_t); - auto* vertexBuffer = device->createBuffer({ + gfx::InputAssemblerInfo iaInfo = {}; + _vb = device->createBuffer({ gfx::BufferUsageBit::VERTEX | gfx::BufferUsageBit::TRANSFER_DST, gfx::MemoryUsageBit::DEVICE | gfx::MemoryUsageBit::HOST, vbStride * 3, vbStride, }); - auto* indexBuffer = device->createBuffer({ + _ib = device->createBuffer({ gfx::BufferUsageBit::INDEX | gfx::BufferUsageBit::TRANSFER_DST, gfx::MemoryUsageBit::DEVICE | gfx::MemoryUsageBit::HOST, ibStride * 3, ibStride, }); - _iaInfo.attributes = _attributes; - _iaInfo.vertexBuffers.emplace_back(vertexBuffer); - _iaInfo.indexBuffer = indexBuffer; + iaInfo.attributes = _attributes; + iaInfo.vertexBuffers.emplace_back(_vb); + iaInfo.indexBuffer = _ib; + _ia = device->createInputAssembler(iaInfo); } - auto* ia = device->createInputAssembler(_iaInfo); - _iaPool.emplace_back(ia); - return ia; + return _ia; } void UIMeshBuffer::syncSharedBufferToNative(uint32_t* buffer) { diff --git a/native/cocos/2d/renderer/UIMeshBuffer.h b/native/cocos/2d/renderer/UIMeshBuffer.h index 1ae94eed180..8e2bbef8e54 100644 --- a/native/cocos/2d/renderer/UIMeshBuffer.h +++ b/native/cocos/2d/renderer/UIMeshBuffer.h @@ -23,9 +23,12 @@ ****************************************************************************/ #pragma once +#include "base/Ptr.h" #include "base/Macros.h" #include "base/TypeDef.h" +#include "renderer/gfx-base/GFXInputAssembler.h" #include "renderer/gfx-base/GFXDef-common.h" +#include "renderer/gfx-base/GFXBuffer.h" namespace cc { @@ -84,11 +87,11 @@ class UIMeshBuffer final { uint32_t _vertexFormatBytes{0}; uint32_t _initVDataCount{0}; uint32_t _initIDataCount{0}; - uint32_t _nextFreeIAHandle{0}; ccstd::vector _attributes; - ccstd::vector _iaPool{}; - gfx::InputAssemblerInfo _iaInfo; + IntrusivePtr _ia; + IntrusivePtr _vb; + IntrusivePtr _ib; bool _dirty{false}; bool _needDeleteVData{false}; diff --git a/native/cocos/renderer/pipeline/InstancedBuffer.cpp b/native/cocos/renderer/pipeline/InstancedBuffer.cpp index 56d2311aa52..bd5f02f1d4b 100644 --- a/native/cocos/renderer/pipeline/InstancedBuffer.cpp +++ b/native/cocos/renderer/pipeline/InstancedBuffer.cpp @@ -74,7 +74,7 @@ void InstancedBuffer::merge(scene::SubModel *subModel, uint32_t passIdx, gfx::Sh } for (auto &instance : _instances) { - if (instance.ia->getIndexBuffer() != sourceIA->getIndexBuffer() || instance.count >= MAX_CAPACITY) { + if (instance.ia->getIndexBuffer() != sourceIA->getIndexBuffer() || instance.drawInfo.instanceCount >= MAX_CAPACITY) { continue; } @@ -99,7 +99,7 @@ void InstancedBuffer::merge(scene::SubModel *subModel, uint32_t passIdx, gfx::Sh if (instance.stride != stride) { continue; } - if (instance.count >= instance.capacity) { // resize buffers + if (instance.drawInfo.instanceCount >= instance.capacity) { // resize buffers instance.capacity <<= 1; const auto newSize = instance.stride * instance.capacity; instance.data = static_cast(CC_REALLOC(instance.data, newSize)); @@ -111,7 +111,7 @@ void InstancedBuffer::merge(scene::SubModel *subModel, uint32_t passIdx, gfx::Sh if (instance.descriptorSet != descriptorSet) { instance.descriptorSet = descriptorSet; } - memcpy(instance.data + instance.stride * instance.count++, attrs.buffer.buffer()->getData(), stride); + memcpy(instance.data + instance.stride * instance.drawInfo.instanceCount++, attrs.buffer.buffer()->getData(), stride); _hasPendingModels = true; return; } @@ -144,24 +144,25 @@ void InstancedBuffer::merge(scene::SubModel *subModel, uint32_t passIdx, gfx::Sh vertexBuffers.emplace_back(vb); const gfx::InputAssemblerInfo iaInfo = {attributes, vertexBuffers, indexBuffer}; auto *ia = _device->createInputAssembler(iaInfo); - InstancedItem item = {1, INITIAL_CAPACITY, vb, data, ia, stride, shader, descriptorSet, - lightingMap, reflectionProbeCubemap, reflectionProbePlanarMap, reflectionProbeType, reflectionProbeBlendCubemap}; + InstancedItem item = {INITIAL_CAPACITY, vb, data, ia, stride, shader, descriptorSet, + lightingMap, reflectionProbeCubemap, reflectionProbePlanarMap, reflectionProbeType, reflectionProbeBlendCubemap, + ia->getDrawInfo()}; + item.drawInfo.instanceCount = 1; _instances.emplace_back(item); _hasPendingModels = true; } void InstancedBuffer::uploadBuffers(gfx::CommandBuffer *cmdBuff) const { for (const auto &instance : _instances) { - if (!instance.count) continue; + if (!instance.drawInfo.instanceCount) continue; cmdBuff->updateBuffer(instance.vb, instance.data, instance.vb->getSize()); - instance.ia->setInstanceCount(instance.count); } } void InstancedBuffer::clear() { for (auto &instance : _instances) { - instance.count = 0; + instance.drawInfo.instanceCount = 0; } _hasPendingModels = false; } diff --git a/native/cocos/renderer/pipeline/InstancedBuffer.h b/native/cocos/renderer/pipeline/InstancedBuffer.h index 0d979365268..e77d9b61d59 100644 --- a/native/cocos/renderer/pipeline/InstancedBuffer.h +++ b/native/cocos/renderer/pipeline/InstancedBuffer.h @@ -38,7 +38,6 @@ namespace pipeline { struct PSOInfo; struct CC_DLL InstancedItem { - uint32_t count = 0; uint32_t capacity = 0; gfx::Buffer *vb = nullptr; uint8_t *data = nullptr; @@ -51,6 +50,7 @@ struct CC_DLL InstancedItem { gfx::Texture *reflectionProbePlanarMap = nullptr; uint32_t reflectionProbeType = 0; gfx::Texture *reflectionProbeBlendCubemap = nullptr; + gfx::DrawInfo drawInfo; }; using InstancedItemList = ccstd::vector; using DynamicOffsetList = ccstd::vector; diff --git a/native/cocos/renderer/pipeline/RenderInstancedQueue.cpp b/native/cocos/renderer/pipeline/RenderInstancedQueue.cpp index ccc84e0b469..4a0a50654cc 100644 --- a/native/cocos/renderer/pipeline/RenderInstancedQueue.cpp +++ b/native/cocos/renderer/pipeline/RenderInstancedQueue.cpp @@ -68,7 +68,7 @@ void RenderInstancedQueue::recordCommandBuffer(gfx::Device * /*device*/, gfx::Re cmdBuffer->bindDescriptorSet(materialSet, pass->getDescriptorSet()); gfx::PipelineState *lastPSO = nullptr; for (const auto &instance : instances) { - if (!instance.count) { + if (!instance.drawInfo.instanceCount) { continue; } auto *pso = PipelineStateManager::getOrCreatePipelineState(pass, instance.shader, instance.ia, renderPass); diff --git a/native/cocos/renderer/pipeline/UIPhase.cpp b/native/cocos/renderer/pipeline/UIPhase.cpp index 6cdf32ee00f..337846ba9d2 100644 --- a/native/cocos/renderer/pipeline/UIPhase.cpp +++ b/native/cocos/renderer/pipeline/UIPhase.cpp @@ -58,7 +58,7 @@ void UIPhase::render(scene::Camera *camera, gfx::RenderPass *renderPass) { cmdBuff->bindDescriptorSet(materialSet, pass->getDescriptorSet()); cmdBuff->bindInputAssembler(inputAssembler); cmdBuff->bindDescriptorSet(localSet, ds); - cmdBuff->draw(inputAssembler); + cmdBuff->draw(batch->getDrawInfo()); } } } diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index c52a13d114c..aefd8293e5c 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -742,7 +742,7 @@ void submitUICommands( cmdBuff->bindInputAssembler(inputAssembler); cmdBuff->bindDescriptorSet( static_cast(pipeline::SetIndex::LOCAL), ds); - cmdBuff->draw(inputAssembler); + cmdBuff->draw(batch->getDrawInfo()); } } } diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp index 4c42773416f..3f95918ac34 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderQueue.cpp @@ -114,7 +114,7 @@ void RenderInstancingQueue::add( instanceBuffer->setPass(&pass); const auto &instances = instanceBuffer->getInstances(); for (const auto &item : instances) { - CC_EXPECTS(item.count == 0); + CC_EXPECTS(item.drawInfo.instanceCount == 0); } } auto &instancedBuffer = *instanceBuffers[iter->second]; @@ -150,7 +150,7 @@ void RenderInstancingQueue::recordCommandBuffer( cmdBuffer->bindDescriptorSet(pipeline::materialSet, drawPass->getDescriptorSet()); gfx::PipelineState *lastPSO = nullptr; for (const auto &instance : instances) { - if (!instance.count) { + if (!instance.drawInfo.instanceCount) { continue; } auto *pso = pipeline::PipelineStateManager::getOrCreatePipelineState( diff --git a/native/cocos/scene/DrawBatch2D.cpp b/native/cocos/scene/DrawBatch2D.cpp index 7266484adc4..9cf626faeca 100644 --- a/native/cocos/scene/DrawBatch2D.cpp +++ b/native/cocos/scene/DrawBatch2D.cpp @@ -58,5 +58,10 @@ void DrawBatch2D::fillPass(Material *mat, const gfx::DepthStencilState *depthSte } } +void DrawBatch2D::setInputAssembler(gfx::InputAssembler *ia) { + _inputAssembler = ia; + _drawInfo = _inputAssembler->getDrawInfo(); +} + } // namespace scene } // namespace cc diff --git a/native/cocos/scene/DrawBatch2D.h b/native/cocos/scene/DrawBatch2D.h index cda702f3098..94bd4a8a809 100644 --- a/native/cocos/scene/DrawBatch2D.h +++ b/native/cocos/scene/DrawBatch2D.h @@ -47,12 +47,15 @@ class DrawBatch2D final : public RefCounted { void clear(); void fillPass(Material *mat, const gfx::DepthStencilState *depthStencilState, ccstd::hash_t dsHash, const ccstd::vector *patches = nullptr); + void setInputAssembler(gfx::InputAssembler *ia); + inline void setFirstIndex(uint32_t index) { _drawInfo.firstIndex = index; } + inline void setIndexCount(uint32_t count) { _drawInfo.indexCount = count; } - inline void setInputAssembler(gfx::InputAssembler *ia) { _inputAssembler = ia; } inline void setDescriptorSet(gfx::DescriptorSet *descriptorSet) { _descriptorSet = descriptorSet; } inline void setVisFlags(uint32_t flags) { _visFlags = flags; } inline void setModel(Model *model) { _model = model; } + inline const gfx::DrawInfo &getDrawInfo() const { return _drawInfo; } inline gfx::InputAssembler *getInputAssembler() const { return _inputAssembler; } inline gfx::DescriptorSet *getDescriptorSet() const { return _descriptorSet; } inline uint32_t getVisFlags() const { return _visFlags; } @@ -68,6 +71,7 @@ class DrawBatch2D final : public RefCounted { ccstd::vector _shaders; Model *_model{nullptr}; + gfx::DrawInfo _drawInfo; CC_DISALLOW_COPY_MOVE_ASSIGN(DrawBatch2D); }; From 2e61800f9f7721aa212ce4b417b959c76ad37abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Thu, 10 Aug 2023 11:37:06 +0800 Subject: [PATCH 074/184] revert custom pipeline pass order (#15915) --- cocos/rendering/post-process/post-process-builder.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cocos/rendering/post-process/post-process-builder.ts b/cocos/rendering/post-process/post-process-builder.ts index bfe9b18377a..550d8fa15dd 100644 --- a/cocos/rendering/post-process/post-process-builder.ts +++ b/cocos/rendering/post-process/post-process-builder.ts @@ -50,14 +50,13 @@ export class PostProcessBuilder implements PipelineBuilder { // depth-based shading this.addPass(new HBAOPass()); - // hdr - this.addPass(new ToneMappingPass()); - // simple fog with LDR after tone-mapping, atmosphere with HDR before tone-mapping - // this.addPass(new FogPass()); - // transparency should after hdr and depth-based shading + // temporary ignore CC_USE_FLOAT_OUTPUT this.addPass(new ForwardTransparencyPass()); + // float output related processing: hdr + fog + this.addPass(new ToneMappingPass()); + // user post-processing this.addPass(new TAAPass()); this.addPass(new FxaaPass()); From ad6e3dcf8acf3bb5292c11c5ab87e23a6ed158a0 Mon Sep 17 00:00:00 2001 From: hyde zhou Date: Thu, 10 Aug 2023 16:43:16 +0800 Subject: [PATCH 075/184] V3.8.1 pipeline (#15906) --- cocos/rendering/custom/pipeline.ts | 13 +- cocos/rendering/custom/types.ts | 6 +- cocos/rendering/custom/web-pipeline.ts | 41 +- .../renderer/frame-graph/ImmutableState.cpp | 8 +- .../cocos/renderer/gfx-base/GFXDef-common.h | 18 +- .../gfx-vulkan/states/VKTextureBarrier.cpp | 8 +- .../pipeline/custom/FGDispatcherTypes.cpp | 3 +- .../pipeline/custom/FGDispatcherTypes.h | 38 +- .../pipeline/custom/FrameGraphDispatcher.cpp | 448 ++++++++++++------ .../pipeline/custom/NativePipelineTypes.h | 127 ++++- .../pipeline/custom/NativeRenderGraph.cpp | 3 +- .../pipeline/custom/NativeRenderGraphUtils.h | 12 +- .../pipeline/custom/NativeResourceGraph.cpp | 10 +- .../renderer/pipeline/custom/NativeSetter.cpp | 15 + .../pipeline/custom/RenderCommonJsb.cpp | 7 + .../custom/RenderCommonSerialization.h | 2 + .../pipeline/custom/RenderCommonTypes.h | 5 + .../pipeline/custom/RenderInterfaceTypes.h | 13 +- 18 files changed, 565 insertions(+), 212 deletions(-) diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index c679c5796dd..68e6d54d984 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -37,9 +37,12 @@ import { GlobalDSManager } from '../global-descriptor-set-manager'; import { Mat4, Quat, Vec2, Vec4 } from '../../core/math'; import { MacroRecord } from '../../render-scene/core/pass-utils'; import { PipelineSceneData } from '../pipeline-scene-data'; +import { PointLight } from '../../render-scene/scene/point-light'; +import { RangedDirectionalLight } from '../../render-scene/scene/ranged-directional-light'; import { AccessType, CopyPair, LightInfo, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency, UploadPair } from './types'; import { RenderWindow } from '../../render-scene/core/render-window'; import { Light, Model } from '../../render-scene/scene'; +import { SphereLight } from '../../render-scene/scene/sphere-light'; import { SpotLight } from '../../render-scene/scene/spot-light'; /** @@ -377,6 +380,11 @@ export interface Setter extends RenderNode { setSampler (name: string, sampler: Sampler): void; setBuiltinCameraConstants (camera: Camera): void; setBuiltinShadowMapConstants (light: DirectionalLight): void; + setBuiltinDirectionalLightConstants (light: DirectionalLight, camera: Camera): void; + setBuiltinSphereLightConstants (light: SphereLight, camera: Camera): void; + setBuiltinSpotLightConstants (light: SpotLight, camera: Camera): void; + setBuiltinPointLightConstants (light: PointLight, camera: Camera): void; + setBuiltinRangedDirectionalLightConstants (light: RangedDirectionalLight, camera: Camera): void; setBuiltinDirectionalLightViewConstants (light: DirectionalLight, level?: number): void; setBuiltinSpotLightViewConstants (light: SpotLight): void; } @@ -402,7 +410,10 @@ export interface RenderQueueBuilder extends Setter { camera: Camera, light: LightInfo, sceneFlags?: SceneFlags): void; - addScene (camera: Camera, sceneFlags: SceneFlags): void; + addScene ( + camera: Camera, + sceneFlags: SceneFlags, + light?: Light | null): void; addSceneCulledByDirectionalLight ( camera: Camera, sceneFlags: SceneFlags, diff --git a/cocos/rendering/custom/types.ts b/cocos/rendering/custom/types.ts index d09e3b8a9fe..bde9ca132f7 100644 --- a/cocos/rendering/custom/types.ts +++ b/cocos/rendering/custom/types.ts @@ -288,12 +288,14 @@ export function getClearValueTypeName (e: ClearValueType): string { } export class LightInfo { - constructor (light: Light | null = null, level = 0) { + constructor (light: Light | null = null, level = 0, culledByLight = false) { this.light = light; this.level = level; + this.culledByLight = culledByLight; } /*refcount*/ light: Light | null; level: number; + culledByLight: boolean; } export enum DescriptorTypeOrder { @@ -505,11 +507,13 @@ export class PipelineStatistics { export function saveLightInfo (ar: OutputArchive, v: LightInfo): void { // skip, v.light: Light ar.writeNumber(v.level); + ar.writeBool(v.culledByLight); } export function loadLightInfo (ar: InputArchive, v: LightInfo): void { // skip, v.light: Light v.level = ar.readNumber(); + v.culledByLight = ar.readBool(); } export function saveDescriptor (ar: OutputArchive, v: Descriptor): void { diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 08e171ab45c..fa46e3dab45 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -31,7 +31,7 @@ import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass } from './render-graph'; import { ComputePassBuilder, ComputeQueueBuilder, ComputeSubpassBuilder, BasicPipeline, PipelineBuilder, RenderPassBuilder, RenderQueueBuilder, RenderSubpassBuilder, PipelineType, BasicRenderPassBuilder, PipelineCapabilities, BasicMultisampleRenderPassBuilder } from './pipeline'; import { PipelineSceneData } from '../pipeline-scene-data'; -import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows } from '../../render-scene/scene'; +import { Model, Camera, ShadowType, CSMLevel, DirectionalLight, SpotLight, PCFType, Shadows, SphereLight, PointLight, RangedDirectionalLight } from '../../render-scene/scene'; import { Light, LightType } from '../../render-scene/scene/light'; import { DescriptorSetData, DescriptorSetLayoutData, LayoutGraphData } from './layout-graph'; import { Executor } from './executor'; @@ -237,7 +237,9 @@ export class WebSetter { public offsetFloat (v: number, offset: number): void { this._copyToBuffer(v, offset, Type.FLOAT); } - public setBuffer (name: string, buffer: Buffer): void {} + public setBuffer (name: string, buffer: Buffer): void { + // TODO + } public setTexture (name: string, texture: Texture): void { if (this._getCurrDescriptorBlock(name) === -1) { return; @@ -245,8 +247,12 @@ export class WebSetter { const num = this._lg.attributeIndex.get(name)!; this._data.textures.set(num, texture); } - public setReadWriteBuffer (name: string, buffer: Buffer): void {} - public setReadWriteTexture (name: string, texture: Texture): void {} + public setReadWriteBuffer (name: string, buffer: Buffer): void { + // TODO + } + public setReadWriteTexture (name: string, texture: Texture): void { + // TODO + } public setSampler (name: string, sampler: Sampler): void { if (this._getCurrDescriptorBlock(name) === -1) { return; @@ -255,16 +261,31 @@ export class WebSetter { this._data.samplers.set(num, sampler); } public setBuiltinCameraConstants (camera: Camera): void { - + // TODO } public setBuiltinShadowMapConstants (light: Light, numLevels?: number): void { - + // TODO } public setBuiltinDirectionalLightViewConstants (light: DirectionalLight): void { - + // TODO } public setBuiltinSpotLightViewConstants (light: SpotLight): void { - + // TODO + } + public setBuiltinDirectionalLightConstants (light: DirectionalLight, camera: Camera): void { + // TODO + } + public setBuiltinSphereLightConstants (light: SphereLight, camera: Camera): void { + // TODO + } + public setBuiltinSpotLightConstants (light: SpotLight, camera: Camera): void { + // TODO + } + public setBuiltinPointLightConstants (light: PointLight, camera: Camera): void { + // TODO + } + public setBuiltinRangedDirectionalLightConstants (light: RangedDirectionalLight, camera: Camera): void { + // TODO } public hasSampler (name: string): boolean { const id = this._lg.attributeIndex.get(name); @@ -1084,7 +1105,7 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR this._pass.rasterViews.set(name, view); } resolveRenderTarget (source: string, target: string): void { - + // TODO } resolveDepthStencil ( source: string, @@ -1092,7 +1113,7 @@ export class WebRenderPassBuilder extends WebSetter implements BasicMultisampleR depthMode?: ResolveMode, stencilMode?: ResolveMode, ): void { - + // TODO } private _addComputeResource (name: string, accessType: AccessType, slotName: string): void { const view = new ComputeView(slotName); diff --git a/native/cocos/renderer/frame-graph/ImmutableState.cpp b/native/cocos/renderer/frame-graph/ImmutableState.cpp index 24a0b9ad604..4c62c3608a3 100644 --- a/native/cocos/renderer/frame-graph/ImmutableState.cpp +++ b/native/cocos/renderer/frame-graph/ImmutableState.cpp @@ -85,10 +85,10 @@ std::pair getBarrier(const ResourceBarrier& ba info.type = barrierInfo.barrierType; info.prevAccesses = getAccessFlags(usage, barrierInfo.beginStatus); info.nextAccesses = getAccessFlags(usage, barrierInfo.endStatus); - info.baseMipLevel = static_cast(barrierInfo.mipRange.base); - info.levelCount = static_cast(barrierInfo.mipRange.len); - info.baseSlice = static_cast(barrierInfo.layerRange.base); - info.sliceCount = static_cast(barrierInfo.layerRange.len); + info.range.mipLevel = static_cast(barrierInfo.mipRange.base); + info.range.levelCount = static_cast(barrierInfo.mipRange.len); + info.range.firstSlice = static_cast(barrierInfo.layerRange.base); + info.range.numSlices = static_cast(barrierInfo.layerRange.len); res.first = gfx::Device::getInstance()->getTextureBarrier(info); res.second = gfxTexture; diff --git a/native/cocos/renderer/gfx-base/GFXDef-common.h b/native/cocos/renderer/gfx-base/GFXDef-common.h index a8a6e4b22d2..da39c2c6dee 100644 --- a/native/cocos/renderer/gfx-base/GFXDef-common.h +++ b/native/cocos/renderer/gfx-base/GFXDef-common.h @@ -1343,6 +1343,18 @@ struct RenderPassInfo { EXPOSE_COPY_FN(RenderPassInfo) }; +struct ResourceRange { + uint32_t width{0}; + uint32_t height{0}; + uint32_t depthOrArraySize{0}; + uint32_t firstSlice{0}; + uint32_t numSlices{0}; + uint32_t mipLevel{0}; + uint32_t levelCount{0}; + uint32_t basePlane{0}; + uint32_t planeCount{0}; +}; + struct ALIGNAS(8) GeneralBarrierInfo { AccessFlags prevAccesses{AccessFlagBit::NONE}; AccessFlags nextAccesses{AccessFlagBit::NONE}; @@ -1360,11 +1372,7 @@ struct ALIGNAS(8) TextureBarrierInfo { BarrierType type{BarrierType::FULL}; - uint32_t baseMipLevel{0}; - uint32_t levelCount{1}; - uint32_t baseSlice{0}; - uint32_t sliceCount{1}; - + ResourceRange range{}; uint64_t discardContents{0}; // @ts-boolean Queue *srcQueue{nullptr}; // @ts-nullable diff --git a/native/cocos/renderer/gfx-vulkan/states/VKTextureBarrier.cpp b/native/cocos/renderer/gfx-vulkan/states/VKTextureBarrier.cpp index 86199a46bc0..61aa80a32e2 100644 --- a/native/cocos/renderer/gfx-vulkan/states/VKTextureBarrier.cpp +++ b/native/cocos/renderer/gfx-vulkan/states/VKTextureBarrier.cpp @@ -44,10 +44,10 @@ CCVKTextureBarrier::CCVKTextureBarrier(const TextureBarrierInfo &info) : Texture _gpuBarrier->barrier.prevLayout = getAccessLayout(info.prevAccesses); _gpuBarrier->barrier.nextLayout = getAccessLayout(info.nextAccesses); _gpuBarrier->barrier.discardContents = !!info.discardContents; - _gpuBarrier->barrier.subresourceRange.baseMipLevel = 0U; - _gpuBarrier->barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; - _gpuBarrier->barrier.subresourceRange.baseArrayLayer = 0U; - _gpuBarrier->barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS; + _gpuBarrier->barrier.subresourceRange.baseMipLevel = info.range.mipLevel; + _gpuBarrier->barrier.subresourceRange.levelCount = info.range.levelCount; + _gpuBarrier->barrier.subresourceRange.baseArrayLayer = info.range.firstSlice; + _gpuBarrier->barrier.subresourceRange.layerCount = info.range.numSlices; _gpuBarrier->barrier.srcQueueFamilyIndex = info.srcQueue ? static_cast(info.srcQueue)->gpuQueue()->queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED; diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp index 1982760fd0a..41d24898bcf 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.cpp @@ -95,7 +95,8 @@ ResourceAccessGraph::ResourceAccessGraph(const allocator_type& alloc) noexcept topologicalOrder(alloc), resourceAccess(alloc), movedTarget(alloc), - movedSourceStatus(alloc) {} + movedSourceStatus(alloc), + movedTargetStatus(alloc) {} // ContinuousContainer void ResourceAccessGraph::reserve(vertices_size_type sz) { diff --git a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h index 25816eaf81c..4f6b586f6f4 100644 --- a/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h +++ b/native/cocos/renderer/pipeline/custom/FGDispatcherTypes.h @@ -60,21 +60,9 @@ struct LeafStatus { bool needCulling{false}; }; -struct ResourceRange { - uint32_t width{0}; - uint32_t height{0}; - uint32_t depthOrArraySize{0}; - uint32_t firstSlice{0}; - uint32_t numSlices{0}; - uint32_t mipLevel{0}; - uint32_t levelCount{0}; - uint32_t basePlane{0}; - uint32_t planeCount{0}; -}; - struct AccessStatus { gfx::AccessFlagBit accessFlag{gfx::AccessFlagBit::NONE}; - ResourceRange range; + gfx::ResourceRange range; }; struct ResourceAccessNode { @@ -135,7 +123,7 @@ struct FGRenderPassInfo { FGRenderPassInfo& operator=(FGRenderPassInfo&& rhs) = default; FGRenderPassInfo& operator=(FGRenderPassInfo const& rhs) = default; - std::vector colorAccesses; + ccstd::vector colorAccesses; LayoutAccess dsAccess; LayoutAccess dsResolveAccess; gfx::RenderPassInfo rpInfo; @@ -156,8 +144,23 @@ struct Barrier { }; struct BarrierNode { - std::vector frontBarriers; - std::vector rearBarriers; + ccstd::vector frontBarriers; + ccstd::vector rearBarriers; +}; + +struct SliceNode { + bool full{false}; + ccstd::vector mips; +}; + +struct TextureNode { + bool full{false}; + ccstd::vector slices; +}; + +struct ResourceNode { + bool full{false}; + ccstd::vector planes; }; struct ResourceAccessGraph { @@ -293,8 +296,9 @@ struct ResourceAccessGraph { PmrFlatMap resourceLifeRecord; ccstd::pmr::vector topologicalOrder; PmrTransparentMap> resourceAccess; - PmrFlatMap> movedTarget; + PmrFlatMap> movedTarget; PmrFlatMap movedSourceStatus; + PmrFlatMap movedTargetStatus; }; struct RelationGraph { diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index 6cdd864a2b4..d18121f8761 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -122,6 +122,57 @@ ResourceGraph::vertex_descriptor FrameGraphDispatcher::realResourceID(const ccst return resourceAccessGraph.resourceIndex.at(name); } +[[nodiscard]] ccstd::pmr::string concatResName( + std::string_view name0, + std::string_view name1, + boost::container::pmr::memory_resource *scratch) { + ccstd::pmr::string name(name0, scratch); + name += "/"; + name += name1; + return name; +} + +[[nodiscard]] ccstd::pmr::string getSubresNameByPlane(const ccstd::pmr::string &resName, + uint32_t planeID, const ResourceGraph &resg, + boost::container::pmr::memory_resource *scratch) { + const auto &desc = get(ResourceGraph::DescTag{}, resg, vertex(resName, resg)); + // depth stencil + if (desc.format == gfx::Format::DEPTH_STENCIL) { + auto nameView = planeID == 0 ? DEPTH_PLANE_NAME : STENCIL_PLANE_NAME; + const auto &subresName = concatResName(resName, nameView, scratch); + return subresName; + } + + // array + if (desc.dimension == ResourceDimension::TEXTURE2D && desc.depthOrArraySize > 1) { + ccstd::pmr::set leaves(scratch); + auto resID = vertex(resName, resg); + + using LeafGatherFunc = std::function &)>; + LeafGatherFunc leafGather = [&](ResourceGraph::vertex_descriptor v, const ResourceGraph &resg, ccstd::pmr::set &names) { + for (const auto &e : makeRange(children(v, resg))) { + if (!out_degree(e.target, resg)) { + const auto &rName = get(ResourceGraph::NameTag{}, resg, e.target); + names.emplace(rName); + } else { + leafGather(e.target, resg, names); + } + } + }; + leafGather(resID, resg, leaves); + + auto iter = leaves.begin(); + std::advance(iter, planeID); + return (*iter); + } + + // cube + + // UNREACHABLE + CC_ASSERT(false); + return ""; +} + ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor resID, const ResourceGraph &resg, std::string_view name) { auto resName = get(ResourceGraph::NameTag{}, resg, resID); resName += "/"; @@ -129,15 +180,12 @@ ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor r return findVertex(resName, resg); } -ResourceGraph::vertex_descriptor locateSubres(ResourceGraph::vertex_descriptor resID, +ResourceGraph::vertex_descriptor locateSubres(const ccstd::pmr::string& originName, const ResourceGraph &resg, - uint32_t basePlane) { - auto ret = resID; - const auto &desc = get(ResourceGraph::DescTag{}, resg, resID); - if (desc.format == gfx::Format::DEPTH_STENCIL) { - ret = basePlane == 0 ? locateSubres(resID, resg, DEPTH_PLANE_NAME) : locateSubres(resID, resg, STENCIL_PLANE_NAME); - } - return ret; + uint32_t basePlane, + boost::container::pmr::memory_resource *scratch) { + const auto &resName = getSubresNameByPlane(originName, basePlane, resg, scratch); + return findVertex(resName, resg); } PmrFlatMap FrameGraphDispatcher::buildDescriptorIndex( @@ -152,7 +200,7 @@ PmrFlatMap FrameGraphDispatcher:: const auto &name = computeView.name; CC_EXPECTS(!name.empty()); const auto nameID = layoutGraph.attributeIndex.at(name); - auto subresID = locateSubres(resID, resourceGraph, computeView.plane); + auto subresID = locateSubres(resName, resourceGraph, computeView.plane, scratch); resourceIndex.emplace(nameID, subresID); } } @@ -317,11 +365,11 @@ LayoutAccess FrameGraphDispatcher::getResourceAccess(ResourceGraph::vertex_descr using PmrString = ccstd::pmr::string; using EdgeList = std::pair; using CloseCircuit = std::pair; -using CloseCircuits = std::vector; +using CloseCircuits = ccstd::vector; using RelationVert = RelationGraph::vertex_descriptor; -using RelationVerts = std::vector; +using RelationVerts = ccstd::vector; using RelationEdge = RelationGraph::edge_descriptor; -using RelationEdges = std::vector; +using RelationEdges = ccstd::vector; using ScoreMap = std::map>; using RasterViewsMap = PmrTransparentMap; using ComputeViewsMap = PmrTransparentMap>; @@ -340,7 +388,7 @@ struct ViewStatus { const AccessType access; const gfx::ShaderStageFlagBit visibility; const gfx::AccessFlags accessFlag; - const ResourceRange ⦥ + const gfx::ResourceRange ⦥ }; constexpr uint32_t EXPECT_START_ID = 0; @@ -423,10 +471,10 @@ bool isResourceView(const ResourceGraph::vertex_descriptor v, const ResourceGrap return resg.isTextureView(v); // || isBufferView } -ResourceRange getResourceRange(const ResourceGraph::vertex_descriptor v, +gfx::ResourceRange getResourceRange(const ResourceGraph::vertex_descriptor v, const ResourceGraph &resg) { const auto &desc = get(ResourceGraph::DescTag{}, resg, v); - ResourceRange range{ + gfx::ResourceRange range{ desc.width, desc.height, desc.depthOrArraySize, @@ -813,16 +861,6 @@ void fillRenderPassInfo(const AttachmentMap &colorMap, } }; -[[nodiscard("concat")]] ccstd::pmr::string concatResName( - std::string_view name0, - std::string_view name1, - boost::container::pmr::memory_resource *scratch) { - ccstd::pmr::string name(name0, scratch); - name += "/"; - name += name1; - return name; -} - void extractNames(const ccstd::pmr::string &resName, const RasterView &view, ccstd::pmr::vector> &names) { @@ -857,26 +895,6 @@ void extractNames(const ccstd::pmr::string &resName, } } -[[nodiscard("subresName")]] ccstd::pmr::string getSubresName(const ccstd::pmr::string &resName, - uint32_t planeID, const ResourceGraph& resg, - boost::container::pmr::memory_resource* scratch) { - const auto& desc = get(ResourceGraph::DescTag{}, resg, vertex(resName, resg)); - if(desc.format == gfx::Format::DEPTH_STENCIL) { - auto nameView = planeID == 0 ? DEPTH_PLANE_NAME : STENCIL_PLANE_NAME; - const auto &subresName = concatResName(resName, nameView, scratch); - return subresName; - } - - - // cube - - // array - - // UNREACHABLE - CC_ASSERT(false); - return ""; -} - auto checkRasterViews(const Graphs &graphs, ResourceAccessGraph::vertex_descriptor ragVertID, ResourceAccessNode &node, @@ -965,8 +983,8 @@ bool checkComputeViews(const Graphs &graphs, ResourceAccessGraph::vertex_descrip tryAddEdge(lastVertId, ragVertID, relationGraph); dependent = lastVertId != EXPECT_START_ID; - if(out_degree(resID, resourceGraph)) { - const auto& subresFullName = getSubresName(resName, computeView.plane, resourceGraph, resourceAccessGraph.resource()); + if (out_degree(resID, resourceGraph) && (computeView.plane != 0xFFFFFFFF)) { + const auto& subresFullName = getSubresNameByPlane(resName, computeView.plane, resourceGraph, resourceAccessGraph.resource()); resourceAccessGraph.resourceIndex.emplace(subresFullName, vertex(subresFullName, resourceGraph)); } } @@ -1352,118 +1370,163 @@ void startRaytracePass(const Graphs &graphs, uint32_t passID, const RaytracePass std::ignore = checkComputeViews(graphs, rlgVertID, accessNode, pass.computeViews); } -namespace { -struct SliceNode { - bool full{false}; - ccstd::pmr::vector mips; -}; - -struct TextureNode { - bool full{false}; - ccstd::pmr::vector slices; -}; - -struct ResourceNode { - ccstd::pmr::vector planes; -}; -} // namespace - -bool rangeCheck(ccstd::pmr::map &status, - const ResourceDesc &desc, - const PmrString &targetName, +bool rangeCheck(ResourceNode &status, + const ResourceDesc &/*desc*/, + const PmrString &/*targetName*/, uint32_t firstSlice, uint32_t numSlices, uint32_t firstMip, uint32_t mipLevels, uint32_t planeIndex) { - if (status.find(targetName) == status.end()) { - status.emplace(targetName, ResourceNode{}); + CC_ASSERT(planeIndex < status.planes.size()); + // spare space in target + bool check = !status.full; + check &= !status.planes[planeIndex].full; + if (check) { + for (auto slice = firstSlice; slice < firstSlice + numSlices; ++slice) { + auto &slices = status.planes[planeIndex].slices; + // no spare space in this slice + check &= !slices[slice].full; + if (!check) { + continue; + } + for (auto mip = firstMip; mip < firstMip + mipLevels; ++mip) { + auto &mips = slices[slice].mips; + // this mip has been taken + check &= mips[mip] == std::numeric_limits::max(); + if (!check) { + continue; + } + mips[mip] = mip; + auto maxIter = std::max_element(mips.begin(), mips.end()); + if ((*maxIter) != std::numeric_limits::max()) { + // linear increasing + check &= (*maxIter) == mips.size() - 1; + slices[slice].full = true; + } + } + if (std::all_of(slices.begin(), slices.end(), [](const SliceNode &sliceNode) { return sliceNode.full; })) { + status.planes[planeIndex].full = true; + } + } } + return check; +} - if (planeIndex >= status[targetName].planes.size()) { - status[targetName].planes.resize(planeIndex + 1); - status[targetName].planes[planeIndex].slices.resize(desc.depthOrArraySize); - for (auto &slice : status[targetName].planes[planeIndex].slices) { - slice.mips.resize(desc.mipLevels, std::numeric_limits::max()); - } +uint32_t getPlaneCount(gfx::Format format) { + switch (format) { + case gfx::Format::DEPTH_STENCIL: + return 2; + default: + return 1; } +} - // no spare space in target - bool check = !status[targetName].planes[planeIndex].full; - for (auto slice = firstSlice; slice < firstSlice + numSlices; ++slice) { - auto &slices = status[targetName].planes[planeIndex].slices; - // no spare space in this slice - check &= !slices[slice].full; - for (auto mip = firstMip; mip < firstMip + mipLevels; ++mip) { - auto &mips = slices[slice].mips; - // this mip has been taken - check &= mips[mip] == std::numeric_limits::max(); - mips[mip] = mip; - auto maxIter = std::max_element(mips.begin(), mips.end()); - if ((*maxIter) != std::numeric_limits::max()) { - // linear increasing - check &= (*maxIter) == mips.size() - 1; - slices[slice].full = true; +bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const ResourceGraph& resourceGraph) { + bool check = true; + ccstd::pmr::vector targets(rag.get_allocator()); + for (const auto &movePair : pass.movePairs) { + const auto &fromResName = movePair.source; + const auto fromResID = resourceGraph.valueIndex.at(fromResName); + const auto &fromResDesc = get(ResourceGraph::DescTag{}, resourceGraph, fromResID); + + const auto &toResName = movePair.target; + const auto toResID = resourceGraph.valueIndex.at(toResName); + const auto &toResDesc = get(ResourceGraph::DescTag{}, resourceGraph, toResID); + + const auto &fromResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, fromResID); + const auto &toResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, toResID); + auto commonUsage = fromResDesc.flags | toResDesc.flags; + + targets.emplace_back(toResName); + + if (rag.movedTargetStatus.find(toResName) == rag.movedTargetStatus.end()) { + rag.movedTargetStatus[toResName].planes.resize(getPlaneCount(toResDesc.format)); + for (auto &plane : rag.movedTargetStatus[toResName].planes) { + plane.slices.resize(toResDesc.depthOrArraySize); + for (auto &slice : plane.slices) { + slice.mips.resize(toResDesc.mipLevels, std::numeric_limits::max()); + } } } - if (std::all_of(slices.begin(), slices.end(), [](const SliceNode &sliceNode) { return sliceNode.full; })) { - status[targetName].planes[planeIndex].full = true; - } + + rangeCheck(rag.movedTargetStatus[toResName], toResDesc, toResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); + uint32_t validConditions[] = { + !fromResTraits.hasSideEffects(), + rag.movedSourceStatus.find(toResName) == rag.movedSourceStatus.end(), + rag.movedSourceStatus.find(fromResName) == rag.movedSourceStatus.end(), + fromResTraits.residency != ResourceResidency::MEMORYLESS && toResTraits.residency != ResourceResidency::MEMORYLESS, + fromResDesc.dimension == toResDesc.dimension, + fromResDesc.width == toResDesc.width, + fromResDesc.height == toResDesc.height, + fromResDesc.format == toResDesc.format, + fromResDesc.sampleCount == toResDesc.sampleCount, + (fromResDesc.depthOrArraySize == toResDesc.depthOrArraySize) || (toResDesc.dimension != ResourceDimension::BUFFER), // full move if resource is buffer + }; + bool val = std::min_element(std::begin(validConditions), std::end(validConditions)); + check &= val; } + + // full check + std::for_each(targets.begin(), targets.end(), [&](const ccstd::pmr::string &target) { + ResourceNode &resNode = rag.movedTargetStatus[target]; + resNode.full |= std::all_of(resNode.planes.begin(), resNode.planes.end(), [](const auto &textureNode) { + return textureNode.full; + }); + }); + return check; } -bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const ResourceGraph& resourceGraph) { - bool check = true; - // ccstd::pmr::map sourceCheck; - ccstd::pmr::map targetCheck; - for (const auto &movePair : pass.movePairs) { - const auto &fromResName = movePair.source; - const auto fromResID = resourceGraph.valueIndex.at(fromResName); - const auto &fromResDesc = get(ResourceGraph::DescTag{}, resourceGraph, fromResID); - - const auto &toResName = movePair.target; - const auto toResID = resourceGraph.valueIndex.at(toResName); - const auto &toResDesc = get(ResourceGraph::DescTag{}, resourceGraph, toResID); - - const auto &fromResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, fromResID); - const auto &toResTraits = get(ResourceGraph::TraitsTag{}, resourceGraph, toResID); - auto commonUsage = fromResDesc.flags | toResDesc.flags; - - // bool sourceRangeValid = rangeCheck(targetCheck, toResDesc, fromResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); - bool targetRangeValid = rangeCheck(targetCheck, toResDesc, toResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); - - uint32_t validConditions[] = { - !fromResTraits.hasSideEffects(), - rag.movedSourceStatus.find(toResName) == rag.movedSourceStatus.end(), - rag.movedSourceStatus.find(fromResName) == rag.movedSourceStatus.end(), - targetRangeValid, - fromResTraits.residency != ResourceResidency::MEMORYLESS && toResTraits.residency != ResourceResidency::MEMORYLESS, - fromResDesc.dimension == toResDesc.dimension, - fromResDesc.width == toResDesc.width, - fromResDesc.height == toResDesc.height, - fromResDesc.format == toResDesc.format, - fromResDesc.sampleCount == toResDesc.sampleCount, - (fromResDesc.depthOrArraySize == toResDesc.depthOrArraySize) || (toResDesc.dimension != ResourceDimension::BUFFER), // full move if resource is buffer - }; - bool val = std::min_element(std::begin(validConditions), std::end(validConditions)); - check &= val; - } - - // full destination - check &= std::all_of(targetCheck.begin(), targetCheck.end(), [](const auto &pair) { - const ResourceNode &resNode = pair.second; - return std::all_of(resNode.planes.begin(), resNode.planes.end(), [](const auto &textureNode) { - return textureNode.full; - }); - }); - - return check; - } +[[nodiscard]] ccstd::pmr::string getSubresourceNameByRange( + const gfx::ResourceRange &range, + boost::container::pmr::memory_resource *scratch) { + ccstd::pmr::string subresName(scratch); + // if () { + // switch (range.firstSlice) { + // case 0: + // return CUBE_RIGHT_NAME.data(); + // case 1: + // return CUBE_LEFT_NAME.data(); + // case 2: + // return CUBE_TOP_NAME.data(); + // case 3: + // return CUBE_BOTTOM_NAME.data(); + // case 4: + // return CUBE_FRONT_NAME.data(); + // case 5: + // return CUBE_REAR_NAME.data(); + // default: + // break; + // } + // } else { + std::string suffix = std::to_string(range.basePlane) + "_" + std::to_string(range.planeCount) + "_" + std::to_string(range.firstSlice) + "_" + std::to_string(range.numSlices) + "_" + std::to_string(range.mipLevel) + "_" + std::to_string(range.levelCount); + subresName = suffix; + // } + return subresName; +} + +gfx::SamplerInfo makePointSamplerInfo() { + return gfx::SamplerInfo{gfx::Filter::POINT, gfx::Filter::POINT, gfx::Filter::POINT}; +} + +SubresourceView makeSubresourceView(const ResourceDesc& desc, const gfx::ResourceRange& range) { + SubresourceView view{}; + view.firstArraySlice = range.firstSlice; + view.numArraySlices = range.numSlices; + view.indexOrFirstMipLevel = range.mipLevel; + view.numMipLevels = range.levelCount; + view.firstPlane = range.basePlane; + view.numPlanes = range.planeCount; + view.format = desc.format; + view.textureView = nullptr; + return view; +} void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass) { const auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; - if(moveValidation(pass, resourceAccessGraph, resourceGraph)) { - for(const auto& pair : pass.movePairs) { + if (moveValidation(pass, resourceAccessGraph, resourceGraph)) { + for (const auto &pair : pass.movePairs) { + auto toleranceRange = getResourceRange(vertex(pair.target, resourceGraph), resourceGraph); auto srcResourceRange = getResourceRange(vertex(pair.source, resourceGraph), resourceGraph); srcResourceRange.firstSlice = pair.targetFirstSlice; srcResourceRange.mipLevel = pair.targetMostDetailedMip; @@ -1471,17 +1534,20 @@ void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass) auto lastStatusIter = resourceAccessGraph.resourceAccess.at(pair.source).rbegin(); resourceAccessGraph.movedSourceStatus.emplace(pair.source, AccessStatus{lastStatusIter->second.accessFlag, srcResourceRange}); - resourceAccessGraph.movedTarget[pair.target].emplace_back(pair.source); + resourceAccessGraph.movedTarget[pair.target].emplace(getSubresourceNameByRange(srcResourceRange, resourceAccessGraph.resource()), pair.source); resourceAccessGraph.resourceAccess[pair.target] = resourceAccessGraph.resourceAccess[pair.source]; auto targetResID = findVertex(pair.target, resourceGraph); resourceAccessGraph.resourceIndex[pair.target] = targetResID; auto &rag = resourceAccessGraph; - std::function feedBack = [&](const ccstd::pmr::string &source, ResourceGraph::vertex_descriptor v) { + std::function feedBack = [&]( + const ccstd::pmr::string &source, + ResourceGraph::vertex_descriptor v) { rag.resourceIndex[source] = v; + if (rag.movedTarget.find(source) != rag.movedTarget.end()) { - for (const auto &prt : rag.movedTarget[source]) { + for (const auto &[rangeStr, prt] : rag.movedTarget[source]) { feedBack(prt, v); } } @@ -1548,19 +1614,67 @@ struct DependencyVisitor : boost::dfs_visitor<> { const Graphs &graphs; }; +void subresourceAnalysis(ResourceAccessGraph& rag, ResourceGraph& resg) { + using RecursiveFuncType = std::function &, const ccstd::pmr::string &)>; + RecursiveFuncType addSubres = [&](const PmrFlatMap &subreses, const ccstd::pmr::string &resName) { + if (subreses.size() == 1) { + const auto &src = subreses.begin()->second; + rag.resourceIndex[src] = rag.resourceIndex.at(resName); + + if (rag.movedTarget.find(src) != rag.movedTarget.end()) { + addSubres(rag.movedTarget.at(src), src); + } + } else { + for (const auto &[rangeStr, subres] : subreses) { + auto targetResID = rag.resourceIndex.at(resName); + const auto &targetName = get(ResourceGraph::NameTag{}, resg, targetResID); + const auto &targetDesc = get(ResourceGraph::DescTag{}, resg, targetResID); + const auto &srcResourceRange = rag.movedSourceStatus.at(subres).range; + const auto &targetTraits = get(ResourceGraph::TraitsTag{}, resg, targetResID); + const auto &indexName = concatResName(targetName, subres, rag.resource()); + auto subresID = findVertex(indexName, resg); + if (subresID == ResourceGraph::null_vertex()) { + const auto &subView = makeSubresourceView(targetDesc, srcResourceRange); + // register to resourcegraph + subresID = addVertex( + SubresourceViewTag{}, + std::forward_as_tuple(indexName), + std::forward_as_tuple(targetDesc), + std::forward_as_tuple(targetTraits), + std::forward_as_tuple(), + std::forward_as_tuple(makePointSamplerInfo()), + std::forward_as_tuple(subView), + resg, + targetResID); + } + rag.resourceIndex[subres] = subresID; + + if (rag.movedTarget.find(subres) != rag.movedTarget.end()) { + addSubres(rag.movedTarget.at(subres), subres); + } + } + } + }; + + for (const auto &[targetName, subreses] : rag.movedTarget) { + if (subreses.size() > 1 && rag.movedSourceStatus.find(targetName) == rag.movedSourceStatus.end()) { + addSubres(rag.movedTarget.at(targetName), targetName); + } + } +} + // status of resource access -void buildAccessGraph(const Graphs &graphs) { +void buildAccessGraph(Graphs &graphs) { // what we need: // - pass dependency // - pass attachment access // AccessTable accessRecord; - const auto &[renderGraph, resourceGraph, layoutGraphData, resourceAccessGraph, relationGraph] = graphs; + auto &[renderGraph, layoutGraphData, resourceGraph, resourceAccessGraph, relationGraph] = graphs; size_t numPasses = 0; numPasses += renderGraph.rasterPasses.size(); numPasses += renderGraph.computePasses.size(); numPasses += renderGraph.copyPasses.size(); - numPasses += renderGraph.movePasses.size(); numPasses += renderGraph.raytracePasses.size(); resourceAccessGraph.reserve(static_cast(numPasses)); @@ -1601,6 +1715,9 @@ void buildAccessGraph(const Graphs &graphs) { } } + // moved resource + subresourceAnalysis(resourceAccessGraph, resourceGraph); + auto &rag = resourceAccessGraph; auto branchCulling = [](ResourceAccessGraph::vertex_descriptor vertex, ResourceAccessGraph &rag) -> void { CC_EXPECTS(out_degree(vertex, rag) == 0); @@ -1669,6 +1786,23 @@ void buildAccessGraph(const Graphs &graphs) { } #pragma region BUILD_BARRIERS +gfx::ResourceRange getOriginRange(ResourceGraph::vertex_descriptor v, const gfx::ResourceRange &currRange, const ResourceGraph &resg) { + gfx::ResourceRange ret = currRange; + auto resID = parent(v, resg); + if (resID == ResourceGraph::null_vertex()) { + return ret; + } + + while (resg.isTextureView(resID)) { + const auto &subresView = get(SubresourceViewTag{}, resID, resg); + ret.firstSlice += subresView.firstArraySlice; + ret.mipLevel += subresView.indexOrFirstMipLevel; + ret.basePlane += subresView.firstPlane; + resID = parent(resID, resg); + } + return ret; +} + void buildBarriers(FrameGraphDispatcher &fgDispatcher) { auto *scratch = fgDispatcher.scratch; const auto &renderGraph = fgDispatcher.renderGraph; @@ -1679,7 +1813,7 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { // record resource current in-access and out-access for every single node if (!fgDispatcher._accessGraphBuilt) { - const Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; + Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; buildAccessGraph(graphs); fgDispatcher._accessGraphBuilt = true; } @@ -1697,14 +1831,11 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { info.type = barrier.type; gfxBarrier = gfx::Device::getInstance()->getBufferBarrier(info); } else { + const auto& originRange = getOriginRange(barrier.resourceID, barrier.endStatus.range, resourceGraph); gfx::TextureBarrierInfo info; info.prevAccesses = barrier.beginStatus.accessFlag; info.nextAccesses = barrier.endStatus.accessFlag; - const auto &range = barrier.beginStatus.range; - info.baseMipLevel = range.mipLevel; - info.levelCount = range.levelCount; - info.baseSlice = range.firstSlice; - info.sliceCount = range.numSlices; + info.range = originRange; info.type = barrier.type; gfxBarrier = gfx::Device::getInstance()->getTextureBarrier(info); } @@ -1736,7 +1867,8 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { if (holds(dstPassID, renderGraph) || holds(dstPassID, renderGraph)) { const auto &fgRenderPassInfo = get(ResourceAccessGraph::RenderPassInfoTag{}, rag, dstRagVertID); - if (fgRenderPassInfo.viewIndex.find(resName) != fgRenderPassInfo.viewIndex.end()) { + if (fgRenderPassInfo.viewIndex.find(resName) != fgRenderPassInfo.viewIndex.end() || + rag.movedTargetStatus.find(resName) != rag.movedTargetStatus.end()) { // renderpass info instead continue; } @@ -2275,7 +2407,7 @@ void passReorder(FrameGraphDispatcher &fgDispatcher) { auto &rag = fgDispatcher.resourceAccessGraph; if (!fgDispatcher._accessGraphBuilt) { - const Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; + Graphs graphs{renderGraph, layoutGraph, resourceGraph, rag, relationGraph}; buildAccessGraph(graphs); fgDispatcher._accessGraphBuilt = true; } @@ -2286,7 +2418,7 @@ void passReorder(FrameGraphDispatcher &fgDispatcher) { boost::transitive_closure(relationGraph, relationGraphTc); CloseCircuits circuits; - std::vector crossEdges; + ccstd::vector crossEdges; PassVisitor visitor(relationGraphTc, circuits); auto colors = relationGraph.colors(scratch); boost::depth_first_search(relationGraph, visitor, get(colors, relationGraph)); @@ -2314,7 +2446,7 @@ void passReorder(FrameGraphDispatcher &fgDispatcher) { RelationVerts candidates; candidates.push_back(EXPECT_START_ID); - std::vector candidateBuffer; + ccstd::vector candidateBuffer; uint32_t coloredVerts = 0; while (coloredVerts < relationGraph._vertices.size()) { // decreasing order, pop back from vector, push into queue, then it's ascending order. diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index b21235bc46b..1fdb0ebed7d 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -88,6 +88,11 @@ class NativeSetter : public NativeRenderNode { void setSampler(const ccstd::string &name, gfx::Sampler *sampler) /*implements*/; void setBuiltinCameraConstants(const scene::Camera *camera) /*implements*/; void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) /*implements*/; + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) /*implements*/; + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) /*implements*/; + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) /*implements*/; + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) /*implements*/; + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) /*implements*/; void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) /*implements*/; void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) /*implements*/; @@ -175,6 +180,21 @@ class NativeRenderQueueBuilder final : public RenderQueueBuilder, public NativeS void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -183,7 +203,7 @@ class NativeRenderQueueBuilder final : public RenderQueueBuilder, public NativeS } void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) override; - void addScene(const scene::Camera *camera, SceneFlags sceneFlags) override; + void addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) override; void addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) override; void addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) override; void addFullscreenQuad(Material *material, uint32_t passID, SceneFlags sceneFlags) override; @@ -250,6 +270,21 @@ class NativeRenderSubpassBuilder final : public RenderSubpassBuilder, public Nat void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -346,6 +381,21 @@ class NativeMultisampleRenderSubpassBuilder final : public MultisampleRenderSubp void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -445,6 +495,21 @@ class NativeComputeSubpassBuilder final : public ComputeSubpassBuilder, public N void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -517,6 +582,21 @@ class NativeRenderPassBuilder final : public RenderPassBuilder, public NativeSet void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -601,6 +681,21 @@ class NativeMultisampleRenderPassBuilder final : public MultisampleRenderPassBui void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -684,6 +779,21 @@ class NativeComputeQueueBuilder final : public ComputeQueueBuilder, public Nativ void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } @@ -751,6 +861,21 @@ class NativeComputePassBuilder final : public ComputePassBuilder, public NativeS void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) override { NativeSetter::setBuiltinShadowMapConstants(light); } + void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinDirectionalLightConstants(light, camera); + } + void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSphereLightConstants(light, camera); + } + void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinSpotLightConstants(light, camera); + } + void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinPointLightConstants(light, camera); + } + void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) override { + NativeSetter::setBuiltinRangedDirectionalLightConstants(light, camera); + } void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) override { NativeSetter::setBuiltinDirectionalLightViewConstants(light, level); } diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp index 91c9dcf73b4..960cb08d0d4 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraph.cpp @@ -736,7 +736,8 @@ void NativeRenderQueueBuilder::addSceneOfCamera( data); } -void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags) { +void NativeRenderQueueBuilder::addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) { + std::ignore = light; SceneData data(camera->getScene(), camera, sceneFlags, LightInfo{}); auto sceneID = addVertex2( diff --git a/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h b/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h index bf1ff547408..a28f1c6fdf7 100644 --- a/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h +++ b/native/cocos/renderer/pipeline/custom/NativeRenderGraphUtils.h @@ -217,12 +217,12 @@ inline bool defaultAttachment(std::string_view slotName) { static constexpr std::string_view DEPTH_PLANE_NAME = "depth"; static constexpr std::string_view STENCIL_PLANE_NAME = "stencil"; -static constexpr std::string_view CUBE_TOP_NAME = "Top"; -static constexpr std::string_view CUBE_BOTTOM_NAME = "Bottom"; -static constexpr std::string_view CUBE_FRONT_NAME = "Front"; -static constexpr std::string_view CUBE_REAR_NAME = "Rear"; -static constexpr std::string_view CUBE_LEFT_NAME = "Left"; -static constexpr std::string_view CUBE_RIGHT_NAME = "Right"; +static constexpr std::string_view CUBE_TOP_NAME = "top"; +static constexpr std::string_view CUBE_BOTTOM_NAME = "bottom"; +static constexpr std::string_view CUBE_FRONT_NAME = "front"; +static constexpr std::string_view CUBE_REAR_NAME = "rear"; +static constexpr std::string_view CUBE_LEFT_NAME = "left"; +static constexpr std::string_view CUBE_RIGHT_NAME = "right"; } // namespace render diff --git a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp index 5c8ce3ee84f..1086f449745 100644 --- a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp @@ -262,21 +262,27 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_EXPECTS(parentID != resg.null_vertex()); CC_EXPECTS(resg.isTexture(parentID)); CC_ENSURES(!resg.isTextureView(parentID)); - mount(device, parentID); // NOLINT(misc-no-recursion) + mount(device, parentID); }, [&](SubresourceView& view) { // NOLINT(misc-no-recursion) + SubresourceView originView = view; auto parentID = parent(vertID, resg); CC_EXPECTS(parentID != resg.null_vertex()); while (resg.isTextureView(parentID)) { + const auto& prtView = get(SubresourceViewTag{}, parentID, resg); + originView.firstPlane += prtView.firstPlane; + originView.firstArraySlice += prtView.firstArraySlice; + originView.indexOrFirstMipLevel += prtView.indexOrFirstMipLevel; parentID = parent(parentID, resg); } CC_EXPECTS(parentID != resg.null_vertex()); CC_EXPECTS(resg.isTexture(parentID)); CC_ENSURES(!resg.isTextureView(parentID)); + mount(device, parentID); // NOLINT(misc-no-recursion) auto* parentTexture = resg.getTexture(parentID); const auto& desc = get(ResourceGraph::DescTag{}, resg, vertID); if (!view.textureView) { - auto textureViewInfo = getTextureViewInfo(view, desc); + auto textureViewInfo = getTextureViewInfo(originView, desc); textureViewInfo.texture = parentTexture; view.textureView = device->createTexture(textureViewInfo); } diff --git a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp index 6f4e2ca6fd9..bb313d6cfca 100644 --- a/native/cocos/renderer/pipeline/custom/NativeSetter.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeSetter.cpp @@ -148,6 +148,21 @@ void NativeSetter::setBuiltinShadowMapConstants( setShadowUBOView(*device, *layoutGraph, sceneData, *light, data); } +void NativeSetter::setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) { +} + +void NativeSetter::setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) { +} + +void NativeSetter::setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) { +} + +void NativeSetter::setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) { +} + +void NativeSetter::setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) { +} + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp index 9bb23563b0b..c7fed6ceedb 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp +++ b/native/cocos/renderer/pipeline/custom/RenderCommonJsb.cpp @@ -44,6 +44,9 @@ bool nativevalue_to_se(const cc::render::LightInfo &from, se::Value &to, se::Obj nativevalue_to_se(from.level, tmp, ctx); obj->setProperty("level", tmp); + nativevalue_to_se(from.culledByLight, tmp, ctx); + obj->setProperty("culledByLight", tmp); + to.setObject(obj); return true; } @@ -242,6 +245,10 @@ bool sevalue_to_native(const se::Value &from, cc::render: if(!field.isNullOrUndefined()) { ok &= sevalue_to_native(field, &(to->level), ctx); } + obj->getProperty("culledByLight", &field, true); + if(!field.isNullOrUndefined()) { + ok &= sevalue_to_native(field, &(to->culledByLight), ctx); + } return ok; } diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h b/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h index 49fa456c4cd..4c9467badf2 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonSerialization.h @@ -40,11 +40,13 @@ namespace render { inline void save(OutputArchive& ar, const LightInfo& v) { // skip, light: IntrusivePtr save(ar, v.level); + save(ar, v.culledByLight); } inline void load(InputArchive& ar, LightInfo& v) { // skip, light: IntrusivePtr load(ar, v.level); + load(ar, v.culledByLight); } inline void save(OutputArchive& ar, const Descriptor& v) { diff --git a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h index eb6dfe6a9b3..cad5d71c02c 100644 --- a/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderCommonTypes.h @@ -211,12 +211,17 @@ enum class ClearValueType { struct LightInfo { LightInfo() = default; + LightInfo(IntrusivePtr lightIn, uint32_t levelIn, bool culledByLightIn) noexcept + : light(std::move(lightIn)), + level(levelIn), + culledByLight(culledByLightIn) {} LightInfo(IntrusivePtr lightIn, uint32_t levelIn) noexcept : light(std::move(lightIn)), level(levelIn) {} IntrusivePtr light; uint32_t level{0}; + bool culledByLight{false}; }; enum class DescriptorTypeOrder { diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 4c5e015b567..77845fd5c64 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -57,7 +57,10 @@ class GeometryRenderer; namespace scene { class DirectionalLight; +class SphereLight; class SpotLight; +class PointLight; +class RangedDirectionalLight; class Model; class RenderScene; class RenderWindow; @@ -452,6 +455,11 @@ class Setter : public RenderNode { virtual void setSampler(const ccstd::string &name, gfx::Sampler *sampler) = 0; virtual void setBuiltinCameraConstants(const scene::Camera *camera) = 0; virtual void setBuiltinShadowMapConstants(const scene::DirectionalLight *light) = 0; + virtual void setBuiltinDirectionalLightConstants(const scene::DirectionalLight *light, const scene::Camera *camera) = 0; + virtual void setBuiltinSphereLightConstants(const scene::SphereLight *light, const scene::Camera *camera) = 0; + virtual void setBuiltinSpotLightConstants(const scene::SpotLight *light, const scene::Camera *camera) = 0; + virtual void setBuiltinPointLightConstants(const scene::PointLight *light, const scene::Camera *camera) = 0; + virtual void setBuiltinRangedDirectionalLightConstants(const scene::RangedDirectionalLight *light, const scene::Camera *camera) = 0; virtual void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light, uint32_t level) = 0; virtual void setBuiltinSpotLightViewConstants(const scene::SpotLight *light) = 0; void setBuiltinDirectionalLightViewConstants(const scene::DirectionalLight *light) { @@ -480,7 +488,7 @@ class RenderQueueBuilder : public Setter { * @param sceneFlags @en Rendering flags of the scene @zh 场景渲染标志位 */ virtual void addSceneOfCamera(scene::Camera *camera, LightInfo light, SceneFlags sceneFlags) = 0; - virtual void addScene(const scene::Camera *camera, SceneFlags sceneFlags) = 0; + virtual void addScene(const scene::Camera *camera, SceneFlags sceneFlags, const scene::Light *light) = 0; virtual void addSceneCulledByDirectionalLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::DirectionalLight *light, uint32_t level) = 0; virtual void addSceneCulledBySpotLight(const scene::Camera *camera, SceneFlags sceneFlags, scene::SpotLight *light) = 0; /** @@ -520,6 +528,9 @@ class RenderQueueBuilder : public Setter { void addSceneOfCamera(scene::Camera *camera, LightInfo light) { addSceneOfCamera(camera, std::move(light), SceneFlags::NONE); } + void addScene(const scene::Camera *camera, SceneFlags sceneFlags) { + addScene(camera, sceneFlags, nullptr); + } void addFullscreenQuad(Material *material, uint32_t passID) { addFullscreenQuad(material, passID, SceneFlags::NONE); } From e1caa285bfcb5086fcb47f580aca5db5e98e987c Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Thu, 10 Aug 2023 16:48:34 +0800 Subject: [PATCH 076/184] update migrated resources and meta files (#15919) --- .../default_materials/default-billboard-material.mtl.meta | 2 +- editor/assets/default_materials/default-clear-stencil.mtl.meta | 2 +- .../default_materials/default-material-transparent.mtl.meta | 2 +- editor/assets/default_materials/default-material.mtl.meta | 2 +- .../default_materials/default-particle-gpu-material.mtl.meta | 2 +- .../assets/default_materials/default-particle-material.mtl.meta | 2 +- editor/assets/default_materials/default-spine-material.mtl.meta | 2 +- .../default_materials/default-sprite-renderer-material.mtl.meta | 2 +- editor/assets/default_materials/default-trail-material.mtl.meta | 2 +- .../assets/default_materials/missing-effect-material.mtl.meta | 2 +- editor/assets/default_materials/missing-material.mtl.meta | 2 +- editor/assets/default_materials/particle-add.mtl.meta | 2 +- editor/assets/default_materials/standard-material.mtl.meta | 2 +- editor/assets/default_materials/ui-alpha-test-material.mtl.meta | 2 +- editor/assets/default_materials/ui-base-material.mtl.meta | 2 +- editor/assets/default_materials/ui-graphics-material.mtl.meta | 2 +- .../default_materials/ui-sprite-alpha-sep-material.mtl.meta | 2 +- .../ui-sprite-gray-alpha-sep-material.mtl.meta | 2 +- .../assets/default_materials/ui-sprite-gray-material.mtl.meta | 2 +- editor/assets/default_materials/ui-sprite-material.mtl.meta | 2 +- editor/assets/default_renderpipeline/deferred-lighting.mtl.meta | 2 +- editor/assets/default_renderpipeline/post-process.mtl.meta | 2 +- editor/assets/default_renderpipeline/tonemap.mtl.meta | 2 +- .../default_skybox/default_skybox_reflection_convolution.meta | 2 +- editor/assets/effects/advanced/car-paint.effect.meta | 2 +- editor/assets/effects/advanced/eye.effect.meta | 2 +- editor/assets/effects/advanced/glass.effect.meta | 2 +- editor/assets/effects/advanced/hair.effect.meta | 2 +- editor/assets/effects/advanced/leaf.effect.meta | 2 +- editor/assets/effects/advanced/simple-skin.effect.meta | 2 +- editor/assets/effects/advanced/skin.effect.meta | 2 +- editor/assets/effects/advanced/sky.effect.meta | 2 +- editor/assets/effects/advanced/water.effect.meta | 2 +- .../assets/effects/builtin-reflection-probe-preview.effect.meta | 2 +- editor/assets/effects/builtin-standard.effect.meta | 2 +- editor/assets/effects/builtin-terrain.effect.meta | 2 +- editor/assets/effects/builtin-toon.effect.meta | 2 +- editor/assets/effects/builtin-unlit.effect | 2 +- editor/assets/effects/builtin-unlit.effect.meta | 2 +- editor/assets/effects/for2d/builtin-spine.effect.meta | 2 +- editor/assets/effects/for2d/builtin-sprite-renderer.effect.meta | 2 +- editor/assets/effects/for2d/builtin-sprite.effect.meta | 2 +- .../assets/effects/internal/builtin-camera-texture.effect.meta | 2 +- .../assets/effects/internal/builtin-clear-stencil.effect.meta | 2 +- .../assets/effects/internal/builtin-debug-renderer.effect.meta | 2 +- .../effects/internal/builtin-geometry-renderer.effect.meta | 2 +- editor/assets/effects/internal/builtin-graphics.effect.meta | 2 +- .../assets/effects/internal/builtin-occlusion-query.effect.meta | 2 +- .../effects/internal/builtin-reflection-deferred.effect.meta | 2 +- editor/assets/effects/internal/builtin-wireframe.effect.meta | 2 +- .../assets/effects/internal/editor/box-height-light.effect.meta | 2 +- editor/assets/effects/internal/editor/gizmo.effect.meta | 2 +- editor/assets/effects/internal/editor/grid-2d.effect.meta | 2 +- editor/assets/effects/internal/editor/grid-stroke.effect.meta | 2 +- editor/assets/effects/internal/editor/grid.effect.meta | 2 +- .../internal/editor/light-probe-visualization.effect.meta | 2 +- editor/assets/effects/internal/editor/light.effect.meta | 2 +- .../effects/internal/editor/terrain-circle-brush.effect.meta | 2 +- .../effects/internal/editor/terrain-image-brush.effect.meta | 2 +- .../effects/internal/editor/terrain-select-brush.effect.meta | 2 +- editor/assets/effects/legacy/standard.effect | 2 +- editor/assets/effects/legacy/standard.effect.meta | 2 +- editor/assets/effects/legacy/terrain.effect.meta | 2 +- editor/assets/effects/legacy/toon.effect | 2 +- editor/assets/effects/legacy/toon.effect.meta | 2 +- editor/assets/effects/particles/builtin-billboard.effect.meta | 2 +- .../assets/effects/particles/builtin-particle-gpu.effect.meta | 2 +- .../assets/effects/particles/builtin-particle-trail.effect.meta | 2 +- .../effects/particles/builtin-particle-xr-trail.effect.meta | 2 +- editor/assets/effects/particles/builtin-particle.effect.meta | 2 +- editor/assets/effects/pipeline/cluster-build.effect.meta | 2 +- editor/assets/effects/pipeline/cluster-culling.effect.meta | 2 +- editor/assets/effects/pipeline/copy-pass.effect.meta | 2 +- editor/assets/effects/pipeline/deferred-lighting.effect.meta | 2 +- editor/assets/effects/pipeline/planar-shadow.effect | 2 +- editor/assets/effects/pipeline/planar-shadow.effect.meta | 2 +- editor/assets/effects/pipeline/post-process.effect.meta | 2 +- .../effects/pipeline/post-process/blit-screen.effect.meta | 2 +- editor/assets/effects/pipeline/post-process/bloom.effect.meta | 2 +- .../effects/pipeline/post-process/color-grading.effect.meta | 2 +- editor/assets/effects/pipeline/post-process/fsr.effect.meta | 2 +- editor/assets/effects/pipeline/post-process/fxaa-hq.effect.meta | 2 +- editor/assets/effects/pipeline/post-process/hbao.effect.meta | 2 +- editor/assets/effects/pipeline/post-process/taa.effect.meta | 2 +- editor/assets/effects/pipeline/skybox.effect.meta | 2 +- editor/assets/effects/pipeline/smaa.effect.meta | 2 +- editor/assets/effects/pipeline/ssss-blur.effect.meta | 2 +- editor/assets/effects/pipeline/tone-mapping.effect.meta | 2 +- editor/assets/effects/pipeline/tonemap.effect.meta | 2 +- editor/assets/effects/util/batched-unlit.effect.meta | 2 +- .../effects/util/dcc/imported-metallic-roughness.effect.meta | 2 +- .../effects/util/dcc/imported-specular-glossiness.effect.meta | 2 +- .../effects/util/dcc/vat/houdini-fluid-v3-liquid.effect.meta | 2 +- .../effects/util/dcc/vat/houdini-rigidbody-v2.effect.meta | 2 +- .../assets/effects/util/dcc/vat/houdini-softbody-v3.effect.meta | 2 +- .../assets/effects/util/dcc/vat/zeno-fluid-liquid.effect.meta | 2 +- editor/assets/effects/util/profiler.effect.meta | 2 +- editor/assets/effects/util/sequence-anim.effect.meta | 2 +- editor/assets/effects/util/splash-screen.effect.meta | 2 +- editor/assets/gizmo/scene-gizmo.mtl.meta | 2 +- editor/assets/primitives.fbx.meta | 2 +- 101 files changed, 101 insertions(+), 101 deletions(-) diff --git a/editor/assets/default_materials/default-billboard-material.mtl.meta b/editor/assets/default_materials/default-billboard-material.mtl.meta index 97c632b971a..30541e5428d 100644 --- a/editor/assets/default_materials/default-billboard-material.mtl.meta +++ b/editor/assets/default_materials/default-billboard-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "78e0584a-4343-4727-8f37-e14e65c2a2db", diff --git a/editor/assets/default_materials/default-clear-stencil.mtl.meta b/editor/assets/default_materials/default-clear-stencil.mtl.meta index 59957ce2d90..eda15d5834f 100644 --- a/editor/assets/default_materials/default-clear-stencil.mtl.meta +++ b/editor/assets/default_materials/default-clear-stencil.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "8bbdbcdd-5cd4-4100-b6d5-b7c9625b6107", diff --git a/editor/assets/default_materials/default-material-transparent.mtl.meta b/editor/assets/default_materials/default-material-transparent.mtl.meta index 3004bebb7e1..b89988be04a 100644 --- a/editor/assets/default_materials/default-material-transparent.mtl.meta +++ b/editor/assets/default_materials/default-material-transparent.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "c31a901b-671b-4c3d-9246-f9a6e5f14b90", diff --git a/editor/assets/default_materials/default-material.mtl.meta b/editor/assets/default_materials/default-material.mtl.meta index 83e5e18ca35..54d86f1c5e2 100644 --- a/editor/assets/default_materials/default-material.mtl.meta +++ b/editor/assets/default_materials/default-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "d3c7820c-2a98-4429-8bc7-b8453bc9ac41", diff --git a/editor/assets/default_materials/default-particle-gpu-material.mtl.meta b/editor/assets/default_materials/default-particle-gpu-material.mtl.meta index 3101eed10c6..26f4857ba72 100644 --- a/editor/assets/default_materials/default-particle-gpu-material.mtl.meta +++ b/editor/assets/default_materials/default-particle-gpu-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "14da1725-c4c2-42b4-ab08-ee0aeb6898b3", diff --git a/editor/assets/default_materials/default-particle-material.mtl.meta b/editor/assets/default_materials/default-particle-material.mtl.meta index 27adeff5d1f..52181681191 100644 --- a/editor/assets/default_materials/default-particle-material.mtl.meta +++ b/editor/assets/default_materials/default-particle-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "c0143906-9aed-447e-9436-2ae8512d1b6e", diff --git a/editor/assets/default_materials/default-spine-material.mtl.meta b/editor/assets/default_materials/default-spine-material.mtl.meta index 239ea622378..28f0270a8ba 100644 --- a/editor/assets/default_materials/default-spine-material.mtl.meta +++ b/editor/assets/default_materials/default-spine-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "b5d6115f-0370-4d7c-aad3-c194cc71cf98", diff --git a/editor/assets/default_materials/default-sprite-renderer-material.mtl.meta b/editor/assets/default_materials/default-sprite-renderer-material.mtl.meta index 36d4b1b9d7d..7522338b2a2 100644 --- a/editor/assets/default_materials/default-sprite-renderer-material.mtl.meta +++ b/editor/assets/default_materials/default-sprite-renderer-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "ade8a15a-dcca-4b3c-84c6-f6476ac875bb", diff --git a/editor/assets/default_materials/default-trail-material.mtl.meta b/editor/assets/default_materials/default-trail-material.mtl.meta index ca98959efa5..ee024a443cf 100644 --- a/editor/assets/default_materials/default-trail-material.mtl.meta +++ b/editor/assets/default_materials/default-trail-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "081cab31-dccd-428e-8652-f2404cc81c47", diff --git a/editor/assets/default_materials/missing-effect-material.mtl.meta b/editor/assets/default_materials/missing-effect-material.mtl.meta index 0d6c0175c70..357c63d4b56 100644 --- a/editor/assets/default_materials/missing-effect-material.mtl.meta +++ b/editor/assets/default_materials/missing-effect-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "bcd64cc6-2dd9-43f6-abbe-66318d332032", diff --git a/editor/assets/default_materials/missing-material.mtl.meta b/editor/assets/default_materials/missing-material.mtl.meta index c0eca933e1d..21c3cc19eb5 100644 --- a/editor/assets/default_materials/missing-material.mtl.meta +++ b/editor/assets/default_materials/missing-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "d930590d-bb92-4cc8-8bd1-23cd027f9edf", diff --git a/editor/assets/default_materials/particle-add.mtl.meta b/editor/assets/default_materials/particle-add.mtl.meta index f39079d5941..8fc08632bc6 100644 --- a/editor/assets/default_materials/particle-add.mtl.meta +++ b/editor/assets/default_materials/particle-add.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "ea7478b0-408d-4052-b703-f0d2355e095f", diff --git a/editor/assets/default_materials/standard-material.mtl.meta b/editor/assets/default_materials/standard-material.mtl.meta index efa764a77fb..d06873e5eff 100644 --- a/editor/assets/default_materials/standard-material.mtl.meta +++ b/editor/assets/default_materials/standard-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "620b6bf3-0369-4560-837f-2a2c00b73c26", diff --git a/editor/assets/default_materials/ui-alpha-test-material.mtl.meta b/editor/assets/default_materials/ui-alpha-test-material.mtl.meta index 9668081cb8c..b812dc8e877 100644 --- a/editor/assets/default_materials/ui-alpha-test-material.mtl.meta +++ b/editor/assets/default_materials/ui-alpha-test-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "50f4348b-c883-4e2f-8f11-ce233b859fa1", diff --git a/editor/assets/default_materials/ui-base-material.mtl.meta b/editor/assets/default_materials/ui-base-material.mtl.meta index 3868077a162..99ec1144165 100644 --- a/editor/assets/default_materials/ui-base-material.mtl.meta +++ b/editor/assets/default_materials/ui-base-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "e9aa9a3e-5b2b-4ac7-a2c7-073de2b2b24f", diff --git a/editor/assets/default_materials/ui-graphics-material.mtl.meta b/editor/assets/default_materials/ui-graphics-material.mtl.meta index e675d6d4285..2ad1171d01d 100644 --- a/editor/assets/default_materials/ui-graphics-material.mtl.meta +++ b/editor/assets/default_materials/ui-graphics-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "f0416e68-0200-4b77-a926-4f9d16e494da", diff --git a/editor/assets/default_materials/ui-sprite-alpha-sep-material.mtl.meta b/editor/assets/default_materials/ui-sprite-alpha-sep-material.mtl.meta index 3daa36ec41a..80b2d330942 100644 --- a/editor/assets/default_materials/ui-sprite-alpha-sep-material.mtl.meta +++ b/editor/assets/default_materials/ui-sprite-alpha-sep-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "f92806d7-1768-443f-afe8-12bcde84d0f0", diff --git a/editor/assets/default_materials/ui-sprite-gray-alpha-sep-material.mtl.meta b/editor/assets/default_materials/ui-sprite-gray-alpha-sep-material.mtl.meta index bd23e805167..60a7e8ab2d4 100644 --- a/editor/assets/default_materials/ui-sprite-gray-alpha-sep-material.mtl.meta +++ b/editor/assets/default_materials/ui-sprite-gray-alpha-sep-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "dd3a144d-ab7f-41f0-82b8-2e43a090d496", diff --git a/editor/assets/default_materials/ui-sprite-gray-material.mtl.meta b/editor/assets/default_materials/ui-sprite-gray-material.mtl.meta index 27b4f4eaf2b..5d36041efd4 100644 --- a/editor/assets/default_materials/ui-sprite-gray-material.mtl.meta +++ b/editor/assets/default_materials/ui-sprite-gray-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "efe8e2a3-eace-427b-b4f1-cb8a937ec77d", diff --git a/editor/assets/default_materials/ui-sprite-material.mtl.meta b/editor/assets/default_materials/ui-sprite-material.mtl.meta index bbcc1cf1853..2d3d0228aa4 100644 --- a/editor/assets/default_materials/ui-sprite-material.mtl.meta +++ b/editor/assets/default_materials/ui-sprite-material.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "fda095cb-831d-4601-ad94-846013963de8", diff --git a/editor/assets/default_renderpipeline/deferred-lighting.mtl.meta b/editor/assets/default_renderpipeline/deferred-lighting.mtl.meta index c696d8160c3..8dcbb302cd2 100644 --- a/editor/assets/default_renderpipeline/deferred-lighting.mtl.meta +++ b/editor/assets/default_renderpipeline/deferred-lighting.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "016951c5-5a09-4dd0-9bb7-f4958a82d690", diff --git a/editor/assets/default_renderpipeline/post-process.mtl.meta b/editor/assets/default_renderpipeline/post-process.mtl.meta index 9fc995df587..1628fe91995 100644 --- a/editor/assets/default_renderpipeline/post-process.mtl.meta +++ b/editor/assets/default_renderpipeline/post-process.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "85c4d630-c264-4b18-90a4-c52d594e6099", diff --git a/editor/assets/default_renderpipeline/tonemap.mtl.meta b/editor/assets/default_renderpipeline/tonemap.mtl.meta index 544c5e13089..b51062591b9 100644 --- a/editor/assets/default_renderpipeline/tonemap.mtl.meta +++ b/editor/assets/default_renderpipeline/tonemap.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "9d9704d8-08b4-4917-ba47-9d778bc77ac6", diff --git a/editor/assets/default_skybox/default_skybox_reflection_convolution.meta b/editor/assets/default_skybox/default_skybox_reflection_convolution.meta index 2016e16c5c9..830a17f0cea 100644 --- a/editor/assets/default_skybox/default_skybox_reflection_convolution.meta +++ b/editor/assets/default_skybox/default_skybox_reflection_convolution.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.0", + "ver": "1.2.0", "importer": "directory", "imported": true, "uuid": "288581a6-1075-4a1a-adab-f3ed958c9fda", diff --git a/editor/assets/effects/advanced/car-paint.effect.meta b/editor/assets/effects/advanced/car-paint.effect.meta index ab9bcd058f7..261f6eaa239 100644 --- a/editor/assets/effects/advanced/car-paint.effect.meta +++ b/editor/assets/effects/advanced/car-paint.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "304a12db-3955-46e4-b712-e5e26f45258b", diff --git a/editor/assets/effects/advanced/eye.effect.meta b/editor/assets/effects/advanced/eye.effect.meta index 0cd76ea35fb..1275e3af3bb 100644 --- a/editor/assets/effects/advanced/eye.effect.meta +++ b/editor/assets/effects/advanced/eye.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "f0475923-826e-45dc-85cc-b5d9c2b220e9", diff --git a/editor/assets/effects/advanced/glass.effect.meta b/editor/assets/effects/advanced/glass.effect.meta index ff18657e4e4..1e94ce3febe 100644 --- a/editor/assets/effects/advanced/glass.effect.meta +++ b/editor/assets/effects/advanced/glass.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "f288f946-150b-443d-b4b3-0227c5117c93", diff --git a/editor/assets/effects/advanced/hair.effect.meta b/editor/assets/effects/advanced/hair.effect.meta index 38cf30eebe5..1fe7a338d61 100644 --- a/editor/assets/effects/advanced/hair.effect.meta +++ b/editor/assets/effects/advanced/hair.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "fc0ce5f8-063d-42da-b13a-2fad25abb951", diff --git a/editor/assets/effects/advanced/leaf.effect.meta b/editor/assets/effects/advanced/leaf.effect.meta index d068f7e67a9..53ee284b278 100644 --- a/editor/assets/effects/advanced/leaf.effect.meta +++ b/editor/assets/effects/advanced/leaf.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "e396231e-43c6-4547-86f5-0ef92bf154ce", diff --git a/editor/assets/effects/advanced/simple-skin.effect.meta b/editor/assets/effects/advanced/simple-skin.effect.meta index 16cc329e815..081faa26feb 100644 --- a/editor/assets/effects/advanced/simple-skin.effect.meta +++ b/editor/assets/effects/advanced/simple-skin.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "472c676f-9f77-4c8d-b550-17825aa0176b", diff --git a/editor/assets/effects/advanced/skin.effect.meta b/editor/assets/effects/advanced/skin.effect.meta index f222e073b8a..4b803714253 100644 --- a/editor/assets/effects/advanced/skin.effect.meta +++ b/editor/assets/effects/advanced/skin.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "4a31bd46-8da1-4d9a-add5-9ac43967159e", diff --git a/editor/assets/effects/advanced/sky.effect.meta b/editor/assets/effects/advanced/sky.effect.meta index ec88f7c3a6a..ef47fae816b 100644 --- a/editor/assets/effects/advanced/sky.effect.meta +++ b/editor/assets/effects/advanced/sky.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "6308c013-7d49-4160-9516-562dd205b480", diff --git a/editor/assets/effects/advanced/water.effect.meta b/editor/assets/effects/advanced/water.effect.meta index c7b13ba16d4..480554d72cc 100644 --- a/editor/assets/effects/advanced/water.effect.meta +++ b/editor/assets/effects/advanced/water.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "113a72d8-20cd-42cd-ba96-37cc1046971a", diff --git a/editor/assets/effects/builtin-reflection-probe-preview.effect.meta b/editor/assets/effects/builtin-reflection-probe-preview.effect.meta index c540294993a..065dc24e40c 100644 --- a/editor/assets/effects/builtin-reflection-probe-preview.effect.meta +++ b/editor/assets/effects/builtin-reflection-probe-preview.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "fe0128c2-5496-4330-880a-cfee413aabf2", diff --git a/editor/assets/effects/builtin-standard.effect.meta b/editor/assets/effects/builtin-standard.effect.meta index 6a8c6858b2d..5717fdff49e 100644 --- a/editor/assets/effects/builtin-standard.effect.meta +++ b/editor/assets/effects/builtin-standard.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "c8f66d17-351a-48da-a12c-0212d28575c4", diff --git a/editor/assets/effects/builtin-terrain.effect.meta b/editor/assets/effects/builtin-terrain.effect.meta index 2c8b10dbf75..75853fa4b44 100644 --- a/editor/assets/effects/builtin-terrain.effect.meta +++ b/editor/assets/effects/builtin-terrain.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "a0fd9f76-74fe-423c-92d9-298906c189ba", diff --git a/editor/assets/effects/builtin-toon.effect.meta b/editor/assets/effects/builtin-toon.effect.meta index cfb5f3d8347..226200a8666 100644 --- a/editor/assets/effects/builtin-toon.effect.meta +++ b/editor/assets/effects/builtin-toon.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "9b20a514-6cc3-49de-b216-b6b863046249", diff --git a/editor/assets/effects/builtin-unlit.effect b/editor/assets/effects/builtin-unlit.effect index 66dd4e82a30..9e66463f93e 100644 --- a/editor/assets/effects/builtin-unlit.effect +++ b/editor/assets/effects/builtin-unlit.effect @@ -224,7 +224,7 @@ CCProgram planar-shadow-vs %{ CCGetWorldMatrixFull(matWorld, matWorldIT); vec3 worldPos = (matWorld * position).xyz; vec4 shadowPos = CalculatePlanarShadowPos(worldPos, cc_cameraPos.xyz, cc_mainLitDir.xyz, cc_planarNDInfo); - position = cc_matProj * cc_matView * vec4(shadowPos.xyz, 1.0); + position = CalculatePlanarShadowClipPos(shadowPos, cc_cameraPos.xyz, cc_matView, cc_matProj, cc_nearFar); v_dist = shadowPos.w; return position; } diff --git a/editor/assets/effects/builtin-unlit.effect.meta b/editor/assets/effects/builtin-unlit.effect.meta index 2fe2e7bace7..0ca98bd11a9 100644 --- a/editor/assets/effects/builtin-unlit.effect.meta +++ b/editor/assets/effects/builtin-unlit.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "a3cd009f-0ab0-420d-9278-b9fdab939bbc", diff --git a/editor/assets/effects/for2d/builtin-spine.effect.meta b/editor/assets/effects/for2d/builtin-spine.effect.meta index fc9e2eb9b3e..8ad4cf39924 100644 --- a/editor/assets/effects/for2d/builtin-spine.effect.meta +++ b/editor/assets/effects/for2d/builtin-spine.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "c27215d8-6835-4b68-bfbb-bdeac6100c04", diff --git a/editor/assets/effects/for2d/builtin-sprite-renderer.effect.meta b/editor/assets/effects/for2d/builtin-sprite-renderer.effect.meta index b8f6101904c..33d4405da8c 100644 --- a/editor/assets/effects/for2d/builtin-sprite-renderer.effect.meta +++ b/editor/assets/effects/for2d/builtin-sprite-renderer.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "6ef1defe-7997-477a-9b35-c18859ff8066", diff --git a/editor/assets/effects/for2d/builtin-sprite.effect.meta b/editor/assets/effects/for2d/builtin-sprite.effect.meta index 527f83b57bc..fe4f27599eb 100644 --- a/editor/assets/effects/for2d/builtin-sprite.effect.meta +++ b/editor/assets/effects/for2d/builtin-sprite.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "60f7195c-ec2a-45eb-ba94-8955f60e81d0", diff --git a/editor/assets/effects/internal/builtin-camera-texture.effect.meta b/editor/assets/effects/internal/builtin-camera-texture.effect.meta index e09762d7403..da163a0e0cf 100644 --- a/editor/assets/effects/internal/builtin-camera-texture.effect.meta +++ b/editor/assets/effects/internal/builtin-camera-texture.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "bf4078d6-d2d7-4073-83bb-cd6f1802e880", diff --git a/editor/assets/effects/internal/builtin-clear-stencil.effect.meta b/editor/assets/effects/internal/builtin-clear-stencil.effect.meta index f63a690ac8b..1d837e5d023 100644 --- a/editor/assets/effects/internal/builtin-clear-stencil.effect.meta +++ b/editor/assets/effects/internal/builtin-clear-stencil.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "810e96e4-e456-4468-9b59-f4e8f39732c0", diff --git a/editor/assets/effects/internal/builtin-debug-renderer.effect.meta b/editor/assets/effects/internal/builtin-debug-renderer.effect.meta index 700e4b98ec1..326701e50ae 100644 --- a/editor/assets/effects/internal/builtin-debug-renderer.effect.meta +++ b/editor/assets/effects/internal/builtin-debug-renderer.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "ff9be190-20a4-4e48-b68c-76e3c7cff085", diff --git a/editor/assets/effects/internal/builtin-geometry-renderer.effect.meta b/editor/assets/effects/internal/builtin-geometry-renderer.effect.meta index 844ce9422c8..433fc41b8a9 100644 --- a/editor/assets/effects/internal/builtin-geometry-renderer.effect.meta +++ b/editor/assets/effects/internal/builtin-geometry-renderer.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "4bb480dd-8384-4bc9-987f-de67cc53052a", diff --git a/editor/assets/effects/internal/builtin-graphics.effect.meta b/editor/assets/effects/internal/builtin-graphics.effect.meta index 97829cf794d..a3cf5c552e4 100644 --- a/editor/assets/effects/internal/builtin-graphics.effect.meta +++ b/editor/assets/effects/internal/builtin-graphics.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "1c02ae6f-4492-4915-b8f8-7492a3b1e4cd", diff --git a/editor/assets/effects/internal/builtin-occlusion-query.effect.meta b/editor/assets/effects/internal/builtin-occlusion-query.effect.meta index a955dc72385..8c8af2eb664 100644 --- a/editor/assets/effects/internal/builtin-occlusion-query.effect.meta +++ b/editor/assets/effects/internal/builtin-occlusion-query.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "d9937e59-61fe-4ec6-92ab-7ac5a19c89b0", diff --git a/editor/assets/effects/internal/builtin-reflection-deferred.effect.meta b/editor/assets/effects/internal/builtin-reflection-deferred.effect.meta index 7d6e2989c6c..672651d87a5 100644 --- a/editor/assets/effects/internal/builtin-reflection-deferred.effect.meta +++ b/editor/assets/effects/internal/builtin-reflection-deferred.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "99498f84-efe6-43a6-a9a7-e6e93eb845c1", diff --git a/editor/assets/effects/internal/builtin-wireframe.effect.meta b/editor/assets/effects/internal/builtin-wireframe.effect.meta index aed6bcd53ed..eeeb9db3123 100644 --- a/editor/assets/effects/internal/builtin-wireframe.effect.meta +++ b/editor/assets/effects/internal/builtin-wireframe.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "81127eb0-7556-453c-b147-670782dd5e53", diff --git a/editor/assets/effects/internal/editor/box-height-light.effect.meta b/editor/assets/effects/internal/editor/box-height-light.effect.meta index 199ad0f4633..b263688f2f1 100644 --- a/editor/assets/effects/internal/editor/box-height-light.effect.meta +++ b/editor/assets/effects/internal/editor/box-height-light.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "084eba38-5336-4444-8c8c-aebb75d5c627", diff --git a/editor/assets/effects/internal/editor/gizmo.effect.meta b/editor/assets/effects/internal/editor/gizmo.effect.meta index 0278556eb7e..940b8cd97c1 100644 --- a/editor/assets/effects/internal/editor/gizmo.effect.meta +++ b/editor/assets/effects/internal/editor/gizmo.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "9d6c6bde-2fe2-44ee-883b-909608948b04", diff --git a/editor/assets/effects/internal/editor/grid-2d.effect.meta b/editor/assets/effects/internal/editor/grid-2d.effect.meta index bba39239f35..26fbab581cb 100644 --- a/editor/assets/effects/internal/editor/grid-2d.effect.meta +++ b/editor/assets/effects/internal/editor/grid-2d.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "cb2c332a-fa5e-4235-a129-f011634bb7ad", diff --git a/editor/assets/effects/internal/editor/grid-stroke.effect.meta b/editor/assets/effects/internal/editor/grid-stroke.effect.meta index c2d9b0d7380..0987e8da4e0 100644 --- a/editor/assets/effects/internal/editor/grid-stroke.effect.meta +++ b/editor/assets/effects/internal/editor/grid-stroke.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "4736e978-c8fa-449f-9cf6-fe0158ded9d7", diff --git a/editor/assets/effects/internal/editor/grid.effect.meta b/editor/assets/effects/internal/editor/grid.effect.meta index a9cef638460..a6cf0c3ca28 100644 --- a/editor/assets/effects/internal/editor/grid.effect.meta +++ b/editor/assets/effects/internal/editor/grid.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "ba35f02e-a81c-464c-bfc5-c788328da667", diff --git a/editor/assets/effects/internal/editor/light-probe-visualization.effect.meta b/editor/assets/effects/internal/editor/light-probe-visualization.effect.meta index 4fe7da93955..9a64267f86a 100644 --- a/editor/assets/effects/internal/editor/light-probe-visualization.effect.meta +++ b/editor/assets/effects/internal/editor/light-probe-visualization.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "5967a800-25ad-4c00-9872-5c4ba7840d17", diff --git a/editor/assets/effects/internal/editor/light.effect.meta b/editor/assets/effects/internal/editor/light.effect.meta index d3ebdc13e52..f3c52d329da 100644 --- a/editor/assets/effects/internal/editor/light.effect.meta +++ b/editor/assets/effects/internal/editor/light.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "e4e4cb19-8dd2-450d-ad20-1a818263b8d3", diff --git a/editor/assets/effects/internal/editor/terrain-circle-brush.effect.meta b/editor/assets/effects/internal/editor/terrain-circle-brush.effect.meta index c7c10c39060..6c30fa011fb 100644 --- a/editor/assets/effects/internal/editor/terrain-circle-brush.effect.meta +++ b/editor/assets/effects/internal/editor/terrain-circle-brush.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "a3e72674-c38f-4336-a285-1826b1799cd7", diff --git a/editor/assets/effects/internal/editor/terrain-image-brush.effect.meta b/editor/assets/effects/internal/editor/terrain-image-brush.effect.meta index 3eb7cb6e671..08fc24c3bcc 100644 --- a/editor/assets/effects/internal/editor/terrain-image-brush.effect.meta +++ b/editor/assets/effects/internal/editor/terrain-image-brush.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "7a115de7-2d94-4620-8b89-766d7f8cbff9", diff --git a/editor/assets/effects/internal/editor/terrain-select-brush.effect.meta b/editor/assets/effects/internal/editor/terrain-select-brush.effect.meta index 91b9d23d7ce..c3a4cc82895 100644 --- a/editor/assets/effects/internal/editor/terrain-select-brush.effect.meta +++ b/editor/assets/effects/internal/editor/terrain-select-brush.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "9b4d3fa5-89bf-4715-b69a-dbbd1efaf6a5", diff --git a/editor/assets/effects/legacy/standard.effect b/editor/assets/effects/legacy/standard.effect index 27a0f682fad..1fb84c73d7e 100644 --- a/editor/assets/effects/legacy/standard.effect +++ b/editor/assets/effects/legacy/standard.effect @@ -479,7 +479,7 @@ CCProgram planar-shadow-vs %{ CCGetWorldMatrixFull(matWorld, matWorldIT); vec3 worldPos = (matWorld * position).xyz; vec4 shadowPos = CalculatePlanarShadowPos(worldPos, cc_cameraPos.xyz, cc_mainLitDir.xyz, cc_planarNDInfo); - position = cc_matProj * cc_matView * vec4(shadowPos.xyz, 1.0); + position = CalculatePlanarShadowClipPos(shadowPos, cc_cameraPos.xyz, cc_matView, cc_matProj, cc_nearFar); v_dist = shadowPos.w; return position; } diff --git a/editor/assets/effects/legacy/standard.effect.meta b/editor/assets/effects/legacy/standard.effect.meta index e0859a963c1..0ba8e3ebf40 100644 --- a/editor/assets/effects/legacy/standard.effect.meta +++ b/editor/assets/effects/legacy/standard.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "1baf0fc9-befa-459c-8bdd-af1a450a0319", diff --git a/editor/assets/effects/legacy/terrain.effect.meta b/editor/assets/effects/legacy/terrain.effect.meta index 887ba0738d1..d6c8fb4b9d0 100644 --- a/editor/assets/effects/legacy/terrain.effect.meta +++ b/editor/assets/effects/legacy/terrain.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "1d08ef62-a503-4ce2-8b9a-46c90873f7d3", diff --git a/editor/assets/effects/legacy/toon.effect b/editor/assets/effects/legacy/toon.effect index 8b17d1f90bc..bb675a2c08a 100644 --- a/editor/assets/effects/legacy/toon.effect +++ b/editor/assets/effects/legacy/toon.effect @@ -383,7 +383,7 @@ CCProgram planar-shadow-vs %{ CCGetWorldMatrixFull(matWorld, matWorldIT); vec3 worldPos = (matWorld * position).xyz; vec4 shadowPos = CalculatePlanarShadowPos(worldPos, cc_cameraPos.xyz, cc_mainLitDir.xyz, cc_planarNDInfo); - position = cc_matProj * cc_matView * vec4(shadowPos.xyz, 1.0); + position = CalculatePlanarShadowClipPos(shadowPos, cc_cameraPos.xyz, cc_matView, cc_matProj, cc_nearFar); v_dist = shadowPos.w; return position; } diff --git a/editor/assets/effects/legacy/toon.effect.meta b/editor/assets/effects/legacy/toon.effect.meta index d270abbe2f3..9d0f3cc5a99 100644 --- a/editor/assets/effects/legacy/toon.effect.meta +++ b/editor/assets/effects/legacy/toon.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "a7612b54-35e3-4238-a1a9-4a7b54635839", diff --git a/editor/assets/effects/particles/builtin-billboard.effect.meta b/editor/assets/effects/particles/builtin-billboard.effect.meta index b90611a1b7e..b6a07c4cdf1 100644 --- a/editor/assets/effects/particles/builtin-billboard.effect.meta +++ b/editor/assets/effects/particles/builtin-billboard.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "711ebe11-f673-4cd9-9a83-63c60ba54c5b", diff --git a/editor/assets/effects/particles/builtin-particle-gpu.effect.meta b/editor/assets/effects/particles/builtin-particle-gpu.effect.meta index 24d7bd9355f..be38363be70 100644 --- a/editor/assets/effects/particles/builtin-particle-gpu.effect.meta +++ b/editor/assets/effects/particles/builtin-particle-gpu.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "971bdb23-3ff6-43eb-b422-1c30165a3663", diff --git a/editor/assets/effects/particles/builtin-particle-trail.effect.meta b/editor/assets/effects/particles/builtin-particle-trail.effect.meta index 1c14836fe56..a08422c7d43 100644 --- a/editor/assets/effects/particles/builtin-particle-trail.effect.meta +++ b/editor/assets/effects/particles/builtin-particle-trail.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "17debcc3-0a6b-4b8a-b00b-dc58b885581e", diff --git a/editor/assets/effects/particles/builtin-particle-xr-trail.effect.meta b/editor/assets/effects/particles/builtin-particle-xr-trail.effect.meta index 1826d5b599e..560e8501fea 100644 --- a/editor/assets/effects/particles/builtin-particle-xr-trail.effect.meta +++ b/editor/assets/effects/particles/builtin-particle-xr-trail.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "e38f81af-70ec-4f7a-b377-767b0ec76377", diff --git a/editor/assets/effects/particles/builtin-particle.effect.meta b/editor/assets/effects/particles/builtin-particle.effect.meta index 5d9e53d8b11..b6087c80a3e 100644 --- a/editor/assets/effects/particles/builtin-particle.effect.meta +++ b/editor/assets/effects/particles/builtin-particle.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "d1346436-ac96-4271-b863-1f4fdead95b0", diff --git a/editor/assets/effects/pipeline/cluster-build.effect.meta b/editor/assets/effects/pipeline/cluster-build.effect.meta index 9a260f92272..3cc9bff3bad 100644 --- a/editor/assets/effects/pipeline/cluster-build.effect.meta +++ b/editor/assets/effects/pipeline/cluster-build.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "45e7c0c8-2699-4912-b45f-d42bb8384189", diff --git a/editor/assets/effects/pipeline/cluster-culling.effect.meta b/editor/assets/effects/pipeline/cluster-culling.effect.meta index 443cf29b85b..5d8158f41f9 100644 --- a/editor/assets/effects/pipeline/cluster-culling.effect.meta +++ b/editor/assets/effects/pipeline/cluster-culling.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "84ac6f69-3086-455a-86a4-561da8ee710b", diff --git a/editor/assets/effects/pipeline/copy-pass.effect.meta b/editor/assets/effects/pipeline/copy-pass.effect.meta index d7d899473cf..3bbb41e6a83 100644 --- a/editor/assets/effects/pipeline/copy-pass.effect.meta +++ b/editor/assets/effects/pipeline/copy-pass.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "5c601d96-e4c7-4698-991b-7ee674b11079", diff --git a/editor/assets/effects/pipeline/deferred-lighting.effect.meta b/editor/assets/effects/pipeline/deferred-lighting.effect.meta index 4a8108c5bcd..c86dad44813 100644 --- a/editor/assets/effects/pipeline/deferred-lighting.effect.meta +++ b/editor/assets/effects/pipeline/deferred-lighting.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "5d45aa00-e064-4938-b314-4265f0c2258c", diff --git a/editor/assets/effects/pipeline/planar-shadow.effect b/editor/assets/effects/pipeline/planar-shadow.effect index 37dfa15ff43..6d2d2ab39b8 100644 --- a/editor/assets/effects/pipeline/planar-shadow.effect +++ b/editor/assets/effects/pipeline/planar-shadow.effect @@ -42,7 +42,7 @@ CCProgram planar-shadow-vs %{ CCGetWorldMatrixFull(matWorld, matWorldIT); vec3 worldPos = (matWorld * position).xyz; vec4 shadowPos = CalculatePlanarShadowPos(worldPos, cc_cameraPos.xyz, cc_mainLitDir.xyz, cc_planarNDInfo); - position = cc_matProj * cc_matView * vec4(shadowPos.xyz, 1.0); + position = CalculatePlanarShadowClipPos(shadowPos, cc_cameraPos.xyz, cc_matView, cc_matProj, cc_nearFar); v_dist = shadowPos.w; return position; } diff --git a/editor/assets/effects/pipeline/planar-shadow.effect.meta b/editor/assets/effects/pipeline/planar-shadow.effect.meta index 46c48545665..b251f4fa0f5 100644 --- a/editor/assets/effects/pipeline/planar-shadow.effect.meta +++ b/editor/assets/effects/pipeline/planar-shadow.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "9361fd90-ba52-4f84-aa93-6e878fd576ca", diff --git a/editor/assets/effects/pipeline/post-process.effect.meta b/editor/assets/effects/pipeline/post-process.effect.meta index e0a6d9bb789..bc3a945662a 100644 --- a/editor/assets/effects/pipeline/post-process.effect.meta +++ b/editor/assets/effects/pipeline/post-process.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "ec8106fe-05bf-4e94-943c-e0d3b7bb5e45", diff --git a/editor/assets/effects/pipeline/post-process/blit-screen.effect.meta b/editor/assets/effects/pipeline/post-process/blit-screen.effect.meta index b4eff22bd22..27b29250e2a 100644 --- a/editor/assets/effects/pipeline/post-process/blit-screen.effect.meta +++ b/editor/assets/effects/pipeline/post-process/blit-screen.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "15049ccd-4dd7-451e-a8ae-af66735c929e", diff --git a/editor/assets/effects/pipeline/post-process/bloom.effect.meta b/editor/assets/effects/pipeline/post-process/bloom.effect.meta index 0c686db6ff8..458a21e4b56 100644 --- a/editor/assets/effects/pipeline/post-process/bloom.effect.meta +++ b/editor/assets/effects/pipeline/post-process/bloom.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "28d6d6b8-3f66-4a73-9795-17a0852ba2d4", diff --git a/editor/assets/effects/pipeline/post-process/color-grading.effect.meta b/editor/assets/effects/pipeline/post-process/color-grading.effect.meta index 9d139cfe59d..0b4c6ba983d 100644 --- a/editor/assets/effects/pipeline/post-process/color-grading.effect.meta +++ b/editor/assets/effects/pipeline/post-process/color-grading.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "cafd95c9-c558-46f9-9812-1224b65c09ee", diff --git a/editor/assets/effects/pipeline/post-process/fsr.effect.meta b/editor/assets/effects/pipeline/post-process/fsr.effect.meta index 267b7c5e580..df5e6864a0e 100644 --- a/editor/assets/effects/pipeline/post-process/fsr.effect.meta +++ b/editor/assets/effects/pipeline/post-process/fsr.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "4361db28-3f24-44cc-8e51-32ee5fd651ac", diff --git a/editor/assets/effects/pipeline/post-process/fxaa-hq.effect.meta b/editor/assets/effects/pipeline/post-process/fxaa-hq.effect.meta index 7c27ed1bb51..9a77b5d4ee6 100644 --- a/editor/assets/effects/pipeline/post-process/fxaa-hq.effect.meta +++ b/editor/assets/effects/pipeline/post-process/fxaa-hq.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "2df0a40b-26c2-47ce-be0d-4d3cd4164737", diff --git a/editor/assets/effects/pipeline/post-process/hbao.effect.meta b/editor/assets/effects/pipeline/post-process/hbao.effect.meta index ac5960d2983..6fc26e66b8c 100644 --- a/editor/assets/effects/pipeline/post-process/hbao.effect.meta +++ b/editor/assets/effects/pipeline/post-process/hbao.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "dace6a58-1705-48c7-a275-70afc9534e88", diff --git a/editor/assets/effects/pipeline/post-process/taa.effect.meta b/editor/assets/effects/pipeline/post-process/taa.effect.meta index 39dc8c8f33a..d832336b57f 100644 --- a/editor/assets/effects/pipeline/post-process/taa.effect.meta +++ b/editor/assets/effects/pipeline/post-process/taa.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "4c3ce6de-e6d1-47f7-aa36-36b9b58f72d3", diff --git a/editor/assets/effects/pipeline/skybox.effect.meta b/editor/assets/effects/pipeline/skybox.effect.meta index d49387be035..56d743815e5 100644 --- a/editor/assets/effects/pipeline/skybox.effect.meta +++ b/editor/assets/effects/pipeline/skybox.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "511d2633-09a7-4bdd-ac42-f778032124b3", diff --git a/editor/assets/effects/pipeline/smaa.effect.meta b/editor/assets/effects/pipeline/smaa.effect.meta index b5c86ff2f42..435be92966b 100644 --- a/editor/assets/effects/pipeline/smaa.effect.meta +++ b/editor/assets/effects/pipeline/smaa.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "6624c63c-0e3d-4d5f-bd15-a7805b71c521", diff --git a/editor/assets/effects/pipeline/ssss-blur.effect.meta b/editor/assets/effects/pipeline/ssss-blur.effect.meta index a825e8b98f6..6f889822566 100644 --- a/editor/assets/effects/pipeline/ssss-blur.effect.meta +++ b/editor/assets/effects/pipeline/ssss-blur.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "39f74202-ead5-4a45-b966-273d526adbf1", diff --git a/editor/assets/effects/pipeline/tone-mapping.effect.meta b/editor/assets/effects/pipeline/tone-mapping.effect.meta index 4d1ff515a04..d4014bb3990 100644 --- a/editor/assets/effects/pipeline/tone-mapping.effect.meta +++ b/editor/assets/effects/pipeline/tone-mapping.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "8f6ac413-2f1e-4b88-b26f-54556b5dd510", diff --git a/editor/assets/effects/pipeline/tonemap.effect.meta b/editor/assets/effects/pipeline/tonemap.effect.meta index 4412f06b567..b003a872005 100644 --- a/editor/assets/effects/pipeline/tonemap.effect.meta +++ b/editor/assets/effects/pipeline/tonemap.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "31b152ff-f689-4082-a292-3eb5a0b33014", diff --git a/editor/assets/effects/util/batched-unlit.effect.meta b/editor/assets/effects/util/batched-unlit.effect.meta index ad474d50d27..c13466188c7 100644 --- a/editor/assets/effects/util/batched-unlit.effect.meta +++ b/editor/assets/effects/util/batched-unlit.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "f1556893-88b6-4c65-8c16-a5256ef3ad25", diff --git a/editor/assets/effects/util/dcc/imported-metallic-roughness.effect.meta b/editor/assets/effects/util/dcc/imported-metallic-roughness.effect.meta index 6bd413e7466..f23a325ce8f 100644 --- a/editor/assets/effects/util/dcc/imported-metallic-roughness.effect.meta +++ b/editor/assets/effects/util/dcc/imported-metallic-roughness.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "2ec11458-f855-4978-b14d-f3ed5cf697fa", diff --git a/editor/assets/effects/util/dcc/imported-specular-glossiness.effect.meta b/editor/assets/effects/util/dcc/imported-specular-glossiness.effect.meta index cb060f0b106..a9bec6e8556 100644 --- a/editor/assets/effects/util/dcc/imported-specular-glossiness.effect.meta +++ b/editor/assets/effects/util/dcc/imported-specular-glossiness.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "f648964e-8d32-41fc-9ac9-7a1e714dd17b", diff --git a/editor/assets/effects/util/dcc/vat/houdini-fluid-v3-liquid.effect.meta b/editor/assets/effects/util/dcc/vat/houdini-fluid-v3-liquid.effect.meta index 9adc94f3cc3..dee128e9120 100644 --- a/editor/assets/effects/util/dcc/vat/houdini-fluid-v3-liquid.effect.meta +++ b/editor/assets/effects/util/dcc/vat/houdini-fluid-v3-liquid.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "fbc18e4a-ab74-48df-9106-38e7bd10ff25", diff --git a/editor/assets/effects/util/dcc/vat/houdini-rigidbody-v2.effect.meta b/editor/assets/effects/util/dcc/vat/houdini-rigidbody-v2.effect.meta index 1040e10497f..d1ea97c6589 100644 --- a/editor/assets/effects/util/dcc/vat/houdini-rigidbody-v2.effect.meta +++ b/editor/assets/effects/util/dcc/vat/houdini-rigidbody-v2.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "08c6d756-c02f-48a2-9e8a-55ec59a8f83d", diff --git a/editor/assets/effects/util/dcc/vat/houdini-softbody-v3.effect.meta b/editor/assets/effects/util/dcc/vat/houdini-softbody-v3.effect.meta index ad98ce231d4..8645d9592ad 100644 --- a/editor/assets/effects/util/dcc/vat/houdini-softbody-v3.effect.meta +++ b/editor/assets/effects/util/dcc/vat/houdini-softbody-v3.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "c3e70c74-2523-40e6-a4e5-4abfa1849608", diff --git a/editor/assets/effects/util/dcc/vat/zeno-fluid-liquid.effect.meta b/editor/assets/effects/util/dcc/vat/zeno-fluid-liquid.effect.meta index 49113370890..18b94dd71a7 100644 --- a/editor/assets/effects/util/dcc/vat/zeno-fluid-liquid.effect.meta +++ b/editor/assets/effects/util/dcc/vat/zeno-fluid-liquid.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "6ce2c98a-5c87-4066-90aa-7be93bcbb738", diff --git a/editor/assets/effects/util/profiler.effect.meta b/editor/assets/effects/util/profiler.effect.meta index 1133058bc04..aeb1326938d 100644 --- a/editor/assets/effects/util/profiler.effect.meta +++ b/editor/assets/effects/util/profiler.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "871c3b6c-7379-419d-bda3-794b239ab90d", diff --git a/editor/assets/effects/util/sequence-anim.effect.meta b/editor/assets/effects/util/sequence-anim.effect.meta index d679d0649dd..55a1c59f7e4 100644 --- a/editor/assets/effects/util/sequence-anim.effect.meta +++ b/editor/assets/effects/util/sequence-anim.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "27cc5a0b-ec0b-4a67-98cf-b42d4fa971de", diff --git a/editor/assets/effects/util/splash-screen.effect.meta b/editor/assets/effects/util/splash-screen.effect.meta index 673fdd2f0b4..66f9a7021ed 100644 --- a/editor/assets/effects/util/splash-screen.effect.meta +++ b/editor/assets/effects/util/splash-screen.effect.meta @@ -1,5 +1,5 @@ { - "ver": "1.7.0", + "ver": "1.7.1", "importer": "effect", "imported": true, "uuid": "970b0598-bcb0-4714-91fb-2e81440dccd8", diff --git a/editor/assets/gizmo/scene-gizmo.mtl.meta b/editor/assets/gizmo/scene-gizmo.mtl.meta index fc18a472abd..f3b08a2958c 100644 --- a/editor/assets/gizmo/scene-gizmo.mtl.meta +++ b/editor/assets/gizmo/scene-gizmo.mtl.meta @@ -1,5 +1,5 @@ { - "ver": "1.0.20", + "ver": "1.0.21", "importer": "material", "imported": true, "uuid": "6d3bfb1f-604a-4fb3-9fd8-789862cc55e7", diff --git a/editor/assets/primitives.fbx.meta b/editor/assets/primitives.fbx.meta index 5221ff981fc..d749817046b 100644 --- a/editor/assets/primitives.fbx.meta +++ b/editor/assets/primitives.fbx.meta @@ -171,7 +171,7 @@ "displayName": "", "id": "aae0f", "name": "primitives.prefab", - "ver": "1.0.13", + "ver": "1.0.14", "imported": true, "files": [ ".json" From 6b8009561e9d5ab301ab12c68647d12c9986959a Mon Sep 17 00:00:00 2001 From: bofeng-song Date: Thu, 10 Aug 2023 17:06:53 +0800 Subject: [PATCH 077/184] refine: erase unneed audio operation & fix potential bug (#15884) * refine: erase unneeded audio operation & fix some potential bug --- cocos/audio/audio-source.ts | 67 ++++++++++++++++++++------- pal/audio/minigame/player-minigame.ts | 25 ++++++++-- pal/audio/operation-queue.ts | 36 +++++++++++++- 3 files changed, 106 insertions(+), 22 deletions(-) diff --git a/cocos/audio/audio-source.ts b/cocos/audio/audio-source.ts index 07f35a44f39..6627ad45353 100644 --- a/cocos/audio/audio-source.ts +++ b/cocos/audio/audio-source.ts @@ -38,6 +38,18 @@ enum AudioSourceEventType { ENDED = 'ended', } +enum AudioOperationType { + PLAY = 'play', + STOP = 'stop', + PAUSE = 'pause', + SEEK = 'seek' +} + +interface AudioOperationInfo { + op: AudioOperationType; + params: any[] | null; +} + /** * @en * A representation of a single audio source,
@@ -68,10 +80,10 @@ export class AudioSource extends Component { @serializable protected _volume = 1; - private _cachedCurrentTime = 0; + private _cachedCurrentTime = -1; // An operation queue to store the operations before loading the AudioPlayer. - private _operationsBeforeLoading: string[] = []; + private _operationsBeforeLoading: AudioOperationInfo[] = []; private _isLoaded = false; private _lastSetClip: AudioClip | null = null; @@ -113,6 +125,7 @@ export class AudioSource extends Component { return; } if (!clip._nativeAsset) { + // eslint-disable-next-line no-console console.error('Invalid audio clip'); return; } @@ -138,6 +151,7 @@ export class AudioSource extends Component { this._player = player; this._syncStates(); this.node?.emit(_LOADED_EVENT); + // eslint-disable-next-line @typescript-eslint/no-empty-function }).catch((e) => {}); } @@ -178,7 +192,9 @@ export class AudioSource extends Component { @tooltip('i18n:audio.loop') set loop (val) { this._loop = val; - this._player && (this._player.loop = val); + if (this._player) { + this._player.loop = val; + } } get loop (): boolean { return this._loop; @@ -214,6 +230,7 @@ export class AudioSource extends Component { @range([0.0, 1.0]) @tooltip('i18n:audio.volume') set volume (val) { + // eslint-disable-next-line no-console if (Number.isNaN(val)) { console.warn('illegal audio volume!'); return; } val = clamp(val, 0, 1); if (this._player) { @@ -275,6 +292,7 @@ export class AudioSource extends Component { public getPCMData (channelIndex: number): Promise { return new Promise((resolve) => { if (channelIndex !== 0 && channelIndex !== 1) { + // eslint-disable-next-line no-console console.warn('Only support channel index 0 or 1 to get buffer'); resolve(undefined); return; @@ -345,13 +363,14 @@ export class AudioSource extends Component { */ public play (): void { if (!this._isLoaded && this.clip) { - this._operationsBeforeLoading.push('play'); + this._operationsBeforeLoading.push({ op: AudioOperationType.PLAY, params: null }); return; } this._registerListener(); audioManager.discardOnePlayingIfNeeded(); // Replay if the audio is playing if (this.state === AudioState.PLAYING) { + // eslint-disable-next-line @typescript-eslint/no-empty-function this._player?.stop().catch((e) => {}); } const player = this._player; @@ -373,9 +392,10 @@ export class AudioSource extends Component { */ public pause (): void { if (!this._isLoaded && this.clip) { - this._operationsBeforeLoading.push('pause'); + this._operationsBeforeLoading.push({ op: AudioOperationType.PAUSE, params: null }); return; } + // eslint-disable-next-line @typescript-eslint/no-empty-function this._player?.pause().catch((e) => {}); } @@ -387,10 +407,11 @@ export class AudioSource extends Component { */ public stop (): void { if (!this._isLoaded && this.clip) { - this._operationsBeforeLoading.push('stop'); + this._operationsBeforeLoading.push({ op: AudioOperationType.STOP, params: null }); return; } if (this._player) { + // eslint-disable-next-line @typescript-eslint/no-empty-function this._player.stop().catch((e) => {}); audioManager.removePlaying(this._player); } @@ -406,6 +427,7 @@ export class AudioSource extends Component { */ public playOneShot (clip: AudioClip, volumeScale = 1): void { if (!clip._nativeAsset) { + // eslint-disable-next-line no-console console.error('Invalid audio clip'); return; } @@ -428,15 +450,22 @@ export class AudioSource extends Component { } protected _syncStates (): void { - if (!this._player) { return; } - this._player.seek(this._cachedCurrentTime).then((): void => { - if (this._player) { - this._player.loop = this._loop; - this._player.volume = this._volume; - this._operationsBeforeLoading.forEach((opName): void => { this[opName]?.(); }); - this._operationsBeforeLoading.length = 0; - } - }).catch((e): void => {}); + if (this._player) { + this._player.loop = this._loop; + this._player.volume = this._volume; + this._operationsBeforeLoading.forEach((opInfo): void => { + if (opInfo.op === AudioOperationType.SEEK) { + this._cachedCurrentTime = (opInfo.params && opInfo.params[0]) as number; + if (this._player) { + // eslint-disable-next-line @typescript-eslint/no-empty-function + this._player.seek(this._cachedCurrentTime).catch((e): void => {}); + } + } else { + this[opInfo.op]?.(); + } + }); + this._operationsBeforeLoading.length = 0; + } } /** @@ -447,9 +476,15 @@ export class AudioSource extends Component { * @param num playback time to jump to. */ set currentTime (num: number) { + // eslint-disable-next-line no-console if (Number.isNaN(num)) { console.warn('illegal audio time!'); return; } num = clamp(num, 0, this.duration); + if (!this._isLoaded && this.clip) { + this._operationsBeforeLoading.push({ op: AudioOperationType.SEEK, params: [num] }); + return; + } this._cachedCurrentTime = num; + // eslint-disable-next-line @typescript-eslint/no-empty-function this._player?.seek(this._cachedCurrentTime).catch((e): void => {}); } @@ -460,7 +495,7 @@ export class AudioSource extends Component { * 以秒为单位获取当前播放时间。 */ get currentTime (): number { - return this._player ? this._player.currentTime : this._cachedCurrentTime; + return this._player ? this._player.currentTime : (this._cachedCurrentTime < 0 ? 0 : this._cachedCurrentTime); } /** diff --git a/pal/audio/minigame/player-minigame.ts b/pal/audio/minigame/player-minigame.ts index e363567f403..d2f81712c3f 100644 --- a/pal/audio/minigame/player-minigame.ts +++ b/pal/audio/minigame/player-minigame.ts @@ -129,6 +129,7 @@ export class AudioPlayerMinigame implements OperationQueueable { this._state = AudioState.PLAYING; eventTarget.emit(AudioEvent.PLAYED); if (this._needSeek) { + // eslint-disable-next-line @typescript-eslint/no-empty-function this.seek(this._cacheTime).catch((e) => {}); } }; @@ -168,6 +169,7 @@ export class AudioPlayerMinigame implements OperationQueueable { if (this._needSeek) { this._needSeek = false; if (this._cacheTime.toFixed(3) !== this._innerAudioContext.currentTime.toFixed(3)) { + // eslint-disable-next-line @typescript-eslint/no-empty-function this.seek(this._cacheTime).catch((e) => {}); } else { this._needSeek = false; @@ -189,7 +191,7 @@ export class AudioPlayerMinigame implements OperationQueueable { ['Play', 'Pause', 'Stop', 'Seeked', 'Ended'].forEach((event) => { this._offEvent(event); }); - // NOTE: innewAudioContext might not stop the audio playing, have to call it explicitly. + // NOTE: innerAudioContext might not stop the audio playing, have to call it explicitly. this._innerAudioContext.stop(); this._innerAudioContext.destroy(); // NOTE: Type 'null' is not assignable to type 'InnerAudioContext' @@ -202,6 +204,7 @@ export class AudioPlayerMinigame implements OperationQueueable { this._state = AudioState.INTERRUPTED; this._readyToHandleOnShow = true; this._eventTarget.emit(AudioEvent.INTERRUPTION_BEGIN); + // eslint-disable-next-line @typescript-eslint/no-empty-function }).catch((e) => {}); } } @@ -214,6 +217,7 @@ export class AudioPlayerMinigame implements OperationQueueable { if (this._state === AudioState.INTERRUPTED) { this.play().then(() => { this._eventTarget.emit(AudioEvent.INTERRUPTION_END); + // eslint-disable-next-line @typescript-eslint/no-empty-function }).catch((e) => {}); } this._readyToHandleOnShow = false; @@ -235,6 +239,7 @@ export class AudioPlayerMinigame implements OperationQueueable { return new Promise((resolve) => { AudioPlayerMinigame.loadNative(url).then((innerAudioContext) => { resolve(new AudioPlayerMinigame(innerAudioContext as InnerAudioContext)); + // eslint-disable-next-line @typescript-eslint/no-empty-function }).catch((e) => {}); }); } @@ -259,6 +264,7 @@ export class AudioPlayerMinigame implements OperationQueueable { clearTimeout(timer); // eslint-disable-next-line no-console console.error('failed to load innerAudioContext'); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument reject(new Error(err)); } innerAudioContext.onCanplay(success); @@ -270,6 +276,7 @@ export class AudioPlayerMinigame implements OperationQueueable { return new Promise((resolve, reject) => { AudioPlayerMinigame.loadNative(url).then((innerAudioContext) => { // HACK: AudioPlayer should be a friend class in OneShotAudio + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument resolve(new (OneShotAudioMinigame as any)(innerAudioContext, volume)); }).catch(reject); }); @@ -318,12 +325,15 @@ export class AudioPlayerMinigame implements OperationQueueable { if (this._state === AudioState.PLAYING && !this._seeking) { time = clamp(time, 0, this.duration); this._seeking = true; + this._eventTarget.once(AudioEvent.SEEKED, resolve); this._innerAudioContext.seek(time); - } else if (this._cacheTime !== time) { // Skip the invalid seek - this._cacheTime = time; - this._needSeek = true; + } else { + if (this._cacheTime !== time) { // Skip the invalid seek + this._cacheTime = time; + this._needSeek = true; + } + resolve(); } - resolve(); }); } @@ -350,6 +360,11 @@ export class AudioPlayerMinigame implements OperationQueueable { @enqueueOperation stop (): Promise { return new Promise((resolve) => { + if (AudioState.INIT === this._state) { + this._resetSeekCache(); + resolve(); + return; + } this._eventTarget.once(AudioEvent.STOPPED, resolve); this._innerAudioContext.stop(); }); diff --git a/pal/audio/operation-queue.ts b/pal/audio/operation-queue.ts index 158b6ea694d..761affd21d4 100644 --- a/pal/audio/operation-queue.ts +++ b/pal/audio/operation-queue.ts @@ -26,6 +26,7 @@ import { EventTarget } from '../../cocos/core'; type OperationMethod = (...args: any[]) => Promise; export interface OperationInfo { + op: string; id: number; func: OperationMethod; args: any[], @@ -37,18 +38,48 @@ export interface OperationQueueable { _eventTarget: EventTarget; } +function removeUnneededCalls (instance: OperationQueueable): void { + const size = instance._operationQueue.length; + const tmpQueue = instance._operationQueue.slice(); + const reserveOps: OperationInfo[] = []; + let seekSearched = false; + for (let i = size - 1; i >= 0; i--) { + const opInfo = tmpQueue[i]; + if (opInfo.op === 'stop') { + reserveOps.push(opInfo); + break; + } else if (opInfo.op === 'seek') { + if (!seekSearched) { + reserveOps.push(opInfo); + seekSearched = true; + } + } else if (seekSearched) { + reserveOps.push(opInfo); + break; + } else if (reserveOps.length === 0) { + reserveOps.push(opInfo); + } + } + instance._operationQueue = reserveOps.reverse(); +} + let operationId = 0; function _tryCallingRecursively (target: T, opInfo: OperationInfo): void { if (opInfo.invoking) { return; } opInfo.invoking = true; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument opInfo.func.call(target, ...opInfo.args).then(() => { opInfo.invoking = false; target._operationQueue.shift(); target._eventTarget.emit(opInfo.id.toString()); + removeUnneededCalls(target); const nextOpInfo: OperationInfo = target._operationQueue[0]; - nextOpInfo && _tryCallingRecursively(target, nextOpInfo); + if (nextOpInfo) { + _tryCallingRecursively(target, nextOpInfo); + } + // eslint-disable-next-line @typescript-eslint/no-empty-function }).catch((e) => {}); } @@ -64,14 +95,17 @@ function _tryCallingRecursively (target: T, opInfo * It means that, for example, you can't call stop in the implementation of play operation, * because that would cause the operation deadlock. */ +// eslint-disable-next-line max-len export function enqueueOperation (target: T, propertyKey: string, descriptor: TypedPropertyDescriptor): void { const originalOperation = descriptor.value!; + // eslint-disable-next-line func-names descriptor.value = function (...args: any[]): Promise { return new Promise((resolve) => { const id = operationId++; const instance = this as OperationQueueable; // enqueue operation instance._operationQueue.push({ + op: propertyKey, id, func: originalOperation, args, From eded5a94434d5bdf4b254a0db0be25c1eac55efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:18:08 +0800 Subject: [PATCH 078/184] add updateEnvMap for native (#15889) --- native/cocos/scene/Skybox.cpp | 14 ++++++++++++++ native/cocos/scene/Skybox.h | 1 + 2 files changed, 15 insertions(+) diff --git a/native/cocos/scene/Skybox.cpp b/native/cocos/scene/Skybox.cpp index 590f13f78fc..a8c59676abc 100644 --- a/native/cocos/scene/Skybox.cpp +++ b/native/cocos/scene/Skybox.cpp @@ -215,6 +215,20 @@ void SkyboxInfo::setMaterialProperty(const ccstd::string &name, const MaterialPr } } +void SkyboxInfo::updateEnvMap(TextureCube *val) { + if (!val) { + setApplyDiffuseMap(false); + setUseIBL(false); + setEnvLightingType(EnvironmentLightingType::HEMISPHERE_DIFFUSE); + } + if (_resource) { + _resource->setEnvMaps(_envmapHDR, _envmapLDR); + _resource->setDiffuseMaps(_diffuseMapHDR, _diffuseMapLDR); + _resource->setReflectionMaps(_reflectionHDR, _reflectionLDR); + _resource->setEnvmap(val); + } +} + void SkyboxInfo::activate(Skybox *resource) { _resource = resource; // weak reference Root::getInstance()->getPipeline()->getPipelineSceneData()->setHDR(_useHDR); diff --git a/native/cocos/scene/Skybox.h b/native/cocos/scene/Skybox.h index ad222dab32d..4312ad2df25 100644 --- a/native/cocos/scene/Skybox.h +++ b/native/cocos/scene/Skybox.h @@ -172,6 +172,7 @@ class SkyboxInfo : public RefCounted { inline Material *getSkyboxMaterial() const { return _editableMaterial; } void setMaterialProperty(const ccstd::string &name, const MaterialPropertyVariant &val, index_t passIdx = CC_INVALID_INDEX) const; + void updateEnvMap(TextureCube *val); void activate(Skybox *resource); From 0eec68226879b5314cbcc327d6a1315434352dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:18:21 +0800 Subject: [PATCH 079/184] fix incorrect display of preview plane for reflection probe (#15896) --- .../reflection-probe/ReflectionProbeFlow.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/native/cocos/renderer/pipeline/reflection-probe/ReflectionProbeFlow.cpp b/native/cocos/renderer/pipeline/reflection-probe/ReflectionProbeFlow.cpp index 4aaad4f02d1..3c3578c3e51 100644 --- a/native/cocos/renderer/pipeline/reflection-probe/ReflectionProbeFlow.cpp +++ b/native/cocos/renderer/pipeline/reflection-probe/ReflectionProbeFlow.cpp @@ -63,6 +63,11 @@ void ReflectionProbeFlow::render(scene::Camera *camera) { const auto *sceneData = _pipeline->getPipelineSceneData(); const auto probes = scene::ReflectionProbeManager::getInstance()->getAllProbes(); for (auto *probe : probes) { +#if CC_EDITOR + if (camera->getCameraUsage() != scene::CameraUsage::SCENE_VIEW) { + continue; + } +#endif if (probe->needRender()) { renderStage(camera, probe); } @@ -81,9 +86,13 @@ void ReflectionProbeFlow::renderStage(scene::Camera *camera, scene::ReflectionPr for (uint32_t faceIdx = 0; faceIdx < 6; faceIdx++) { //update camera dirction probe->updateCameraDir(faceIdx); - RenderTexture *rt = probe->getBakedCubeTextures()[faceIdx]; + ccstd::vector> cubeFaces = probe->getBakedCubeTextures(); + if (cubeFaces.empty()) { + probe->setNeedRender(false); + return; + } auto *reflectionProbeStage = static_cast(stage.get()); - reflectionProbeStage->setUsage(rt->getWindow()->getFramebuffer(), probe); + reflectionProbeStage->setUsage(cubeFaces[faceIdx]->getWindow()->getFramebuffer(), probe); reflectionProbeStage->render(camera); } probe->setNeedRender(false); From 78e3b6eece06d6543015a4f0fc297dce55a038c1 Mon Sep 17 00:00:00 2001 From: mmyduckx <308303735@qq.com> Date: Thu, 10 Aug 2023 17:51:34 +0800 Subject: [PATCH 080/184] add preferredScreenEdgesDeferringSystemGestures to prevent accidental touch (#15920) --- templates/ios/ViewController.mm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/templates/ios/ViewController.mm b/templates/ios/ViewController.mm index 1c1e77a4262..eba965cc7cf 100644 --- a/templates/ios/ViewController.mm +++ b/templates/ios/ViewController.mm @@ -50,9 +50,15 @@ - (BOOL)prefersStatusBarHidden { return YES; } -// Controls the application's preferred home indicator auto-hiding when this view controller is shown. +// Controls the application's screen edge gesture delay to prevent accidental touches +- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures +{ + return UIRectEdgeAll; +} + +// Controls the application's preferred home indicator auto-showing otherwise preferredScreenEdgesDeferringSystemGestures is invalidation - (BOOL)prefersHomeIndicatorAutoHidden { - return YES; + return NO; } - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { From fa0a4fefef8e55830a509cbaca0632a322558194 Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Fri, 11 Aug 2023 10:10:04 +0800 Subject: [PATCH 081/184] fix Native Pipeline with render texture. (#15913) * fix shader block memory overwrite issue. * fix Native Pipeline with render texture. --- native/cocos/core/assets/EffectAsset.cpp | 13 ++++++++++--- .../cocos/renderer/gfx-gles3/GLES3Commands.cpp | 16 ++++++++++++++-- native/cocos/scene/Pass.cpp | 13 ++----------- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/native/cocos/core/assets/EffectAsset.cpp b/native/cocos/core/assets/EffectAsset.cpp index da675688ea5..3de9bb7c778 100644 --- a/native/cocos/core/assets/EffectAsset.cpp +++ b/native/cocos/core/assets/EffectAsset.cpp @@ -226,9 +226,16 @@ void EffectAsset::precompile() { continue; } - ccstd::vector defines = EffectAsset::doCombine(ccstd::vector(), combination, combination.begin()); - for (auto &define : defines) { - ProgramLib::getInstance()->getGFXShader(root->getDevice(), shader.name, define, root->getPipeline()); + // Native Program Lib can not precompile shader variant without phaseID. + // Shaders are compiled only during the compilation of PSO. A new mechanism may be needed for pre-compilation. + auto *programLib = render::getProgramLibrary(); + if (programLib == nullptr) { + ccstd::vector defines = EffectAsset::doCombine( + ccstd::vector(), combination, combination.begin()); + for (auto &define: defines) { + ProgramLib::getInstance()->getGFXShader(root->getDevice(), shader.name, define, + root->getPipeline()); + } } } } diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp index 231ed1d3b5e..104ebfe5ce3 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp @@ -1594,7 +1594,12 @@ void cmdFuncGLES3CreateFramebuffer(GLES3Device *device, GLES3GPUFramebuffer *gpu if (lazilyAllocated && // MS attachment should be memoryless resolveView->gpuTexture->swapchain == nullptr && // not back buffer i < supportCount) { // extension limit - gpuFBO->framebuffer.bindColorMultiSample(resolveView, colorIndex, view->gpuTexture->glSamples, resolveDesc); + auto validateDesc = resolveDesc; + // implicit MS take color slot, so color loadOP should be used. + // resolve attachment with Store::Discard is meaningless. + validateDesc.loadOp = desc.loadOp; + validateDesc.storeOp = StoreOp::STORE; + gpuFBO->framebuffer.bindColorMultiSample(resolveView, colorIndex, view->gpuTexture->glSamples, validateDesc); } else { // implicit MS not supported, fallback to MS Renderbuffer gpuFBO->colorBlitPairs.emplace_back(colorIndex, resolveColorIndex); @@ -1620,7 +1625,14 @@ void cmdFuncGLES3CreateFramebuffer(GLES3Device *device, GLES3GPUFramebuffer *gpu resolveView->gpuTexture->swapchain == nullptr && // not back buffer supportCount > 1 && // extension limit useDsResolve) { // enable ds resolve - gpuFBO->framebuffer.bindDepthStencilMultiSample(resolveView, view->gpuTexture->glSamples, resolveDesc); + auto validateDesc = resolveDesc; + // implicit MS take ds slot, so ds MS loadOP should be used. + // resolve attachment with Store::Discard is meaningless. + validateDesc.depthLoadOp = desc.depthLoadOp; + validateDesc.depthStoreOp = StoreOp::STORE; + validateDesc.stencilLoadOp = desc.stencilLoadOp; + validateDesc.stencilStoreOp = StoreOp::STORE; + gpuFBO->framebuffer.bindDepthStencilMultiSample(resolveView, view->gpuTexture->glSamples, validateDesc); } else { // implicit MS not supported, fallback to MS Renderbuffer gpuFBO->dsResolveMask = getColorBufferMask(desc.format); diff --git a/native/cocos/scene/Pass.cpp b/native/cocos/scene/Pass.cpp index 16ad740e353..13518a78464 100644 --- a/native/cocos/scene/Pass.cpp +++ b/native/cocos/scene/Pass.cpp @@ -416,17 +416,8 @@ void Pass::resetUBOs() { ofs += size; } }; - auto *programLib = render::getProgramLibrary(); - if (programLib) { - const auto &set = _shaderInfo->descriptors.at( - static_cast(pipeline::SetIndex::MATERIAL)); - for (const auto &block : set.blocks) { - updateBuffer(block); - } - } else { - for (const auto &u : _shaderInfo->blocks) { - updateBuffer(u); - } + for (const auto &u : _shaderInfo->blocks) { + updateBuffer(u); } _rootBufferDirty = true; } From 6e653079a1778bf5f631f52ae66834b75d8f70da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=A3=AE=E6=96=8C?= Date: Fri, 11 Aug 2023 11:30:17 +0800 Subject: [PATCH 082/184] fix reset property in inspector (#15864) --- editor/inspector/contributions/node.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/editor/inspector/contributions/node.js b/editor/inspector/contributions/node.js index 07504266776..13285f5336a 100644 --- a/editor/inspector/contributions/node.js +++ b/editor/inspector/contributions/node.js @@ -81,7 +81,7 @@ exports.listeners = { snapshotLock(panel, true, panel.uuidList); } - const dump = event.target.dump; + const dump = target.dump; if (!dump || panel.isDialoging) { return; } @@ -181,7 +181,7 @@ exports.listeners = { // Editor.Message.send('scene', 'snapshot'); const undoID = await beginRecording(panel.uuidList); - const dump = event.target.dump; + const dump = target.dump; let cancel = false; try { for (let i = 0; i < panel.uuidList.length; i++) { @@ -214,7 +214,7 @@ exports.listeners = { clearTimeout(panel.previewTimeId); const undoID = await beginRecording(panel.uuidList); - const dump = event.target.dump; + const dump = target.dump; try { for (let i = 0; i < panel.uuidList.length; i++) { const uuid = panel.uuidList[i]; @@ -240,7 +240,7 @@ exports.listeners = { return; } - const dump = event.target.dump; + const dump = target.dump; if (!dump || panel.isDialoging) { return; } From 60b5a7de66943e156968dc29dae3a011addc33f6 Mon Sep 17 00:00:00 2001 From: zxx43 Date: Fri, 11 Aug 2023 14:07:30 +0800 Subject: [PATCH 083/184] 3.8.1 add spine jsb apis (#15674) * open some spine apis * add some apis * add spine jsb convert * add some manual interfaces * fix some jsb * fix getAttachments * remove findAttachmentsForSlot * manual VertexEffect::begin * remove SkinEntry * change some apis * fix isObject * use entry ptr instead of entry * remove array.get() * remove array.get() * fix ci * fix ci * change include * fix SWIGINTERN * fix test-case * use rename * check spine instance null * fix eslint * fix eslint * add some missing apis * add getAttachmentByName * modify jsb api * fix eslint --- cocos/spine/skeleton.ts | 25 +- native/CMakeLists.txt | 5 +- .../bindings/manual/jsb_conversions_spec.cpp | 23 + .../bindings/manual/jsb_conversions_spec.h | 5 + .../bindings/manual/jsb_spine_manual.cpp | 318 +++++++++ .../spine-creator-support/Vector2.cpp | 48 ++ .../spine-creator-support/Vector2.h | 54 ++ native/tools/swig-config/spine.i | 623 +++++++++++++++--- platforms/native/engine/jsb-spine-skeleton.js | 4 +- 9 files changed, 990 insertions(+), 115 deletions(-) create mode 100644 native/cocos/editor-support/spine-creator-support/Vector2.cpp create mode 100644 native/cocos/editor-support/spine-creator-support/Vector2.h diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index 691702d985a..c4e81ab9dab 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -626,6 +626,7 @@ export class Skeleton extends UIRenderer { this._updateDebugDraw(); } + // eslint-disable-next-line @typescript-eslint/no-empty-function public onRestore (): void { } @@ -730,8 +731,10 @@ export class Skeleton extends UIRenderer { if (this.debugBones || this.debugSlots) { warn('Debug bones or slots is invalid in cached mode'); } - const skeletonInfo = this._skeletonCache!.getSkeletonCache(this.skeletonData!.uuid, skeletonData); - this._skeleton = skeletonInfo.skeleton; + if (this.skeletonData) { + const skeletonInfo = this._skeletonCache!.getSkeletonCache(this.skeletonData.uuid, skeletonData); + this._skeleton = skeletonInfo.skeleton; + } } else { this._skeleton = this._instance.initSkeleton(skeletonData); this._state = this._instance.getAnimationState(); @@ -993,15 +996,7 @@ export class Skeleton extends UIRenderer { for (let i = 0; i < this._drawList.length; i++) { const dc = this._drawList.data[i]; if (dc.texture) { - batcher.commitMiddleware( - this, - meshBuffer, - origin + dc.indexOffset, - dc.indexCount, - dc.texture, - dc.material!, - this._enableBatch, - ); + batcher.commitMiddleware(this, meshBuffer, origin + dc.indexOffset, dc.indexCount, dc.texture, dc.material!, this._enableBatch); } indicesCount += dc.indexCount; } @@ -1189,7 +1184,7 @@ export class Skeleton extends UIRenderer { * skeleton.setAnimationCacheMode(sp.Skeleton.AnimationCacheMode.SHARED_CACHE); */ public setAnimationCacheMode (cacheMode: AnimationCacheMode): void { - if (this._preCacheMode !== cacheMode) { + if (this._preCacheMode !== cacheMode) { this._cacheMode = cacheMode; //this.setSkin(this.defaultSkin); this._updateSkeletonData(); @@ -1407,7 +1402,7 @@ export class Skeleton extends UIRenderer { }; for (let i = 0, l = bones.length; i < l; i++) { const bd = bones[i].data; - const boneName = getBoneName(bones[i]); + const boneName: string = getBoneName(bones[i]); this._cachedSockets.set(boneName, bd.index); } } @@ -1473,7 +1468,9 @@ export class Skeleton extends UIRenderer { this._debugRenderer.node.destroy(); this._debugRenderer = null; if (!this.isAnimationCached()) { - if (!JSB) this._instance.setDebugMode(false); + if (this._instance) { + this._instance.setDebugMode(false); + } } } } diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index a1c3dacce9b..a1da31bfede 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -2374,7 +2374,10 @@ if(USE_MIDDLEWARE) NO_WERROR cocos/editor-support/spine-creator-support/spine-cocos2dx.cpp cocos/editor-support/spine-creator-support/spine-cocos2dx.h NO_WERROR cocos/editor-support/spine-creator-support/VertexEffectDelegate.cpp - cocos/editor-support/spine-creator-support/VertexEffectDelegate.h + cocos/editor-support/spine-creator-support/VertexEffectDelegate.h + cocos/editor-support/spine-creator-support/VertexEffectDelegate.h + NO_WERROR cocos/editor-support/spine-creator-support/Vector2.cpp + cocos/editor-support/spine-creator-support/Vector2.h ) cocos_source_files( diff --git a/native/cocos/bindings/manual/jsb_conversions_spec.cpp b/native/cocos/bindings/manual/jsb_conversions_spec.cpp index e0e27adc138..91620cd2c13 100644 --- a/native/cocos/bindings/manual/jsb_conversions_spec.cpp +++ b/native/cocos/bindings/manual/jsb_conversions_spec.cpp @@ -50,6 +50,10 @@ #include "scene/Shadow.h" #include "scene/Skybox.h" +#if CC_USE_SPINE +#include "cocos/editor-support/spine-creator-support/Vector2.h" +#endif + ///////////////////////// utils ///////////////////////// #define CHECK_ASSIGN_PRVOBJ_RET(jsObj, nativeObj) \ @@ -1162,6 +1166,25 @@ bool sevalue_to_native(const se::Value &v, spine::Vector *ret, se return true; } + +bool sevalue_to_native(const se::Value &from, spine::Vector2 *to, se::Object * /*unused*/) { + SE_PRECONDITION2(from.isObject(), false, "Convert parameter to Vec2 failed!"); + + se::Object *obj = from.toObject(); + CHECK_ASSIGN_PRVOBJ_RET(obj, to) + se::Value tmp; + set_member_field(obj, to, "x", &spine::Vector2::x, tmp); + set_member_field(obj, to, "y", &spine::Vector2::y, tmp); + return true; +} + +bool nativevalue_to_se(const spine::Vector2 &from, se::Value &to, se::Object * /*unused*/) { + se::HandleObject obj(se::Object::createPlainObject()); + obj->setProperty("x", se::Value(from.x)); + obj->setProperty("y", se::Value(from.y)); + to.setObject(obj); + return true; +} #endif #if CC_USE_MIDDLEWARE diff --git a/native/cocos/bindings/manual/jsb_conversions_spec.h b/native/cocos/bindings/manual/jsb_conversions_spec.h index d36a7dc5bc7..09ef024954b 100644 --- a/native/cocos/bindings/manual/jsb_conversions_spec.h +++ b/native/cocos/bindings/manual/jsb_conversions_spec.h @@ -133,6 +133,7 @@ template class Vector; template class Map; +class Vector2; } // namespace spine #endif @@ -600,6 +601,10 @@ bool nativevalue_to_se(const spine::String &obj, se::Value &val, se::Object *ctx bool sevalue_to_native(const se::Value &v, spine::Vector *ret, se::Object *ctx); // NOLINT(readability-identifier-naming) +bool sevalue_to_native(const se::Value &from, spine::Vector2 *to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming) + +bool nativevalue_to_se(const spine::Vector2 &from, se::Value &to, se::Object * /*unused*/); // NOLINT(readability-identifier-naming) + #endif inline bool nativevalue_to_se(const se::Object *from, se::Value &to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming) diff --git a/native/cocos/bindings/manual/jsb_spine_manual.cpp b/native/cocos/bindings/manual/jsb_spine_manual.cpp index 5eef2266929..6e550dc889d 100644 --- a/native/cocos/bindings/manual/jsb_spine_manual.cpp +++ b/native/cocos/bindings/manual/jsb_spine_manual.cpp @@ -37,6 +37,7 @@ #include "spine-creator-support/SkeletonDataMgr.h" #include "spine-creator-support/SkeletonRenderer.h" #include "spine-creator-support/spine-cocos2dx.h" +#include "spine-creator-support/Vector2.h" using namespace cc; @@ -213,6 +214,311 @@ static bool js_register_spine_retainSkeletonData(se::State &s) { } SE_BIND_FUNC(js_register_spine_retainSkeletonData) +static bool js_VertexAttachment_computeWorldVertices(se::State &s) { + const auto &args = s.args(); + + spine::VertexAttachment *vertexAttachment = SE_THIS_OBJECT(s); + if (nullptr == vertexAttachment) return true; + + spine::Slot *slot = nullptr; + size_t start = 0, count = 0, offset = 0, stride = 0; + se::Value worldVerticesVal; + + bool ok = false; + ok = sevalue_to_native(args[0], &slot, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing slot"); + + ok = sevalue_to_native(args[1], &start, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing start"); + + ok = sevalue_to_native(args[2], &worldVerticesVal, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing vertices"); + + ok = sevalue_to_native(args[3], &count, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing count"); + + ok = sevalue_to_native(args[4], &offset, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing offset"); + + ok = sevalue_to_native(args[5], &stride, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing stride"); + + if (worldVerticesVal.toObject()->isTypedArray()) { + uint8_t* ptr = nullptr; + size_t len = 0; + worldVerticesVal.toObject()->getTypedArrayData(&ptr, &len); + vertexAttachment->computeWorldVertices(*slot, start, count, reinterpret_cast(ptr), offset, stride); + } else if (worldVerticesVal.toObject()->isArray()) { + spine::Vector worldVertices; + worldVertices.ensureCapacity(count); + vertexAttachment->computeWorldVertices(*slot, start, count, worldVertices, 0); + + int tCount = offset + (count >> 1) * stride; + + for (size_t i = offset, t = 0; i < tCount; i += stride, t += 2) { + worldVerticesVal.toObject()->setArrayElement(i, se::Value(worldVertices[t])); + worldVerticesVal.toObject()->setArrayElement(i + 1, se::Value(worldVertices[t + 1])); + } + } + return true; +} +SE_BIND_FUNC(js_VertexAttachment_computeWorldVertices) + +static bool js_RegionAttachment_computeWorldVertices(se::State &s) { + const auto &args = s.args(); + + spine::RegionAttachment *regionAttachment = SE_THIS_OBJECT(s); + if (nullptr == regionAttachment) return true; + + spine::Bone *bone = nullptr; + size_t offset = 0, stride = 0; + se::Value worldVerticesVal; + + bool ok = false; + ok = sevalue_to_native(args[0], &bone, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + ok = sevalue_to_native(args[1], &worldVerticesVal, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + ok = sevalue_to_native(args[2], &offset, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + ok = sevalue_to_native(args[3], &stride, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + if (worldVerticesVal.toObject()->isTypedArray()) { + uint8_t* ptr = nullptr; + size_t len = 0; + worldVerticesVal.toObject()->getTypedArrayData(&ptr, &len); + regionAttachment->computeWorldVertices(*bone, reinterpret_cast(ptr), offset, stride); + } else if (worldVerticesVal.toObject()->isArray()) { + spine::Vector worldVertices; + int count = 8; + worldVertices.ensureCapacity(count); + regionAttachment->computeWorldVertices(*bone, worldVertices, 0); + + int curr = offset; + worldVerticesVal.toObject()->setArrayElement(curr, se::Value(worldVertices[0])); + worldVerticesVal.toObject()->setArrayElement(curr + 1, se::Value(worldVertices[1])); + + curr += stride; + worldVerticesVal.toObject()->setArrayElement(curr, se::Value(worldVertices[2])); + worldVerticesVal.toObject()->setArrayElement(curr + 1, se::Value(worldVertices[3])); + + curr += stride; + worldVerticesVal.toObject()->setArrayElement(curr, se::Value(worldVertices[4])); + worldVerticesVal.toObject()->setArrayElement(curr + 1, se::Value(worldVertices[5])); + + curr += stride; + worldVerticesVal.toObject()->setArrayElement(curr, se::Value(worldVertices[6])); + worldVerticesVal.toObject()->setArrayElement(curr + 1, se::Value(worldVertices[7])); + } + return true; +} +SE_BIND_FUNC(js_RegionAttachment_computeWorldVertices) + +static bool js_Skeleton_getBounds(se::State &s) { + const auto &args = s.args(); + spine::Skeleton* skeleton = SE_THIS_OBJECT(s); + if (nullptr == skeleton) return true; + + se::Value temp; + + bool ok = false; + ok = sevalue_to_native(args[2], &temp, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + { + float offx = 0.F, offy = 0.F, sizex = 0.F, sizey = 0.F; + spine::Vector outVertexBuffer; + skeleton->getBounds(offx, offy, sizex, sizey, outVertexBuffer); + args[0].toObject()->setProperty("x", se::Value(offx)); + args[0].toObject()->setProperty("y", se::Value(offy)); + args[1].toObject()->setProperty("x", se::Value(sizex)); + args[1].toObject()->setProperty("y", se::Value(sizey)); + if (temp.isObject()) { + for (int i = 0; i < outVertexBuffer.size(); ++i) { + temp.toObject()->setArrayElement(i, se::Value(outVertexBuffer[i])); + } + } + } + return true; +} +SE_BIND_FUNC(js_Skeleton_getBounds) + +static bool js_Bone_worldToLocal(se::State &s) { + const auto &args = s.args(); + spine::Bone* bone = SE_THIS_OBJECT(s); + if (nullptr == bone) return true; + + spine::Vector2 world(0, 0); + + bool ok = false; + ok = sevalue_to_native(args[0], &world, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + float outX = 0.F, outY = 0.F; + bone->worldToLocal(world.x, world.y, outX, outY); + + spine::Vector2 outNative(outX, outY); + se::Value ret; + nativevalue_to_se(outNative, ret, s.thisObject()); + s.rval().setObject(ret.toObject()); + return true; +} +SE_BIND_FUNC(js_Bone_worldToLocal) + +static bool js_Bone_localToWorld(se::State &s) { + const auto &args = s.args(); + spine::Bone* bone = SE_THIS_OBJECT(s); + if (nullptr == bone) return true; + + spine::Vector2 local(0, 0); + + bool ok = false; + ok = sevalue_to_native(args[0], &local, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + float outX = 0.F, outY = 0.F; + bone->localToWorld(local.x, local.y, outX, outY); + + spine::Vector2 outNative(outX, outY); + se::Value ret; + nativevalue_to_se(outNative, ret, s.thisObject()); + s.rval().setObject(ret.toObject()); + return true; +} +SE_BIND_FUNC(js_Bone_localToWorld) + +static bool js_PointAttachment_computeWorldPosition(se::State &s) { + const auto &args = s.args(); + spine::PointAttachment* pointAttachment = SE_THIS_OBJECT(s); + if (nullptr == pointAttachment) return true; + + spine::Bone* bone = nullptr; + + bool ok = false; + ok = sevalue_to_native(args[0], &bone, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + float outX = 0.F, outY = 0.F; + pointAttachment->computeWorldPosition(*bone, outX, outY); + + spine::Vector2 outNative(outX, outY); + se::Value ret; + nativevalue_to_se(outNative, ret, s.thisObject()); + s.rval().setObject(ret.toObject()); + return true; +} +SE_BIND_FUNC(js_PointAttachment_computeWorldPosition) + +static bool js_Skin_findAttachmentsForSlot(se::State &s) { + const auto &args = s.args(); + spine::Skin* skin = SE_THIS_OBJECT(s); + if (nullptr == skin) return true; + + size_t slotIndex = 0; + se::Value attachmentsVal; + + bool ok = false; + ok = sevalue_to_native(args[0], &slotIndex, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + attachmentsVal = args[1]; + ok = attachmentsVal.isObject(); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + spine::Skin::AttachmentMap::Entries entries = skin->getAttachments(); + uint32_t index = 0; + while (entries.hasNext()) { + spine::Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) { + se::Value entryVal; + ok = nativevalue_to_se(&entry, entryVal); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + attachmentsVal.toObject()->setArrayElement(index++, entryVal); + } + } + return true; +} +SE_BIND_FUNC(js_Skin_findAttachmentsForSlot) + +static bool js_VertexEffect_transform(se::State &s) { + const auto &args = s.args(); + spine::VertexEffect* effect = SE_THIS_OBJECT(s); + if (nullptr == effect) return true; + + float outX = 0.F, outY = 0.F; + effect->transform(outX, outY); + + args[0].toObject()->setProperty("x", se::Value(outX)); + args[0].toObject()->setProperty("y", se::Value(outY)); + return true; +} +SE_BIND_FUNC(js_VertexEffect_transform) + +static bool js_SwirlVertexEffect_transform(se::State &s) { + const auto &args = s.args(); + spine::SwirlVertexEffect* effect = SE_THIS_OBJECT(s); + if (nullptr == effect) return true; + + float outX = 0.F, outY = 0.F; + effect->transform(outX, outY); + + args[0].toObject()->setProperty("x", se::Value(outX)); + args[0].toObject()->setProperty("y", se::Value(outY)); + return true; +} +SE_BIND_FUNC(js_SwirlVertexEffect_transform) + +static bool js_JitterVertexEffect_transform(se::State &s) { + const auto &args = s.args(); + spine::JitterVertexEffect* effect = SE_THIS_OBJECT(s); + if (nullptr == effect) return true; + + float outX = 0.F, outY = 0.F; + effect->transform(outX, outY); + + args[0].toObject()->setProperty("x", se::Value(outX)); + args[0].toObject()->setProperty("y", se::Value(outY)); + return true; +} +SE_BIND_FUNC(js_JitterVertexEffect_transform) + +static bool js_spine_Skin_getAttachments(se::State& s) { + CC_UNUSED bool ok = true; + const auto& args = s.args(); + size_t argc = args.size(); + spine::Skin *skin = (spine::Skin *) NULL ; + + if(argc != 0) { + SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 0); + return false; + } + skin = SE_THIS_OBJECT(s); + if (nullptr == skin) return true; + spine::Skin::AttachmentMap::Entries attachments = skin->getAttachments(); + + std::vector entries; + while (attachments.hasNext()) { + spine::Skin::AttachmentMap::Entry &entry = attachments.next(); + se::Value entryVal; + ok = nativevalue_to_se(&entry, entryVal); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + entries.push_back(entryVal); + } + + se::HandleObject array(se::Object::createArrayObject(entries.size())); + for (int i = 0; i < entries.size(); ++i) { + array->setArrayElement(i, entries[i]); + } + s.rval().setObject(array); + + return true; +} +SE_BIND_FUNC(js_spine_Skin_getAttachments) + bool register_all_spine_manual(se::Object *obj) { // Get the ns se::Value nsVal; @@ -228,6 +534,18 @@ bool register_all_spine_manual(se::Object *obj) { ns->defineFunction("retainSkeletonData", _SE(js_register_spine_retainSkeletonData)); ns->defineFunction("disposeSkeletonData", _SE(js_register_spine_disposeSkeletonData)); + __jsb_spine_VertexAttachment_proto->defineFunction("computeWorldVertices", _SE(js_VertexAttachment_computeWorldVertices)); + __jsb_spine_RegionAttachment_proto->defineFunction("computeWorldVertices", _SE(js_RegionAttachment_computeWorldVertices)); + __jsb_spine_Skeleton_proto->defineFunction("getBounds", _SE(js_Skeleton_getBounds)); + __jsb_spine_Skin_proto->defineFunction("getAttachmentsForSlot", _SE(js_Skin_findAttachmentsForSlot)); + __jsb_spine_Bone_proto->defineFunction("worldToLocal", _SE(js_Bone_worldToLocal)); + __jsb_spine_Bone_proto->defineFunction("localToWorld", _SE(js_Bone_localToWorld)); + __jsb_spine_PointAttachment_proto->defineFunction("computeWorldPosition", _SE(js_PointAttachment_computeWorldPosition)); + __jsb_spine_VertexEffect_proto->defineFunction("transform", _SE(js_VertexEffect_transform)); + __jsb_spine_SwirlVertexEffect_proto->defineFunction("transform", _SE(js_SwirlVertexEffect_transform)); + __jsb_spine_JitterVertexEffect_proto->defineFunction("transform", _SE(js_JitterVertexEffect_transform)); + __jsb_spine_Skin_proto->defineFunction("getAttachments", _SE(js_spine_Skin_getAttachments)); + spine::setSpineObjectDisposeCallback([](void *spineObj) { if (!se::NativePtrToObjectMap::isValid()) { return; diff --git a/native/cocos/editor-support/spine-creator-support/Vector2.cpp b/native/cocos/editor-support/spine-creator-support/Vector2.cpp new file mode 100644 index 00000000000..3b18308506c --- /dev/null +++ b/native/cocos/editor-support/spine-creator-support/Vector2.cpp @@ -0,0 +1,48 @@ +#include "Vector2.h" +#include +namespace spine { + +Vector2::Vector2(): x(0), y(0) { + +} + +Vector2::Vector2(float x, float y) { + this->x = x; + this->y = y; +} + +Vector2::~Vector2() {} + +void Vector2::setX(float x) { + this->x = x; +} + +float Vector2::getX() { + return x; +} + +void Vector2::setY(float y) { + this->y = y; +} + +float Vector2::getY() { + return y; +} + +Vector2& Vector2::set(float x, float y) { + this->setX(x); + this->setY(y); + return *this; +} + +float Vector2::length() { + return sqrt(x * x + y * y); +} + +Vector2& Vector2::normalize() { + float invLen = 1.F / length(); + this->setX(x * invLen); + this->setY(y * invLen); + return *this; +} +} \ No newline at end of file diff --git a/native/cocos/editor-support/spine-creator-support/Vector2.h b/native/cocos/editor-support/spine-creator-support/Vector2.h new file mode 100644 index 00000000000..0f62883bc4c --- /dev/null +++ b/native/cocos/editor-support/spine-creator-support/Vector2.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Spine Runtimes License Agreement + * Last updated January 1, 2020. Replaces all prior versions. + * + * Copyright (c) 2013-2020, Esoteric Software LLC + * + * Integration of the Spine Runtimes into software or otherwise creating + * derivative works of the Spine Runtimes is permitted under the terms and + * conditions of Section 2 of the Spine Editor License Agreement: + * http://esotericsoftware.com/spine-editor-license + * + * Otherwise, it is permitted to integrate the Spine Runtimes into software + * or otherwise create derivative works of the Spine Runtimes (collectively, + * "Products"), provided that each user of the Products must obtain their own + * Spine Editor license and redistribution of the Products in any form must + * include this license and copyright notice. + * + * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, + * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#pragma once + +#include "spine/spine.h" + +namespace spine { + class Vector2 + { + public: + float x, y; + public: + Vector2(); + Vector2(float x, float y); + ~Vector2(); + + void setX(float x); + float getX(); + + void setY(float y); + float getY(); + + Vector2 &set(float x, float y); + float length(); + Vector2 &normalize(); + }; +} \ No newline at end of file diff --git a/native/tools/swig-config/spine.i b/native/tools/swig-config/spine.i index 2bde5f2acdd..4d92e47b311 100644 --- a/native/tools/swig-config/spine.i +++ b/native/tools/swig-config/spine.i @@ -13,6 +13,7 @@ #include "bindings/jswrapper/SeApi.h" #include "bindings/manual/jsb_conversions.h" #include "editor-support/spine-creator-support/spine-cocos2dx.h" +#include "editor-support/spine-creator-support/Vector2.h" %} // Insert code at the beginning of generated source file (.cpp) @@ -22,6 +23,8 @@ #include "bindings/auto/jsb_cocos_auto.h" #include "bindings/auto/jsb_spine_auto.h" using namespace spine; + +#define SWIGINTERN static %} // ----- Ignore Section ------ @@ -37,66 +40,17 @@ using namespace spine; // 1. 'Ignore Section' should be placed before attribute definition and %import/%include // 2. namespace is needed // +%ignore spine::MathUtil; %ignore cc::RefCounted; %ignore *::rtti; %ignore spine::SkeletonCache::SegmentData; %ignore spine::SkeletonCache::BoneData; %ignore spine::SkeletonCache::FrameData; %ignore spine::SkeletonCache::AnimationData; -%ignore spine::Skin::AttachmentMap; - -%ignore spine::Animation::Animation; -%ignore spine::TrackEntry::TrackEntry; -%ignore spine::AnimationState::AnimationState; -%ignore spine::AnimationStateData::AnimationStateData; -%ignore spine::Attachment::Attachment; -%ignore spine::AttachmentTimeline::AttachmentTimeline; -%ignore spine::BoundingBoxAttachment::BoundingBoxAttachment; -%ignore spine::Bone::Bone; -%ignore spine::BoneData::BoneData; -%ignore spine::ClippingAttachment::ClippingAttachment; -%ignore spine::Color::Color; -%ignore spine::ColorTimeline::ColorTimeline; -%ignore spine::CurveTimeline::CurveTimeline; -%ignore spine::DeformTimeline::DeformTimeline; -%ignore spine::DrawOrderTimeline::DrawOrderTimeline; -%ignore spine::Event::Event; -%ignore spine::EventData::EventData; -%ignore spine::EventTimeline::EventTimeline; -%ignore spine::IkConstraint::IkConstraint; -%ignore spine::IkConstraintData::IkConstraintData; -%ignore spine::IkConstraintTimeline::IkConstraintTimeline; -%ignore spine::MeshAttachment::MeshAttachment; +%ignore spine::Skin::AttachmentMap::getEntries; + %ignore spine::Polygon::Polygon; %ignore spine::Polygon::_vertices; -%ignore spine::PathAttachment::PathAttachment; -%ignore spine::PathConstraint::PathConstraint; -%ignore spine::PathConstraintData::PathConstraintData; -%ignore spine::PathConstraintMixTimeline::PathConstraintMixTimeline; -%ignore spine::PathConstraintPositionTimeline::PathConstraintPositionTimeline; -%ignore spine::PathConstraintSpacingTimeline::PathConstraintSpacingTimeline; -%ignore spine::PointAttachment::PointAttachment; -%ignore spine::RegionAttachment::RegionAttachment; -%ignore spine::RotateTimeline::RotateTimeline; -%ignore spine::ScaleTimeline::ScaleTimeline; -%ignore spine::ShearTimeline::ShearTimeline; -%ignore spine::Skeleton::Skeleton; -%ignore spine::Slot::Slot; -%ignore spine::Skin::Skin; -%ignore spine::SlotData::SlotData; -%ignore spine::SkeletonBounds::SkeletonBounds; -%ignore spine::SkeletonData::SkeletonData; -%ignore spine::Timeline::Timeline; -%ignore spine::TransformConstraint::TransformConstraint; -%ignore spine::TransformConstraintData::TransformConstraintData; -%ignore spine::TransformConstraintTimeline::TransformConstraintTimeline; -%ignore spine::TranslateTimeline::TranslateTimeline; -%ignore spine::TwoColorTimeline::TwoColorTimeline; -%ignore spine::VertexAttachment::VertexAttachment; -%ignore spine::VertexEffect::VertexEffect; -%ignore spine::JitterVertexEffect::JitterVertexEffect; -%ignore spine::SwirlVertexEffect::SwirlVertexEffect; -%ignore spine::ConstraintData::ConstraintData; %ignore spine::SkeletonRenderer::create; %ignore spine::SkeletonRenderer::initWithJsonFile; @@ -110,83 +64,43 @@ using namespace spine; %ignore spine::SkeletonAnimation::createWithData; %ignore spine::SkeletonAnimation::onTrackEntryEvent; %ignore spine::SkeletonAnimation::onAnimationStateEvent; -%ignore spine::Animation::apply; %ignore spine::TrackEntry::setListener; -%ignore spine::AnimationState::apply; %ignore spine::AnimationState::setListener; %ignore spine::Attachment::getRTTI; -%ignore spine::AttachmentTimeline::apply; %ignore spine::AttachmentTimeline::getRTTI; %ignore spine::BoundingBoxAttachment::getRTTI; -%ignore spine::Bone::worldToLocal; -%ignore spine::Bone::localToWorld; %ignore spine::Bone::getRTTI; +%ignore spine::Bone::worldToLocal(float, float, float&, float&); +%ignore spine::Bone::localToWorld(float, float, float&, float&); %ignore spine::ClippingAttachment::getRTTI; -%ignore spine::Color::set; -%ignore spine::Color::add; -%ignore spine::ColorTimeline::apply; %ignore spine::ColorTimeline::getRTTI; -%ignore spine::CurveTimeline::apply; %ignore spine::CurveTimeline::getRTTI; -%ignore spine::DeformTimeline::apply; -%ignore spine::DeformTimeline::setFrame; %ignore spine::DeformTimeline::getVertices; %ignore spine::DeformTimeline::getRTTI; -%ignore spine::DrawOrderTimeline::apply; -%ignore spine::DrawOrderTimeline::setFrame; -%ignore spine::DrawOrderTimeline::getDrawOrders; %ignore spine::DrawOrderTimeline::getRTTI; -%ignore spine::EventTimeline::apply; %ignore spine::EventTimeline::getRTTI; -%ignore spine::IkConstraint::apply; %ignore spine::IkConstraint::getRTTI; -%ignore spine::IkConstraintTimeline::apply; +%ignore spine::IkConstraint::apply(Bone&, float, float, bool, bool, bool, float); +%ignore spine::IkConstraint::apply(Bone&, Bone&, float, float, int, bool, float, float); %ignore spine::IkConstraintTimeline::getRTTI; %ignore spine::MeshAttachment::getRTTI; %ignore spine::PathAttachment::getRTTI; %ignore spine::PathConstraint::getRTTI; -%ignore spine::PathConstraintMixTimeline::apply; %ignore spine::PathConstraintMixTimeline::getRTTI; -%ignore spine::PathConstraintPositionTimeline::apply; %ignore spine::PathConstraintPositionTimeline::getRTTI; -%ignore spine::PathConstraintSpacingTimeline::apply; %ignore spine::PathConstraintSpacingTimeline::getRTTI; -%ignore spine::PointAttachment::computeWorldPosition; %ignore spine::PointAttachment::getRTTI; -%ignore spine::PointAttachment::computeWorldRotation; -%ignore spine::RegionAttachment::computeWorldVertices; %ignore spine::RegionAttachment::getRTTI; -%ignore spine::RotateTimeline::apply; %ignore spine::RotateTimeline::getRTTI; -%ignore spine::ScaleTimeline::apply; %ignore spine::ScaleTimeline::getRTTI; -%ignore spine::ShearTimeline::apply; %ignore spine::ShearTimeline::getRTTI; -%ignore spine::Skeleton::getBounds; -%ignore spine::Skin::getAttachments; -%ignore spine::Skin::findAttachmentsForSlot; %ignore spine::Skin::findNamesForSlot; -%ignore spine::SkeletonBounds::update; -%ignore spine::SkeletonBounds::aabbIntersectsSkeleton; -%ignore spine::Timeline::apply; +%ignore spine::Skin::getAttachments; %ignore spine::Timeline::getRTTI; %ignore spine::TransformConstraint::getRTTI; -%ignore spine::TransformConstraintTimeline::apply; %ignore spine::TransformConstraintTimeline::getRTTI; -%ignore spine::TranslateTimeline::apply; %ignore spine::TranslateTimeline::getRTTI; -%ignore spine::TwoColorTimeline::apply; %ignore spine::TwoColorTimeline::getRTTI; -%ignore spine::VertexEffect::begin; -%ignore spine::VertexEffect::transform; -%ignore spine::VertexEffect::end; -%ignore spine::JitterVertexEffect::begin; -%ignore spine::JitterVertexEffect::transform; -%ignore spine::JitterVertexEffect::end; -%ignore spine::SwirlVertexEffect::begin; -%ignore spine::SwirlVertexEffect::transform; -%ignore spine::SwirlVertexEffect::end; -%ignore spine::VertexAttachment::computeWorldVertices; %ignore spine::VertexAttachment::getRTTI; %ignore spine::SkeletonDataMgr::destroyInstance; %ignore spine::SkeletonDataMgr::hasSkeletonData; @@ -196,6 +110,32 @@ using namespace spine; %ignore spine::SkeletonCacheAnimation::render; %ignore spine::SkeletonCacheAnimation::requestDrawInfo; %ignore spine::SkeletonCacheAnimation::requestMaterial; +%ignore spine::Timeline::apply(Skeleton&, float, float, Vector*, float, MixBlend, MixDirection); +%ignore spine::AnimationState::apply(Skeleton&); +%ignore spine::Animation::apply(Skeleton&, float, float, bool, Vector*, float, MixBlend, MixDirection); +%ignore spine::VertexAttachment::computeWorldVertices; +%ignore spine::Bone::Bone(BoneData&, Skeleton&, Bone*); +%ignore spine::Bone::Bone(BoneData&, Skeleton&); +%ignore spine::Event::Event(float, const EventData&); +%ignore spine::IkConstraint::IkConstraint(IkConstraintData&, Skeleton&); +%ignore spine::PathConstraint::PathConstraint(PathConstraintData&, Skeleton&); +%ignore spine::PointAttachment::computeWorldPosition; +%ignore spine::PointAttachment::computeWorldRotation(Bone&); +%ignore spine::RegionAttachment::computeWorldVertices; +%ignore spine::Slot::Slot(SlotData&, Bone&); +%ignore spine::VertexEffect::begin(Skeleton &); +%ignore spine::TransformConstraint::TransformConstraint(TransformConstraintData&, Skeleton&); +%ignore spine::SkeletonBounds::update(Skeleton&, bool); +%ignore spine::SlotData::SlotData(int, const String&, BoneData&); +%ignore spine::SwirlVertexEffect::SwirlVertexEffect(float, Interpolation&); +%ignore spine::SwirlVertexEffect::transform(float&, float&); +%ignore spine::JitterVertexEffect::transform(float&, float&); +%ignore spine::VertexEffect::transform(float&, float&); +%ignore spine::DeformTimeline::setFrame(int, float, Vector&); +%ignore spine::DrawOrderTimeline::setFrame(size_t, float, Vector&); +%ignore spine::Skeleton::getBounds; +%ignore spine::Bone::updateWorldTransform(float, float, float, float, float, float, float); +%ignore spine::Skin::findAttachmentsForSlot; // ----- Rename Section ------ // Brief: Classes, methods or attributes needs to be renamed @@ -214,6 +154,56 @@ using namespace spine; %rename(setTrackCompleteListenerNative) spine::SkeletonAnimation::setTrackCompleteListener; %rename(create) spine::SkeletonRenderer::createWithFile; +%rename(frames) spine::TranslateTimeline::_frames; +%rename(boneIndex) spine::TranslateTimeline::_boneIndex; +%rename(frames) spine::TwoColorTimeline::_frames; +%rename(frames) spine::IkConstraintTimeline::_frames; +%rename(ikConstraintIndex) spine::IkConstraintTimeline::_ikConstraintIndex; +%rename(frames) spine::TransformConstraintTimeline::_frames; +%rename(transformConstraintIndex) spine::TransformConstraintTimeline::_transformConstraintIndex; +%rename(frames) spine::PathConstraintPositionTimeline::_frames; +%rename(pathConstraintIndex) spine::PathConstraintPositionTimeline::_pathConstraintIndex; +%rename(frames) spine::PathConstraintMixTimeline::_frames; +%rename(pathConstraintIndex) spine::PathConstraintMixTimeline::_pathConstraintIndex; +%rename(events) spine::AnimationState::_events; +%rename(queue) spine::AnimationState::_queue; +%rename(animationsChanged) spine::AnimationState::_animationsChanged; +%rename(trackEntryPool) spine::AnimationState::_trackEntryPool; +%rename(listener) spine::TrackEntry::_listener; +%rename(nextAnimationLast) spine::TrackEntry::_nextAnimationLast; +%rename(trackLast) spine::TrackEntry::_trackLast; +%rename(nextTrackLast) spine::TrackEntry::_nextTrackLast; +%rename(interruptAlpha) spine::TrackEntry::_interruptAlpha; +%rename(totalAlpha) spine::TrackEntry::_totalAlpha; +%rename(timelineMode) spine::TrackEntry::_timelineMode; +%rename(timelineHoldMix) spine::TrackEntry::_timelineHoldMix; +%rename(timelinesRotation) spine::TrackEntry::_timelinesRotation; +%rename(drainDisabled) spine::EventQueue::_drainDisabled; +%rename(animState) spine::EventQueue::_state; +%rename(setMixWith) spine::AnimationStateData::setMix; +%rename(TextureAtlas) spine::Atlas; +%rename(sorted) spine::Bone::_sorted; +%rename(spaces) spine::PathConstraint::_spaces; +%rename(positions) spine::PathConstraint::_positions; +%rename(world) spine::PathConstraint::_world; +%rename(curves) spine::PathConstraint::_curves; +%rename(lengths) spine::PathConstraint::_lengths; +%rename(segments) spine::PathConstraint::_segments; +%rename(attachmentLoader) spine::SkeletonBinary::_attachmentLoader; +%rename(minX) spine::SkeletonBounds::_minX; +%rename(minY) spine::SkeletonBounds::_minY; +%rename(maxX) spine::SkeletonBounds::_maxX; +%rename(maxY) spine::SkeletonBounds::_maxY; +%rename(boundingBoxes) spine::SkeletonBounds::_boundingBoxes; +%rename(polygons) spine::SkeletonBounds::_polygons; +%rename(attachmentLoader) spine::SkeletonJson::_attachmentLoader; +%rename(JitterEffect) spine::JitterVertexEffect; +%rename(SwirlEffect) spine::SwirlVertexEffect; +%rename(setSkinByName) spine::Skeleton::setSkin(const String &); +%rename(slotIndex) spine::Skin::AttachmentMap::Entry::_slotIndex; +%rename(name) spine::Skin::AttachmentMap::Entry::_name; +%rename(attachment) spine::Skin::AttachmentMap::Entry::_attachment; + // ----- Module Macro Section ------ // Brief: Generated code should be wrapped inside a macro // Usage: @@ -243,6 +233,300 @@ using namespace spine; // 4. 'Attribute Section' should be placed before 'Import Section' and 'Include Section' // +%attribute(spine::Animation, spine::String&, name, getName); +%attribute(spine::Animation, spine::Vector&, timelines, getTimelines); +%attribute(spine::Animation, float, duration, getDuration, setDuration); + +%attribute(spine::RotateTimeline, int, boneIndex, getBoneIndex, setBoneIndex); +%attribute(spine::RotateTimeline, spine::Vector&, frames, getFrames); + +%attribute(spine::ColorTimeline, int, slotIndex, getSlotIndex, setSlotIndex); +%attribute(spine::ColorTimeline, spine::Vector&, frames, getFrames); + +%attribute(spine::TwoColorTimeline, int, slotIndex, getSlotIndex, setSlotIndex); + +%attribute(spine::AttachmentTimeline, size_t, slotIndex, getSlotIndex, setSlotIndex); +%attribute(spine::AttachmentTimeline, spine::Vector&, frames, getFrames); +%attribute(spine::AttachmentTimeline, spine::Vector&, attachmentNames, getAttachmentNames); + +%attribute(spine::DeformTimeline, int, slotIndex, getSlotIndex, setSlotIndex); +%attribute(spine::DeformTimeline, spine::Vector&, frames, getFrames); +%attribute(spine::DeformTimeline, spine::Vector&, frameVertices, getVertices); +%attribute(spine::DeformTimeline, spine::VertexAttachment*, attachment, getAttachment); + +%attribute(spine::EventTimeline, spine::Vector, frames, getFrames); +%attribute(spine::EventTimeline, spine::Vector&, events, getEvents); + +%attribute(spine::DrawOrderTimeline, spine::Vector&, frames, getFrames); +%attribute(spine::DrawOrderTimeline, spine::Vector>&, drawOrders, getDrawOrders); + +%attribute(spine::AnimationState, spine::AnimationStateData*, data, getData); +%attribute(spine::AnimationState, spine::Vector&, tracks, getTracks); +%attribute(spine::AnimationState, float, timeScale, getTimeScale, setTimeScale); + +%attribute(spine::TrackEntry, spine::Animation*, animation, getAnimation); +%attribute(spine::TrackEntry, spine::TrackEntry*, next, getNext); +%attribute(spine::TrackEntry, spine::TrackEntry*, mixingFrom, getMixingFrom); +%attribute(spine::TrackEntry, spine::TrackEntry*, mixingTo, getMixingTo); +%attribute(spine::TrackEntry, int, trackIndex, getTrackIndex); +%attribute(spine::TrackEntry, bool, loop, getLoop, setLoop); +%attribute(spine::TrackEntry, bool, holdPrevious, getHoldPrevious, setHoldPrevious); +%attribute(spine::TrackEntry, float, eventThreshold, getEventThreshold, setEventThreshold); +%attribute(spine::TrackEntry, float, attachmentThreshold, getAttachmentThreshold, setAttachmentThreshold); +%attribute(spine::TrackEntry, float, drawOrderThreshold, getDrawOrderThreshold, setDrawOrderThreshold); +%attribute(spine::TrackEntry, float, animationStart, getAnimationStart, setAnimationStart); +%attribute(spine::TrackEntry, float, animationEnd, getAnimationEnd, setAnimationEnd); +%attribute(spine::TrackEntry, float, animationLast, getAnimationLast, setAnimationLast); +%attribute(spine::TrackEntry, float, delay, getDelay, setDelay); +%attribute(spine::TrackEntry, float, trackTime, getTrackTime, setTrackTime); +%attribute(spine::TrackEntry, float, trackEnd, getTrackEnd, setTrackEnd); +%attribute(spine::TrackEntry, float, timeScale, getTimeScale, setTimeScale); +%attribute(spine::TrackEntry, float, alpha, getAlpha, setAlpha); +%attribute(spine::TrackEntry, float, mixTime, getMixTime, setMixTime); +%attribute(spine::TrackEntry, float, mixDuration, getMixDuration, setMixDuration); +%attribute(spine::TrackEntry, spine::MixBlend, mixBlend, getMixBlend, setMixBlend); + +%attribute(spine::AnimationStateData, spine::SkeletonData*, skeletonData, getSkeletonData); +%attribute(spine::AnimationStateData, float, defaultMix, getDefaultMix, setDefaultMix); + +%attribute(spine::Bone, spine::BoneData&, data, getData); +%attribute(spine::Bone, spine::Skeleton&, skeleton, getSkeleton); +%attribute(spine::Bone, spine::Bone*, parent, getParent); +%attribute(spine::Bone, spine::Vector&, children, getChildren); +%attribute(spine::Bone, float, x, getX, setX); +%attribute(spine::Bone, float, y, getY, setY); +%attribute(spine::Bone, float, rotation, getRotation, setRotation); +%attribute(spine::Bone, float, scaleX, getScaleX, setScaleX); +%attribute(spine::Bone, float, scaleY, getScaleY, setScaleY); +%attribute(spine::Bone, float, shearX, getShearX, setShearX); +%attribute(spine::Bone, float, shearY, getShearY, setShearY); +%attribute(spine::Bone, float, ax, getAX, setAX); +%attribute(spine::Bone, float, ay, getAY, setAY); +%attribute(spine::Bone, float, arotation, getAppliedRotation, setAppliedRotation); +%attribute(spine::Bone, float, ascaleX, getAScaleX, setAScaleX); +%attribute(spine::Bone, float, ascaleY, getAScaleY, setAScaleY); +%attribute(spine::Bone, float, ashearX, getAShearX, setAShearX); +%attribute(spine::Bone, float, ashearY, getAShearY, setAShearY); +%attribute(spine::Bone, bool, appliedValid, isAppliedValid, setAppliedValid); +%attribute(spine::Bone, float, a, getA, setA); +%attribute(spine::Bone, float, b, getB, setB); +%attribute(spine::Bone, float, c, getC, setC); +%attribute(spine::Bone, float, d, getD, setD); +%attribute(spine::Bone, float, worldX, getWorldX, setWorldX); +%attribute(spine::Bone, float, worldY, getWorldY, setWorldY); +%attribute(spine::Bone, bool, active, isActive, setActive); + +%attribute(spine::BoneData, int, index, getIndex); +%attribute(spine::BoneData, spine::String&, name, getName); +%attribute(spine::BoneData, spine::BoneData*, parent, getParent); +%attribute(spine::BoneData, float, length, getLength, setLength); +%attribute(spine::BoneData, float, x, getX, setX); +%attribute(spine::BoneData, float, y, getY, setY); +%attribute(spine::BoneData, float, rotation, getRotation, setRotation); +%attribute(spine::BoneData, float, scaleX, getScaleX, setScaleX); +%attribute(spine::BoneData, float, scaleY, getScaleY, setScaleY); +%attribute(spine::BoneData, float, shearX, getShearX, setShearX); +%attribute(spine::BoneData, float, shearY, getShearY, setShearY); +%attribute(spine::BoneData, spine::TransformMode, transformMode, getTransformMode, setTransformMode); +%attribute(spine::BoneData, bool, skinRequired, isSkinRequired, setSkinRequired); + +%attribute(spine::ConstraintData, spine::String&, name, getName); +%attribute(spine::ConstraintData, size_t, order, getOrder, setOrder); +%attribute(spine::ConstraintData, bool, skinRequired, isSkinRequired, setSkinRequired); + +%attribute(spine::Event, spine::EventData&, data, getData); +%attribute(spine::Event, int, intValue, getIntValue, setIntValue); +%attribute(spine::Event, float, floatValue, getFloatValue, setFloatValue); +%attribute(spine::Event, spine::String&, stringValue, getStringValue, setStringValue); +%attribute(spine::Event, float, time, getTime); +%attribute(spine::Event, float, volume, getVolume, setVolume); +%attribute(spine::Event, float, balance, getBalance, setBalance); + +%attribute(spine::EventData, spine::String&, name, getName); +%attribute(spine::EventData, int, intValue, getIntValue, setIntValue); +%attribute(spine::EventData, float, floatValue, getFloatValue, setFloatValue); +%attribute(spine::EventData, spine::String&, stringValue, getStringValue, setStringValue); +%attribute(spine::EventData, float, volume, getVolume, setVolume); +%attribute(spine::EventData, float, balance, getBalance, setBalance); +%attribute(spine::EventData, spine::String&, audioPath, getAudioPath, setAudioPath); + +%attribute(spine::IkConstraint, spine::IkConstraintData&, data, getData); +%attribute(spine::IkConstraint, spine::Vector&, bones, getBones); +%attribute(spine::IkConstraint, spine::Bone*, target, getTarget, setTarget); +%attribute(spine::IkConstraint, int, bendDirection, getBendDirection, setBendDirection); +%attribute(spine::IkConstraint, bool, compress, getCompress, setCompress); +%attribute(spine::IkConstraint, bool, stretch, getStretch, setStretch); +%attribute(spine::IkConstraint, float, mix, getMix, setMix); +%attribute(spine::IkConstraint, float, softness, getSoftness, setSoftness); +%attribute(spine::IkConstraint, bool, active, isActive, setActive); + +%attribute(spine::IkConstraintData, spine::Vector&, bones, getBones); +%attribute(spine::IkConstraintData, spine::BoneData*, target, getTarget); +%attribute(spine::IkConstraintData, int, bendDirection, getBendDirection, setBendDirection); +%attribute(spine::IkConstraintData, bool, compress, getCompress, setCompress); +%attribute(spine::IkConstraintData, bool, stretch, getStretch, setStretch); +%attribute(spine::IkConstraintData, bool, uniform, getUniform, setUniform); +%attribute(spine::IkConstraintData, float, mix, getMix, setMix); +%attribute(spine::IkConstraintData, float, softness, getSoftness, setSoftness); + +%attribute(spine::PathConstraint, spine::PathConstraintData&, data, getData); +%attribute(spine::PathConstraint, spine::Vector&, bones, getBones); +%attribute(spine::PathConstraint, spine::Slot*, target, getTarget, setTarget); +%attribute(spine::PathConstraint, float, position, getPosition, setPosition); +%attribute(spine::PathConstraint, float, spacing, getSpacing, setSpacing); +%attribute(spine::PathConstraint, float, rotateMix, getRotateMix, setRotateMix); +%attribute(spine::PathConstraint, float, translateMix, getTranslateMix, setTranslateMix); +%attribute(spine::PathConstraint, bool, active, isActive, setActive); + +%attribute(spine::PathConstraintData, spine::Vector&, bones, getBones); +%attribute(spine::PathConstraintData, spine::SlotData*, target, getTarget, setTarget); +%attribute(spine::PathConstraintData, spine::PositionMode, positionMode, getPositionMode, setPositionMode); +%attribute(spine::PathConstraintData, spine::SpacingMode, spacingMode, getSpacingMode, setSpacingMode); +%attribute(spine::PathConstraintData, spine::RotateMode, rotateMode, getRotateMode, setRotateMode); +%attribute(spine::PathConstraintData, float, offsetRotation, getOffsetRotation, setOffsetRotation); +%attribute(spine::PathConstraintData, float, position, getPosition, setPosition); +%attribute(spine::PathConstraintData, float, spacing, getSpacing, setSpacing); +%attribute(spine::PathConstraintData, float, rotateMix, getRotateMix, setRotateMix); +%attribute(spine::PathConstraintData, float, translateMix, getTranslateMix, setTranslateMix); + +%attribute(spine::Skeleton, spine::SkeletonData*, data, getData); +%attribute(spine::Skeleton, spine::Vector&, bones, getBones); +%attribute(spine::Skeleton, spine::Vector&, slots, getSlots); +%attribute(spine::Skeleton, spine::Vector&, drawOrder, getDrawOrder); +%attribute(spine::Skeleton, spine::Vector&, ikConstraints, getIkConstraints); +%attribute(spine::Skeleton, spine::Vector&, transformConstraints, getTransformConstraints); +%attribute(spine::Skeleton, spine::Vector&, pathConstraints, getPathConstraints); +%attribute(spine::Skeleton, spine::Vector&, _updateCache, getUpdateCacheList); +%attribute(spine::Skeleton, spine::Skin*, skin, getSkin, setSkin); +%attribute(spine::Skeleton, spine::Color&, color, getColor); +%attribute(spine::Skeleton, float, time, getTime, setTime); +%attribute(spine::Skeleton, float, scaleX, getScaleX, setScaleX); +%attribute(spine::Skeleton, float, scaleY, getScaleY, setScaleY); +%attribute(spine::Skeleton, float, x, getX, setX); +%attribute(spine::Skeleton, float, y, getY, setY); + +%attribute(spine::SkeletonBinary, float, scale, setScale); + +%attribute(spine::SkeletonClipping, spine::Vector&, clippedVertices, getClippedVertices); +%attribute(spine::SkeletonClipping, spine::Vector&, clippedTriangles, getClippedTriangles); + +%attribute(spine::SkeletonData, spine::String&, name, getName, setName); +%attribute(spine::SkeletonData, spine::Vector&, bones, getBones); +%attribute(spine::SkeletonData, spine::Vector&, slots, getSlots); +%attribute(spine::SkeletonData, spine::Vector&, skins, getSkins); +%attribute(spine::SkeletonData, spine::Skin*, defaultSkin, getDefaultSkin, setDefaultSkin); +%attribute(spine::SkeletonData, spine::Vector&, events, getEvents); +%attribute(spine::SkeletonData, spine::Vector&, animations, getAnimations); +%attribute(spine::SkeletonData, spine::Vector&, ikConstraints, getIkConstraints); +%attribute(spine::SkeletonData, spine::Vector&, transformConstraints, getTransformConstraints); +%attribute(spine::SkeletonData, spine::Vector&, pathConstraints, getPathConstraints); +%attribute(spine::SkeletonData, float, x, getX, setX); +%attribute(spine::SkeletonData, float, y, getY, setY); +%attribute(spine::SkeletonData, float, width, getWidth, setWidth); +%attribute(spine::SkeletonData, float, height, getHeight, setHeight); +%attribute(spine::SkeletonData, spine::String&, version, getVersion, setVersion); +%attribute(spine::SkeletonData, spine::String&, hash, getHash, setHash); +%attribute(spine::SkeletonData, float, fps, getFps, setFps); +%attribute(spine::SkeletonData, spine::String&, imagesPath, getImagesPath, setImagesPath); +%attribute(spine::SkeletonData, spine::String&, audioPath, getAudioPath, setAudioPath); + +%attribute(spine::SkeletonJson, float, scale, setScale); + +%attribute(spine::Skin, spine::String&, name, getName); +%attribute(spine::Skin, spine::Vector&, bones, getBones); +%attribute(spine::Skin, spine::Vector&, constraints, getConstraints); + +%attribute(spine::Slot, spine::SlotData&, data, getData); +%attribute(spine::Slot, spine::Bone&, bone, getBone); +%attribute(spine::Slot, spine::Color&, color, getColor); +%attribute(spine::Slot, spine::Color&, darkColor, getDarkColor); +%attribute(spine::Slot, spine::Attachment*, attachment, getAttachment, setAttachment); +%attribute(spine::Slot, spine::Vector&, deform, getDeform); + +%attribute(spine::SlotData, int, index, getIndex); +%attribute(spine::SlotData, spine::String&, name, getName); +%attribute(spine::SlotData, spine::BoneData&, boneData, getBoneData); +%attribute(spine::SlotData, spine::Color&, color, getColor); +%attribute(spine::SlotData, spine::Color&, darkColor, getDarkColor); +%attribute(spine::SlotData, spine::String&, attachmentName, getAttachmentName, setAttachmentName); +%attribute(spine::SlotData, spine::BlendMode, blendMode, getBlendMode, setBlendMode); + +%attribute(spine::TransformConstraint, spine::TransformConstraintData&, data, getData); +%attribute(spine::TransformConstraint, spine::Vector&, bones, getBones); +%attribute(spine::TransformConstraint, spine::Bone*, target, getTarget, setTarget); +%attribute(spine::TransformConstraint, float, rotateMix, getRotateMix, setRotateMix); +%attribute(spine::TransformConstraint, float, translateMix, getTranslateMix, setTranslateMix); +%attribute(spine::TransformConstraint, float, scaleMix, getScaleMix, setScaleMix); +%attribute(spine::TransformConstraint, float, shearMix, getShearMix, setShearMix); +%attribute(spine::TransformConstraint, bool, active, isActive, setActive); + +%attribute(spine::TransformConstraintData, spine::Vector&, bones, getBones); +%attribute(spine::TransformConstraintData, spine::BoneData*, target, getTarget); +%attribute(spine::TransformConstraintData, float, rotateMix, getRotateMix); +%attribute(spine::TransformConstraintData, float, translateMix, getTranslateMix); +%attribute(spine::TransformConstraintData, float, scaleMix, getScaleMix); +%attribute(spine::TransformConstraintData, float, shearMix, getShearMix); +%attribute(spine::TransformConstraintData, float, offsetRotation, getOffsetRotation); +%attribute(spine::TransformConstraintData, float, offsetX, getOffsetX); +%attribute(spine::TransformConstraintData, float, offsetY, getOffsetY); +%attribute(spine::TransformConstraintData, float, offsetScaleX, getOffsetScaleX); +%attribute(spine::TransformConstraintData, float, offsetScaleY, getOffsetScaleY); +%attribute(spine::TransformConstraintData, float, offsetShearY, getOffsetShearY); +%attribute(spine::TransformConstraintData, bool, relative, isRelative); +%attribute(spine::TransformConstraintData, bool, local, isLocal); + +%attribute(spine::Attachment, spine::String&, name, getName); + +%attribute(spine::VertexAttachment, int, id, getId); +%attribute(spine::VertexAttachment, spine::Vector&, bones, getBones); +%attribute(spine::VertexAttachment, spine::Vector&, vertices, getVertices); +%attribute(spine::VertexAttachment, size_t, worldVerticesLength, getWorldVerticesLength, setWorldVerticesLength); +%attribute(spine::VertexAttachment, spine::VertexAttachment*, deformAttachment, getDeformAttachment, setDeformAttachment); + +%attribute(spine::ClippingAttachment, spine::SlotData*, endSlot, getEndSlot, setEndSlot); + +%attribute(spine::MeshAttachment, spine::String&, path, getPath, setPath); +%attribute(spine::MeshAttachment, spine::Vector&, regionUVs, getRegionUVs); +%attribute(spine::MeshAttachment, spine::Vector&, uvs, getUVs); +%attribute(spine::MeshAttachment, spine::Vector&, triangles, getTriangles); +%attribute(spine::MeshAttachment, spine::Color&, color, getColor); +%attribute(spine::MeshAttachment, float, width, getWidth, setWidth); +%attribute(spine::MeshAttachment, float, height, getHeight, setHeight); +%attribute(spine::MeshAttachment, int, hullLength, getHullLength, setHullLength); +%attribute(spine::MeshAttachment, spine::Vector&, edges, getEdges); + +%attribute(spine::PathAttachment, spine::Vector&, lengths, getLengths); +%attribute(spine::PathAttachment, bool, closed, isClosed, setClosed); +%attribute(spine::PathAttachment, bool, constantSpeed, isConstantSpeed, setConstantSpeed); + +%attribute(spine::PointAttachment, float, x, getX, setX); +%attribute(spine::PointAttachment, float, y, getY, setY); +%attribute(spine::PointAttachment, float, rotation, getRotation, setRotation); + +%attribute(spine::RegionAttachment, float, x, getX, setX); +%attribute(spine::RegionAttachment, float, y, getY, setY); +%attribute(spine::RegionAttachment, float, scaleX, getScaleX, setScaleX); +%attribute(spine::RegionAttachment, float, scaleY, getScaleY, setScaleY); +%attribute(spine::RegionAttachment, float, rotation, getRotation, setRotation); +%attribute(spine::RegionAttachment, float, width, getWidth, setWidth); +%attribute(spine::RegionAttachment, float, height, getHeight, setHeight); +%attribute(spine::RegionAttachment, spine::Color&, color, getColor); +%attribute(spine::RegionAttachment, spine::String&, path, getPath, setPath); +%attribute(spine::RegionAttachment, void*, rendererObject, getRendererObject, setRendererObject); +%attribute(spine::RegionAttachment, spine::Vector&, offset, getOffset); +%attribute(spine::RegionAttachment, spine::Vector&, uvs, getUVs); + +%attribute(spine::JitterVertexEffect, float, jitterX, getJitterX, setJitterX); +%attribute(spine::JitterVertexEffect, float, jitterY, getJitterY, setJitterY); + +%attribute(spine::SwirlVertexEffect, float, centerX, getCenterX, setCenterX); +%attribute(spine::SwirlVertexEffect, float, centerY, getCenterY, setCenterY); +%attribute(spine::SwirlVertexEffect, float, radius, getRadius, setRadius); +%attribute(spine::SwirlVertexEffect, float, angle, getAngle, setAngle); + +%attribute(spine::Vector2, float, x, getX, setX); +%attribute(spine::Vector2, float, y, getY, setY); + // ----- Import Section ------ // Brief: Import header files which are depended by 'Include Section' // Note: @@ -257,6 +541,7 @@ using namespace spine; // ----- Include Section ------ // Brief: Include header files in which classes and methods will be bound +%include "editor-support/spine/MathUtil.h" %include "editor-support/spine/MixBlend.h" %include "editor-support/spine/MixDirection.h" %include "editor-support/spine/TransformMode.h" @@ -318,4 +603,146 @@ using namespace spine; %include "editor-support/spine-creator-support/SkeletonAnimation.h" %include "editor-support/spine-creator-support/SkeletonDataMgr.h" %include "editor-support/spine-creator-support/SkeletonCacheAnimation.h" -%include "editor-support/spine-creator-support/SkeletonCacheMgr.h" \ No newline at end of file +%include "editor-support/spine-creator-support/SkeletonCacheMgr.h" + +%extend spine::IkConstraint { + void apply1(Bone *bone, float targetX, float targetY, bool compress, bool stretch, bool uniform, float alpha) { + IkConstraint::apply(*bone, targetX, targetY, compress, stretch, uniform, alpha); + } + + void apply2(Bone *parent, Bone *child, float targetX, float targetY, int bendDir, bool stretch, float softness, float alpha) { + IkConstraint::apply(*parent, *child, targetX, targetY, bendDir, stretch, softness, alpha); + } +}; + +%extend spine::Bone { + Bone(spine::BoneData *data, spine::Skeleton *skeleton, spine::Bone *parent) { + return new Bone(*data, *skeleton, parent); + } + + void updateWorldTransformWith(float x, float y, float rotation, float scaleX, float scaleY, float shearX, float shearY) { + $self->updateWorldTransform(x, y, rotation, scaleX, scaleY, shearX, shearY); + } +} + +%extend spine::Slot { + Slot(spine::SlotData *data, spine::Bone *bone) { + return new Slot(*data, *bone); + } +} + +%extend spine::Timeline { + void apply(spine::Skeleton *skeleton, float lastTime, float time, const ccstd::vector& events, float alpha, spine::MixBlend blend, spine::MixDirection direction) { + spine::Vector spEvents; + for (int i = 0; i < events.size(); ++i) { + spEvents.add(events[i]); + } + $self->apply(*skeleton, lastTime, time, &spEvents, alpha, blend, direction); + } +} + +%extend spine::AnimationState { + void apply(spine::Skeleton* skeleton) { + $self->apply(*skeleton); + } +} + +%extend spine::Animation { + void apply(spine::Skeleton *skeleton, float lastTime, float time, bool loop, const ccstd::vector& events, float alpha, spine::MixBlend blend, spine::MixDirection direction) { + spine::Vector spEvents; + for (int i = 0; i < events.size(); ++i) { + spEvents.add(events[i]); + } + $self->apply(*skeleton, lastTime, time, loop, &spEvents, alpha, blend, direction); + } +} + +%extend spine::Event { + Event(float time, spine::EventData *data) { + return new Event(time, *data); + } +} + +%extend spine::IkConstraint { + IkConstraint(spine::IkConstraintData *data, spine::Skeleton *skeleton) { + return new IkConstraint(*data, *skeleton); + } +} + +%extend spine::PathConstraint { + PathConstraint(spine::PathConstraintData* data, spine::Skeleton* skeleton) { + return new PathConstraint(*data, *skeleton); + } +} + +%extend spine::PointAttachment { + float computeWorldRotation(spine::Bone* bone) { + return $self->computeWorldRotation(*bone); + } +} + +%extend spine::SkeletonBounds { + void update(spine::Skeleton* skeleton, bool updateAabb) { + $self->update(*skeleton, updateAabb); + } +} + +%extend spine::TransformConstraint { + TransformConstraint(spine::TransformConstraintData* data, spine::Skeleton* skeleton) { + return new TransformConstraint(*data, *skeleton); + } +} + +%extend spine::SlotData { + SlotData(int index, const ccstd::string *name, spine::BoneData *boneData) { + spine::String spName(name->data()); + return new SlotData(index, spName, *boneData); + } +} + +%extend spine::VertexEffect { + void begin(spine::Skeleton *skeleton) { + $self->begin(*skeleton); + } +} + +%extend spine::SwirlVertexEffect { + SwirlVertexEffect(float radius, spine::Interpolation *interpolation) { + return new SwirlVertexEffect(radius, *interpolation); + } +} + +%extend spine::DeformTimeline { + void setFrame(int frameIndex, float time, const ccstd::vector& vertices) { + spine::Vector spVertices; + for (int i = 0; i < vertices.size(); ++i) { + spVertices.add(vertices[i]); + } + $self->setFrame(frameIndex, time, spVertices); + } +} + +%extend spine::DrawOrderTimeline { + void setFrame(size_t frameIndex, float time, const ccstd::vector& drawOrder) { + spine::Vector spDrawOrder; + spDrawOrder.ensureCapacity(drawOrder.size()); + for (int i = 0; i < drawOrder.size(); ++i) { + spDrawOrder.add(drawOrder[i]); + } + $self->setFrame(frameIndex, time, spDrawOrder); + } +} + +%extend spine::Color { + spine::Color &setFromColor(const spine::Color &other) { + return $self->set(other); + } +} + +%extend spine::Skeleton { + spine::Attachment &getAttachmentByName(const std::string &slotName, const std::string &attachmentName) { + spine::String slot(slotName.data()); + spine::String attachment(attachmentName.data()); + return *($self->getAttachment(slot, attachment)); + } +} \ No newline at end of file diff --git a/platforms/native/engine/jsb-spine-skeleton.js b/platforms/native/engine/jsb-spine-skeleton.js index ae233945e23..10e1bacf9a6 100644 --- a/platforms/native/engine/jsb-spine-skeleton.js +++ b/platforms/native/engine/jsb-spine-skeleton.js @@ -133,8 +133,8 @@ const cacheManager = require('./jsb-cache-manager'); } this._skeletonCache = spine.initSkeletonData(uuid, filePath, atlasText, jsbTextures, this.scale); if (this._skeletonCache) { - this.width = this._skeletonCache.getWidth(); - this.height = this._skeletonCache.getHeight(); + this.width = this._skeletonCache.width; + this.height = this._skeletonCache.height; } }; From c04f35599c2e5c8302239ae7df15152232d65bbb Mon Sep 17 00:00:00 2001 From: Zeqiang Li Date: Fri, 11 Aug 2023 16:06:12 +0800 Subject: [PATCH 084/184] Merge branch 'v3.8.1-pipeline' of github.com:star-e/engine into v3.8.1-pipeline (#15930) --- native/cocos/renderer/gfx-base/GFXBarrier.cpp | 16 ++--- .../pipeline/custom/FrameGraphDispatcher.cpp | 61 +++++++++++++------ 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/native/cocos/renderer/gfx-base/GFXBarrier.cpp b/native/cocos/renderer/gfx-base/GFXBarrier.cpp index 688c9a42612..b495fd4d031 100644 --- a/native/cocos/renderer/gfx-base/GFXBarrier.cpp +++ b/native/cocos/renderer/gfx-base/GFXBarrier.cpp @@ -270,7 +270,7 @@ constexpr AccessElem ACCESS_MAP[] = { // ACCESS_READ | RES_TEXTURE | SHADERSTAGE_FRAG | CMN_IB_OR_CA, // AccessFlags::COLOR_ATTACHMENT_READ}, - {CARE_MEMACCESS | CARE_RESTYPE | CARE_CMNUSAGE, + {CARE_MEMACCESS | CARE_RESTYPE | CARE_CMNUSAGE | CARE_SHADERSTAGE, ACCESS_READ | RES_TEXTURE | CMN_VB_OR_DS | CMN_ROM, AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ}, @@ -280,12 +280,14 @@ constexpr AccessElem ACCESS_MAP[] = { {IGNORE_MEMUSAGE, ACCESS_READ | RES_TEXTURE | SHADERSTAGE_COMP | CMN_ROM, - AccessFlags::COMPUTE_SHADER_READ_TEXTURE}, + AccessFlags::COMPUTE_SHADER_READ_TEXTURE, + CMN_VB_OR_DS}, // shading rate has its own flag {CARE_MEMACCESS | CARE_SHADERSTAGE | CARE_CMNUSAGE, ACCESS_READ | SHADERSTAGE_COMP | CMN_STORAGE, - AccessFlags::COMPUTE_SHADER_READ_OTHER}, + AccessFlags::COMPUTE_SHADER_READ_OTHER, + RES_TEXTURE | CMN_ROM}, {CARE_MEMACCESS | CARE_CMNUSAGE, ACCESS_READ | CMN_COPY_SRC, @@ -350,10 +352,10 @@ constexpr bool validateAccess(ResourceType type, CommonUsage usage, MemoryAccess res = !(*std::max_element(std::begin(conflicts), std::end(conflicts))); } else if (type == ResourceType::TEXTURE) { uint32_t conflicts[] = { - hasAnyFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::VB_OR_DS | CommonUsage::INDIRECT_OR_INPUT) && !hasFlag(visibility, ShaderStageFlags::FRAGMENT), // color/ds/input not in fragment - hasFlag(usage, CommonUsage::INDIRECT_OR_INPUT) && !hasFlag(access, MemoryAccess::READ_ONLY), // input needs read - hasAllFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::STORAGE), // storage ^ sampled - hasFlag(usage, CommonUsage::COPY_SRC) && !hasAllFlags(MemoryAccess::READ_ONLY, access), // transfer src ==> read_only + // hasAnyFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::VB_OR_DS | CommonUsage::INDIRECT_OR_INPUT) && !hasFlag(visibility, ShaderStageFlags::FRAGMENT), // color/ds/input not in fragment + hasFlag(usage, CommonUsage::INDIRECT_OR_INPUT) && !hasFlag(access, MemoryAccess::READ_ONLY), // input needs read + hasAllFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::STORAGE), // storage ^ sampled + hasFlag(usage, CommonUsage::COPY_SRC) && !hasAllFlags(MemoryAccess::READ_ONLY, access), // transfer src ==> read_only hasFlag(usage, CommonUsage::COPY_DST) && !hasAllFlags(MemoryAccess::WRITE_ONLY, access), hasFlag(usage, CommonUsage::INDIRECT_OR_INPUT) && !hasAnyFlags(usage, CommonUsage::IB_OR_CA | CommonUsage::VB_OR_DS), // input needs to specify color or ds // transfer dst ==> write_only hasAllFlags(usage, CommonUsage::COPY_SRC | CommonUsage::COPY_DST), // both src and dst diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index d18121f8761..60babdea94f 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -143,6 +143,11 @@ ResourceGraph::vertex_descriptor FrameGraphDispatcher::realResourceID(const ccst return subresName; } + auto namedID = findVertex(resName, resg); + if (parent(namedID, resg) == ResourceGraph::null_vertex()) { + return resName; + } + // array if (desc.dimension == ResourceDimension::TEXTURE2D && desc.depthOrArraySize > 1) { ccstd::pmr::set leaves(scratch); @@ -188,6 +193,21 @@ ResourceGraph::vertex_descriptor locateSubres(const ccstd::pmr::string& originNa return findVertex(resName, resg); } +ResourceGraph::vertex_descriptor locateSubres(const ccstd::pmr::string &originName, + const ResourceGraph &resg, + uint32_t basePlane, + const ResourceAccessGraph& rag, + boost::container::pmr::memory_resource *scratch) { + auto originID = findVertex(originName, resg); + if (rag.movedSourceStatus.find(originName) != rag.movedSourceStatus.end()) { + return rag.resourceIndex.at(originName); + } + + const auto &resName = getSubresNameByPlane(originName, basePlane, resg, scratch); + return findVertex(resName, resg); +} + + PmrFlatMap FrameGraphDispatcher::buildDescriptorIndex( const PmrTransparentMap> &computeViews, boost::container::pmr::memory_resource *scratch) const { @@ -200,7 +220,7 @@ PmrFlatMap FrameGraphDispatcher:: const auto &name = computeView.name; CC_EXPECTS(!name.empty()); const auto nameID = layoutGraph.attributeIndex.at(name); - auto subresID = locateSubres(resName, resourceGraph, computeView.plane, scratch); + auto subresID = locateSubres(resName, resourceGraph, computeView.plane, resourceAccessGraph, scratch); resourceIndex.emplace(nameID, subresID); } } @@ -1448,6 +1468,8 @@ bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const Resour } } + auto safeShift = [](uint32_t num, uint8_t bit) { return std::max(1u, num >> bit); }; + rangeCheck(rag.movedTargetStatus[toResName], toResDesc, toResName, movePair.targetFirstSlice, movePair.numSlices, movePair.targetMostDetailedMip, movePair.mipLevels, movePair.targetPlaneSlice); uint32_t validConditions[] = { !fromResTraits.hasSideEffects(), @@ -1455,13 +1477,13 @@ bool moveValidation(const MovePass& pass, ResourceAccessGraph& rag, const Resour rag.movedSourceStatus.find(fromResName) == rag.movedSourceStatus.end(), fromResTraits.residency != ResourceResidency::MEMORYLESS && toResTraits.residency != ResourceResidency::MEMORYLESS, fromResDesc.dimension == toResDesc.dimension, - fromResDesc.width == toResDesc.width, - fromResDesc.height == toResDesc.height, + fromResDesc.width == safeShift(toResDesc.width, movePair.targetMostDetailedMip), + fromResDesc.height == safeShift(toResDesc.height, movePair.targetMostDetailedMip), fromResDesc.format == toResDesc.format, fromResDesc.sampleCount == toResDesc.sampleCount, (fromResDesc.depthOrArraySize == toResDesc.depthOrArraySize) || (toResDesc.dimension != ResourceDimension::BUFFER), // full move if resource is buffer }; - bool val = std::min_element(std::begin(validConditions), std::end(validConditions)); + bool val = *std::min_element(std::begin(validConditions), std::end(validConditions)); check &= val; } @@ -1535,7 +1557,11 @@ void startMovePass(const Graphs &graphs, uint32_t passID, const MovePass &pass) auto lastStatusIter = resourceAccessGraph.resourceAccess.at(pair.source).rbegin(); resourceAccessGraph.movedSourceStatus.emplace(pair.source, AccessStatus{lastStatusIter->second.accessFlag, srcResourceRange}); resourceAccessGraph.movedTarget[pair.target].emplace(getSubresourceNameByRange(srcResourceRange, resourceAccessGraph.resource()), pair.source); - resourceAccessGraph.resourceAccess[pair.target] = resourceAccessGraph.resourceAccess[pair.source]; + + const auto &srcAccess = resourceAccessGraph.resourceAccess.at(pair.source); + auto &targetAccess = resourceAccessGraph.resourceAccess[pair.target]; + targetAccess.clear(); + targetAccess.emplace(*srcAccess.rbegin()); auto targetResID = findVertex(pair.target, resourceGraph); resourceAccessGraph.resourceIndex[pair.target] = targetResID; @@ -1846,12 +1872,9 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { // : or no extra barrier needed. for (auto &accessPair : rag.resourceAccess) { const auto &resName = accessPair.first; - if (rag.movedSourceStatus.find(resName) != rag.movedSourceStatus.end()) { - // moved, history of this resource access will be copied to moved target. - continue; - } - const auto &resID = findVertex(resName, resourceGraph); + auto resID = findVertex(resName, resourceGraph); + auto realResourceID = resID; const auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); bool isBuffer = desc.dimension == ResourceDimension::BUFFER; @@ -1908,11 +1931,15 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { continue; } + if (rag.movedSourceStatus.find(resName) != rag.movedSourceStatus.end()) { + realResourceID = rag.resourceIndex.at(resName); + } + // undefined access - if (iter == accessRecord.begin()) { + if (srcRagVertID == 0) { auto &dstBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, dstRagVertID); auto &firstMeetBarrier = dstBarrierNode.frontBarriers.emplace_back(); - firstMeetBarrier.resourceID = resID; + firstMeetBarrier.resourceID = realResourceID; firstMeetBarrier.type = gfx::BarrierType::FULL; firstMeetBarrier.beginVert = dstPassID; firstMeetBarrier.endVert = dstPassID; @@ -1922,7 +1949,7 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { } else if (accessDependent(iter->second.accessFlag, nextIter->second.accessFlag, isBuffer)) { auto &srcBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, srcRagVertID); auto &beginBarrier = srcBarrierNode.rearBarriers.emplace_back(); - beginBarrier.resourceID = resID; + beginBarrier.resourceID = realResourceID; beginBarrier.beginVert = srcPassID; beginBarrier.endVert = dstPassID; beginBarrier.beginStatus = iter->second; @@ -1934,7 +1961,7 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { auto &dstBarrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, dstRagVertID); auto &endBarrier = dstBarrierNode.frontBarriers.emplace_back(); - endBarrier.resourceID = resID; + endBarrier.resourceID = realResourceID; endBarrier.type = gfx::BarrierType::SPLIT_END; endBarrier.beginVert = srcPassID; endBarrier.endVert = dstPassID; @@ -1945,15 +1972,15 @@ void buildBarriers(FrameGraphDispatcher &fgDispatcher) { beginBarrier.barrier = getGFXBarrier(beginBarrier); } } - const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, resID); - auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, resID); + const auto &traits = get(ResourceGraph::TraitsTag{}, resourceGraph, realResourceID); + auto &states = get(ResourceGraph::StatesTag{}, resourceGraph, realResourceID); if (traits.hasSideEffects()) { states.states = iter->second.accessFlag; if (traits.residency == ResourceResidency::BACKBUFFER) { auto lastAccessPassID = get(ResourceAccessGraph::PassIDTag{}, rag, iter->first); auto &barrierNode = get(ResourceAccessGraph::BarrierTag{}, rag, iter->first); auto &presentBarrier = barrierNode.rearBarriers.emplace_back(); - presentBarrier.resourceID = resID; + presentBarrier.resourceID = realResourceID; presentBarrier.type = gfx::BarrierType::FULL; presentBarrier.beginVert = lastAccessPassID; presentBarrier.endVert = lastAccessPassID; From 85eaac8d5e819aaaffdb75c8471a5078a290ccf4 Mon Sep 17 00:00:00 2001 From: troublemaker52025 Date: Fri, 11 Aug 2023 17:28:16 +0800 Subject: [PATCH 085/184] revert Synchronize groundLightingColor settings from #14509 (#15931) --- native/cocos/scene/Ambient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/cocos/scene/Ambient.cpp b/native/cocos/scene/Ambient.cpp index 85d3fc65c73..7aebad344e0 100644 --- a/native/cocos/scene/Ambient.cpp +++ b/native/cocos/scene/Ambient.cpp @@ -98,7 +98,7 @@ float AmbientInfo::getSkyIllum() const { } void AmbientInfo::setGroundLightingColor(const Color &val) { - const Vec4 v4(val.r, val.g, val.b, val.a); + const Vec4 v4(static_cast(val.r) / 255.F, static_cast(val.g) / 255.F, static_cast(val.b) / 255.F, static_cast(val.a) / 255.F); const bool isHDR = Root::getInstance()->getPipeline()->getPipelineSceneData()->isHDR(); if (isHDR) { _groundAlbedoHDR.set(v4); From 9aafdbdd0512c3b2d7b5b0c5b48c9ec321f84c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Fri, 11 Aug 2023 17:30:32 +0800 Subject: [PATCH 086/184] fix switch Env Lighting Type in the editor displays incorrectly and probe does not update position from parent node (#15925) --- .../reflection-probe-component.ts | 18 ++++++++---------- cocos/render-scene/scene/skybox.ts | 3 ++- editor/inspector/contributions/node.js | 4 ++-- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/cocos/3d/reflection-probe/reflection-probe-component.ts b/cocos/3d/reflection-probe/reflection-probe-component.ts index 2f3c06e53d6..e5c36ee2fb6 100644 --- a/cocos/3d/reflection-probe/reflection-probe-component.ts +++ b/cocos/3d/reflection-probe/reflection-probe-component.ts @@ -326,14 +326,12 @@ export class ReflectionProbe extends Component { ReflectionProbeManager.probeManager.onUpdateProbes(true); this._probe.enable(); } - this.node.on(Node.EventType.TRANSFORM_CHANGED, this._onProbeTransformChanged, this); } onDisable (): void { if (this._probe) { ReflectionProbeManager.probeManager.unregister(this._probe); this._probe.disable(); } - this.node.off(Node.EventType.TRANSFORM_CHANGED, this._onProbeTransformChanged); } public start (): void { @@ -373,6 +371,14 @@ export class ReflectionProbe extends Component { this.probe.renderPlanarReflection(this.sourceCamera.camera); } } + + if (this.node.hasChangedFlags) { + this.probe.updateBoundingBox(); + } + if (this.node.hasChangedFlags & TransformBit.POSITION) { + ReflectionProbeManager.probeManager.onUpdateProbes(true); + ReflectionProbeManager.probeManager.updateProbeData(); + } } /** @@ -385,14 +391,6 @@ export class ReflectionProbe extends Component { ReflectionProbeManager.probeManager.updatePreviewSphere(this.probe); } - private _onProbeTransformChanged (type: TransformBit): void { - this.probe.updateBoundingBox(); - if (type & Node.TransformBit.POSITION) { - ReflectionProbeManager.probeManager.onUpdateProbes(true); - ReflectionProbeManager.probeManager.updateProbeData(); - } - } - private _createProbe (): void { if (this._probeId === -1 || ReflectionProbeManager.probeManager.exists(this._probeId)) { this._probeId = ReflectionProbeManager.probeManager.getNewReflectionProbeId(); diff --git a/cocos/render-scene/scene/skybox.ts b/cocos/render-scene/scene/skybox.ts index 2d8b6da60f7..30ce5bb5960 100644 --- a/cocos/render-scene/scene/skybox.ts +++ b/cocos/render-scene/scene/skybox.ts @@ -365,7 +365,8 @@ export class Skybox { const pipeline = root.pipeline; const useIBLValue = this.useIBL ? (this.isRGBE ? 2 : 1) : 0; - const useDiffuseMapValue = (this.useIBL && this.useDiffuseMap && this.diffuseMap) ? (this.isRGBE ? 2 : 1) : 0; + const useDiffuseMapValue = (this.useIBL && this.useDiffuseMap && this.diffuseMap && this.diffuseMap !== this._default) + ? (this.isRGBE ? 2 : 1) : 0; const useHDRValue = this.useHDR; const useConvMapValue = this.useConvolutionMap; diff --git a/editor/inspector/contributions/node.js b/editor/inspector/contributions/node.js index 13285f5336a..e454f83b46d 100644 --- a/editor/inspector/contributions/node.js +++ b/editor/inspector/contributions/node.js @@ -454,7 +454,7 @@ exports.$ = { sceneSkyboxAfter: '.container > .body > .scene > .skybox > .after', sceneOctree: '.container > .body > .scene > .octree', sceneSkin: '.container > .body > .scene > .skin', - scenePostSettings: '.scene > .postSettings', + scenePostSettings: '.container > .body > .scene > .postSettings', node: '.container > .body > .node', nodeHeader: '.container > .body > .node > .component-header', @@ -1077,7 +1077,7 @@ const Elements = { const uuid = $prop.dump.value.uuid; Elements.scene.setEnvMapAndConvolutionMap.call(panel, uuid); - panel.$.scenePostSettings.style.display = useHDR ? 'inline-flex' : 'none'; + panel.$.scenePostSettings.style.display = useHDR ? 'block' : 'none'; }, skyboxEnvmapChange(useHDR, event) { const panel = this; From 0c47721fad34da5ba14a14d8772737facf0bb4f4 Mon Sep 17 00:00:00 2001 From: James Chen Date: Mon, 14 Aug 2023 09:55:59 +0800 Subject: [PATCH 087/184] fixed #15885: [bug] Crash or freeze if restarting game many times on non-android platforms. (#15922) --- native/cocos/storage/local-storage/LocalStorage.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/native/cocos/storage/local-storage/LocalStorage.cpp b/native/cocos/storage/local-storage/LocalStorage.cpp index 20b5fb277a8..1aa2edd17e4 100644 --- a/native/cocos/storage/local-storage/LocalStorage.cpp +++ b/native/cocos/storage/local-storage/LocalStorage.cpp @@ -40,6 +40,7 @@ #endif #include "base/Macros.h" +#include "base/Log.h" static int _initialized = 0; static sqlite3 *_db; @@ -109,8 +110,15 @@ void localStorageFree() { sqlite3_finalize(_stmt_select); sqlite3_finalize(_stmt_remove); sqlite3_finalize(_stmt_update); + sqlite3_finalize(_stmt_clear); + sqlite3_finalize(_stmt_key); + sqlite3_finalize(_stmt_count); - sqlite3_close(_db); + int ret = sqlite3_close(_db); + CC_ASSERT(ret == SQLITE_OK); + if (ret != SQLITE_OK) { + CC_LOG_ERROR("sqlite3_close failed, ret: %d", ret); + } _initialized = 0; } From 2b266acce7d014706b631eccfc3283063cf1ec21 Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Mon, 14 Aug 2023 09:56:59 +0800 Subject: [PATCH 088/184] fix gles3 gl target (#15914) * fix gles3 gl target * remove texture view type. --- .../renderer/gfx-gles3/GLES3CommandBuffer.cpp | 4 +- .../renderer/gfx-gles3/GLES3Commands.cpp | 101 +++++++++++------- .../cocos/renderer/gfx-gles3/GLES3Commands.h | 15 +-- .../cocos/renderer/gfx-gles3/GLES3Device.cpp | 2 +- .../renderer/gfx-gles3/GLES3GPUObjects.h | 11 +- .../gfx-gles3/GLES3PrimaryCommandBuffer.cpp | 16 +-- .../cocos/renderer/gfx-gles3/GLES3Texture.cpp | 4 + 7 files changed, 90 insertions(+), 63 deletions(-) diff --git a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp index 706dd795a59..a7396a35587 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp @@ -309,8 +309,8 @@ void GLES3CommandBuffer::resolveTexture(Texture *srcTexture, Texture *dstTexture void GLES3CommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { GLES3CmdBlitTexture *cmd = _cmdAllocator->blitTextureCmdPool.alloc(); - if (srcTexture) cmd->gpuTextureSrc = static_cast(srcTexture)->gpuTexture(); - if (dstTexture) cmd->gpuTextureDst = static_cast(dstTexture)->gpuTexture(); + if (srcTexture) cmd->gpuTextureSrcView = static_cast(srcTexture)->gpuTextureView(); + if (dstTexture) cmd->gpuTextureDstView = static_cast(dstTexture)->gpuTextureView(); cmd->regions = regions; cmd->count = count; cmd->filter = filter; diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp index 104ebfe5ce3..46581b89681 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp @@ -491,12 +491,17 @@ GLenum formatToGLType(Format format) { } } -GLenum getTextureTarget(TextureType type) { - switch (type) { - case TextureType::TEX2D: return GL_TEXTURE_2D; +GLenum getTextureViewTarget(GLES3GPUTextureView *view) { + switch (view->type) { case TextureType::TEX2D_ARRAY: return GL_TEXTURE_2D_ARRAY; case TextureType::TEX3D: return GL_TEXTURE_3D; case TextureType::CUBE: return GL_TEXTURE_CUBE_MAP; + case TextureType::TEX2D: { + if (hasFlag(view->gpuTexture->flags, TextureFlagBit::EXTERNAL_OES)) { + return GL_TEXTURE_EXTERNAL_OES; + } + return view->gpuTexture->type == TextureType::CUBE ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + view->baseLayer : GL_TEXTURE_2D; + } default: CC_ABORT(); return GL_NONE; @@ -819,7 +824,6 @@ static void textureStorage(GLES3Device *device, GLES3GPUTexture *gpuTexture) { GLuint &glTexture = device->stateCache()->glTextures[device->stateCache()->texUint]; if (gpuTexture->glTexture != glTexture) { - GL_CHECK(glBindTexture(gpuTexture->glTarget, gpuTexture->glTexture)); glTexture = gpuTexture->glTexture; } uint32_t w = gpuTexture->width; @@ -829,22 +833,31 @@ static void textureStorage(GLES3Device *device, GLES3GPUTexture *gpuTexture) { switch (gpuTexture->type) { case TextureType::CUBE: CC_ASSERT(gpuTexture->glSamples <= 1); + GL_CHECK(glBindTexture(GL_TEXTURE_CUBE_MAP, gpuTexture->glTexture)); + GL_CHECK(glTexStorage2D(GL_TEXTURE_CUBE_MAP, gpuTexture->mipLevel, gpuTexture->glInternalFmt, w, h)); + break; case TextureType::TEX2D: if (gpuTexture->glSamples > 1 && !gpuTexture->immutable && device->constantRegistry()->glMinorVersion >= 1) { - gpuTexture->glTarget = GL_TEXTURE_2D_MULTISAMPLE; - GL_CHECK(glTexStorage2DMultisample(gpuTexture->glTarget, gpuTexture->glSamples, gpuTexture->glInternalFmt, w, h, GL_FALSE)); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, gpuTexture->glTexture)); + GL_CHECK(glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, gpuTexture->glSamples, gpuTexture->glInternalFmt, w, h, GL_FALSE)); } else { - GL_CHECK(glTexStorage2D(gpuTexture->glTarget, gpuTexture->mipLevel, gpuTexture->glInternalFmt, w, h)); + auto target = hasFlag(gpuTexture->flags, TextureFlagBit::EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; + GL_CHECK(glBindTexture(target, gpuTexture->glTexture)); + GL_CHECK(glTexStorage2D(target, gpuTexture->mipLevel, gpuTexture->glInternalFmt, w, h)); } break; case TextureType::TEX3D: CC_ASSERT(gpuTexture->glSamples <= 1); + GL_CHECK(glBindTexture(GL_TEXTURE_3D, gpuTexture->glTexture)); + GL_CHECK(glTexStorage3D(GL_TEXTURE_3D, gpuTexture->mipLevel, gpuTexture->glInternalFmt, w, h, d)); + break; case TextureType::TEX2D_ARRAY: if (gpuTexture->glSamples > 1 && !gpuTexture->immutable && device->constantRegistry()->glMinorVersion >= 1) { - gpuTexture->glTarget = GL_TEXTURE_2D_MULTISAMPLE_ARRAY; - GL_CHECK(glTexStorage3DMultisample(gpuTexture->glTarget, gpuTexture->glSamples, gpuTexture->glInternalFmt, w, h, d, GL_FALSE)); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, gpuTexture->glTexture)); + GL_CHECK(glTexStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, gpuTexture->glSamples, gpuTexture->glInternalFmt, w, h, d, GL_FALSE)); } else { - GL_CHECK(glTexStorage3D(gpuTexture->glTarget, gpuTexture->mipLevel, gpuTexture->glInternalFmt, w, h, d)); + GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, gpuTexture->glTexture)); + GL_CHECK(glTexStorage3D(GL_TEXTURE_2D_ARRAY, gpuTexture->mipLevel, gpuTexture->glInternalFmt, w, h, d)); } break; default: @@ -870,31 +883,19 @@ void cmdFuncGLES3CreateTexture(GLES3Device *device, GLES3GPUTexture *gpuTexture) // Allocate render buffer when binding a framebuffer if the MSRT extension is not present. if (gpuTexture->useRenderBuffer && hasFlag(gpuTexture->flags, TextureFlagBit::LAZILY_ALLOCATED)) { - gpuTexture->glTarget = GL_RENDERBUFFER; gpuTexture->memoryAllocated = false; return; } } - if (gpuTexture->glTexture) { - if (hasFlag(gpuTexture->flags, TextureFlagBit::EXTERNAL_OES)) { - gpuTexture->glTarget = GL_TEXTURE_EXTERNAL_OES; - } else { - gpuTexture->glTarget = GL_TEXTURE_2D; - } - return; - } - - if (gpuTexture->size == 0) { + if (gpuTexture->glTexture || gpuTexture->size == 0) { return; } if (gpuTexture->useRenderBuffer) { - gpuTexture->glTarget = GL_RENDERBUFFER; GL_CHECK(glGenRenderbuffers(1, &gpuTexture->glRenderbuffer)); renderBufferStorage(device, gpuTexture); } else { - gpuTexture->glTarget = getTextureTarget(gpuTexture->type); GL_CHECK(glGenTextures(1, &gpuTexture->glTexture)); textureStorage(device, gpuTexture); } @@ -940,6 +941,10 @@ void cmdFuncGLES3ResizeTexture(GLES3Device *device, GLES3GPUTexture *gpuTexture) } } +void cmdFuncGLES3CreateTextureView(GLES3Device */*device*/, GLES3GPUTextureView *gpuTextureView) { + gpuTextureView->glTarget = getTextureViewTarget(gpuTextureView); +} + void cmdFuncGLES3PrepareSamplerInfo(GLES3Device * /*device*/, GLES3GPUSampler *gpuSampler) { if (gpuSampler->minFilter == Filter::LINEAR || gpuSampler->minFilter == Filter::ANISOTROPIC) { if (gpuSampler->mipFilter == Filter::LINEAR || gpuSampler->mipFilter == Filter::ANISOTROPIC) { @@ -2281,7 +2286,7 @@ void cmdFuncGLES3BindState(GLES3Device *device, GLES3GPUPipelineState *gpuPipeli GL_CHECK(glActiveTexture(GL_TEXTURE0 + unit)); cache->texUint = unit; } - GL_CHECK(glBindTexture(gpuTexture->glTarget, glTexture)); + GL_CHECK(glBindTexture(gpuTextureView->glTarget, glTexture)); cache->glTextures[unit] = glTexture; } @@ -2661,7 +2666,6 @@ void cmdFuncGLES3CopyBuffersToTexture(GLES3Device *device, const uint8_t *const GLuint &glTexture = device->stateCache()->glTextures[device->stateCache()->texUint]; if (glTexture != gpuTexture->glTexture) { - GL_CHECK(glBindTexture(gpuTexture->glTarget, gpuTexture->glTexture)); glTexture = gpuTexture->glTexture; } @@ -2673,11 +2677,15 @@ void cmdFuncGLES3CopyBuffersToTexture(GLES3Device *device, const uint8_t *const uint32_t destWidth = 0; uint32_t destHeight = 0; - switch (gpuTexture->glTarget) { - case GL_TEXTURE_2D: { + auto target = GL_NONE; + switch (gpuTexture->type) { + case TextureType::TEX2D: { Extent extent{}; Offset offset{}; Extent stride{}; + + target = GL_TEXTURE_2D; + GL_CHECK(glBindTexture(GL_TEXTURE_2D, gpuTexture->glTexture)); for (size_t i = 0; i < count; ++i) { const BufferTextureCopy ®ion = regions[i]; uint32_t mipLevel = region.texSubres.mipLevel; @@ -2720,10 +2728,13 @@ void cmdFuncGLES3CopyBuffersToTexture(GLES3Device *device, const uint8_t *const } break; } - case GL_TEXTURE_2D_ARRAY: { + case TextureType::TEX2D_ARRAY: { Extent extent{}; Offset offset{}; Extent stride{}; + + target = GL_TEXTURE_2D_ARRAY; + GL_CHECK(glBindTexture(GL_TEXTURE_2D_ARRAY, gpuTexture->glTexture)); for (size_t i = 0; i < count; ++i) { const BufferTextureCopy ®ion = regions[i]; uint32_t d = region.texSubres.layerCount; @@ -2773,11 +2784,13 @@ void cmdFuncGLES3CopyBuffersToTexture(GLES3Device *device, const uint8_t *const } break; } - case GL_TEXTURE_3D: { + case TextureType::TEX3D: { Extent extent{}; Offset offset{}; Extent stride{}; + target = GL_TEXTURE_3D; + GL_CHECK(glBindTexture(GL_TEXTURE_3D, gpuTexture->glTexture)); for (size_t i = 0; i < count; ++i) { const BufferTextureCopy ®ion = regions[i]; uint32_t mipLevel = region.texSubres.mipLevel; @@ -2822,10 +2835,13 @@ void cmdFuncGLES3CopyBuffersToTexture(GLES3Device *device, const uint8_t *const } break; } - case GL_TEXTURE_CUBE_MAP: { + case TextureType::CUBE: { Extent extent{}; Offset offset{}; Extent stride{}; + + target = GL_TEXTURE_CUBE_MAP; + GL_CHECK(glBindTexture(GL_TEXTURE_CUBE_MAP, gpuTexture->glTexture)); for (size_t i = 0; i < count; ++i) { const BufferTextureCopy ®ion = regions[i]; uint32_t mipLevel = region.texSubres.mipLevel; @@ -2879,20 +2895,21 @@ void cmdFuncGLES3CopyBuffersToTexture(GLES3Device *device, const uint8_t *const break; } - if (!isCompressed && hasFlag(gpuTexture->flags, TextureFlagBit::GEN_MIPMAP)) { - GL_CHECK(glBindTexture(gpuTexture->glTarget, gpuTexture->glTexture)); - GL_CHECK(glGenerateMipmap(gpuTexture->glTarget)); + if (!isCompressed && hasFlag(gpuTexture->flags, TextureFlagBit::GEN_MIPMAP) && target != GL_NONE) { + GL_CHECK(glBindTexture(target, gpuTexture->glTexture)); + GL_CHECK(glGenerateMipmap(target)); } } -void cmdFuncGLES3CopyTextureToBuffers(GLES3Device *device, GLES3GPUTexture *gpuTexture, uint8_t *const *buffers, const BufferTextureCopy *regions, uint32_t count) { +void cmdFuncGLES3CopyTextureToBuffers(GLES3Device *device, GLES3GPUTextureView *gpuTextureView, uint8_t *const *buffers, const BufferTextureCopy *regions, uint32_t count) { + const auto *gpuTexture = gpuTextureView->gpuTexture; auto glFormat = gpuTexture->glFormat; auto glType = gpuTexture->glType; for (uint32_t i = 0; i < count; ++i) { auto region = regions[i]; uint8_t *copyDst = buffers[i]; - auto framebuffer = device->framebufferCacheMap()->getFramebufferFromTexture(gpuTexture, region.texSubres); + auto framebuffer = device->framebufferCacheMap()->getFramebufferFromTexture(gpuTextureView, region.texSubres); if (device->stateCache()->glReadFramebuffer != framebuffer) { GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer)); device->stateCache()->glReadFramebuffer = framebuffer; @@ -2901,9 +2918,11 @@ void cmdFuncGLES3CopyTextureToBuffers(GLES3Device *device, GLES3GPUTexture *gpuT } } -void cmdFuncGLES3BlitTexture(GLES3Device *device, GLES3GPUTexture *gpuTextureSrc, GLES3GPUTexture *gpuTextureDst, +void cmdFuncGLES3BlitTexture(GLES3Device *device, GLES3GPUTextureView *gpuTextureSrcView, GLES3GPUTextureView *gpuTextureDstView, const TextureBlit *regions, uint32_t count, Filter filter) { GLES3GPUStateCache *cache = device->stateCache(); + const auto *gpuTextureSrc = gpuTextureSrcView->gpuTexture; + const auto *gpuTextureDst = gpuTextureDstView->gpuTexture; GLbitfield mask = getColorBufferMask(gpuTextureSrc->format); for (uint32_t i = 0U; i < count; ++i) { @@ -2915,7 +2934,7 @@ void cmdFuncGLES3BlitTexture(GLES3Device *device, GLES3GPUTexture *gpuTextureSrc if (gpuTextureSrc->swapchain) { srcFramebuffer = gpuTextureSrc->swapchain->glFramebuffer; } else { - srcFramebuffer = device->framebufferCacheMap()->getFramebufferFromTexture(gpuTextureSrc, region.srcSubres); + srcFramebuffer = device->framebufferCacheMap()->getFramebufferFromTexture(gpuTextureSrcView, region.srcSubres); } if (cache->glReadFramebuffer != srcFramebuffer) { GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFramebuffer)); @@ -2926,7 +2945,7 @@ void cmdFuncGLES3BlitTexture(GLES3Device *device, GLES3GPUTexture *gpuTextureSrc if (gpuTextureDst->swapchain) { dstFramebuffer = gpuTextureDst->swapchain->glFramebuffer; } else { - dstFramebuffer = device->framebufferCacheMap()->getFramebufferFromTexture(gpuTextureDst, region.dstSubres); + dstFramebuffer = device->framebufferCacheMap()->getFramebufferFromTexture(gpuTextureDstView, region.dstSubres); } if (cache->glDrawFramebuffer != dstFramebuffer) { GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFramebuffer)); @@ -3001,7 +3020,7 @@ void cmdFuncGLES3ExecuteCmds(GLES3Device *device, GLES3CmdPackage *cmdPackage) { } case GLESCmdType::BLIT_TEXTURE: { GLES3CmdBlitTexture *cmd = cmdPackage->blitTextureCmds[cmdIdx]; - cmdFuncGLES3BlitTexture(device, cmd->gpuTextureSrc, cmd->gpuTextureDst, cmd->regions, cmd->count, cmd->filter); + cmdFuncGLES3BlitTexture(device, cmd->gpuTextureSrcView, cmd->gpuTextureDstView, cmd->regions, cmd->count, cmd->filter); break; } case GLESCmdType::QUERY: { @@ -3127,9 +3146,9 @@ void GLES3GPUFramebufferObject::finalize(GLES3GPUStateCache *cache) { GL_CHECK(glGenRenderbuffers(1, &view->gpuTexture->glRenderbuffer)); renderBufferStorage(GLES3Device::getInstance(), texture); } - GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, attachment, texture->glTarget, texture->glRenderbuffer)); + GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, texture->glRenderbuffer)); } else { - GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, texture->glTarget, texture->glTexture, view->baseLevel)); + GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, view->glTarget, texture->glTexture, view->baseLevel)); } }; diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.h b/native/cocos/renderer/gfx-gles3/GLES3Commands.h index c9d612550de..c04634354c6 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.h +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.h @@ -133,8 +133,8 @@ class GLES3CmdCopyBufferToTexture final : public GLESCmd { class GLES3CmdBlitTexture final : public GLESCmd { public: - GLES3GPUTexture *gpuTextureSrc = nullptr; - GLES3GPUTexture *gpuTextureDst = nullptr; + GLES3GPUTextureView *gpuTextureSrcView = nullptr; + GLES3GPUTextureView *gpuTextureDstView = nullptr; const TextureBlit *regions = nullptr; uint32_t count = 0U; Filter filter = Filter::POINT; @@ -142,8 +142,8 @@ class GLES3CmdBlitTexture final : public GLESCmd { GLES3CmdBlitTexture() : GLESCmd(GLESCmdType::BLIT_TEXTURE) {} void clear() override { - gpuTextureSrc = nullptr; - gpuTextureDst = nullptr; + gpuTextureSrcView = nullptr; + gpuTextureDstView = nullptr; regions = nullptr; count = 0U; } @@ -246,6 +246,7 @@ void cmdFuncGLES3ResizeBuffer(GLES3Device *device, GLES3GPUBuffer *gpuBuffer); void cmdFuncGLES3CreateTexture(GLES3Device *device, GLES3GPUTexture *gpuTexture); void cmdFuncGLES3DestroyTexture(GLES3Device *device, GLES3GPUTexture *gpuTexture); void cmdFuncGLES3ResizeTexture(GLES3Device *device, GLES3GPUTexture *gpuTexture); +void cmdFuncGLES3CreateTextureView(GLES3Device *device, GLES3GPUTextureView *gpuTextureView); void cmdFuncGLES3CreateShader(GLES3Device *device, GLES3GPUShader *gpuShader, GLES3GPUPipelineLayout *pipelineLayout); void cmdFuncGLES3DestroyShader(GLES3Device *device, GLES3GPUShader *gpuShader); void cmdFuncGLES3CreateRenderPass(GLES3Device *device, GLES3GPURenderPass *gpuRenderPass); @@ -294,14 +295,14 @@ void cmdFuncGLES3CopyBuffersToTexture(GLES3Device *device, const BufferTextureCopy *regions, uint32_t count); void cmdFuncGLES3CopyTextureToBuffers(GLES3Device *device, - GLES3GPUTexture *gpuTexture, + GLES3GPUTextureView *gpuTextureView, uint8_t *const *buffers, const BufferTextureCopy *regions, uint32_t count); void cmdFuncGLES3BlitTexture(GLES3Device *device, - GLES3GPUTexture *gpuTextureSrc, - GLES3GPUTexture *gpuTextureDst, + GLES3GPUTextureView *gpuTextureSrcView, + GLES3GPUTextureView *gpuTextureDstView, const TextureBlit *regions, uint32_t count, Filter filter); diff --git a/native/cocos/renderer/gfx-gles3/GLES3Device.cpp b/native/cocos/renderer/gfx-gles3/GLES3Device.cpp index 79bc6937af8..e97f7e00c79 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Device.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Device.cpp @@ -604,7 +604,7 @@ void GLES3Device::copyBuffersToTexture(const uint8_t *const *buffers, Texture *d void GLES3Device::copyTextureToBuffers(Texture *srcTexture, uint8_t *const *buffers, const BufferTextureCopy *regions, uint32_t count) { CC_PROFILE(GLES3DeviceCopyTextureToBuffers); - cmdFuncGLES3CopyTextureToBuffers(this, static_cast(srcTexture)->gpuTexture(), buffers, regions, count); + cmdFuncGLES3CopyTextureToBuffers(this, static_cast(srcTexture)->gpuTextureView(), buffers, regions, count); } void GLES3Device::getQueryPoolResults(QueryPool *queryPool) { diff --git a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h index 0005cf0c6b8..66588d21014 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h +++ b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h @@ -135,7 +135,6 @@ struct GLES3GPUTexture { bool isPowerOf2{false}; bool useRenderBuffer{false}; bool memoryAllocated{true}; // false if swapchain image or implicit ms render buffer. - GLenum glTarget{0}; GLenum glInternalFmt{0}; GLenum glFormat{0}; GLenum glType{0}; @@ -156,8 +155,11 @@ struct GLES3GPUTextureView { Format format = Format::UNKNOWN; uint32_t baseLevel = 0U; uint32_t levelCount = 1U; + uint32_t baseLayer = 0U; + uint32_t layerCount = 1U; uint32_t basePlane = 0U; uint32_t planeCount = 0U; + GLenum glTarget{0}; }; using GLES3GPUTextureViewList = ccstd::vector; @@ -574,7 +576,8 @@ class GLES3GPUFramebufferCacheMap final { } } - GLuint getFramebufferFromTexture(const GLES3GPUTexture *gpuTexture, const TextureSubresLayers &subres) { + GLuint getFramebufferFromTexture(const GLES3GPUTextureView *gpuTextureView, const TextureSubresLayers &subres) { + const auto *gpuTexture = gpuTextureView->gpuTexture; bool isTexture = gpuTexture->glTexture; GLuint glResource = isTexture ? gpuTexture->glTexture : gpuTexture->glRenderbuffer; auto &cacheMap = isTexture ? _textureMap : _renderbufferMap; @@ -601,9 +604,9 @@ class GLES3GPUFramebufferCacheMap final { attachment = GL_DEPTH_ATTACHMENT; } if (isTexture) { - GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, gpuTexture->glTarget, glResource, mipLevel)); + GL_CHECK(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, gpuTextureView->glTarget, glResource, mipLevel)); } else { - GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, attachment, gpuTexture->glTarget, glResource)); + GL_CHECK(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, attachment, GL_RENDERBUFFER, glResource)); } GLenum status; diff --git a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp index c409f6023a8..86219e7e151 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp @@ -143,10 +143,10 @@ void GLES3PrimaryCommandBuffer::resolveTexture(Texture *srcTexture, Texture *dst } void GLES3PrimaryCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTexture, const TextureCopy *regions, uint32_t count) { - GLES3GPUTexture *gpuTextureSrc = nullptr; - GLES3GPUTexture *gpuTextureDst = nullptr; - if (srcTexture) gpuTextureSrc = static_cast(srcTexture)->gpuTexture(); - if (dstTexture) gpuTextureDst = static_cast(dstTexture)->gpuTexture(); + GLES3GPUTextureView *gpuTextureSrc = nullptr; + GLES3GPUTextureView *gpuTextureDst = nullptr; + if (srcTexture) gpuTextureSrc = static_cast(srcTexture)->gpuTextureView(); + if (dstTexture) gpuTextureDst = static_cast(dstTexture)->gpuTextureView(); ccstd::vector blitRegions(count); for (uint32_t i = 0; i < count; ++i) { @@ -166,10 +166,10 @@ void GLES3PrimaryCommandBuffer::copyTexture(Texture *srcTexture, Texture *dstTex } void GLES3PrimaryCommandBuffer::blitTexture(Texture *srcTexture, Texture *dstTexture, const TextureBlit *regions, uint32_t count, Filter filter) { - GLES3GPUTexture *gpuTextureSrc = nullptr; - GLES3GPUTexture *gpuTextureDst = nullptr; - if (srcTexture) gpuTextureSrc = static_cast(srcTexture)->gpuTexture(); - if (dstTexture) gpuTextureDst = static_cast(dstTexture)->gpuTexture(); + GLES3GPUTextureView *gpuTextureSrc = nullptr; + GLES3GPUTextureView *gpuTextureDst = nullptr; + if (srcTexture) gpuTextureSrc = static_cast(srcTexture)->gpuTextureView(); + if (dstTexture) gpuTextureDst = static_cast(dstTexture)->gpuTextureView(); cmdFuncGLES3BlitTexture(GLES3Device::getInstance(), gpuTextureSrc, gpuTextureDst, regions, count, filter); } diff --git a/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp b/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp index 2026ec3d019..2bab251e70b 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Texture.cpp @@ -95,8 +95,12 @@ void GLES3Texture::createTextureView() { _gpuTextureView->format = _viewInfo.format; _gpuTextureView->baseLevel = _viewInfo.baseLevel; _gpuTextureView->levelCount = _viewInfo.levelCount; + _gpuTextureView->baseLayer = _viewInfo.baseLayer; + _gpuTextureView->layerCount = _viewInfo.layerCount; _gpuTextureView->basePlane = _viewInfo.basePlane; _gpuTextureView->planeCount = _viewInfo.planeCount; + cmdFuncGLES3CreateTextureView(GLES3Device::getInstance(), _gpuTextureView); + } void GLES3Texture::doDestroy() { From 8403962f94d256a56243bb1ef751b713a0e6571d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 14 Aug 2023 10:29:38 +0800 Subject: [PATCH 089/184] AnimationGraph: fix clip overriding in nested structure (#15932) * Bug introduce FF * Fix clip overriding in animation graph * Fix lint * Fix lint --- .../marionette/animation-graph-context.ts | 6 ++- cocos/animation/marionette/graph-eval.ts | 8 ++-- .../marionette/motion/animation-blend-1d.ts | 17 ++++--- .../marionette/motion/animation-blend-2d.ts | 9 +--- .../motion/animation-blend-direct.ts | 2 - .../marionette/motion/animation-blend.ts | 24 +++------- .../marionette/motion/clip-motion.ts | 14 +++--- cocos/animation/marionette/motion/motion.ts | 7 +-- .../pose-graph/default-top-level-pose-node.ts | 9 +--- .../pose-graph/pose-nodes/play-motion.ts | 2 +- .../pose-graph/pose-nodes/sample-motion.ts | 11 +++-- .../pose-graph/pose-nodes/state-machine.ts | 1 - .../state-machine/state-machine-eval.ts | 22 ++++----- editor/src/marionette/preview.ts | 2 +- .../pose-nodes/state-machine-node.test.ts | 46 +++++++++++++++++++ .../animation/new-gen-anim/utils/eval-mock.ts | 3 +- 16 files changed, 104 insertions(+), 79 deletions(-) diff --git a/cocos/animation/marionette/animation-graph-context.ts b/cocos/animation/marionette/animation-graph-context.ts index 2072fb19444..ea090ca4bac 100644 --- a/cocos/animation/marionette/animation-graph-context.ts +++ b/cocos/animation/marionette/animation-graph-context.ts @@ -289,10 +289,12 @@ const checkBindStatus = (bindStarted = false): MethodDecorator => (_, _propertyK if (vendor) { // eslint-disable-next-line func-names descriptor.value = function (this: { readonly _bindStarted: boolean }, ...args: unknown[]): any { - assertIsTrue(this._bindStarted === bindStarted, + assertIsTrue( + this._bindStarted === bindStarted, bindStarted ? `The operation is invalid since bind has not been started.` - : `The operation is invalid since bind has already been started.`); + : `The operation is invalid since bind has already been started.`, + ); // eslint-disable-next-line @typescript-eslint/no-unsafe-return return vendor.call(this, ...args); }; diff --git a/cocos/animation/marionette/graph-eval.ts b/cocos/animation/marionette/graph-eval.ts index 52558d27d7f..997f5871795 100644 --- a/cocos/animation/marionette/graph-eval.ts +++ b/cocos/animation/marionette/graph-eval.ts @@ -80,9 +80,7 @@ export class AnimationGraphEval { const poseLayoutMaintainer = new AnimationGraphPoseLayoutMaintainer(root, this._auxiliaryCurveRegistry); this._poseLayoutMaintainer = poseLayoutMaintainer; - const bindingContext = new AnimationGraphBindingContext( - root, poseLayoutMaintainer, this._varInstances, controller, - ); + const bindingContext = new AnimationGraphBindingContext(root, poseLayoutMaintainer, this._varInstances, controller); bindingContext._setClipOverrides(clipOverrides ?? undefined); this._bindingContext = bindingContext; @@ -97,7 +95,6 @@ export class AnimationGraphEval { this._rootPoseNode = new DefaultTopLevelPoseNode( graph, bindingContext, - clipOverrides, poseStashAllocator, ); @@ -221,7 +218,8 @@ export class AnimationGraphEval { poseLayoutMaintainer.startBind(); - this._rootPoseNode.overrideClips(overrides, this._bindingContext); + this._bindingContext._setClipOverrides(overrides); + this._rootPoseNode.overrideClips(this._bindingContext); this._updateAfterPossiblePoseLayoutChange(); } diff --git a/cocos/animation/marionette/motion/animation-blend-1d.ts b/cocos/animation/marionette/motion/animation-blend-1d.ts index 27499753ad7..1e609a29cb7 100644 --- a/cocos/animation/marionette/motion/animation-blend-1d.ts +++ b/cocos/animation/marionette/motion/animation-blend-1d.ts @@ -80,12 +80,15 @@ export class AnimationBlend1D extends AnimationBlend { public [createEval] ( context: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, ): any { const evaluation = new AnimationBlend1DEval( - context, clipOverrides, ignoreEmbeddedPlayers, - this, this._items, this._items.map(({ threshold }) => threshold), 0.0, + context, + ignoreEmbeddedPlayers, + this, + this._items, + this._items.map(({ threshold }) => threshold), + 0.0, ); const initialValue = bindOr( context, @@ -109,11 +112,13 @@ class AnimationBlend1DEval extends AnimationBlendEval { constructor ( context: AnimationGraphBindingContext, - overrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, - base: AnimationBlend, items: AnimationBlendItem[], thresholds: readonly number[], input: number, + base: AnimationBlend, + items: AnimationBlendItem[], + thresholds: readonly number[], + input: number, ) { - super(context, overrides, ignoreEmbeddedPlayers, base, items, [input]); + super(context, ignoreEmbeddedPlayers, base, items, [input]); this._thresholds = thresholds; this.doEval(); } diff --git a/cocos/animation/marionette/motion/animation-blend-2d.ts b/cocos/animation/marionette/motion/animation-blend-2d.ts index b4ce6ab9a16..40b4f822a2e 100644 --- a/cocos/animation/marionette/motion/animation-blend-2d.ts +++ b/cocos/animation/marionette/motion/animation-blend-2d.ts @@ -116,7 +116,6 @@ export class AnimationBlend2D extends AnimationBlend { public [createEval] ( context: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, ): AnimationBlendEval { const { algorithm } = this; @@ -126,7 +125,6 @@ export class AnimationBlend2D extends AnimationBlend { assertIsTrue(this._polarSpaceGBI, `The polar space interpolator is not setup correctly!`); evaluation = new PolarSpaceGradientBandBlend2DEval( context, - clipOverrides, ignoreEmbeddedPlayers, this, this._items, @@ -141,7 +139,6 @@ export class AnimationBlend2D extends AnimationBlend { case Algorithm.FREEFORM_CARTESIAN: evaluation = new AnimationBlend2DEval( context, - clipOverrides, ignoreEmbeddedPlayers, this, this._items, @@ -200,7 +197,6 @@ class AnimationBlend2DEval extends AnimationBlendEval { constructor ( context: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, base: AnimationBlend, items: AnimationBlendItem[], @@ -208,7 +204,7 @@ class AnimationBlend2DEval extends AnimationBlendEval { algorithm: Algorithm.SIMPLE_DIRECTIONAL | Algorithm.FREEFORM_CARTESIAN, inputs: [number, number], ) { - super(context, clipOverrides, ignoreEmbeddedPlayers, base, items, inputs); + super(context, ignoreEmbeddedPlayers, base, items, inputs); this._thresholds = thresholds; this._algorithm = algorithm; this.doEval(); @@ -236,14 +232,13 @@ class PolarSpaceGradientBandBlend2DEval extends AnimationBlendEval { constructor ( context: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, base: AnimationBlend, items: AnimationBlendItem[], interpolator: PolarSpaceGradientBandInterpolator2D, inputs: [number, number], ) { - super(context, clipOverrides, ignoreEmbeddedPlayers, base, items, inputs); + super(context, ignoreEmbeddedPlayers, base, items, inputs); this._interpolator = interpolator; this.doEval(); } diff --git a/cocos/animation/marionette/motion/animation-blend-direct.ts b/cocos/animation/marionette/motion/animation-blend-direct.ts index 0a59f8d8f3e..ce53ebbf2bc 100644 --- a/cocos/animation/marionette/motion/animation-blend-direct.ts +++ b/cocos/animation/marionette/motion/animation-blend-direct.ts @@ -74,12 +74,10 @@ export class AnimationBlendDirect extends AnimationBlend { public [createEval] ( context: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, ): AnimationBlendDirectEval { const myEval: AnimationBlendDirectEval = new AnimationBlendDirectEval( context, - clipOverrides, ignoreEmbeddedPlayers, this, this._items, diff --git a/cocos/animation/marionette/motion/animation-blend.ts b/cocos/animation/marionette/motion/animation-blend.ts index 9162838c109..cfe62a039bf 100644 --- a/cocos/animation/marionette/motion/animation-blend.ts +++ b/cocos/animation/marionette/motion/animation-blend.ts @@ -27,7 +27,6 @@ import { Motion, MotionEval, MotionPort } from './motion'; import { createEval } from '../create-eval'; import { VariableTypeMismatchedError } from '../errors'; import { ClipStatus } from '../state-machine/state-machine-eval'; -import type { ReadonlyClipOverrideMap } from '../clip-overriding'; import { CLASS_NAME_PREFIX_ANIM } from '../../define'; import { getMotionRuntimeID, RUNTIME_ID_ENABLED } from '../graph-debug'; @@ -37,14 +36,6 @@ import { blendPoseInto, Pose } from '../../core/pose'; const { ccclass, serializable } = _decorator; -export interface AnimationBlend extends Motion, EditorExtendable { - [createEval] ( - _context: AnimationGraphBindingContext, - overrides: ReadonlyClipOverrideMap | null, - ignoreEmbeddedPlayers: boolean, - ): MotionEval | null; -} - @ccclass(`${CLASS_NAME_PREFIX_ANIM}AnimationBlendItem`) export class AnimationBlendItem { @serializable @@ -73,7 +64,7 @@ export abstract class AnimationBlend extends Motion { } } -export class AnimationBlendEval implements MotionEval { +export abstract class AnimationBlendEval implements MotionEval { public declare runtimeId?: number; private declare _childEvaluators: (MotionEval | null)[]; @@ -82,13 +73,12 @@ export class AnimationBlendEval implements MotionEval { constructor ( context: AnimationGraphBindingContext, - overrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, base: AnimationBlend, children: AnimationBlendItem[], inputs: number[], ) { - this._childEvaluators = children.map((child) => child.motion?.[createEval](context, overrides, ignoreEmbeddedPlayers) ?? null); + this._childEvaluators = children.map((child) => child.motion?.[createEval](context, ignoreEmbeddedPlayers) ?? null); this._weights = new Array(this._childEvaluators.length).fill(0); this._inputs = [...inputs]; if (RUNTIME_ID_ENABLED) { @@ -180,9 +170,9 @@ export class AnimationBlendEval implements MotionEval { return context.pushDefaultedPose(); } - public overrideClips (overrides: ReadonlyClipOverrideMap, context: AnimationGraphBindingContext): void { + public overrideClips (context: AnimationGraphBindingContext): void { for (let iChild = 0; iChild < this._childEvaluators.length; ++iChild) { - this._childEvaluators[iChild]?.overrideClips(overrides, context); + this._childEvaluators[iChild]?.overrideClips(context); } } @@ -195,9 +185,7 @@ export class AnimationBlendEval implements MotionEval { this.eval(this._weights, this._inputs); } - protected eval (_weights: number[], _inputs: readonly number[]): void { - - } + protected abstract eval (_weights: number[], _inputs: readonly number[]): void; } class AnimationBlendPort implements MotionPort { @@ -212,7 +200,7 @@ class AnimationBlendPort implements MotionPort { return this._host.__evaluatePort(this, progress, context); } - public reenter () { + public reenter (): void { const { childPorts } = this; const nChildPorts = childPorts.length; for (let iChild = 0; iChild < nChildPorts; ++iChild) { diff --git a/cocos/animation/marionette/motion/clip-motion.ts b/cocos/animation/marionette/motion/clip-motion.ts index def4d6ca5af..8cfce0db347 100644 --- a/cocos/animation/marionette/motion/clip-motion.ts +++ b/cocos/animation/marionette/motion/clip-motion.ts @@ -48,13 +48,12 @@ export class ClipMotion extends Motion { public [createEval] ( context: AnimationGraphBindingContext, - overrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, ): ClipMotionEval | null { if (!this.clip) { return null; } - const clipMotionEval = new ClipMotionEval(context, this.clip, overrides, ignoreEmbeddedPlayers); + const clipMotionEval = new ClipMotionEval(context, this.clip, ignoreEmbeddedPlayers); if (RUNTIME_ID_ENABLED) { clipMotionEval.runtimeId = getMotionRuntimeID(this); } @@ -82,12 +81,11 @@ class ClipMotionEval implements MotionEval { constructor ( context: AnimationGraphBindingContext, clip: AnimationClip, - clipOverrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, ) { this._originalClip = clip; this._ignoreEmbeddedPlayers = ignoreEmbeddedPlayers; - const overriding = clipOverrides?.get(clip) ?? clip; + const overriding = context.clipOverrides?.get(clip) ?? clip; this._setClip(overriding, context); } @@ -160,15 +158,15 @@ class ClipMotionEval implements MotionEval { return pose; } - public overrideClips (clipOverrides: ReadonlyClipOverrideMap, context: AnimationGraphBindingContext): void { + public overrideClips (context: AnimationGraphBindingContext): void { const { _originalClip: originalClip } = this; - const overriding = clipOverrides.get(originalClip); + const overriding = context.clipOverrides?.get(originalClip); if (overriding) { this._setClip(overriding, context); } } - public reenter () { + public reenter (): void { this._frameEventEval?.reset(); } @@ -216,7 +214,7 @@ class ClipMotionPort implements MotionPort { return this._eval[evaluatePortTag](progress, context); } - public reenter () { + public reenter (): void { this._eval.reenter(); } diff --git a/cocos/animation/marionette/motion/motion.ts b/cocos/animation/marionette/motion/motion.ts index d6084f3db26..f22a3195a4f 100644 --- a/cocos/animation/marionette/motion/motion.ts +++ b/cocos/animation/marionette/motion/motion.ts @@ -58,7 +58,7 @@ export interface MotionEval { getClipStatuses(baseWeight: number): Iterator; - overrideClips(clipOverrides: ReadonlyClipOverrideMap, context: AnimationGraphBindingContext): void; + overrideClips(context: AnimationGraphBindingContext): void; createPort(): MotionPort; } @@ -69,7 +69,6 @@ export interface MotionEval { export abstract class Motion extends EditorExtendable { abstract [createEval] ( context: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, ignoreEmbeddedPlayers: boolean, ): MotionEval | null; @@ -79,7 +78,9 @@ export abstract class Motion extends EditorExtendable { * // TODO: HACK * @internal */ - __callOnAfterDeserializeRecursive (): void { } + __callOnAfterDeserializeRecursive (): void { + // Can be overrode in subclasses. + } } export interface MotionPort { diff --git a/cocos/animation/marionette/pose-graph/default-top-level-pose-node.ts b/cocos/animation/marionette/pose-graph/default-top-level-pose-node.ts index 47396c48a76..bf57c6b5f46 100644 --- a/cocos/animation/marionette/pose-graph/default-top-level-pose-node.ts +++ b/cocos/animation/marionette/pose-graph/default-top-level-pose-node.ts @@ -4,7 +4,6 @@ import { AnimationGraph, Layer } from '../animation-graph'; import { AnimationGraphBindingContext, AnimationGraphEvaluationContext, AnimationGraphSettleContext, AnimationGraphUpdateContext } from '../animation-graph-context'; import { AnimationMask } from '../animation-mask'; -import { ReadonlyClipOverrideMap } from '../clip-overriding'; import { TopLevelStateMachineEvaluation } from '../state-machine/state-machine-eval'; import { PoseNode } from './pose-node'; import { RuntimeMotionSyncManager } from './motion-sync/runtime-motion-sync'; @@ -14,7 +13,6 @@ export class DefaultTopLevelPoseNode extends PoseNode { constructor ( graph: AnimationGraph, bindingContext: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, poseStashAllocator: PoseStashAllocator, ) { super(); @@ -23,7 +21,6 @@ export class DefaultTopLevelPoseNode extends PoseNode { const record = new LayerEvaluationRecord( layer, bindingContext, - clipOverrides, poseStashAllocator, ); @@ -69,13 +66,13 @@ export class DefaultTopLevelPoseNode extends PoseNode { return this._layerRecords[layerIndex].stateMachineEvaluation; } - public overrideClips (overrides: ReadonlyClipOverrideMap, context: AnimationGraphBindingContext): void { + public overrideClips (context: AnimationGraphBindingContext): void { const { _layerRecords: layerRecords } = this; const nLayers = layerRecords.length; for (let iLayer = 0; iLayer < nLayers; ++iLayer) { const layerRecord = layerRecords[iLayer]; context._pushAdditiveFlag(layerRecord.additive); - layerRecord.stateMachineEvaluation.overrideClips(overrides, context); + layerRecord.stateMachineEvaluation.overrideClips(context); context._popAdditiveFlag(); } } @@ -116,7 +113,6 @@ class LayerEvaluationRecord { constructor ( layer: Layer, bindingContext: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, poseStashAllocator: PoseStashAllocator, ) { const stashManager = new RuntimeStashManager(poseStashAllocator); @@ -145,7 +141,6 @@ class LayerEvaluationRecord { layer.stateMachine, layer.name, bindingContext, - clipOverrides, ); bindingContext._popAdditiveFlag(); diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/play-motion.ts b/cocos/animation/marionette/pose-graph/pose-nodes/play-motion.ts index 78e8b8b3c5f..9560ac9a3fe 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/play-motion.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/play-motion.ts @@ -69,7 +69,7 @@ export class PoseNodePlayMotion extends PoseNode { if (!motion) { return; } - const motionEval = motion[createEval](context, context.clipOverrides ?? null, false); + const motionEval = motion[createEval](context, false); if (!motionEval) { return; } diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/sample-motion.ts b/cocos/animation/marionette/pose-graph/pose-nodes/sample-motion.ts index 7e8fb921505..fac5e8fe16f 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/sample-motion.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/sample-motion.ts @@ -43,7 +43,7 @@ export class PoseNodeSampleMotion extends PoseNode { if (!motion) { return; } - const motionEval = motion[createEval](context, context.clipOverrides ?? null, true); + const motionEval = motion[createEval](context, true); if (!motionEval) { return; } @@ -51,11 +51,16 @@ export class PoseNodeSampleMotion extends PoseNode { this._workspace = workspace; } - public settle (context: AnimationGraphSettleContext): void { } + public settle (context: AnimationGraphSettleContext): void { + // Do nothing. + } - public reenter (): void { } + public reenter (): void { + // Do nothing. + } protected doUpdate (context: AnimationGraphUpdateContext): void { + // Do nothing. } protected doEvaluate (context: AnimationGraphEvaluationContext): Pose { diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/state-machine.ts b/cocos/animation/marionette/pose-graph/pose-nodes/state-machine.ts index bd88711ab4d..35e0122e9f1 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/state-machine.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/state-machine.ts @@ -42,7 +42,6 @@ export class PoseNodeStateMachine extends PoseNode { this.stateMachine, '', context, - null, ); } diff --git a/cocos/animation/marionette/state-machine/state-machine-eval.ts b/cocos/animation/marionette/state-machine/state-machine-eval.ts index 56114bff2a1..9536abb54f4 100644 --- a/cocos/animation/marionette/state-machine/state-machine-eval.ts +++ b/cocos/animation/marionette/state-machine/state-machine-eval.ts @@ -119,7 +119,6 @@ class TopLevelStateMachineEvaluation { stateMachine: StateMachine, name: string, context: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, ) { this._additive = context.additive; this.name = name; @@ -128,7 +127,6 @@ class TopLevelStateMachineEvaluation { stateMachine, null, context, - clipOverrides, name, ); this._topLevelEntry = entry; @@ -252,12 +250,12 @@ class TopLevelStateMachineEvaluation { } } - public overrideClips (overrides: ReadonlyClipOverrideMap, context: AnimationGraphBindingContext): void { + public overrideClips (context: AnimationGraphBindingContext): void { const { _motionStates: motionStates } = this; const nMotionStates = motionStates.length; for (let iMotionState = 0; iMotionState < nMotionStates; ++iMotionState) { const node = motionStates[iMotionState]; - node.overrideClips(overrides, context); + node.overrideClips(context); } } @@ -285,7 +283,6 @@ class TopLevelStateMachineEvaluation { graph: StateMachine, parentStateMachineInfo: StateMachineInfo | null, context: AnimationGraphBindingContext, - clipOverrides: ReadonlyClipOverrideMap | null, __DEBUG_ID__: string, ): StateMachineInfo { const nodes = Array.from(graph.states()); @@ -296,7 +293,7 @@ class TopLevelStateMachineEvaluation { const nodeEvaluations = nodes.map((node): NodeEval | VMSMEval | null => { if (node instanceof MotionState) { - const motionStateEval = new VMSMEval(node, context, clipOverrides); + const motionStateEval = new VMSMEval(node, context); this._motionStates.push(motionStateEval); return motionStateEval; } else if (node === graph.entryState) { @@ -342,7 +339,6 @@ class TopLevelStateMachineEvaluation { node.stateMachine, stateMachineInfo, context, - clipOverrides, `${__DEBUG_ID__}/${node.name}`, ); subStateMachineInfo.components = new InstantiatedComponents(node); @@ -682,9 +678,7 @@ class TopLevelStateMachineEvaluation { * * @returns The transition matched, or null if there's no matched transition. */ - private _matchTransition ( - node: NodeEval, realNode: NodeEval, - ): TransitionEval | null { + private _matchTransition (node: NodeEval, realNode: NodeEval): TransitionEval | null { assertIsTrue(node === realNode || node.kind === NodeKind.any); const { _conditionEvaluationContext: conditionEvaluationContext } = this; @@ -1214,7 +1208,7 @@ interface StateMachineInfo { * Track the evaluation of a virtual motion state-machine. */ class VMSMEval { - constructor (state: MotionState, context: AnimationGraphBindingContext, overrides: ReadonlyClipOverrideMap | null) { + constructor (state: MotionState, context: AnimationGraphBindingContext) { const name = state.name; this._baseSpeed = state.speed; @@ -1231,7 +1225,7 @@ class VMSMEval { } } - const sourceEval = state.motion?.[createEval](context, overrides, false) ?? null; + const sourceEval = state.motion?.[createEval](context, false) ?? null; if (sourceEval) { Object.defineProperty(sourceEval, '__DEBUG_ID__', { value: name }); } @@ -1298,8 +1292,8 @@ class VMSMEval { } } - public overrideClips (overrides: ReadonlyClipOverrideMap, context: AnimationGraphBindingContext): void { - this._source?.overrideClips(overrides, context); + public overrideClips (context: AnimationGraphBindingContext): void { + this._source?.overrideClips(context); } private _source: MotionEval | null = null; diff --git a/editor/src/marionette/preview.ts b/editor/src/marionette/preview.ts index c7b8d2f16ce..b0b92d39d38 100644 --- a/editor/src/marionette/preview.ts +++ b/editor/src/marionette/preview.ts @@ -432,7 +432,7 @@ class MotionEvalRecord { } public rebind(bindContext: AnimationGraphBindingContext) { - const motionEval = this._motion[createEval](bindContext, null, true); + const motionEval = this._motion[createEval](bindContext, true); if (!motionEval) { return; diff --git a/tests/animation/new-gen-anim/pose-graph/pose-nodes/state-machine-node.test.ts b/tests/animation/new-gen-anim/pose-graph/pose-nodes/state-machine-node.test.ts index c58704f9fd3..692043569bb 100644 --- a/tests/animation/new-gen-anim/pose-graph/pose-nodes/state-machine-node.test.ts +++ b/tests/animation/new-gen-anim/pose-graph/pose-nodes/state-machine-node.test.ts @@ -1,4 +1,5 @@ import { AnimationController } from "../../../../../cocos/animation/animation"; +import { AnimationGraphVariant } from "../../../../../cocos/animation/marionette/animation-graph-variant"; import { lerp } from "../../../../../exports/base"; import { AnimationGraphEvalMock } from "../../utils/eval-mock"; import { createAnimationGraph, StateMachineParams, VariableDeclarationParams } from "../../utils/factory"; @@ -187,4 +188,49 @@ describe(`Reentering`, () => { }, }; } +}); + +test(`Clip overriding in state machine node`, () => { + const fixture = { + animation_1: new LinearRealValueAnimationFixture(1., 2., 3.), + animation_2: new LinearRealValueAnimationFixture(-0.5, -3, 1), + }; + + const valueObserver = new SingleRealValueObserver(); + + const motion1 = fixture.animation_1.createMotion(valueObserver.getCreateMotionContext()); + const motion2 = fixture.animation_2.createMotion(valueObserver.getCreateMotionContext()); + + const animationGraph = createAnimationGraph({ + layers: [{ + // Outer SM. + stateMachine: { + entryTransitions: [{ to: 'innerSM' }], + states: { + 'innerSM': { + type: 'procedural', + graph: { + rootNode: { + 'type': 'state-machine', + // Inner SM. + stateMachine: { + entryTransitions: [{ to: 'm' }], + states: { 'm': { type: 'motion', motion: motion1 } }, + }, + }, + }, + }, + }, + }, + }], + }); + + const animationGraphVariant = new AnimationGraphVariant(); + animationGraphVariant.original = animationGraph; + animationGraphVariant.clipOverrides.set(motion1.clip, motion2.clip); + + const evalMock = new AnimationGraphEvalMock(valueObserver.root, animationGraphVariant); + + evalMock.step(fixture.animation_2.duration * 0.3); + expect(valueObserver.value).toBeCloseTo(fixture.animation_2.getExpected(evalMock.current), 5); }); \ No newline at end of file diff --git a/tests/animation/new-gen-anim/utils/eval-mock.ts b/tests/animation/new-gen-anim/utils/eval-mock.ts index 4cad7f4403b..6919ee07416 100644 --- a/tests/animation/new-gen-anim/utils/eval-mock.ts +++ b/tests/animation/new-gen-anim/utils/eval-mock.ts @@ -1,12 +1,13 @@ import { AnimationController } from "../../../../cocos/animation/animation"; import { AnimationGraph } from "../../../../cocos/animation/marionette/animation-graph"; +import { AnimationGraphVariant } from "../../../../cocos/animation/marionette/animation-graph-variant"; import { AnimationGraphEval } from "../../../../cocos/animation/marionette/graph-eval"; import { Node } from "../../../../cocos/scene-graph"; export class AnimationGraphEvalMock { constructor( node: Node, - animationGraph: AnimationGraph, + animationGraph: AnimationGraph | AnimationGraphVariant, ) { const controller = node.addComponent(AnimationController) as AnimationController; this._controller = controller; From 4ca3c88d8d465c425582ef18f16a630ef36fe7b7 Mon Sep 17 00:00:00 2001 From: bofeng-song Date: Mon, 14 Aug 2023 10:48:24 +0800 Subject: [PATCH 090/184] Fix the issue on some platform, the audio cannot start playing at the exact position after calling stop and then seek (#15924) * Fix the issue On the Huawei platform, the audio cannot start playing at the exact position after calling stop and then seek --- pal/audio/minigame/player-minigame.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pal/audio/minigame/player-minigame.ts b/pal/audio/minigame/player-minigame.ts index d2f81712c3f..cecf6e83231 100644 --- a/pal/audio/minigame/player-minigame.ts +++ b/pal/audio/minigame/player-minigame.ts @@ -24,7 +24,7 @@ import { minigame } from 'pal/minigame'; import { systemInfo } from 'pal/system-info'; -import { TAOBAO, TAOBAO_MINIGAME } from 'internal:constants'; +import { TAOBAO, TAOBAO_MINIGAME, HUAWEI, VIVO, OPPO } from 'internal:constants'; import { EventTarget } from '../../../cocos/core/event'; import { AudioEvent, AudioPCMDataView, AudioState, AudioType } from '../type'; import { clamp, clamp01 } from '../../../cocos/core'; @@ -107,6 +107,9 @@ export class AudioPlayerMinigame implements OperationQueueable { this._cacheTime = 0; this._needSeek = false; this._seeking = false; + if ((HUAWEI || VIVO || OPPO) && this._innerAudioContext) { + this._innerAudioContext.startTime = 0; + } } /** * @deprecated since v3.5.0, this is an engine private interface that will be removed in the future. @@ -168,11 +171,9 @@ export class AudioPlayerMinigame implements OperationQueueable { this._seeking = false; if (this._needSeek) { this._needSeek = false; - if (this._cacheTime.toFixed(3) !== this._innerAudioContext.currentTime.toFixed(3)) { + if (this._cacheTime.toFixed(2) !== this._innerAudioContext.currentTime.toFixed(2)) { // eslint-disable-next-line @typescript-eslint/no-empty-function this.seek(this._cacheTime).catch((e) => {}); - } else { - this._needSeek = false; } } }; @@ -304,6 +305,9 @@ export class AudioPlayerMinigame implements OperationQueueable { return this._innerAudioContext.duration; } get currentTime (): number { + if ((HUAWEI || VIVO || OPPO) && (this._state === AudioState.STOPPED || this._state === AudioState.INIT)) { + return this._innerAudioContext.startTime; + } if (this._state !== AudioState.PLAYING || this._needSeek || this._seeking) { return this._cacheTime; } @@ -328,7 +332,10 @@ export class AudioPlayerMinigame implements OperationQueueable { this._eventTarget.once(AudioEvent.SEEKED, resolve); this._innerAudioContext.seek(time); } else { - if (this._cacheTime !== time) { // Skip the invalid seek + //Huawei, vivo, Oppo platform, after stop, regardless of whether the seek has been called, the playback will always start from 0 again + if ((HUAWEI || VIVO || OPPO) && (this._state === AudioState.STOPPED || this._state === AudioState.INIT)) { + this._innerAudioContext.startTime = time; + } else if (this._cacheTime !== time) { // Skip the invalid seek this._cacheTime = time; this._needSeek = true; } From 6d04a1477a00d1ebb0672cb34ebe6b94c1e1e5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 14 Aug 2023 11:38:52 +0800 Subject: [PATCH 091/184] Re-support non-transform animation in animation graph (#15842) --- .../animation-graph-animation-clip-binding.ts | 49 +++++- tests/animation/newgenanim.test.ts | 157 +++++++++++++++++- 2 files changed, 195 insertions(+), 11 deletions(-) diff --git a/cocos/animation/marionette/animation-graph-animation-clip-binding.ts b/cocos/animation/marionette/animation-graph-animation-clip-binding.ts index 0c2ab2d0297..4d01923400b 100644 --- a/cocos/animation/marionette/animation-graph-animation-clip-binding.ts +++ b/cocos/animation/marionette/animation-graph-animation-clip-binding.ts @@ -8,7 +8,7 @@ import { AuxiliaryCurveHandle, TransformHandle } from '../core/animation-handle' import { calculateDeltaPose, Pose } from '../core/pose'; import { createEvalSymbol } from '../define'; import { ExoticTrsAGEvaluation } from '../exotic-animation/exotic-animation'; -import { isTrsPropertyName, normalizedFollowTag, Track, TrackBinding, trackBindingTag, TrackEval } from '../tracks/track'; +import { isTrsPropertyName, normalizedFollowTag, RuntimeBinding, Track, TrackBinding, trackBindingTag, TrackEval } from '../tracks/track'; import { UntypedTrack } from '../tracks/untyped-track'; import { AnimationGraphEvaluationContext } from './animation-graph-context'; @@ -204,6 +204,26 @@ function bindPoseTransform ( } } +class NonTransformPoseBinding implements PoseBinding { + constructor ( + public readonly binding: RuntimeBinding, + ) { + + } + + destroy (): void { + // Needs no destroy. + } + + setValue (value: any, _pose: Pose): void { + this.binding.setValue(value); + } + + getValue (pose: Pose): any { + return this.binding.getValue?.() ?? undefined; + } +} + /** * Describes the evaluation of a animation clip track in sense of animation graph. */ @@ -230,7 +250,11 @@ class AGTrackEvaluation { private _trackSampler: TrackEval; } -function bindTrackAG (animationClip: AnimationClip, track: Track, bindContext: AnimationClipGraphBindingContext): PoseBinding | undefined { +function bindTrackAG ( + animationClip: AnimationClip, + track: Track, + bindContext: AnimationClipGraphBindingContext, +): PoseBinding | undefined { const trackBinding = track[trackBindingTag]; const trackTarget = createRuntimeBindingAG(trackBinding, bindContext); if (DEBUG && !trackTarget) { @@ -247,7 +271,10 @@ function bindTrackAG (animationClip: AnimationClip, track: Track, bindContext: A return trackTarget ?? undefined; } -function createRuntimeBindingAG (track: TrackBinding, bindContext: AnimationClipGraphBindingContext): PoseBinding | null | undefined { +function createRuntimeBindingAG ( + track: TrackBinding, + bindContext: AnimationClipGraphBindingContext, +): PoseBinding | null | undefined { const { origin, } = bindContext; @@ -288,10 +315,16 @@ function createRuntimeBindingAG (track: TrackBinding, bindContext: AnimationClip } } - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // TODO: here should be resolved before this can be landed. - error(`Animation graph currently only supports (bone) transform animations.`); - return undefined; + // If this path does not aim a transform target, + // we create `NonTransformPoseBinding` using default binding. + { + const nonTransformBinding = track.createRuntimeBinding(bindContext.origin, undefined, false); + if (!nonTransformBinding) { + return null; + } + + return new NonTransformPoseBinding(nonTransformBinding); + } } class AuxiliaryCurveEvaluation { @@ -363,7 +396,7 @@ class AnimationClipAGEvaluationRegular implements AnimationClipAGEvaluation { for (const track of tracks) { if (track instanceof UntypedTrack) { - // Untyped track is not supported in AG. + // Untyped track is not supported in AG. continue; } if (Array.from(track.channels()).every(({ curve }) => curve.keyFramesCount === 0)) { diff --git a/tests/animation/newgenanim.test.ts b/tests/animation/newgenanim.test.ts index b7b668ea281..f7234da60a8 100644 --- a/tests/animation/newgenanim.test.ts +++ b/tests/animation/newgenanim.test.ts @@ -10,7 +10,7 @@ import '../utils/matcher-deep-close-to'; import { BinaryCondition, UnaryCondition, TriggerCondition } from '../../cocos/animation/marionette/state-machine/condition'; import { AnimationController } from '../../cocos/animation/marionette/animation-controller'; import { StateMachineComponent } from '../../cocos/animation/marionette/state-machine/state-machine-component'; -import { VectorTrack } from '../../cocos/animation/animation'; +import { RealTrack, VectorTrack } from '../../cocos/animation/animation'; import 'jest-extended'; import { assertIsTrue } from '../../cocos/core/data/utils/asserts'; import { additiveSettingsTag, AnimationClip } from '../../cocos/animation/animation-clip'; @@ -19,12 +19,13 @@ import { MotionState } from '../../cocos/animation/marionette/state-machine/moti import { Node, Component } from '../../cocos/scene-graph'; import * as maskTestHelper from './new-gen-anim/utils/mask-test-helper'; import '../utils/matchers/value-type-asymmetric-matchers'; -import { AnimationBlend1DFixture, LinearRealValueAnimationFixture, ConstantRealValueAnimationFixture, RealValueAnimationFixture } from './new-gen-anim/utils/fixtures'; +import { AnimationBlend1DFixture, LinearRealValueAnimationFixture, ConstantRealValueAnimationFixture, RealValueAnimationFixture, CreateMotionContext } from './new-gen-anim/utils/fixtures'; import { NodeTransformValueObserver } from './new-gen-anim/utils/node-transform-value-observer'; import { SingleRealValueObserver } from './new-gen-anim/utils/single-real-value-observer'; import { createAnimationGraph, StateParams, TransitionParams } from './new-gen-anim/utils/factory'; import { captureWarns } from '../utils/log-capture'; -import { AnimationGraphEvalMock } from './new-gen-anim/utils/eval-mock'; +import { AnimationGraphEvalMock, generateIntervals } from './new-gen-anim/utils/eval-mock'; +import { ccclass } from '../../cocos/core/data/class-decorator'; /** * Notable changes @@ -5247,6 +5248,156 @@ describe('NewGen Anim', () => { return animationGraph; } }); + + describe(`Non-transform animation`, () => { + test(`Behavior in state machine`, () => { + /// In below: + /// - "tp" means "target property". + + const fixture = { + common_tp_default_value: 9, + animation_1: ((duration: number) => ({ + duration, + exclusive_tp_default_value: 3., + exclusive_animation: new LinearRealValueAnimationFixture(1, 2, duration), + common_animation: new LinearRealValueAnimationFixture(3, 4, duration), + }))(2.0), + animation_2: ((duration: number) => ({ + duration, + exclusive_tp_default_value: 2., + exclusive_animation: new LinearRealValueAnimationFixture(5, 6, duration), + common_animation: new LinearRealValueAnimationFixture(7, 8, duration), + }))(1.5), + transitionDuration: 0.3, + }; + + @ccclass('TargetObject') + class TargetObject extends Component { + tp_common = fixture.common_tp_default_value; + tp_anim_1_only = fixture.animation_1.exclusive_tp_default_value; + tp_anim_2_only = fixture.animation_2.exclusive_tp_default_value; + } + + const createMotion = (params: typeof fixture.animation_1, exclusive_tp_key: keyof TargetObject) => { + const clip = new AnimationClip(); + clip.duration = params.duration; + { + const track = new RealTrack(); + track.path.toComponent(TargetObject).toProperty('tp_common' as keyof TargetObject); + params.common_animation.setupCurve(track.channel.curve); + clip.addTrack(track); + } + { + const track = new RealTrack(); + track.path.toComponent(TargetObject).toProperty(exclusive_tp_key); + params.exclusive_animation.setupCurve(track.channel.curve); + clip.addTrack(track); + } + const clipMotion = new ClipMotion(); + clipMotion.clip = clip; + return clipMotion as NonNullableClipMotion; + }; + + const clipMotion1 = createMotion(fixture.animation_1, 'tp_anim_1_only'); + const clipMotion2 = createMotion(fixture.animation_2, 'tp_anim_2_only'); + const animationGraph = createAnimationGraph({ + variableDeclarations: { 'EnableTransition': { type: 'boolean' } }, + layers: [{ + stateMachine: { + entryTransitions: [{ to: 'motion1' }], + transitions: [{ + from: 'motion1', to: 'motion2', exitTimeEnabled: false, duration: fixture.transitionDuration, + conditions: [{ type: 'unary', operand: { type: 'variable', name: 'EnableTransition' }, operator: 'to-be-true' }], + }], + states: { + 'motion1': { type: 'motion', motion: clipMotion1, }, + 'motion2': { type: 'motion', motion: clipMotion2 }, + }, + }, + }], + }); + + const origin = new Node(); + + const targetObject = origin.addComponent(TargetObject) as TargetObject; + + const check = (() => { + let expected_common = fixture.common_tp_default_value; + let expected_anim_1_only = fixture.animation_1.exclusive_tp_default_value; + let expected_anim_2_only = fixture.animation_2.exclusive_tp_default_value; + + return ({ + common, + anim_1_only: anim_1_exclusive, + anim_2_only: anim_2_exclusive, + }: Partial<{ + common: number, + anim_1_only: number, + anim_2_only: number, + }>) => { + expected_common = common ?? expected_common; + expected_anim_1_only = anim_1_exclusive ?? expected_anim_1_only; + expected_anim_2_only = anim_2_exclusive ?? expected_anim_2_only; + expect(targetObject.tp_common).toBeCloseTo(expected_common, 5); + expect(targetObject.tp_anim_1_only).toBeCloseTo(expected_anim_1_only, 5); + expect(targetObject.tp_anim_2_only).toBeCloseTo(expected_anim_2_only, 5); + }; + })(); + + const evalMock = new AnimationGraphEvalMock(origin, animationGraph); + + check({}); + + // If no transition, the animation is normally sampled. + for (const [t] of generateIntervals(0.2, 0.7, 0.9)) { + evalMock.step(fixture.animation_1.duration * t); + + const tAnim = Math.min(evalMock.current, fixture.animation_1.duration); + check({ + anim_1_only: fixture.animation_1.exclusive_animation.getExpected(tAnim), + + common: fixture.animation_1.common_animation.getExpected(tAnim), + + // Not changed since anim2 is not playing. + anim_2_only: undefined, + }); + } + + // During transition or after transition finished. + evalMock.controller.setValue('EnableTransition', true); + const start_time_of_motion2_state = evalMock.current; + for (const [t] of generateIntervals(0.15, 0.88)) { + evalMock.step(fixture.transitionDuration * t); + + const tAnim = Math.min(evalMock.current - start_time_of_motion2_state, fixture.animation_1.duration); + check({ + // Anim1's exclusive property is not affected. + anim_1_only: fixture.animation_1.exclusive_animation.getExpected(Math.min(evalMock.current, fixture.animation_1.duration)), + + // But the common property is fully governed by anim2 instead. + common: fixture.animation_2.common_animation.getExpected(tAnim), + + anim_2_only: fixture.animation_2.exclusive_animation.getExpected(tAnim), + }); + } + + // After transition finished, only motion2 plays. + for (const [t] of generateIntervals(1.2, 1.5)) { + evalMock.step(fixture.transitionDuration * t); + + const tAnim = Math.min(evalMock.current - start_time_of_motion2_state, fixture.animation_1.duration); + check({ + // Not changed since anim2 is not playing. + anim_1_only: undefined, + + // But the common property is fully governed by anim2 instead. + common: fixture.animation_2.common_animation.getExpected(tAnim), + + anim_2_only: fixture.animation_2.exclusive_animation.getExpected(tAnim), + }); + } + }); + }); }); function assertivelyGetGraphVariable(graph: AnimationGraph, name: string) { From ac4fa7462467c0b25887976c5a6ef0001e995a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=88=98?= <40414978+PatriceJiang@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:40:13 +0800 Subject: [PATCH 092/184] Windows: Suppressing the Warning When Linking (#15943) --- native/CMakeLists.txt | 5 +++++ templates/windows/CMakeLists.txt | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index a1da31bfede..8e0e4296446 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -3105,6 +3105,11 @@ if(MSVC) /wd4098 # defaultlib conflicts /wd4099 # PDB 'filename' was not found with 'object/library' or at 'path'; linking object as if no debug info ) + target_link_options(${ENGINE_NAME} PUBLIC + /ignore:4099 # PDB 'filename' was not found with 'object/library' or at 'path'; linking object as if no debug info + /ignore:4098 # defaultlib 'library' conflicts with use of other libs; use /NODEFAULTLIB:library + /ignore:4204 # 'filename' is missing debugging information for referencing module; linking object as if no debug info + ) endif() if(CC_USE_VULKAN) diff --git a/templates/windows/CMakeLists.txt b/templates/windows/CMakeLists.txt index c91dd01ad48..9f3d15f91f8 100644 --- a/templates/windows/CMakeLists.txt +++ b/templates/windows/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.18) set(APP_NAME "CocosGame" CACHE STRING "Project Name") project(${APP_NAME} CXX) From e09252efd8d9ff36d064d5a1c5dbc98c54f9b39f Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Mon, 14 Aug 2023 14:11:18 +0800 Subject: [PATCH 093/184] export downloadJson and downloadArraybuffer (#15905) * export downloadJson and downloadArraybuffer add underscore * Update cocos/asset/asset-manager/downloader.ts * Update cocos/asset/asset-manager/downloader.ts * fix lint * fix lint --- cocos/asset/asset-manager/download-file.ts | 14 ++--- cocos/asset/asset-manager/downloader.ts | 62 +++++++++++-------- .../minigame/common/engine/AssetManager.js | 2 + platforms/native/engine/jsb-loader.js | 2 + .../runtime/common/engine/asset-manager.js | 2 + 5 files changed, 49 insertions(+), 33 deletions(-) diff --git a/cocos/asset/asset-manager/download-file.ts b/cocos/asset/asset-manager/download-file.ts index e331b6ebbd6..daceda1279a 100644 --- a/cocos/asset/asset-manager/download-file.ts +++ b/cocos/asset/asset-manager/download-file.ts @@ -22,27 +22,27 @@ THE SOFTWARE. */ -type FileProgressCallback = (loaded: number, total: number) => void; +export type FileProgressCallback = (loaded: number, total: number) => void; export default function downloadFile ( url: string, options: Record, onProgress: FileProgressCallback | null | undefined, - onComplete: ((err: Error | null, data?: any | null) => void), + onComplete: ((err: Error | null, data?: any) => void), ): XMLHttpRequest { const xhr = new XMLHttpRequest(); const errInfo = `download failed: ${url}, status: `; xhr.open('GET', url, true); - if (options.xhrResponseType !== undefined) { xhr.responseType = options.xhrResponseType; } - if (options.xhrWithCredentials !== undefined) { xhr.withCredentials = options.xhrWithCredentials; } - if (options.xhrMimeType !== undefined && xhr.overrideMimeType) { xhr.overrideMimeType(options.xhrMimeType); } - if (options.xhrTimeout !== undefined) { xhr.timeout = options.xhrTimeout; } + if (options.xhrResponseType !== undefined) { xhr.responseType = options.xhrResponseType as XMLHttpRequestResponseType; } + if (options.xhrWithCredentials !== undefined) { xhr.withCredentials = options.xhrWithCredentials as boolean; } + if (options.xhrMimeType !== undefined && xhr.overrideMimeType) { xhr.overrideMimeType(options.xhrMimeType as string); } + if (options.xhrTimeout !== undefined) { xhr.timeout = options.xhrTimeout as number; } if (options.xhrHeader) { for (const header in options.xhrHeader) { - xhr.setRequestHeader(header, options.xhrHeader[header]); + xhr.setRequestHeader(header, options.xhrHeader[header] as string); } } diff --git a/cocos/asset/asset-manager/downloader.ts b/cocos/asset/asset-manager/downloader.ts index d763e639e84..18548777aab 100644 --- a/cocos/asset/asset-manager/downloader.ts +++ b/cocos/asset/asset-manager/downloader.ts @@ -26,45 +26,45 @@ import { BUILD, EDITOR, EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; import { sys, js, misc, path, cclegacy } from '../../core'; import Cache from './cache'; import downloadDomImage from './download-dom-image'; -import downloadFile from './download-file'; +import downloadFile, { FileProgressCallback } from './download-file'; import downloadScript from './download-script'; import { files } from './shared'; import { retry, RetryFunction, urlAppendTimestamp } from './utilities'; import { IConfigOption } from './config'; import { CCON, parseCCONJson, decodeCCONBinary } from '../../serialization/ccon'; -export type DownloadHandler = (url: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)) => void; +export type DownloadHandler = (url: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)) => void; interface IDownloadRequest { id: string; priority: number; url: string; options: Record; - done: ((err: Error | null, data?: any | null) => void); + done: ((err: Error | null, data?: any) => void); handler: DownloadHandler; } const REGEX = /^(?:\w+:\/\/|\.+\/).+/; -const downloadImage = (url: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)): void => { +const downloadImage = (url: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)): void => { // if createImageBitmap is valid, we can transform blob to ImageBitmap. Otherwise, just use HTMLImageElement to load const func = sys.hasFeature(sys.Feature.IMAGE_BITMAP) && cclegacy.assetManager.allowImageBitmap ? downloadBlob : downloadDomImage; func(url, options, onComplete); }; -const downloadBlob = (url: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)): void => { +const downloadBlob = (url: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)): void => { options.xhrResponseType = 'blob'; - downloadFile(url, options, options.onFileProgress, onComplete); + downloadFile(url, options, options.onFileProgress as FileProgressCallback, onComplete); }; const downloadJson = (url: string, options: Record, onComplete: ((err: Error | null, data?: Record | null) => void)): void => { options.xhrResponseType = 'json'; - downloadFile(url, options, options.onFileProgress, onComplete); + downloadFile(url, options, options.onFileProgress as FileProgressCallback, onComplete); }; -const downloadArrayBuffer = (url: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)): void => { +const downloadArrayBuffer = (url: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)): void => { options.xhrResponseType = 'arraybuffer'; - downloadFile(url, options, options.onFileProgress, onComplete); + downloadFile(url, options, options.onFileProgress as FileProgressCallback, onComplete); }; const downloadCCON = (url: string, options: Record, onComplete: ((err: Error | null, data?: CCON | null) => void)): void => { @@ -75,7 +75,7 @@ const downloadCCON = (url: string, options: Record, onComplete: ((e } const cconPreface = parseCCONJson(json); const chunkPromises = Promise.all(cconPreface.chunks.map((chunk): Promise => new Promise((resolve, reject): void => { - downloadArrayBuffer(`${path.mainFileName(url)}${chunk}`, {}, (errChunk, chunkBuffer): void => { + downloadArrayBuffer(`${path.mainFileName(url)}${chunk}`, {}, (errChunk, chunkBuffer: ArrayBuffer): void => { if (err) { reject(err); } else { @@ -86,7 +86,7 @@ const downloadCCON = (url: string, options: Record, onComplete: ((e chunkPromises.then((chunks): void => { const ccon = new CCON(cconPreface.document, chunks); onComplete(null, ccon); - }).catch((err): void => { + }).catch((err: Error): void => { onComplete(err); }); }); @@ -107,12 +107,12 @@ const downloadCCONB = (url: string, options: Record, onComplete: (( }); }; -const downloadText = (url: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)): void => { +const downloadText = (url: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)): void => { options.xhrResponseType = 'text'; - downloadFile(url, options, options.onFileProgress, onComplete); + downloadFile(url, options, options.onFileProgress as FileProgressCallback, onComplete); }; -const downloadBundle = (nameOrUrl: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)): void => { +const downloadBundle = (nameOrUrl: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)): void => { const bundleName = path.basename(nameOrUrl); let url = nameOrUrl; if (!REGEX.test(url)) { @@ -262,6 +262,16 @@ export class Downloader { */ public downloadScript = downloadScript; + /** + * @engineInternal + */ + public _downloadArrayBuffer = downloadArrayBuffer; + + /** + * @engineInternal + */ + public _downloadJson = downloadJson; + // default handler map private _downloaders: Record = { // Images @@ -310,7 +320,7 @@ export class Downloader { default: downloadText, }; - private _downloading = new Cache<((err: Error | null, data?: any | null) => void)[]>(); + private _downloading = new Cache<((err: Error | null, data?: any) => void)[]>(); private _queue: IDownloadRequest[] = []; private _queueDirty = false; // the number of loading thread @@ -360,11 +370,11 @@ export class Downloader { * '.ext': (url, options, onComplete) => onComplete(null, null)}); * */ - public register (type: string, handler: (url: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)) => void): void; - public register (map: Record, onComplete: ((err: Error | null, data?: any | null) => void)) => void>): void; + public register (type: string, handler: (url: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)) => void): void; + public register (map: Record, onComplete: ((err: Error | null, data?: any) => void)) => void>): void; public register ( - type: string | Record, onComplete: ((err: Error | null, data?: any | null) => void)) => void>, - handler?: (url: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)) => void, + type: string | Record, onComplete: ((err: Error | null, data?: any) => void)) => void>, + handler?: (url: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)) => void, ): void { if (typeof type === 'object') { js.mixin(this._downloaders, type); @@ -397,7 +407,7 @@ export class Downloader { * download('http://example.com/test.tga', '.tga', { onFileProgress: (loaded, total) => console.log(loaded/total) }, * onComplete: (err) => console.log(err)); */ - public download (id: string, url: string, type: string, options: Record, onComplete: ((err: Error | null, data?: any | null) => void)): void { + public download (id: string, url: string, type: string, options: Record, onComplete: ((err: Error | null, data?: any) => void)): void { // if it is downloaded, don't download again const file = files.get(id); if (file) { @@ -419,9 +429,9 @@ export class Downloader { } // if download fail, should retry - const maxRetryCount = typeof options.maxRetryCount !== 'undefined' ? options.maxRetryCount : this.maxRetryCount; - const maxConcurrency = typeof options.maxConcurrency !== 'undefined' ? options.maxConcurrency : this.maxConcurrency; - const maxRequestsPerFrame = typeof options.maxRequestsPerFrame !== 'undefined' ? options.maxRequestsPerFrame : this.maxRequestsPerFrame; + const maxRetryCount = typeof options.maxRetryCount !== 'undefined' ? options.maxRetryCount as number : this.maxRetryCount; + const maxConcurrency = typeof options.maxConcurrency !== 'undefined' ? options.maxConcurrency as number : this.maxConcurrency; + const maxRequestsPerFrame = typeof options.maxRequestsPerFrame !== 'undefined' ? options.maxRequestsPerFrame as number : this.maxRequestsPerFrame; const handler = this._downloaders[type] || this._downloaders.default; const process: RetryFunction = (index, callback): void => { @@ -437,7 +447,7 @@ export class Downloader { // refresh this._updateTime(); - const done: ((err: Error | null, data?: any | null) => void) = (err, data): void => { + const done: ((err: Error | null, data?: any) => void) = (err, data): void => { // when finish downloading, update _totalNum this._totalNum--; this._handleQueueInNextFrame(maxConcurrency, maxRequestsPerFrame); @@ -458,9 +468,9 @@ export class Downloader { }; // when retry finished, invoke callbacks - const finale = (err, result): void => { + const finale = (err: Error | null, result : any): void => { if (!err) { files.add(id, result); } - const callbacks = this._downloading.remove(id) as ((err: Error | null, data?: any | null) => void)[]; + const callbacks = this._downloading.remove(id) as ((err: Error | null, data?: any) => void)[]; for (let i = 0, l = callbacks.length; i < l; i++) { callbacks[i](err, result); } diff --git a/platforms/minigame/common/engine/AssetManager.js b/platforms/minigame/common/engine/AssetManager.js index 7d1ceee4a83..8ff48de056b 100644 --- a/platforms/minigame/common/engine/AssetManager.js +++ b/platforms/minigame/common/engine/AssetManager.js @@ -325,6 +325,8 @@ const parsePlist = function (url, options, onComplete) { }; downloader.downloadScript = downloadScript; +downloader._downloadArrayBuffer = downloadArrayBuffer; +downloader._downloadJson = downloadJson; parser.parsePVRTex = parsePVRTex; parser.parsePKMTex = parsePKMTex; parser.parseASTCTex = parseASTCTex; diff --git a/platforms/native/engine/jsb-loader.js b/platforms/native/engine/jsb-loader.js index 5b430aa61c7..f310b02549b 100644 --- a/platforms/native/engine/jsb-loader.js +++ b/platforms/native/engine/jsb-loader.js @@ -291,6 +291,8 @@ parser.parsePKMTex = downloader.downloadDomImage; parser.parseASTCTex = downloader.downloadDomImage; parser.parsePlist = parsePlist; downloader.downloadScript = downloadScript; +downloader._downloadArrayBuffer = downloadArrayBuffer; +downloader._downloadJson = downloadJson; function loadAudioPlayer (url, options, onComplete) { cc.AudioPlayer.load(url).then((player) => { diff --git a/platforms/runtime/common/engine/asset-manager.js b/platforms/runtime/common/engine/asset-manager.js index 7dc1f7d126b..10b691be7ad 100644 --- a/platforms/runtime/common/engine/asset-manager.js +++ b/platforms/runtime/common/engine/asset-manager.js @@ -288,6 +288,8 @@ const parsePlist = function (url, options, onComplete) { }; downloader.downloadScript = downloadScript; +downloader._downloadArrayBuffer = downloadArrayBuffer; +downloader._downloadJson = downloadJson; parser.parsePVRTex = parsePVRTex; parser.parsePKMTex = parsePKMTex; parser.parseASTCTex = parseASTCTex; From b76a4053b583b65d151e75ab907f6104ea3e7934 Mon Sep 17 00:00:00 2001 From: minggo Date: Mon, 14 Aug 2023 15:07:14 +0800 Subject: [PATCH 094/184] remove duplicate codes and unify logic (#15854) --- cocos/game/game.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cocos/game/game.ts b/cocos/game/game.ts index 5f3eac8149d..14086b18be7 100644 --- a/cocos/game/game.ts +++ b/cocos/game/game.ts @@ -646,9 +646,7 @@ export class Game extends EventTarget { */ public on (type: string, callback: () => void, target?: any, once?: boolean): any { // Make sure EVENT_ENGINE_INITED callbacks to be invoked - if ((this._engineInited && type === Game.EVENT_ENGINE_INITED) - || (this._inited && type === Game.EVENT_GAME_INITED) - || (this._rendererInitialized && type === Game.EVENT_RENDERER_INITED)) { + if (this.canRegisterEvent(type)) { callback.call(target); } return this.eventTargetOn(type, callback, target, once); @@ -668,12 +666,18 @@ export class Game extends EventTarget { */ public once (type: string, callback: () => void, target?: any): any { // Make sure EVENT_ENGINE_INITED callbacks to be invoked - if (this._engineInited && type === Game.EVENT_ENGINE_INITED) { + if (this.canRegisterEvent(type)) { return callback.call(target); } return this.eventTargetOnce(type, callback, target); } + private canRegisterEvent (type: string): boolean { + return this._engineInited && type === Game.EVENT_ENGINE_INITED + || this._inited && type === Game.EVENT_GAME_INITED + || this._rendererInitialized && type === Game.EVENT_RENDERER_INITED; + } + /** * @en Init game with configuration object. Initialization process like below: * -PreBaseInitEvent From 7cbb06fa0021c0c6a2d395c7d10adb91d49438e5 Mon Sep 17 00:00:00 2001 From: minggo Date: Mon, 14 Aug 2023 15:34:03 +0800 Subject: [PATCH 095/184] fix some eslint error (#15948) --- cocos/rendering/debug-view.ts | 1 - cocos/rendering/define.ts | 63 ++++-- cocos/rendering/geometry-renderer.ts | 181 +++++++++++++++--- cocos/rendering/index.ts | 1 - cocos/rendering/instanced-buffer.ts | 5 +- cocos/rendering/pipeline-state-manager.ts | 5 +- cocos/rendering/pipeline-ubo.ts | 29 ++- .../post-process/components/blit-screen.ts | 6 +- .../rendering/post-process/components/fsr.ts | 2 +- .../post-process/components/taa-mask.ts | 4 +- .../rendering/post-process/components/taa.ts | 8 +- .../post-process/passes/base-pass.ts | 6 +- .../post-process/passes/blit-screen-pass.ts | 6 +- .../post-process/passes/bloom-pass.ts | 4 +- .../post-process/passes/color-grading-pass.ts | 4 +- .../post-process/passes/forward-final-pass.ts | 6 +- .../passes/forward-transparency-pass.ts | 6 +- .../forward-transparency-simple-pass.ts | 6 +- .../rendering/post-process/passes/fsr-pass.ts | 1 - .../post-process/passes/hbao-pass.ts | 22 ++- .../post-process/passes/setting-pass.ts | 2 +- .../post-process/passes/shadow-pass.ts | 8 +- .../rendering/post-process/passes/taa-pass.ts | 2 +- .../post-process/passes/tone-mapping-pass.ts | 4 +- .../post-process/utils/pass-context.ts | 24 +-- cocos/rendering/render-instanced-queue.ts | 11 +- cocos/rendering/scene-culling.ts | 3 +- 27 files changed, 303 insertions(+), 117 deletions(-) diff --git a/cocos/rendering/debug-view.ts b/cocos/rendering/debug-view.ts index 395b37581b7..28d661ced23 100644 --- a/cocos/rendering/debug-view.ts +++ b/cocos/rendering/debug-view.ts @@ -22,7 +22,6 @@ THE SOFTWARE. */ -import { JSB } from 'internal:constants'; import { cclegacy } from '../core'; import { Root } from '../root'; diff --git a/cocos/rendering/define.ts b/cocos/rendering/define.ts index 5d0d24d6643..6b9c1a3593d 100644 --- a/cocos/rendering/define.ts +++ b/cocos/rendering/define.ts @@ -651,8 +651,13 @@ localDescriptorSetLayout.bindings[UNIFORM_POSITION_MORPH_TEXTURE_BINDING] = UNIF const UNIFORM_NORMAL_MORPH_TEXTURE_NAME = 'cc_NormalDisplacements'; export const UNIFORM_NORMAL_MORPH_TEXTURE_BINDING = ModelLocalBindings.SAMPLER_MORPH_NORMAL; const UNIFORM_NORMAL_MORPH_TEXTURE_DESCRIPTOR = new DescriptorSetLayoutBinding(UNIFORM_NORMAL_MORPH_TEXTURE_BINDING, DescriptorType.SAMPLER_TEXTURE, 1, ShaderStageFlagBit.VERTEX); -const UNIFORM_NORMAL_MORPH_TEXTURE_LAYOUT = new UniformSamplerTexture(SetIndex.LOCAL, UNIFORM_NORMAL_MORPH_TEXTURE_BINDING, - UNIFORM_NORMAL_MORPH_TEXTURE_NAME, Type.SAMPLER2D, 1); +const UNIFORM_NORMAL_MORPH_TEXTURE_LAYOUT = new UniformSamplerTexture( + SetIndex.LOCAL, + UNIFORM_NORMAL_MORPH_TEXTURE_BINDING, + UNIFORM_NORMAL_MORPH_TEXTURE_NAME, + Type.SAMPLER2D, + 1, +); localDescriptorSetLayout.layouts[UNIFORM_NORMAL_MORPH_TEXTURE_NAME] = UNIFORM_NORMAL_MORPH_TEXTURE_LAYOUT; localDescriptorSetLayout.bindings[UNIFORM_NORMAL_MORPH_TEXTURE_BINDING] = UNIFORM_NORMAL_MORPH_TEXTURE_DESCRIPTOR; @@ -663,8 +668,13 @@ localDescriptorSetLayout.bindings[UNIFORM_NORMAL_MORPH_TEXTURE_BINDING] = UNIFOR const UNIFORM_TANGENT_MORPH_TEXTURE_NAME = 'cc_TangentDisplacements'; export const UNIFORM_TANGENT_MORPH_TEXTURE_BINDING = ModelLocalBindings.SAMPLER_MORPH_TANGENT; const UNIFORM_TANGENT_MORPH_TEXTURE_DESCRIPTOR = new DescriptorSetLayoutBinding(UNIFORM_TANGENT_MORPH_TEXTURE_BINDING, DescriptorType.SAMPLER_TEXTURE, 1, ShaderStageFlagBit.VERTEX); -const UNIFORM_TANGENT_MORPH_TEXTURE_LAYOUT = new UniformSamplerTexture(SetIndex.LOCAL, UNIFORM_TANGENT_MORPH_TEXTURE_BINDING, - UNIFORM_TANGENT_MORPH_TEXTURE_NAME, Type.SAMPLER2D, 1); +const UNIFORM_TANGENT_MORPH_TEXTURE_LAYOUT = new UniformSamplerTexture( + SetIndex.LOCAL, + UNIFORM_TANGENT_MORPH_TEXTURE_BINDING, + UNIFORM_TANGENT_MORPH_TEXTURE_NAME, + Type.SAMPLER2D, + 1, +); localDescriptorSetLayout.layouts[UNIFORM_TANGENT_MORPH_TEXTURE_NAME] = UNIFORM_TANGENT_MORPH_TEXTURE_LAYOUT; localDescriptorSetLayout.bindings[UNIFORM_TANGENT_MORPH_TEXTURE_BINDING] = UNIFORM_TANGENT_MORPH_TEXTURE_DESCRIPTOR; @@ -675,8 +685,13 @@ localDescriptorSetLayout.bindings[UNIFORM_TANGENT_MORPH_TEXTURE_BINDING] = UNIFO const UNIFORM_LIGHTMAP_TEXTURE_NAME = 'cc_lightingMap'; export const UNIFORM_LIGHTMAP_TEXTURE_BINDING = ModelLocalBindings.SAMPLER_LIGHTMAP; const UNIFORM_LIGHTMAP_TEXTURE_DESCRIPTOR = new DescriptorSetLayoutBinding(UNIFORM_LIGHTMAP_TEXTURE_BINDING, DescriptorType.SAMPLER_TEXTURE, 1, ShaderStageFlagBit.FRAGMENT); -const UNIFORM_LIGHTMAP_TEXTURE_LAYOUT = new UniformSamplerTexture(SetIndex.LOCAL, UNIFORM_LIGHTMAP_TEXTURE_BINDING, - UNIFORM_LIGHTMAP_TEXTURE_NAME, Type.SAMPLER2D, 1); +const UNIFORM_LIGHTMAP_TEXTURE_LAYOUT = new UniformSamplerTexture( + SetIndex.LOCAL, + UNIFORM_LIGHTMAP_TEXTURE_BINDING, + UNIFORM_LIGHTMAP_TEXTURE_NAME, + Type.SAMPLER2D, + 1, +); localDescriptorSetLayout.layouts[UNIFORM_LIGHTMAP_TEXTURE_NAME] = UNIFORM_LIGHTMAP_TEXTURE_LAYOUT; localDescriptorSetLayout.bindings[UNIFORM_LIGHTMAP_TEXTURE_BINDING] = UNIFORM_LIGHTMAP_TEXTURE_DESCRIPTOR; @@ -720,8 +735,13 @@ localDescriptorSetLayout.bindings[UNIFORM_REFLECTION_STORAGE_BINDING] = UNIFORM_ const UNIFORM_REFLECTION_PROBE_CUBEMAP_NAME = 'cc_reflectionProbeCubemap'; export const UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING = ModelLocalBindings.SAMPLER_REFLECTION_PROBE_CUBE; const UNIFORM_REFLECTION_PROBE_CUBEMAP_DESCRIPTOR = new DescriptorSetLayoutBinding(UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING, DescriptorType.SAMPLER_TEXTURE, 1, ShaderStageFlagBit.FRAGMENT); -const UNIFORM_REFLECTION_PROBE_CUBEMAP_LAYOUT = new UniformSamplerTexture(SetIndex.LOCAL, UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING, - UNIFORM_REFLECTION_PROBE_CUBEMAP_NAME, Type.SAMPLER_CUBE, 1); +const UNIFORM_REFLECTION_PROBE_CUBEMAP_LAYOUT = new UniformSamplerTexture( + SetIndex.LOCAL, + UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING, + UNIFORM_REFLECTION_PROBE_CUBEMAP_NAME, + Type.SAMPLER_CUBE, + 1, +); localDescriptorSetLayout.layouts[UNIFORM_REFLECTION_PROBE_CUBEMAP_NAME] = UNIFORM_REFLECTION_PROBE_CUBEMAP_LAYOUT; localDescriptorSetLayout.bindings[UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING] = UNIFORM_REFLECTION_PROBE_CUBEMAP_DESCRIPTOR; @@ -732,8 +752,13 @@ localDescriptorSetLayout.bindings[UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING] = UN const UNIFORM_REFLECTION_PROBE_TEXTURE_NAME = 'cc_reflectionProbePlanarMap'; export const UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING = ModelLocalBindings.SAMPLER_REFLECTION_PROBE_PLANAR; const UNIFORM_REFLECTION_PROBE_TEXTURE_DESCRIPTOR = new DescriptorSetLayoutBinding(UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING, DescriptorType.SAMPLER_TEXTURE, 1, ShaderStageFlagBit.FRAGMENT); -const UNIFORM_REFLECTION_PROBE_TEXTURE_LAYOUT = new UniformSamplerTexture(SetIndex.LOCAL, UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING, - UNIFORM_REFLECTION_PROBE_TEXTURE_NAME, Type.SAMPLER2D, 1); +const UNIFORM_REFLECTION_PROBE_TEXTURE_LAYOUT = new UniformSamplerTexture( + SetIndex.LOCAL, + UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING, + UNIFORM_REFLECTION_PROBE_TEXTURE_NAME, + Type.SAMPLER2D, + 1, +); localDescriptorSetLayout.layouts[UNIFORM_REFLECTION_PROBE_TEXTURE_NAME] = UNIFORM_REFLECTION_PROBE_TEXTURE_LAYOUT; localDescriptorSetLayout.bindings[UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING] = UNIFORM_REFLECTION_PROBE_TEXTURE_DESCRIPTOR; @@ -744,8 +769,13 @@ localDescriptorSetLayout.bindings[UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING] = UN const UNIFORM_REFLECTION_PROBE_DATA_MAP_NAME = 'cc_reflectionProbeDataMap'; export const UNIFORM_REFLECTION_PROBE_DATA_MAP_BINDING = ModelLocalBindings.SAMPLER_REFLECTION_PROBE_DATA_MAP; const UNIFORM_REFLECTION_PROBE_DATA_MAP_DESCRIPTOR = new DescriptorSetLayoutBinding(UNIFORM_REFLECTION_PROBE_DATA_MAP_BINDING, DescriptorType.SAMPLER_TEXTURE, 1, ShaderStageFlagBit.FRAGMENT); -const UNIFORM_REFLECTION_PROBE_DATA_MAP_LAYOUT = new UniformSamplerTexture(SetIndex.LOCAL, UNIFORM_REFLECTION_PROBE_DATA_MAP_BINDING, - UNIFORM_REFLECTION_PROBE_DATA_MAP_NAME, Type.SAMPLER2D, 1); +const UNIFORM_REFLECTION_PROBE_DATA_MAP_LAYOUT = new UniformSamplerTexture( + SetIndex.LOCAL, + UNIFORM_REFLECTION_PROBE_DATA_MAP_BINDING, + UNIFORM_REFLECTION_PROBE_DATA_MAP_NAME, + Type.SAMPLER2D, + 1, +); localDescriptorSetLayout.layouts[UNIFORM_REFLECTION_PROBE_DATA_MAP_NAME] = UNIFORM_REFLECTION_PROBE_DATA_MAP_LAYOUT; localDescriptorSetLayout.bindings[UNIFORM_REFLECTION_PROBE_DATA_MAP_BINDING] = UNIFORM_REFLECTION_PROBE_DATA_MAP_DESCRIPTOR; @@ -756,8 +786,13 @@ localDescriptorSetLayout.bindings[UNIFORM_REFLECTION_PROBE_DATA_MAP_BINDING] = U const UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_NAME = 'cc_reflectionProbeBlendCubemap'; export const UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING = ModelLocalBindings.SAMPLER_REFLECTION_PROBE_BLEND_CUBE; const UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_DESCRIPTOR = new DescriptorSetLayoutBinding(UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING, DescriptorType.SAMPLER_TEXTURE, 1, ShaderStageFlagBit.FRAGMENT); -const UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_LAYOUT = new UniformSamplerTexture(SetIndex.LOCAL, UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING, - UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_NAME, Type.SAMPLER_CUBE, 1); +const UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_LAYOUT = new UniformSamplerTexture( + SetIndex.LOCAL, + UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING, + UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_NAME, + Type.SAMPLER_CUBE, + 1, +); localDescriptorSetLayout.layouts[UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_NAME] = UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_LAYOUT; localDescriptorSetLayout.bindings[UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING] = UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_DESCRIPTOR; diff --git a/cocos/rendering/geometry-renderer.ts b/cocos/rendering/geometry-renderer.ts index 6b4eee1aaf9..41ebe43f715 100644 --- a/cocos/rendering/geometry-renderer.ts +++ b/cocos/rendering/geometry-renderer.ts @@ -93,8 +93,12 @@ class GeometryVertexBuffer { this._vertexCount = 0; this._stride = stride; this._vertices = new Float32Array(maxVertices * stride / Float32Array.BYTES_PER_ELEMENT); - this._buffer = device.createBuffer(new BufferInfo(BufferUsageBit.VERTEX | BufferUsageBit.TRANSFER_DST, - MemoryUsageBit.DEVICE, maxVertices * stride, stride)); + this._buffer = device.createBuffer(new BufferInfo( + BufferUsageBit.VERTEX | BufferUsageBit.TRANSFER_DST, + MemoryUsageBit.DEVICE, + maxVertices * stride, + stride, + )); this._inputAssembler = device.createInputAssembler(new InputAssemblerInfo(attributes, [this._buffer], null)); } @@ -395,8 +399,15 @@ export class GeometryRenderer { } } - public addBoundingBox (aabb: geometry.AABB, color: Color, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform: Mat4 = new Mat4()): void { + public addBoundingBox ( + aabb: geometry.AABB, + color: Color, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform: Mat4 = new Mat4(), + ): void { /** * 2---3 * / / @@ -490,8 +501,19 @@ export class GeometryRenderer { this.addLine(vertices[3], vertices[7], color, depthTest); } - public addCapsule (center: Vec3, radius: number, height: number, color: Color, segmentsU = 32, hemiSegmentsV = 8, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addCapsule ( + center: Vec3, + radius: number, + height: number, + color: Color, + segmentsU = 32, + hemiSegmentsV = 8, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { const deltaPhi = Math.PI * 2.0 / segmentsU; const deltaTheta = Math.PI / 2.0 / hemiSegmentsV; const bottomCenter = new Vec3(center.x, center.y - height / 2.0, center.z); @@ -551,8 +573,18 @@ export class GeometryRenderer { } } - public addCylinder (center: Vec3, radius: number, height: number, color: Color, segments = 32, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addCylinder ( + center: Vec3, + radius: number, + height: number, + color: Color, + segments = 32, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { const deltaPhi = Math.PI * 2.0 / segments; const bottomCenter = new Vec3(center.x, center.y - height / 2.0, center.z); const topCenter = new Vec3(center.x, center.y + height / 2.0, center.z); @@ -587,8 +619,18 @@ export class GeometryRenderer { } } - public addCone (center: Vec3, radius: number, height: number, color: Color, segments = 32, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addCone ( + center: Vec3, + radius: number, + height: number, + color: Color, + segments = 32, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { const deltaPhi = Math.PI * 2.0 / segments; const bottomCenter = new Vec3(center.x, center.y - height / 2.0, center.z); const topCenter = new Vec3(center.x, center.y + height / 2.0, center.z); @@ -636,8 +678,17 @@ export class GeometryRenderer { } } - public addArc (center: Vec3, radius: number, color: Color, startAngle: number, endAngle: number, segments = 32, - depthTest = true, useTransform = false, transform = new Mat4()): void { + public addArc ( + center: Vec3, + radius: number, + color: Color, + startAngle: number, + endAngle: number, + segments = 32, + depthTest = true, + useTransform = false, + transform = new Mat4(), + ): void { const startRadian = toRadian(startAngle); const endRadian = toRadian(endAngle); const deltaPhi = (endRadian - startRadian) / segments; @@ -660,8 +711,17 @@ export class GeometryRenderer { } } - public addPolygon (center: Vec3, radius: number, color: Color, segments = 6, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addPolygon ( + center: Vec3, + radius: number, + color: Color, + segments = 6, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { if (wireframe) { this.addCircle(center, radius, color, segments, depthTest, useTransform, transform); } else { @@ -669,8 +729,17 @@ export class GeometryRenderer { } } - public addDisc (center: Vec3, radius: number, color: Color, segments = 32, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addDisc ( + center: Vec3, + radius: number, + color: Color, + segments = 32, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { const deltaPhi = Math.PI * 2.0 / segments; const points = new Array(); const newCenter = new Vec3(center); @@ -701,8 +770,19 @@ export class GeometryRenderer { } } - public addSector (center: Vec3, radius: number, color: Color, startAngle: number, endAngle: number, segments = 32, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addSector ( + center: Vec3, + radius: number, + color: Color, + startAngle: number, + endAngle: number, + segments = 32, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { const startRadian = toRadian(startAngle); const endRadian = toRadian(endAngle); const deltaPhi = (endRadian - startRadian) / segments; @@ -735,8 +815,18 @@ export class GeometryRenderer { } } - public addSphere (center: Vec3, radius: number, color: Color, segmentsU = 32, segmentsV = 16, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addSphere ( + center: Vec3, + radius: number, + color: Color, + segmentsU = 32, + segmentsV = 16, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { const deltaPhi = Math.PI * 2.0 / segmentsU; const deltaTheta = Math.PI / segmentsV; const points = new Array>(); @@ -777,8 +867,19 @@ export class GeometryRenderer { } } - public addTorus (center: Vec3, bigRadius: number, radius: number, color: Color, segmentsU = 32, segmentsV = 16, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addTorus ( + center: Vec3, + bigRadius: number, + radius: number, + color: Color, + segmentsU = 32, + segmentsV = 16, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { const deltaPhi = Math.PI * 2.0 / segmentsU; const deltaTheta = Math.PI * 2.0 / segmentsV; const points = new Array>(); @@ -818,8 +919,16 @@ export class GeometryRenderer { } } - public addOctahedron (center: Vec3, radius: number, color: Color, - wireframe = true, depthTest = true, unlit = false, useTransform = false, transform = new Mat4()): void { + public addOctahedron ( + center: Vec3, + radius: number, + color: Color, + wireframe = true, + depthTest = true, + unlit = false, + useTransform = false, + transform = new Mat4(), + ): void { const points = new Array(); points.push(new Vec3(radius + center.x, center.y, center.z)); @@ -862,8 +971,17 @@ export class GeometryRenderer { } } - public addBezier (v0: Vec3, v1: Vec3, v2: Vec3, v3: Vec3, color: Color, segments = 32, - depthTest = true, useTransform = false, transform = new Mat4()): void { + public addBezier ( + v0: Vec3, + v1: Vec3, + v2: Vec3, + v3: Vec3, + color: Color, + segments = 32, + depthTest = true, + useTransform = false, + transform = new Mat4(), + ): void { const deltaT = 1.0 / segments; const points = new Array(); @@ -936,8 +1054,15 @@ export class GeometryRenderer { } } - public addIndexedMesh (center: Vec3, vertices: Array, indices: Array, color: Color, - depthTest = true, useTransform = false, transform = new Mat4()): void { + public addIndexedMesh ( + center: Vec3, + vertices: Array, + indices: Array, + color: Color, + depthTest = true, + useTransform = false, + transform = new Mat4(), + ): void { for (let i = 0; i < indices.length; i += 3) { const v0 = new Vec3(center.x + vertices[indices[i]].x, center.y + vertices[indices[i]].y, center.z + vertices[indices[i]].z); const v1 = new Vec3(center.x + vertices[indices[i + 1]].x, center.y + vertices[indices[i + 1]].y, center.z + vertices[indices[i + 1]].z); diff --git a/cocos/rendering/index.ts b/cocos/rendering/index.ts index df06cd7656e..b99dea2b298 100644 --- a/cocos/rendering/index.ts +++ b/cocos/rendering/index.ts @@ -24,7 +24,6 @@ import './deprecated'; import * as pipeline from './define'; -import { ForwardPipeline } from './forward/forward-pipeline'; export { pipeline }; diff --git a/cocos/rendering/instanced-buffer.ts b/cocos/rendering/instanced-buffer.ts index 7df49320153..005ff7bc4ee 100644 --- a/cocos/rendering/instanced-buffer.ts +++ b/cocos/rendering/instanced-buffer.ts @@ -23,8 +23,9 @@ */ import { Pass } from '../render-scene'; -import { IInstancedAttributeBlock, SubModel } from '../render-scene/scene'; -import { UNIFORM_LIGHTMAP_TEXTURE_BINDING, UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING, UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING, UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING } from './define'; +import { SubModel } from '../render-scene/scene'; +import { UNIFORM_LIGHTMAP_TEXTURE_BINDING, UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING, UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING, + UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING } from './define'; import { BufferUsageBit, MemoryUsageBit, Device, Texture, InputAssembler, InputAssemblerInfo, Attribute, Buffer, BufferInfo, CommandBuffer, Shader, DescriptorSet } from '../gfx'; diff --git a/cocos/rendering/pipeline-state-manager.ts b/cocos/rendering/pipeline-state-manager.ts index 2df742117a1..4dbb7cd3c3a 100644 --- a/cocos/rendering/pipeline-state-manager.ts +++ b/cocos/rendering/pipeline-state-manager.ts @@ -41,7 +41,10 @@ export class PipelineStateManager { const pipelineLayout = pass.pipelineLayout; const inputState = new InputState(ia.attributes); const psoInfo = new PipelineStateInfo( - shader, pipelineLayout, renderPass, inputState, + shader, + pipelineLayout, + renderPass, + inputState, pass.rasterizerState, pass.depthStencilState, pass.blendState, diff --git a/cocos/rendering/pipeline-ubo.ts b/cocos/rendering/pipeline-ubo.ts index 4961924d62a..38bfb231123 100644 --- a/cocos/rendering/pipeline-ubo.ts +++ b/cocos/rendering/pipeline-ubo.ts @@ -35,7 +35,6 @@ import { RenderWindow } from '../render-scene/core/render-window'; import { builtinResMgr } from '../asset/asset-manager/builtin-res-mgr'; import { Texture2D } from '../asset/assets'; import { DebugViewCompositeType } from './debug-view'; -import { legacyCC } from '../core/global-exports'; import { getDescBindingFromName } from './custom/define'; const _matShadowView = new Mat4(); @@ -91,8 +90,11 @@ export class PipelineUBO { fv[UBOGlobal.DEBUG_VIEW_MODE_OFFSET + 3] += (debugView.csmLayerColoration ? 1.0 : 0.0) * (10.0 ** 7.0); } - public static updateCameraUBOView (pipeline: PipelineRuntime, bufferView: Float32Array, - camera: Camera): void { + public static updateCameraUBOView ( + pipeline: PipelineRuntime, + bufferView: Float32Array, + camera: Camera, + ): void { const scene = camera.scene ? camera.scene : cclegacy.director.getScene().renderScene; const mainLight = scene.mainLight; const sceneData = pipeline.pipelineSceneData; @@ -217,8 +219,12 @@ export class PipelineUBO { shadowUBO[UBOShadow.PLANAR_NORMAL_DISTANCE_INFO_OFFSET + 3] = -shadowInfo.distance; } - public static updateShadowUBOView (pipeline: PipelineRuntime, shadowBufferView: Float32Array, - csmBufferView: Float32Array, camera: Camera): void { + public static updateShadowUBOView ( + pipeline: PipelineRuntime, + shadowBufferView: Float32Array, + csmBufferView: Float32Array, + camera: Camera, + ): void { const device = pipeline.device; const mainLight = camera.scene!.mainLight; const sceneData = pipeline.pipelineSceneData; @@ -395,8 +401,17 @@ export class PipelineUBO { Mat4.invert(_matShadowView, (light as any).node.getWorldMatrix()); Mat4.toArray(sv, _matShadowView, UBOShadow.MAT_LIGHT_VIEW_OFFSET); - Mat4.perspective(_matShadowProj, (light as any).angle, 1.0, 0.001, (light as any).range, - true, cap.clipSpaceMinZ, cap.clipSpaceSignY, 0); + Mat4.perspective( + _matShadowProj, + (light as any).angle, + 1.0, + 0.001, + (light as any).range, + true, + cap.clipSpaceMinZ, + cap.clipSpaceSignY, + 0, + ); Mat4.multiply(_matShadowViewProj, _matShadowProj, _matShadowView); Mat4.toArray(sv, _matShadowViewProj, UBOShadow.MAT_LIGHT_VIEW_PROJ_OFFSET); diff --git a/cocos/rendering/post-process/components/blit-screen.ts b/cocos/rendering/post-process/components/blit-screen.ts index bf78dc464ac..32363fb6609 100644 --- a/cocos/rendering/post-process/components/blit-screen.ts +++ b/cocos/rendering/post-process/components/blit-screen.ts @@ -18,7 +18,7 @@ class BlitScreenMaterial { } @property - enable = true + enable = true; } @ccclass('cc.BlitScreen') @@ -28,7 +28,7 @@ class BlitScreenMaterial { @executeInEditMode export class BlitScreen extends PostProcessSetting { @property(Material) - _activeMaterials: Material[] = [] + _activeMaterials: Material[] = []; @property({ type: Material, visible: false }) get activeMaterials (): Material[] { return this._activeMaterials; @@ -47,7 +47,7 @@ export class BlitScreen extends PostProcessSetting { } @property(BlitScreenMaterial) - _materials: BlitScreenMaterial[] = [] + _materials: BlitScreenMaterial[] = []; @property(BlitScreenMaterial) get materials (): BlitScreenMaterial[] { diff --git a/cocos/rendering/post-process/components/fsr.ts b/cocos/rendering/post-process/components/fsr.ts index a5ab8f739bf..db52428a12c 100644 --- a/cocos/rendering/post-process/components/fsr.ts +++ b/cocos/rendering/post-process/components/fsr.ts @@ -10,7 +10,7 @@ import { PostProcessSetting } from './post-process-setting'; @executeInEditMode export class FSR extends PostProcessSetting { @serializable - _sharpness = 0.8 + _sharpness = 0.8; @tooltip('i18n:fsr.sharpness') @slide diff --git a/cocos/rendering/post-process/components/taa-mask.ts b/cocos/rendering/post-process/components/taa-mask.ts index 8f257576696..ff416e93a0c 100644 --- a/cocos/rendering/post-process/components/taa-mask.ts +++ b/cocos/rendering/post-process/components/taa-mask.ts @@ -14,7 +14,7 @@ export class TAAMask extends Component { _mask: RenderTexture | undefined; - get mask () { + get mask (): RenderTexture | undefined { if (!this.maskCamera || !this.maskCamera.enabledInHierarchy) { return undefined; } @@ -25,7 +25,7 @@ export class TAAMask extends Component { return this._mask; } - start () { + start (): void { if (!this.maskCamera) { warn('Can not find a Camera for TAAMask'); return; diff --git a/cocos/rendering/post-process/components/taa.ts b/cocos/rendering/post-process/components/taa.ts index 343ee1e4953..fb9c2a6c746 100644 --- a/cocos/rendering/post-process/components/taa.ts +++ b/cocos/rendering/post-process/components/taa.ts @@ -9,13 +9,13 @@ import { PostProcessSetting } from './post-process-setting'; @executeInEditMode export class TAA extends PostProcessSetting { @property - _sampleScale = 1 + _sampleScale = 1; @tooltip('i18n:taa.sampleScale') @slide @range([0.01, 5, 0.01]) @property - get sampleScale () { + get sampleScale (): number { return this._sampleScale; } set sampleScale (v) { @@ -23,12 +23,12 @@ export class TAA extends PostProcessSetting { } @property - _feedback = 0.95 + _feedback = 0.95; @tooltip('i18n:taa.feedback') @slide @range([0.0, 1, 0.01]) @property - get feedback () { + get feedback (): number { return this._feedback; } set feedback (v) { diff --git a/cocos/rendering/post-process/passes/base-pass.ts b/cocos/rendering/post-process/passes/base-pass.ts index cef4cb7942d..3038bfaf661 100644 --- a/cocos/rendering/post-process/passes/base-pass.ts +++ b/cocos/rendering/post-process/passes/base-pass.ts @@ -55,7 +55,7 @@ export abstract class BasePass { abstract name: string; effectName = 'pipeline/post-process/blit-screen'; - _id = 0 + _id = 0; constructor () { this._id = _BasePassID++; } @@ -65,7 +65,7 @@ export abstract class BasePass { // private _materialMap: Map = new Map() - _material: Material | undefined + _material: Material | undefined; get material (): Material { const effectReloaded = false; // if (EDITOR && this._material) { @@ -97,7 +97,7 @@ export abstract class BasePass { } enable = true; - outputNames: string[] = [] + outputNames: string[] = []; lastPass: BasePass | undefined; diff --git a/cocos/rendering/post-process/passes/blit-screen-pass.ts b/cocos/rendering/post-process/passes/blit-screen-pass.ts index 11f8001ee80..3e862328db1 100644 --- a/cocos/rendering/post-process/passes/blit-screen-pass.ts +++ b/cocos/rendering/post-process/passes/blit-screen-pass.ts @@ -1,5 +1,3 @@ -import { EDITOR } from 'internal:constants'; - import { Format } from '../../../gfx'; import { Camera } from '../../../render-scene/scene'; import { Pipeline } from '../../custom/pipeline'; @@ -14,10 +12,10 @@ const outputNames = ['BlitScreenColor0', 'BlitScreenColor1']; export class BlitScreenPass extends SettingPass { get setting (): BlitScreen { return getSetting(BlitScreen); } - name = 'BlitScreenPass' + name = 'BlitScreenPass'; effectName = 'pipeline/post-process/blit-screen'; - outputName = outputNames[0] + outputName = outputNames[0]; slotName (camera: Camera, index = 0): string { return this.outputName; diff --git a/cocos/rendering/post-process/passes/bloom-pass.ts b/cocos/rendering/post-process/passes/bloom-pass.ts index 6c53ec842a1..85330ea852f 100644 --- a/cocos/rendering/post-process/passes/bloom-pass.ts +++ b/cocos/rendering/post-process/passes/bloom-pass.ts @@ -24,9 +24,9 @@ export class BloomPass extends SettingPass { return enable; } - name = 'BloomPass' + name = 'BloomPass'; effectName = 'pipeline/post-process/bloom'; - outputNames = ['BloomColor'] + outputNames = ['BloomColor']; public render (camera: Camera, ppl: Pipeline): void { const cameraID = getCameraUniqueID(camera); diff --git a/cocos/rendering/post-process/passes/color-grading-pass.ts b/cocos/rendering/post-process/passes/color-grading-pass.ts index 6f4dee97a86..d824d077e9f 100644 --- a/cocos/rendering/post-process/passes/color-grading-pass.ts +++ b/cocos/rendering/post-process/passes/color-grading-pass.ts @@ -20,9 +20,9 @@ export class ColorGradingPass extends SettingPass { return enable; } - name = 'ColorGradingPass' + name = 'ColorGradingPass'; effectName = 'pipeline/post-process/color-grading'; - outputNames = ['ColorGrading'] + outputNames = ['ColorGrading']; public render (camera: Camera, ppl: Pipeline): void { const cameraID = getCameraUniqueID(camera); diff --git a/cocos/rendering/post-process/passes/forward-final-pass.ts b/cocos/rendering/post-process/passes/forward-final-pass.ts index 06372f2c185..1ae8bdead67 100644 --- a/cocos/rendering/post-process/passes/forward-final-pass.ts +++ b/cocos/rendering/post-process/passes/forward-final-pass.ts @@ -1,8 +1,4 @@ -import { EDITOR } from 'internal:constants'; - import { Vec4 } from '../../../core'; -import { director } from '../../../game'; - import { ClearFlagBit, Format } from '../../../gfx'; import { Camera } from '../../../render-scene/scene'; import { getCameraUniqueID } from '../../custom/define'; @@ -12,7 +8,7 @@ import { BasePass } from './base-pass'; export class ForwardFinalPass extends BasePass { name = 'ForwardFinalPass'; - outputNames = ['ForwardFinalColor'] + outputNames = ['ForwardFinalColor']; enableInAllEditorCamera = true; diff --git a/cocos/rendering/post-process/passes/forward-transparency-pass.ts b/cocos/rendering/post-process/passes/forward-transparency-pass.ts index 5214195e162..22d438656ef 100644 --- a/cocos/rendering/post-process/passes/forward-transparency-pass.ts +++ b/cocos/rendering/post-process/passes/forward-transparency-pass.ts @@ -72,8 +72,10 @@ export class ForwardTransparencyPass extends BasePass { } pass.addQueue(QueueHint.RENDER_TRANSPARENT) - .addSceneOfCamera(camera, + .addSceneOfCamera( + camera, new LightInfo(), - SceneFlags.UI | SceneFlags.TRANSPARENT_OBJECT | SceneFlags.GEOMETRY); + SceneFlags.UI | SceneFlags.TRANSPARENT_OBJECT | SceneFlags.GEOMETRY, + ); } } diff --git a/cocos/rendering/post-process/passes/forward-transparency-simple-pass.ts b/cocos/rendering/post-process/passes/forward-transparency-simple-pass.ts index 620c7a56347..72d371eba7b 100644 --- a/cocos/rendering/post-process/passes/forward-transparency-simple-pass.ts +++ b/cocos/rendering/post-process/passes/forward-transparency-simple-pass.ts @@ -39,8 +39,10 @@ export class ForwardTransparencySimplePass extends BasePass { public render (camera: Camera, ppl: Pipeline): void { const pass = passContext.pass!; pass.addQueue(QueueHint.RENDER_TRANSPARENT) - .addSceneOfCamera(camera, + .addSceneOfCamera( + camera, new LightInfo(), - SceneFlags.UI | SceneFlags.TRANSPARENT_OBJECT | SceneFlags.GEOMETRY); + SceneFlags.UI | SceneFlags.TRANSPARENT_OBJECT | SceneFlags.GEOMETRY, + ); } } diff --git a/cocos/rendering/post-process/passes/fsr-pass.ts b/cocos/rendering/post-process/passes/fsr-pass.ts index 1231470b58e..b9353c1282a 100644 --- a/cocos/rendering/post-process/passes/fsr-pass.ts +++ b/cocos/rendering/post-process/passes/fsr-pass.ts @@ -8,7 +8,6 @@ import { passContext } from '../utils/pass-context'; import { FSR } from '../components/fsr'; import { getSetting, SettingPass } from './setting-pass'; -import { game } from '../../../game'; const tempVec4 = new Vec4(); diff --git a/cocos/rendering/post-process/passes/hbao-pass.ts b/cocos/rendering/post-process/passes/hbao-pass.ts index 384fb3aa632..aea741f6d32 100644 --- a/cocos/rendering/post-process/passes/hbao-pass.ts +++ b/cocos/rendering/post-process/passes/hbao-pass.ts @@ -182,9 +182,9 @@ export class HBAOPass extends SettingPass { get setting (): HBAO { return getSetting(HBAO); } - name = 'HBAOPass' + name = 'HBAOPass'; effectName = 'pipeline/post-process/hbao'; - outputNames = ['hbaoRTName', 'hbaoBluredRTName'] + outputNames = ['hbaoRTName', 'hbaoBluredRTName']; checkEnable (camera: Camera): boolean { let enable = super.checkEnable(camera); @@ -267,14 +267,16 @@ export class HBAOPass extends SettingPass { this.material.setProperty('uvDepthToEyePosParams', this._hbaoParams!.uvDepthToEyePosParams, passIdx); this.material.setProperty('radiusParam', this._hbaoParams!.radiusParam, passIdx); this.material.setProperty('miscParam', this._hbaoParams!.miscParam, passIdx); - this.material.setProperty('randomTexSize', + this.material.setProperty( + 'randomTexSize', new Vec4( this._hbaoParams!.randomTexture.width, this._hbaoParams!.randomTexture.height, 1.0 / this._hbaoParams!.randomTexture.width, 1.0 / this._hbaoParams!.randomTexture.height, ), - passIdx); + passIdx, + ); this.material.setProperty('blurParam', this._hbaoParams!.blurParam, passIdx); passContext.clearBlack(); @@ -301,14 +303,16 @@ export class HBAOPass extends SettingPass { this.material.setProperty('uvDepthToEyePosParams', this._hbaoParams!.uvDepthToEyePosParams, passIdx); this.material.setProperty('radiusParam', this._hbaoParams!.radiusParam, passIdx); this.material.setProperty('miscParam', this._hbaoParams!.miscParam, passIdx); - this.material.setProperty('randomTexSize', + this.material.setProperty( + 'randomTexSize', new Vec4( this._hbaoParams!.randomTexture.width, this._hbaoParams!.randomTexture.height, 1.0 / this._hbaoParams!.randomTexture.width, 1.0 / this._hbaoParams!.randomTexture.height, ), - passIdx); + passIdx, + ); this.material.setProperty('blurParam', this._hbaoParams!.blurParam, passIdx); let outputRT = super.slotName(camera, 1); @@ -337,14 +341,16 @@ export class HBAOPass extends SettingPass { this.material.setProperty('uvDepthToEyePosParams', this._hbaoParams!.uvDepthToEyePosParams, passIdx); this.material.setProperty('radiusParam', this._hbaoParams!.radiusParam, passIdx); this.material.setProperty('miscParam', this._hbaoParams!.miscParam, passIdx); - this.material.setProperty('randomTexSize', + this.material.setProperty( + 'randomTexSize', new Vec4( this._hbaoParams!.randomTexture.width, this._hbaoParams!.randomTexture.height, 1.0 / this._hbaoParams!.randomTexture.width, 1.0 / this._hbaoParams!.randomTexture.height, ), - passIdx); + passIdx, + ); this.material.setProperty('blurParam', this._hbaoParams!.blurParam, passIdx); passContext.clearFlag = ClearFlagBit.NONE; diff --git a/cocos/rendering/post-process/passes/setting-pass.ts b/cocos/rendering/post-process/passes/setting-pass.ts index 2e7b5326af8..66dd313f000 100644 --- a/cocos/rendering/post-process/passes/setting-pass.ts +++ b/cocos/rendering/post-process/passes/setting-pass.ts @@ -13,7 +13,7 @@ export function getSetting (settingClass: new () = } export abstract class SettingPass extends BasePass { - getSetting = getSetting + getSetting = getSetting; get setting (): PostProcessSetting { return this.getSetting(PostProcessSetting); } checkEnable (camera: Camera): boolean { diff --git a/cocos/rendering/post-process/passes/shadow-pass.ts b/cocos/rendering/post-process/passes/shadow-pass.ts index af623a6f019..417a6a99795 100644 --- a/cocos/rendering/post-process/passes/shadow-pass.ts +++ b/cocos/rendering/post-process/passes/shadow-pass.ts @@ -1,14 +1,14 @@ import { Camera } from '../../../render-scene/scene'; import { buildShadowPasses, getCameraUniqueID } from '../../custom/define'; -import { Pipeline, PipelineType } from '../../custom/pipeline'; +import { Pipeline } from '../../custom/pipeline'; import { passContext } from '../utils/pass-context'; import { BasePass } from './base-pass'; export class ShadowPass extends BasePass { - name = 'ShadowPass' + name = 'ShadowPass'; - mainLightShadows: string[] = [] - spotLightShadows: string[] = [] + mainLightShadows: string[] = []; + spotLightShadows: string[] = []; public render (camera: Camera, ppl: Pipeline): void { passContext.shadowPass = this; diff --git a/cocos/rendering/post-process/passes/taa-pass.ts b/cocos/rendering/post-process/passes/taa-pass.ts index 8ac1904eefc..a8688cd62f1 100644 --- a/cocos/rendering/post-process/passes/taa-pass.ts +++ b/cocos/rendering/post-process/passes/taa-pass.ts @@ -86,7 +86,7 @@ const SampleOffsets = { export class TAAPass extends SettingPass { get setting (): TAA { return getSetting(TAA); } - name = 'TAAPass' + name = 'TAAPass'; effectName = 'pipeline/post-process/taa'; outputNames = ['TAA_First', 'TAA_Second']; diff --git a/cocos/rendering/post-process/passes/tone-mapping-pass.ts b/cocos/rendering/post-process/passes/tone-mapping-pass.ts index 721a9fae0f5..9231c71742b 100644 --- a/cocos/rendering/post-process/passes/tone-mapping-pass.ts +++ b/cocos/rendering/post-process/passes/tone-mapping-pass.ts @@ -33,9 +33,9 @@ import { SettingPass } from './setting-pass'; import { Root } from '../../../root'; export class ToneMappingPass extends SettingPass { - name = 'ToneMappingPass' + name = 'ToneMappingPass'; effectName = 'pipeline/tone-mapping'; - outputNames = ['ToneMapping'] + outputNames = ['ToneMapping']; enableInAllEditorCamera = true; enable = true; diff --git a/cocos/rendering/post-process/utils/pass-context.ts b/cocos/rendering/post-process/utils/pass-context.ts index a3677222b70..a8d783e92b2 100644 --- a/cocos/rendering/post-process/utils/pass-context.ts +++ b/cocos/rendering/post-process/utils/pass-context.ts @@ -11,15 +11,15 @@ import { Vec4 } from '../../../core'; export class PassContext { clearFlag: ClearFlagBit = ClearFlagBit.COLOR; - clearColor = new Color() - clearDepthColor = new Color() - ppl: Pipeline| undefined - camera: Camera| undefined - material: Material| undefined - pass: RenderPassBuilder| undefined - rasterWidth = 0 - rasterHeight = 0 - layoutName = '' + clearColor = new Color(); + clearDepthColor = new Color(); + ppl: Pipeline| undefined; + camera: Camera| undefined; + material: Material| undefined; + pass: RenderPassBuilder| undefined; + rasterWidth = 0; + rasterHeight = 0; + layoutName = ''; shadingScale = 1; viewport = new Rect(); @@ -171,8 +171,10 @@ export class PassContext { blitScreen (passIdx = 0): PassContext { this.pass!.addQueue(QueueHint.RENDER_TRANSPARENT).addCameraQuad( - this.camera!, this.material!, passIdx, - SceneFlags.NONE, + this.camera!, +this.material!, +passIdx, +SceneFlags.NONE, ); return this; } diff --git a/cocos/rendering/render-instanced-queue.ts b/cocos/rendering/render-instanced-queue.ts index c97467799c9..7c94ca12372 100644 --- a/cocos/rendering/render-instanced-queue.ts +++ b/cocos/rendering/render-instanced-queue.ts @@ -38,7 +38,7 @@ export class RenderInstancedQueue { */ public queue = new Set(); - private _renderQueue : InstancedBuffer[] = []; + private _renderQueue: InstancedBuffer[] = []; /** * @en Clear the render queue @@ -86,8 +86,13 @@ export class RenderInstancedQueue { * @zh 记录命令缓冲。 * @param cmdBuff The command buffer to store the result */ - public recordCommandBuffer (device: Device, renderPass: RenderPass, cmdBuff: CommandBuffer, - descriptorSet: DescriptorSet | null = null, dynamicOffsets?: Readonly): void { + public recordCommandBuffer ( + device: Device, + renderPass: RenderPass, + cmdBuff: CommandBuffer, + descriptorSet: DescriptorSet | null = null, + dynamicOffsets?: Readonly, + ): void { const it = this._renderQueue.length === 0 ? this.queue.values() : this._renderQueue[Symbol.iterator](); let res = it.next(); diff --git a/cocos/rendering/scene-culling.ts b/cocos/rendering/scene-culling.ts index 419a0bda854..ca507ed247e 100644 --- a/cocos/rendering/scene-culling.ts +++ b/cocos/rendering/scene-culling.ts @@ -21,10 +21,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import { EDITOR } from 'internal:constants'; import { Model } from '../render-scene/scene/model'; import { Camera, CameraUsage, SKYBOX_FLAG } from '../render-scene/scene/camera'; -import { Vec3, Pool, warnID, geometry, cclegacy } from '../core'; +import { Vec3, Pool, geometry, cclegacy } from '../core'; import { RenderPipeline } from './render-pipeline'; import { IRenderObject, UBOShadow } from './define'; import { ShadowType, CSMOptimizationMode } from '../render-scene/scene/shadows'; From ceb15e9410a801e0b66f50716d5c54f66cc96c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Mon, 14 Aug 2023 15:45:24 +0800 Subject: [PATCH 096/184] Optimize CCON downloading code (#15950) --- cocos/asset/asset-manager/downloader.ts | 8 ++-- .../minigame/common/engine/AssetManager.js | 43 ------------------- platforms/native/engine/jsb-loader.js | 43 ------------------- .../runtime/common/engine/asset-manager.js | 43 ------------------- 4 files changed, 4 insertions(+), 133 deletions(-) diff --git a/cocos/asset/asset-manager/downloader.ts b/cocos/asset/asset-manager/downloader.ts index 18548777aab..fa87cb3fac9 100644 --- a/cocos/asset/asset-manager/downloader.ts +++ b/cocos/asset/asset-manager/downloader.ts @@ -68,14 +68,14 @@ const downloadArrayBuffer = (url: string, options: Record, onComple }; const downloadCCON = (url: string, options: Record, onComplete: ((err: Error | null, data?: CCON | null) => void)): void => { - downloadJson(url, options, (err, json): void => { + downloader._downloadJson(url, options, (err, json): void => { if (err) { onComplete(err); return; } const cconPreface = parseCCONJson(json); const chunkPromises = Promise.all(cconPreface.chunks.map((chunk): Promise => new Promise((resolve, reject): void => { - downloadArrayBuffer(`${path.mainFileName(url)}${chunk}`, {}, (errChunk, chunkBuffer: ArrayBuffer): void => { + downloader._downloadArrayBuffer(`${path.mainFileName(url)}${chunk}`, {}, (errChunk, chunkBuffer: ArrayBuffer): void => { if (err) { reject(err); } else { @@ -93,7 +93,7 @@ const downloadCCON = (url: string, options: Record, onComplete: ((e }; const downloadCCONB = (url: string, options: Record, onComplete: ((err: Error | null, data?: CCON | null) => void)): void => { - downloadArrayBuffer(url, options, (err, arrayBuffer: ArrayBuffer): void => { + downloader._downloadArrayBuffer(url, options, (err, arrayBuffer: ArrayBuffer): void => { if (err) { onComplete(err); return; @@ -468,7 +468,7 @@ export class Downloader { }; // when retry finished, invoke callbacks - const finale = (err: Error | null, result : any): void => { + const finale = (err: Error | null, result: any): void => { if (!err) { files.add(id, result); } const callbacks = this._downloading.remove(id) as ((err: Error | null, data?: any) => void)[]; for (let i = 0, l = callbacks.length; i < l; i++) { diff --git a/platforms/minigame/common/engine/AssetManager.js b/platforms/minigame/common/engine/AssetManager.js index 8ff48de056b..1f60dac52f2 100644 --- a/platforms/minigame/common/engine/AssetManager.js +++ b/platforms/minigame/common/engine/AssetManager.js @@ -165,46 +165,6 @@ function downloadAsset (url, options, onComplete) { download(url, doNothing, options, options.onFileProgress, onComplete); } -const downloadCCON = (url, options, onComplete) => { - downloadJson(url, options, (err, json) => { - if (err) { - onComplete(err); - return; - } - const cconPreface = cc.internal.parseCCONJson(json); - const chunkPromises = Promise.all(cconPreface.chunks.map((chunk) => new Promise((resolve, reject) => { - downloadArrayBuffer(`${cc.path.mainFileName(url)}${chunk}`, {}, (errChunk, chunkBuffer) => { - if (errChunk) { - reject(errChunk); - } else { - resolve(new Uint8Array(chunkBuffer)); - } - }); - }))); - chunkPromises.then((chunks) => { - const ccon = new cc.internal.CCON(cconPreface.document, chunks); - onComplete(null, ccon); - }).catch((err) => { - onComplete(err); - }); - }); -}; - -const downloadCCONB = (url, options, onComplete) => { - downloadArrayBuffer(url, options, (err, arrayBuffer) => { - if (err) { - onComplete(err); - return; - } - try { - const ccon = cc.internal.decodeCCONBinary(new Uint8Array(arrayBuffer)); - onComplete(null, ccon); - } catch (err) { - onComplete(err); - } - }); -}; - function downloadBundle (nameOrUrl, options, onComplete) { const bundleName = cc.path.basename(nameOrUrl); const version = options.version || cc.assetManager.downloader.bundleVers[bundleName]; @@ -362,9 +322,6 @@ downloader.register({ '.svg': downloadAsset, '.ttc': downloadAsset, - '.ccon': downloadCCON, - '.cconb': downloadCCONB, - // Txt '.txt': downloadAsset, '.xml': downloadAsset, diff --git a/platforms/native/engine/jsb-loader.js b/platforms/native/engine/jsb-loader.js index f310b02549b..59e88aaa395 100644 --- a/platforms/native/engine/jsb-loader.js +++ b/platforms/native/engine/jsb-loader.js @@ -219,46 +219,6 @@ function downloadBundle (nameOrUrl, options, onComplete) { }); } -const downloadCCON = (url, options, onComplete) => { - downloadJson(url, options, (err, json) => { - if (err) { - onComplete(err); - return; - } - const cconPreface = cc.internal.parseCCONJson(json); - const chunkPromises = Promise.all(cconPreface.chunks.map((chunk) => new Promise((resolve, reject) => { - downloadArrayBuffer(`${cc.path.mainFileName(url)}${chunk}`, {}, (errChunk, chunkBuffer) => { - if (errChunk) { - reject(errChunk); - } else { - resolve(new Uint8Array(chunkBuffer)); - } - }); - }))); - chunkPromises.then((chunks) => { - const ccon = new cc.internal.CCON(cconPreface.document, chunks); - onComplete(null, ccon); - }).catch((err) => { - onComplete(err); - }); - }); -}; - -const downloadCCONB = (url, options, onComplete) => { - downloadArrayBuffer(url, options, (err, arrayBuffer) => { - if (err) { - onComplete(err); - return; - } - try { - const ccon = cc.internal.decodeCCONBinary(new Uint8Array(arrayBuffer)); - onComplete(null, ccon); - } catch (err) { - onComplete(err); - } - }); -}; - function downloadArrayBuffer (url, options, onComplete) { download(url, parseArrayBuffer, options, options.onFileProgress, onComplete); } @@ -333,9 +293,6 @@ downloader.register({ '.wav': downloadAsset, '.m4a': downloadAsset, - '.ccon': downloadCCON, - '.cconb': downloadCCONB, - // Video '.mp4': downloadAsset, '.avi': downloadAsset, diff --git a/platforms/runtime/common/engine/asset-manager.js b/platforms/runtime/common/engine/asset-manager.js index 10b691be7ad..ea4645c8d2c 100644 --- a/platforms/runtime/common/engine/asset-manager.js +++ b/platforms/runtime/common/engine/asset-manager.js @@ -211,46 +211,6 @@ function downloadBundle (nameOrUrl, options, onComplete) { } } -const downloadCCON = (url, options, onComplete) => { - downloadJson(url, options, (err, json) => { - if (err) { - onComplete(err); - return; - } - const cconPreface = cc.internal.parseCCONJson(json); - const chunkPromises = Promise.all(cconPreface.chunks.map((chunk) => new Promise((resolve, reject) => { - downloadArrayBuffer(`${cc.path.mainFileName(url)}${chunk}`, {}, (errChunk, chunkBuffer) => { - if (errChunk) { - reject(errChunk); - } else { - resolve(new Uint8Array(chunkBuffer)); - } - }); - }))); - chunkPromises.then((chunks) => { - const ccon = new cc.internal.CCON(cconPreface.document, chunks); - onComplete(null, ccon); - }).catch((err) => { - onComplete(err); - }); - }); -}; - -const downloadCCONB = (url, options, onComplete) => { - downloadArrayBuffer(url, options, (err, arrayBuffer) => { - if (err) { - onComplete(err); - return; - } - try { - const ccon = cc.internal.decodeCCONBinary(new Uint8Array(arrayBuffer)); - onComplete(null, ccon); - } catch (err) { - onComplete(err); - } - }); -}; - function downloadArrayBuffer (url, options, onComplete) { download(url, parseArrayBuffer, options, options.onFileProgress, onComplete); } @@ -340,9 +300,6 @@ downloader.register({ '.json': downloadJson, '.ExportJson': downloadAsset, - '.ccon': downloadCCON, - '.cconb': downloadCCONB, - '.binary': downloadAsset, '.bin': downloadAsset, '.dbbin': downloadAsset, From d007151f2a4cfa9e82a2add4d3c1ad31e370458f Mon Sep 17 00:00:00 2001 From: yinkaile <501251991@qq.com> Date: Mon, 14 Aug 2023 16:02:55 +0800 Subject: [PATCH 097/184] refine code style (#15947) --- .../rendering/post-process/components/blit-screen.ts | 12 ++++++------ cocos/rendering/post-process/components/fsr.ts | 4 ++-- .../post-process/components/post-process-setting.ts | 2 +- .../post-process/components/post-process.ts | 2 +- cocos/rendering/post-process/components/taa.ts | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cocos/rendering/post-process/components/blit-screen.ts b/cocos/rendering/post-process/components/blit-screen.ts index 32363fb6609..ebd4a3fc2f7 100644 --- a/cocos/rendering/post-process/components/blit-screen.ts +++ b/cocos/rendering/post-process/components/blit-screen.ts @@ -7,7 +7,7 @@ import { PostProcessSetting } from './post-process-setting'; @ccclass('cc.BlitScreenMaterial') class BlitScreenMaterial { @property(Material) - _material: Material | undefined; + protected _material: Material | undefined; @property(Material) get material (): Material | undefined { @@ -28,7 +28,7 @@ class BlitScreenMaterial { @executeInEditMode export class BlitScreen extends PostProcessSetting { @property(Material) - _activeMaterials: Material[] = []; + protected _activeMaterials: Material[] = []; @property({ type: Material, visible: false }) get activeMaterials (): Material[] { return this._activeMaterials; @@ -47,7 +47,7 @@ export class BlitScreen extends PostProcessSetting { } @property(BlitScreenMaterial) - _materials: BlitScreenMaterial[] = []; + protected _materials: BlitScreenMaterial[] = []; @property(BlitScreenMaterial) get materials (): BlitScreenMaterial[] { @@ -60,10 +60,10 @@ export class BlitScreen extends PostProcessSetting { globalThis.cce.Engine.repaintInEditMode(); }, 50); } - this.updateActiveMateirals(); + this.updateActiveMaterials(); } - updateActiveMateirals (): void { + updateActiveMaterials (): void { const materials = this._materials; this._activeMaterials.length = 0; for (let i = 0; i < materials.length; i++) { @@ -75,6 +75,6 @@ export class BlitScreen extends PostProcessSetting { } onLoad (): void { - this.updateActiveMateirals(); + this.updateActiveMaterials(); } } diff --git a/cocos/rendering/post-process/components/fsr.ts b/cocos/rendering/post-process/components/fsr.ts index db52428a12c..b3d74377028 100644 --- a/cocos/rendering/post-process/components/fsr.ts +++ b/cocos/rendering/post-process/components/fsr.ts @@ -10,7 +10,7 @@ import { PostProcessSetting } from './post-process-setting'; @executeInEditMode export class FSR extends PostProcessSetting { @serializable - _sharpness = 0.8; + protected _sharpness = 0.8; @tooltip('i18n:fsr.sharpness') @slide @@ -19,7 +19,7 @@ export class FSR extends PostProcessSetting { get sharpness (): number { return this._sharpness; } - set sharpness (v) { + set sharpness (v: number) { this._sharpness = v; } } diff --git a/cocos/rendering/post-process/components/post-process-setting.ts b/cocos/rendering/post-process/components/post-process-setting.ts index 0e7cb12306e..9f27b5bc50e 100644 --- a/cocos/rendering/post-process/components/post-process-setting.ts +++ b/cocos/rendering/post-process/components/post-process-setting.ts @@ -6,7 +6,7 @@ import { PostProcess } from './post-process'; @requireComponent(PostProcess) @executeInEditMode export class PostProcessSetting extends Component { - static _default: PostProcessSetting | undefined + protected static _default: PostProcessSetting | undefined; static get default (): PostProcessSetting { if (!this._default) { this._default = new this(); diff --git a/cocos/rendering/post-process/components/post-process.ts b/cocos/rendering/post-process/components/post-process.ts index ac5454530ad..ef98e92990f 100644 --- a/cocos/rendering/post-process/components/post-process.ts +++ b/cocos/rendering/post-process/components/post-process.ts @@ -17,7 +17,7 @@ export class PostProcess extends Component { global = true; @property - _shadingScale = 1; + protected _shadingScale = 1; @tooltip('i18n:postprocess.shadingScale') @slide @range([0.01, 4, 0.01]) diff --git a/cocos/rendering/post-process/components/taa.ts b/cocos/rendering/post-process/components/taa.ts index fb9c2a6c746..8622b429542 100644 --- a/cocos/rendering/post-process/components/taa.ts +++ b/cocos/rendering/post-process/components/taa.ts @@ -9,7 +9,7 @@ import { PostProcessSetting } from './post-process-setting'; @executeInEditMode export class TAA extends PostProcessSetting { @property - _sampleScale = 1; + protected _sampleScale = 1; @tooltip('i18n:taa.sampleScale') @slide @@ -18,12 +18,12 @@ export class TAA extends PostProcessSetting { get sampleScale (): number { return this._sampleScale; } - set sampleScale (v) { + set sampleScale (v: number) { this._sampleScale = v; } @property - _feedback = 0.95; + protected _feedback = 0.95; @tooltip('i18n:taa.feedback') @slide @range([0.0, 1, 0.01]) @@ -31,7 +31,7 @@ export class TAA extends PostProcessSetting { get feedback (): number { return this._feedback; } - set feedback (v) { + set feedback (v: number) { this._feedback = v; } } From 06327fe407295fa75dc83f88a2314dddd8bb70b5 Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Tue, 15 Aug 2023 11:09:05 +0800 Subject: [PATCH 098/184] fix webgl framebuffer get(width/ height) issue (#15927) --- cocos/gfx/webgl/webgl-framebuffer.ts | 16 ++++++++++++++-- cocos/gfx/webgl2/webgl2-framebuffer.ts | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/cocos/gfx/webgl/webgl-framebuffer.ts b/cocos/gfx/webgl/webgl-framebuffer.ts index e60aa0b3691..aeab6338e91 100644 --- a/cocos/gfx/webgl/webgl-framebuffer.ts +++ b/cocos/gfx/webgl/webgl-framebuffer.ts @@ -69,13 +69,25 @@ export class WebGLFramebuffer extends Framebuffer { glFramebuffer: null, isOffscreen: true, get width (): number { - return this.isOffscreen ? width : this.gpuColorTextures[0].width; + if (this.isOffscreen) { + return width; + } else if (this.gpuColorTextures.length > 0) { + return this.gpuColorTextures[0].width; + } else { + return this.gpuDepthStencilTexture!.width; + } }, set width (val) { width = val; }, get height (): number { - return this.isOffscreen ? height : this.gpuColorTextures[0].height; + if (this.isOffscreen) { + return height; + } else if (this.gpuColorTextures.length > 0) { + return this.gpuColorTextures[0].height; + } else { + return this.gpuDepthStencilTexture!.height; + } }, set height (val) { height = val; diff --git a/cocos/gfx/webgl2/webgl2-framebuffer.ts b/cocos/gfx/webgl2/webgl2-framebuffer.ts index 8ee609cb4b5..255c7a9a6b3 100644 --- a/cocos/gfx/webgl2/webgl2-framebuffer.ts +++ b/cocos/gfx/webgl2/webgl2-framebuffer.ts @@ -77,7 +77,7 @@ export class WebGL2Framebuffer extends Framebuffer { }, get height (): number { if (this.isOffscreen) { - return width; + return height; } else if (this.gpuColorViews.length > 0) { return this.gpuColorViews[0].gpuTexture.height; } else { From c24a5186dd192b427636f0d5f7e22a51324ffdaa Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Tue, 15 Aug 2023 13:00:30 +0800 Subject: [PATCH 099/184] Custom Pipeline Debug Marker && gfx push marker(gles2,3, vk) (#15957) --- .../renderer/gfx-agent/CommandBufferAgent.cpp | 29 ++++++++++++ .../renderer/gfx-agent/CommandBufferAgent.h | 3 ++ .../renderer/gfx-base/GFXCommandBuffer.h | 3 ++ .../cocos/renderer/gfx-base/GFXDef-common.h | 5 ++ .../renderer/gfx-empty/EmptyCommandBuffer.cpp | 9 ++++ .../renderer/gfx-empty/EmptyCommandBuffer.h | 3 ++ .../renderer/gfx-gles2/GLES2CommandBuffer.cpp | 9 ++++ .../renderer/gfx-gles2/GLES2CommandBuffer.h | 3 ++ .../renderer/gfx-gles2/GLES2Commands.cpp | 18 +++++++ .../cocos/renderer/gfx-gles2/GLES2Commands.h | 4 ++ .../cocos/renderer/gfx-gles2/GLES2Device.cpp | 4 ++ .../renderer/gfx-gles2/GLES2GPUObjects.h | 1 + .../gfx-gles2/GLES2PrimaryCommandBuffer.cpp | 12 +++++ .../gfx-gles2/GLES2PrimaryCommandBuffer.h | 3 ++ .../renderer/gfx-gles3/GLES3CommandBuffer.cpp | 9 ++++ .../renderer/gfx-gles3/GLES3CommandBuffer.h | 3 ++ .../renderer/gfx-gles3/GLES3Commands.cpp | 18 +++++++ .../cocos/renderer/gfx-gles3/GLES3Commands.h | 4 ++ .../cocos/renderer/gfx-gles3/GLES3Device.cpp | 4 ++ .../renderer/gfx-gles3/GLES3GPUObjects.h | 1 + .../gfx-gles3/GLES3PrimaryCommandBuffer.cpp | 12 +++++ .../gfx-gles3/GLES3PrimaryCommandBuffer.h | 3 ++ .../renderer/gfx-metal/MTLCommandBuffer.h | 3 ++ .../renderer/gfx-metal/MTLCommandBuffer.mm | 7 +++ .../gfx-validator/CommandBufferValidator.cpp | 12 +++++ .../gfx-validator/CommandBufferValidator.h | 3 ++ .../renderer/gfx-vulkan/VKCommandBuffer.cpp | 47 +++++++++++++++++++ .../renderer/gfx-vulkan/VKCommandBuffer.h | 5 ++ native/cocos/renderer/gfx-vulkan/VKDevice.cpp | 13 +++++ .../renderer/gfx-vulkan/VKGPUContext.cpp | 3 +- .../cocos/renderer/gfx-vulkan/VKGPUObjects.h | 2 + .../renderer/gfx-wgpu/WGPUCommandBuffer.cpp | 11 +++++ .../renderer/gfx-wgpu/WGPUCommandBuffer.h | 3 ++ .../pipeline/custom/NativeExecutor.cpp | 38 +++++++++++++-- 34 files changed, 301 insertions(+), 6 deletions(-) diff --git a/native/cocos/renderer/gfx-agent/CommandBufferAgent.cpp b/native/cocos/renderer/gfx-agent/CommandBufferAgent.cpp index 7689387fd31..6e1d70febdb 100644 --- a/native/cocos/renderer/gfx-agent/CommandBufferAgent.cpp +++ b/native/cocos/renderer/gfx-agent/CommandBufferAgent.cpp @@ -199,6 +199,35 @@ void CommandBufferAgent::endRenderPass() { }); } +void CommandBufferAgent::insertMarker(const MarkerInfo &marker) { + ENQUEUE_MESSAGE_2( + _messageQueue, CommandBufferInsertMarker, + actor, getActor(), + marker, marker, + { + actor->insertMarker(marker); + }); +} + +void CommandBufferAgent::beginMarker(const MarkerInfo &marker) { + ENQUEUE_MESSAGE_2( + _messageQueue, CommandBufferBeginMarker, + actor, getActor(), + marker, marker, + { + actor->beginMarker(marker); + }); +} + +void CommandBufferAgent::endMarker() { + ENQUEUE_MESSAGE_1( + _messageQueue, CommandBufferEndMarker, + actor, getActor(), + { + actor->endMarker(); + }); +} + void CommandBufferAgent::execute(CommandBuffer *const *cmdBuffs, uint32_t count) { if (!count) return; diff --git a/native/cocos/renderer/gfx-agent/CommandBufferAgent.h b/native/cocos/renderer/gfx-agent/CommandBufferAgent.h index b3cf37ff0e8..87a6ce8276e 100644 --- a/native/cocos/renderer/gfx-agent/CommandBufferAgent.h +++ b/native/cocos/renderer/gfx-agent/CommandBufferAgent.h @@ -44,6 +44,9 @@ class CC_DLL CommandBufferAgent final : public Agent { void end() override; void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void bindPipelineState(PipelineState *pso) override; void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override; void bindInputAssembler(InputAssembler *ia) override; diff --git a/native/cocos/renderer/gfx-base/GFXCommandBuffer.h b/native/cocos/renderer/gfx-base/GFXCommandBuffer.h index 00a6d46e2aa..d521474ea0c 100644 --- a/native/cocos/renderer/gfx-base/GFXCommandBuffer.h +++ b/native/cocos/renderer/gfx-base/GFXCommandBuffer.h @@ -46,6 +46,9 @@ class CC_DLL CommandBuffer : public GFXObject, public RefCounted { virtual void end() = 0; virtual void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) = 0; virtual void endRenderPass() = 0; + virtual void insertMarker(const MarkerInfo &marker) = 0; + virtual void beginMarker(const MarkerInfo &marker) = 0; + virtual void endMarker() = 0; virtual void bindPipelineState(PipelineState *pso) = 0; virtual void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) = 0; virtual void bindInputAssembler(InputAssembler *ia) = 0; diff --git a/native/cocos/renderer/gfx-base/GFXDef-common.h b/native/cocos/renderer/gfx-base/GFXDef-common.h index da39c2c6dee..32712dbba97 100644 --- a/native/cocos/renderer/gfx-base/GFXDef-common.h +++ b/native/cocos/renderer/gfx-base/GFXDef-common.h @@ -964,6 +964,11 @@ struct Color { }; using ColorList = ccstd::vector; +struct MarkerInfo { + ccstd::string name; + Color color; +}; + struct BindingMappingInfo { /** * For non-vulkan backends, to maintain compatibility and maximize diff --git a/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.cpp b/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.cpp index 8c2e17a36b1..3a6b283ca88 100644 --- a/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.cpp @@ -45,6 +45,15 @@ void EmptyCommandBuffer::beginRenderPass(RenderPass *renderPass, Framebuffer *fb void EmptyCommandBuffer::endRenderPass() { } +void EmptyCommandBuffer::insertMarker(const MarkerInfo &marker) { +} + +void EmptyCommandBuffer::beginMarker(const MarkerInfo &marker) { +} + +void EmptyCommandBuffer::endMarker() { +} + void EmptyCommandBuffer::execute(CommandBuffer *const *cmdBuffs, uint32_t count) { } diff --git a/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.h b/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.h index d429d23f61c..77ef43864f7 100644 --- a/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.h +++ b/native/cocos/renderer/gfx-empty/EmptyCommandBuffer.h @@ -35,6 +35,9 @@ class CC_DLL EmptyCommandBuffer final : public CommandBuffer { void end() override; void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void bindPipelineState(PipelineState *pso) override; void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override; void bindInputAssembler(InputAssembler *ia) override; diff --git a/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cpp b/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cpp index daaf4efc6e9..34efe7a17db 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.cpp @@ -138,6 +138,15 @@ void GLES2CommandBuffer::nextSubpass() { _curCmdPackage->cmds.push(GLESCmdType::BEGIN_RENDER_PASS); } +void GLES2CommandBuffer::insertMarker(const MarkerInfo &marker) { + std::ignore = marker; +} +void GLES2CommandBuffer::beginMarker(const MarkerInfo &marker) { + std::ignore = marker; +} +void GLES2CommandBuffer::endMarker() { +} + void GLES2CommandBuffer::bindPipelineState(PipelineState *pso) { GLES2GPUPipelineState *gpuPipelineState = static_cast(pso)->gpuPipelineState(); if (_curGPUPipelineState != gpuPipelineState) { diff --git a/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h b/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h index 06185861895..ad4275dad47 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h +++ b/native/cocos/renderer/gfx-gles2/GLES2CommandBuffer.h @@ -48,6 +48,9 @@ class CC_GLES2_API GLES2CommandBuffer : public CommandBuffer { void end() override; void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void bindPipelineState(PipelineState *pso) override; void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override; void bindInputAssembler(InputAssembler *ia) override; diff --git a/native/cocos/renderer/gfx-gles2/GLES2Commands.cpp b/native/cocos/renderer/gfx-gles2/GLES2Commands.cpp index 1d9ca68f441..0ec135ac3ca 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2Commands.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2Commands.cpp @@ -3039,6 +3039,24 @@ GLint cmdFuncGLES2GetMaxSampleCount() { return maxSamples; } +void cmdFuncGLES2InsertMarker(GLES2Device *device, GLsizei length, const char *marker) { + if (device->constantRegistry()->debugMarker) { + glInsertEventMarkerEXT(length, marker); + } +} + +void cmdFuncGLES2PushGroupMarker(GLES2Device *device, GLsizei length, const char *marker) { + if (device->constantRegistry()->debugMarker) { + glPushGroupMarkerEXT(length, marker); + } +} + +void cmdFuncGLES2PopGroupMarker(GLES2Device *device) { + if (device->constantRegistry()->debugMarker) { + glPopGroupMarkerEXT(); + } +} + void GLES2GPUBlitManager::initialize() { _gpuShader.name = "Blit Pass"; _gpuShader.blocks.push_back({ diff --git a/native/cocos/renderer/gfx-gles2/GLES2Commands.h b/native/cocos/renderer/gfx-gles2/GLES2Commands.h index 670b8e3ae34..80ab7d90cf8 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2Commands.h +++ b/native/cocos/renderer/gfx-gles2/GLES2Commands.h @@ -246,6 +246,10 @@ void cmdFuncGLES2BlitTexture(GLES2Device *device, void cmdFuncGLES2ExecuteCmds(GLES2Device *device, GLES2CmdPackage *cmdPackage); +void cmdFuncGLES2InsertMarker(GLES2Device *device, GLsizei length, const char *marker); +void cmdFuncGLES2PushGroupMarker(GLES2Device *device, GLsizei length, const char *marker); +void cmdFuncGLES2PopGroupMarker(GLES2Device *device); + GLint cmdFuncGLES2GetMaxSampleCount(); } // namespace gfx diff --git a/native/cocos/renderer/gfx-gles2/GLES2Device.cpp b/native/cocos/renderer/gfx-gles2/GLES2Device.cpp index 38d0864da4b..f07071766e8 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2Device.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2Device.cpp @@ -178,6 +178,10 @@ bool GLES2Device::doInit(const DeviceInfo & /*info*/) { #endif _features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] = false; // not implement yet. + if (checkExtension(CC_TOSTR(GL_EXT_debug_marker))) { + _gpuConstantRegistry->debugMarker = true; + } + ccstd::string compressedFmts; if (getFormatFeatures(Format::ETC_RGB8) != FormatFeature::NONE) { compressedFmts += "etc1 "; diff --git a/native/cocos/renderer/gfx-gles2/GLES2GPUObjects.h b/native/cocos/renderer/gfx-gles2/GLES2GPUObjects.h index 99ce522f08d..3a37c01abfb 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2GPUObjects.h +++ b/native/cocos/renderer/gfx-gles2/GLES2GPUObjects.h @@ -42,6 +42,7 @@ struct GLES2GPUConstantRegistry { bool useDrawInstanced = false; bool useInstancedArrays = false; bool useDiscardFramebuffer = false; + bool debugMarker = false; }; class GLES2GPUStateCache; diff --git a/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.cpp b/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.cpp index 1c3832849a8..cdf297701a2 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.cpp @@ -80,6 +80,18 @@ void GLES2PrimaryCommandBuffer::nextSubpass() { cmdFuncGLES2BeginRenderPass(GLES2Device::getInstance(), ++_curSubpassIdx); } +void GLES2PrimaryCommandBuffer::insertMarker(const MarkerInfo &marker) { + cmdFuncGLES2InsertMarker(GLES2Device::getInstance(), marker.name.size(), marker.name.data()); +} + +void GLES2PrimaryCommandBuffer::beginMarker(const MarkerInfo &marker) { + cmdFuncGLES2PushGroupMarker(GLES2Device::getInstance(), marker.name.size(), marker.name.data()); +} + +void GLES2PrimaryCommandBuffer::endMarker() { + cmdFuncGLES2PopGroupMarker(GLES2Device::getInstance()); +} + void GLES2PrimaryCommandBuffer::draw(const DrawInfo &info) { CC_PROFILE(GLES2PrimaryCommandBufferDraw); if (_isStateInvalid) { diff --git a/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.h b/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.h index 2a3411c9eef..8ef11408f63 100644 --- a/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.h +++ b/native/cocos/renderer/gfx-gles2/GLES2PrimaryCommandBuffer.h @@ -39,6 +39,9 @@ class CC_GLES2_API GLES2PrimaryCommandBuffer final : public GLES2CommandBuffer { void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; void nextSubpass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void draw(const DrawInfo &info) override; void setViewport(const Viewport &vp) override; void setScissor(const Rect &rect) override; diff --git a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp index a7396a35587..b0321b81d40 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.cpp @@ -139,6 +139,15 @@ void GLES3CommandBuffer::nextSubpass() { _curCmdPackage->cmds.push(GLESCmdType::BEGIN_RENDER_PASS); } +void GLES3CommandBuffer::insertMarker(const MarkerInfo &marker) { + std::ignore = marker; +} +void GLES3CommandBuffer::beginMarker(const MarkerInfo &marker) { + std::ignore = marker; +} +void GLES3CommandBuffer::endMarker() { +} + void GLES3CommandBuffer::bindPipelineState(PipelineState *pso) { GLES3GPUPipelineState *gpuPipelineState = static_cast(pso)->gpuPipelineState(); if (_curGPUPipelineState != gpuPipelineState) { diff --git a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h index d42b50d43bc..25af0d6d22e 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h +++ b/native/cocos/renderer/gfx-gles3/GLES3CommandBuffer.h @@ -47,6 +47,9 @@ class CC_GLES3_API GLES3CommandBuffer : public CommandBuffer { void end() override; void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void bindPipelineState(PipelineState *pso) override; void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override; void bindInputAssembler(InputAssembler *ia) override; diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp index 46581b89681..03a57149824 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.cpp @@ -2564,6 +2564,24 @@ void cmdFuncGLES3MemoryBarrier(GLES3Device * /*device*/, GLbitfield barriers, GL if (barriersByRegion) GL_CHECK(glMemoryBarrierByRegion(barriersByRegion)); } +void cmdFuncGLES3InsertMarker(GLES3Device *device, GLsizei length, const char *marker) { + if (device->constantRegistry()->debugMarker) { + glInsertEventMarkerEXT(length, marker); + } +} + +void cmdFuncGLES3PushGroupMarker(GLES3Device *device, GLsizei length, const char *marker) { + if (device->constantRegistry()->debugMarker) { + glPushGroupMarkerEXT(length, marker); + } +} + +void cmdFuncGLES3PopGroupMarker(GLES3Device *device) { + if (device->constantRegistry()->debugMarker) { + glPopGroupMarkerEXT(); + } +} + static void uploadBufferData(GLenum target, GLintptr offset, GLsizeiptr length, const void *buffer) { #if 0 GL_CHECK(glBufferSubData(target, offset, length, buffer)); diff --git a/native/cocos/renderer/gfx-gles3/GLES3Commands.h b/native/cocos/renderer/gfx-gles3/GLES3Commands.h index c04634354c6..ef9eee6365b 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Commands.h +++ b/native/cocos/renderer/gfx-gles3/GLES3Commands.h @@ -313,6 +313,10 @@ void cmdFuncGLES3Dispatch(GLES3Device *device, const GLES3GPUDispatchInfo &info) void cmdFuncGLES3MemoryBarrier(GLES3Device *device, GLbitfield barriers, GLbitfield barriersByRegion); +void cmdFuncGLES3InsertMarker(GLES3Device *device, GLsizei length, const char *marker); +void cmdFuncGLES3PushGroupMarker(GLES3Device *device, GLsizei length, const char *marker); +void cmdFuncGLES3PopGroupMarker(GLES3Device *device); + GLint cmdFuncGLES3GetMaxSampleCount(const GLES3Device *device, Format format, TextureUsage usage, TextureFlags flags); } // namespace gfx diff --git a/native/cocos/renderer/gfx-gles3/GLES3Device.cpp b/native/cocos/renderer/gfx-gles3/GLES3Device.cpp index e97f7e00c79..6f3043b9aec 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3Device.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3Device.cpp @@ -148,6 +148,10 @@ bool GLES3Device::doInit(const DeviceInfo & /*info*/) { _features[toNumber(Feature::SUBPASS_COLOR_INPUT)] = true; } + if (checkExtension(CC_TOSTR(GL_EXT_debug_marker))) { + _gpuConstantRegistry->debugMarker = true; + } + if (checkExtension(CC_TOSTR(ARM_shader_framebuffer_fetch_depth_stencil))) { _features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = true; fbfLevelStr += "_DEPTH_STENCIL"; diff --git a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h index 66588d21014..46332eee71f 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h +++ b/native/cocos/renderer/gfx-gles3/GLES3GPUObjects.h @@ -43,6 +43,7 @@ struct GLES3GPUConstantRegistry { MSRTSupportLevel mMSRT{MSRTSupportLevel::NONE}; FBFSupportLevel mFBF{FBFSupportLevel::NONE}; + bool debugMarker = false; }; class GLES3GPUStateCache; diff --git a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp index 86219e7e151..bde2aac8991 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.cpp @@ -80,6 +80,18 @@ void GLES3PrimaryCommandBuffer::nextSubpass() { ++_curSubpassIdx; } +void GLES3PrimaryCommandBuffer::insertMarker(const MarkerInfo &marker) { + cmdFuncGLES3InsertMarker(GLES3Device::getInstance(), marker.name.size(), marker.name.data()); +} + +void GLES3PrimaryCommandBuffer::beginMarker(const MarkerInfo &marker) { + cmdFuncGLES3PushGroupMarker(GLES3Device::getInstance(), marker.name.size(), marker.name.data()); +} + +void GLES3PrimaryCommandBuffer::endMarker() { + cmdFuncGLES3PopGroupMarker(GLES3Device::getInstance()); +} + void GLES3PrimaryCommandBuffer::draw(const DrawInfo &info) { CC_PROFILE(GLES3PrimaryCommandBufferDraw); if (_isStateInvalid) { diff --git a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h index 3ae09735302..93ab3a06dd7 100644 --- a/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h +++ b/native/cocos/renderer/gfx-gles3/GLES3PrimaryCommandBuffer.h @@ -39,6 +39,9 @@ class CC_GLES3_API GLES3PrimaryCommandBuffer final : public GLES3CommandBuffer { void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; void nextSubpass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void draw(const DrawInfo &info) override; void setViewport(const Viewport &vp) override; void setScissor(const Rect &rect) override; diff --git a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.h b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.h index bb38f1530cd..51941df646a 100644 --- a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.h +++ b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.h @@ -56,6 +56,9 @@ class CCMTLCommandBuffer final : public CommandBuffer { void end() override; void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void bindPipelineState(PipelineState *pso) override; void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override; void bindInputAssembler(InputAssembler *ia) override; diff --git a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm index eef51f0eef7..b1a11e32e84 100644 --- a/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm +++ b/native/cocos/renderer/gfx-metal/MTLCommandBuffer.mm @@ -332,6 +332,13 @@ of this software and associated engine source code (the "Software"), a limited, _gpuCommandBufferObj->renderPass->reset(); } +void CCMTLCommandBuffer::insertMarker(const MarkerInfo &marker) { +} +void CCMTLCommandBuffer::beginMarker(const MarkerInfo &marker) { +} +void CCMTLCommandBuffer::endMarker() { +} + void CCMTLCommandBuffer::afterCommit() { _gpuCommandBufferObj->renderPass = nullptr; _gpuCommandBufferObj->fbo = nullptr; diff --git a/native/cocos/renderer/gfx-validator/CommandBufferValidator.cpp b/native/cocos/renderer/gfx-validator/CommandBufferValidator.cpp index bab7e3c6ca5..fcc1a2c571d 100644 --- a/native/cocos/renderer/gfx-validator/CommandBufferValidator.cpp +++ b/native/cocos/renderer/gfx-validator/CommandBufferValidator.cpp @@ -206,6 +206,18 @@ void CommandBufferValidator::endRenderPass() { _actor->endRenderPass(); } +void CommandBufferValidator::insertMarker(const MarkerInfo &marker) { + _actor->insertMarker(marker); +} + +void CommandBufferValidator::beginMarker(const MarkerInfo &marker) { + _actor->beginMarker(marker); +} + +void CommandBufferValidator::endMarker() { + _actor->endMarker(); +} + void CommandBufferValidator::execute(CommandBuffer *const *cmdBuffs, uint32_t count) { CC_ASSERT(isInited()); diff --git a/native/cocos/renderer/gfx-validator/CommandBufferValidator.h b/native/cocos/renderer/gfx-validator/CommandBufferValidator.h index 3ec70240be2..75071593d8b 100644 --- a/native/cocos/renderer/gfx-validator/CommandBufferValidator.h +++ b/native/cocos/renderer/gfx-validator/CommandBufferValidator.h @@ -41,6 +41,9 @@ class CC_DLL CommandBufferValidator final : public Agent { void end() override; void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void bindPipelineState(PipelineState *pso) override; void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override; void bindInputAssembler(InputAssembler *ia) override; diff --git a/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp b/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp index 7aefa9312fc..f1a7da28720 100644 --- a/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.cpp @@ -245,6 +245,53 @@ void CCVKCommandBuffer::endRenderPass() { } } +void CCVKCommandBuffer::insertMarker(const MarkerInfo &marker) { + auto *context = CCVKDevice::getInstance()->gpuContext(); + if (context->debugUtils) { + _utilLabelInfo.pLabelName = marker.name.c_str(); + _utilLabelInfo.color[0] = marker.color.x; + _utilLabelInfo.color[1] = marker.color.y; + _utilLabelInfo.color[2] = marker.color.z; + _utilLabelInfo.color[3] = marker.color.w; + vkCmdInsertDebugUtilsLabelEXT(_gpuCommandBuffer->vkCommandBuffer, &_utilLabelInfo); + } else if (context->debugReport) { + _markerInfo.pMarkerName = marker.name.c_str(); + _markerInfo.color[0] = marker.color.x; + _markerInfo.color[1] = marker.color.y; + _markerInfo.color[2] = marker.color.z; + _markerInfo.color[3] = marker.color.w; + vkCmdDebugMarkerInsertEXT(_gpuCommandBuffer->vkCommandBuffer, &_markerInfo); + } +} + +void CCVKCommandBuffer::beginMarker(const MarkerInfo &marker) { + auto *context = CCVKDevice::getInstance()->gpuContext(); + if (context->debugUtils) { + _utilLabelInfo.pLabelName = marker.name.c_str(); + _utilLabelInfo.color[0] = marker.color.x; + _utilLabelInfo.color[1] = marker.color.y; + _utilLabelInfo.color[2] = marker.color.z; + _utilLabelInfo.color[3] = marker.color.w; + vkCmdBeginDebugUtilsLabelEXT(_gpuCommandBuffer->vkCommandBuffer, &_utilLabelInfo); + } else if (context->debugReport) { + _markerInfo.pMarkerName = marker.name.c_str(); + _markerInfo.color[0] = marker.color.x; + _markerInfo.color[1] = marker.color.y; + _markerInfo.color[2] = marker.color.z; + _markerInfo.color[3] = marker.color.w; + vkCmdDebugMarkerBeginEXT(_gpuCommandBuffer->vkCommandBuffer, &_markerInfo); + } +} + +void CCVKCommandBuffer::endMarker() { + auto *context = CCVKDevice::getInstance()->gpuContext(); + if (context->debugUtils) { + vkCmdEndDebugUtilsLabelEXT(_gpuCommandBuffer->vkCommandBuffer); + } else if (context->debugReport) { + vkCmdDebugMarkerEndEXT(_gpuCommandBuffer->vkCommandBuffer); + } +} + void CCVKCommandBuffer::bindPipelineState(PipelineState *pso) { CCVKGPUPipelineState *gpuPipelineState = static_cast(pso)->gpuPipelineState(); diff --git a/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.h b/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.h index 1eae85158ed..55adb5a8e57 100644 --- a/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.h +++ b/native/cocos/renderer/gfx-vulkan/VKCommandBuffer.h @@ -41,6 +41,9 @@ class CC_VULKAN_API CCVKCommandBuffer final : public CommandBuffer { void end() override; void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void bindPipelineState(PipelineState *pso) override; void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override; void bindInputAssembler(InputAssembler *ia) override; @@ -105,6 +108,8 @@ class CC_VULKAN_API CCVKCommandBuffer final : public CommandBuffer { ccstd::unordered_map _barrierEvents; ccstd::queue _pendingQueue; + VkDebugMarkerMarkerInfoEXT _markerInfo = {VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT, nullptr}; + VkDebugUtilsLabelEXT _utilLabelInfo = {VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT, nullptr}; }; } // namespace gfx diff --git a/native/cocos/renderer/gfx-vulkan/VKDevice.cpp b/native/cocos/renderer/gfx-vulkan/VKDevice.cpp index 85d9bacdfcb..ce3e89b09dc 100644 --- a/native/cocos/renderer/gfx-vulkan/VKDevice.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKDevice.cpp @@ -123,6 +123,9 @@ bool CCVKDevice::doInit(const DeviceInfo & /*info*/) { VK_KHR_SWAPCHAIN_EXTENSION_NAME, }; requestedExtensions.push_back(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME); +#if CC_DEBUG + requestedExtensions.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME); +#endif if (_gpuDevice->minorVersion < 2) { requestedExtensions.push_back(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME); } @@ -769,6 +772,16 @@ void CCVKDevice::initDeviceFeature() { _features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = true; _features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = true; _features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] = checkExtension("VK_KHR_depth_stencil_resolve"); + + _gpuContext->debugReport = _gpuContext->checkExtension(VK_EXT_DEBUG_REPORT_EXTENSION_NAME) && + checkExtension(VK_EXT_DEBUG_MARKER_EXTENSION_NAME) && + (vkCmdDebugMarkerBeginEXT != nullptr) && + (vkCmdDebugMarkerInsertEXT != nullptr) && + (vkCmdDebugMarkerEndEXT != nullptr); + _gpuContext->debugUtils = _gpuContext->checkExtension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME) && + (vkCmdBeginDebugUtilsLabelEXT != nullptr) && + (vkCmdInsertDebugUtilsLabelEXT != nullptr) && + (vkCmdEndDebugUtilsLabelEXT != nullptr); } void CCVKDevice::initFormatFeature() { diff --git a/native/cocos/renderer/gfx-vulkan/VKGPUContext.cpp b/native/cocos/renderer/gfx-vulkan/VKGPUContext.cpp index 52af6780706..3a3a114aeae 100644 --- a/native/cocos/renderer/gfx-vulkan/VKGPUContext.cpp +++ b/native/cocos/renderer/gfx-vulkan/VKGPUContext.cpp @@ -190,7 +190,9 @@ bool CCVKGPUContext::initialize() { break; } } +#endif +#if CC_DEBUG // Check if VK_EXT_debug_utils is supported, which supersedes VK_EXT_Debug_Report bool debugUtils = false; if (isExtensionSupported(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, supportedExtensions)) { @@ -338,7 +340,6 @@ bool CCVKGPUContext::initialize() { vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, nullptr); queueFamilyProperties.resize(queueFamilyPropertiesCount); vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, queueFamilyProperties.data()); - return true; } diff --git a/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h b/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h index edb7dfc6f42..71c4e9cbd2b 100644 --- a/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h +++ b/native/cocos/renderer/gfx-vulkan/VKGPUObjects.h @@ -62,6 +62,8 @@ class CCVKGPUContext final { uint32_t minorVersion = 0; bool validationEnabled = false; + bool debugUtils = false; + bool debugReport = false; ccstd::vector layers; ccstd::vector extensions; diff --git a/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.cpp b/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.cpp index d5591fb82cb..1900ad1e405 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.cpp +++ b/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.cpp @@ -239,6 +239,17 @@ void CCWGPUCommandBuffer::endRenderPass() { _gpuCommandBufferObj->renderPassBegan = false; } +void CCWGPUCommandBuffer::insertMarker(const MarkerInfo &marker) { + std::ignore = marker; +} + +void CCWGPUCommandBuffer::beginMarker(const MarkerInfo &marker) { + std::ignore = marker; +} + +void CCWGPUCommandBuffer::endMarker() { +} + void CCWGPUCommandBuffer::bindPipelineState(PipelineState *pso) { _gpuCommandBufferObj->stateCache.pipelineState = static_cast(pso); } diff --git a/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.h b/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.h index e621bbcc346..345ba104f4c 100644 --- a/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.h +++ b/native/cocos/renderer/gfx-wgpu/WGPUCommandBuffer.h @@ -46,6 +46,9 @@ class CCWGPUCommandBuffer final : public CommandBuffer { void end() override; void beginRenderPass(RenderPass *renderPass, Framebuffer *fbo, const Rect &renderArea, const Color *colors, float depth, uint32_t stencil, CommandBuffer *const *secondaryCBs, uint32_t secondaryCBCount) override; void endRenderPass() override; + void insertMarker(const MarkerInfo &marker) override; + void beginMarker(const MarkerInfo &marker) override; + void endMarker() override; void bindPipelineState(PipelineState *pso) override; void bindDescriptorSet(uint32_t set, DescriptorSet *descriptorSet, uint32_t dynamicOffsetCount, const uint32_t *dynamicOffsets) override; void bindInputAssembler(InputAssembler *ia) override; diff --git a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp index aefd8293e5c..bacbc8a90a6 100644 --- a/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeExecutor.cpp @@ -59,6 +59,13 @@ namespace render { namespace { constexpr uint32_t INVALID_ID = 0xFFFFFFFF; +constexpr gfx::Color RASTER_COLOR{0.0, 1.0, 0.0, 1.0}; +constexpr gfx::Color RENDER_QUEUE_COLOR{0.0, 0.5, 0.5, 1.0}; +constexpr gfx::Color COMPUTE_COLOR{0.0, 0.0, 1.0, 1.0}; + +gfx::MarkerInfo makeMarkerInfo(const char *str, const gfx::Color &color) { + return gfx::MarkerInfo{str, color}; +} struct RenderGraphVisitorContext { RenderGraphVisitorContext(RenderGraphVisitorContext&&) = delete; @@ -1117,6 +1124,9 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { } } void begin(const RasterPass& pass, RenderGraph::vertex_descriptor vertID) const { +#if CC_DEBUG + ctx.cmdBuff->beginMarker(makeMarkerInfo(get(RenderGraph::NameTag{}, ctx.g, vertID).c_str(), RASTER_COLOR)); +#endif const auto& renderData = get(RenderGraph::DataTag{}, ctx.g, vertID); if (!renderData.custom.empty()) { const auto& passes = ctx.ppl->custom.renderPasses; @@ -1142,13 +1152,11 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { auto& res = fetchOrCreateFramebuffer(ctx, pass, ctx.scratch); const auto& data = res; auto* cmdBuff = ctx.cmdBuff; - cmdBuff->beginRenderPass( data.renderPass.get(), data.framebuffer.get(), scissor, data.clearColors.data(), data.clearDepth, data.clearStencil); - ctx.currentPass = data.renderPass.get(); } @@ -1156,6 +1164,10 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { tryBindPerPassDescriptorSet(vertID); } void begin(const RasterSubpass& subpass, RenderGraph::vertex_descriptor vertID) const { // NOLINT(readability-convert-member-functions-to-static) +#if CC_DEBUG + ctx.cmdBuff->insertMarker(makeMarkerInfo(get(RenderGraph::NameTag{}, ctx.g, vertID).c_str(), RASTER_COLOR)); +#endif + const auto& renderData = get(RenderGraph::DataTag{}, ctx.g, vertID); if (!renderData.custom.empty()) { const auto& subpasses = ctx.ppl->custom.renderSubpasses; @@ -1191,6 +1203,10 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { // noop } void begin(const ComputePass& pass, RenderGraph::vertex_descriptor vertID) const { // NOLINT(readability-convert-member-functions-to-static) +#if CC_DEBUG + ctx.cmdBuff->beginMarker(makeMarkerInfo(get(RenderGraph::NameTag{}, ctx.g, vertID).c_str(), COMPUTE_COLOR)); +#endif + const auto& renderData = get(RenderGraph::DataTag{}, ctx.g, vertID); if (!renderData.custom.empty()) { const auto& passes = ctx.ppl->custom.computePasses; @@ -1339,6 +1355,10 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { CC_EXPECTS(false); } void begin(const RenderQueue& queue, RenderGraph::vertex_descriptor vertID) const { // NOLINT(readability-convert-member-functions-to-static) +#if CC_DEBUG + ctx.cmdBuff->beginMarker(makeMarkerInfo(get(RenderGraph::NameTag{}, ctx.g, vertID).c_str(), RENDER_QUEUE_COLOR)); +#endif + const auto& renderData = get(RenderGraph::DataTag{}, ctx.g, vertID); if (!renderData.custom.empty()) { const auto& queues = ctx.ppl->custom.renderQueues; @@ -1348,7 +1368,6 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { return; } } - if (queue.viewport.width != 0 && queue.viewport.height != 0) { ctx.cmdBuff->setViewport(queue.viewport); } @@ -1462,6 +1481,10 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { ctx.cmdBuff->endRenderPass(); ctx.currentPass = nullptr; ctx.currentPassLayoutID = LayoutGraphData::null_vertex(); + +#if CC_DEBUG + ctx.cmdBuff->endMarker(); +#endif } void end(const RasterSubpass& subpass, RenderGraph::vertex_descriptor vertID) const { // NOLINT(readability-convert-member-functions-to-static) const auto& renderData = get(RenderGraph::DataTag{}, ctx.g, vertID); @@ -1504,7 +1527,9 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { return; } } - +#if CC_DEBUG + ctx.cmdBuff->endMarker(); +#endif std::ignore = pass; } void end(const ResolvePass& pass, RenderGraph::vertex_descriptor vertID) const { @@ -1529,6 +1554,9 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { return; } } +#if CC_DEBUG + ctx.cmdBuff->endMarker(); +#endif std::ignore = pass; } void end(const SceneData& pass, RenderGraph::vertex_descriptor vertID) const { @@ -1551,7 +1579,7 @@ struct RenderGraphVisitor : boost::dfs_visitor<> { } void end(const gfx::Viewport& pass, RenderGraph::vertex_descriptor vertID) const { } - + void mountResource(const ccstd::pmr::string& name) const { // NOLINT(misc-no-recursion) auto resIter = ctx.fgd.resourceAccessGraph.resourceIndex.find(name); if (resIter != ctx.fgd.resourceAccessGraph.resourceIndex.end()) { From 7a554ea28ec7c2777e8d29e985e7d9b607969dcc Mon Sep 17 00:00:00 2001 From: Jiujiang Liu <37231523+moshuying@users.noreply.github.com> Date: Tue, 15 Aug 2023 14:25:08 +0800 Subject: [PATCH 100/184] [Feature] Improve interacive preview (#15655) * improve preview * support key f * eslint fix * support reset camera * update code * format code * format code * update code format * remove key down * update code format --- editor/inspector/assets/fbx/preview.js | 16 ++++++++++++---- editor/inspector/assets/material-header.js | 12 +++++++++++- editor/inspector/assets/mesh-preview.js | 12 +++++++++++- editor/inspector/assets/skeleton-preview.js | 11 ++++++++++- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/editor/inspector/assets/fbx/preview.js b/editor/inspector/assets/fbx/preview.js index 8b4fed5d2bb..ad9b5fa0967 100644 --- a/editor/inspector/assets/fbx/preview.js +++ b/editor/inspector/assets/fbx/preview.js @@ -13,7 +13,7 @@ exports.template = /* html */`
-
+
@@ -352,7 +352,7 @@ const Elements = { ready() { const panel = this; panel.$.canvas.addEventListener('mousedown', async (event) => { - await callModelPreviewFunction('onMouseDown', { x: event.x, y: event.y }); + await callModelPreviewFunction('onMouseDown', { x: event.x, y: event.y, button: event.button }); async function mousemove(event) { await callModelPreviewFunction('onMouseMove', { @@ -381,6 +381,14 @@ const Elements = { panel.isPreviewDataDirty = true; }); + panel.$.canvas.addEventListener('wheel', async (event) => { + await callModelPreviewFunction('onMouseWheel', { + wheelDeltaY: event.wheelDeltaY, + wheelDeltaX: event.wheelDeltaX, + }); + panel.isPreviewDataDirty = true; + }); + const GlPreview = Editor._Module.require('PreviewExtends').default; panel.glPreview = new GlPreview('scene:model-preview', 'query-model-preview-data'); panel.isPreviewDataDirty = true; @@ -441,8 +449,8 @@ const Elements = { exports.methods = { /** - * - * @param {boolean} hasModel + * + * @param {boolean} hasModel */ updatePanelHidden(hasModel) { this.$.noModel.hidden = hasModel; diff --git a/editor/inspector/assets/material-header.js b/editor/inspector/assets/material-header.js index 504f650ac97..f0ab30cb00b 100644 --- a/editor/inspector/assets/material-header.js +++ b/editor/inspector/assets/material-header.js @@ -95,6 +95,7 @@ exports.methods = { exports.ready = async function() { const panel = this; + callMaterialPreviewFunction('resetCamera'); callMaterialPreviewFunction('setLightEnable', true); panel.$.light.addEventListener('confirm', async () => { await callMaterialPreviewFunction('setLightEnable', this.$.light.checked); @@ -108,7 +109,7 @@ exports.ready = async function() { }); panel.$.canvas.addEventListener('mousedown', async (event) => { - await callMaterialPreviewFunction('onMouseDown', { x: event.x, y: event.y }); + await callMaterialPreviewFunction('onMouseDown', { x: event.x, y: event.y, button: event.button }); async function mousemove(event) { await callMaterialPreviewFunction('onMouseMove', { @@ -136,6 +137,14 @@ exports.ready = async function() { panel.isPreviewDataDirty = true; }); + panel.$.canvas.addEventListener('wheel', async (event) => { + await callMaterialPreviewFunction('onMouseWheel', { + wheelDeltaY: event.wheelDeltaY, + wheelDeltaX: event.wheelDeltaX + }); + panel.isPreviewDataDirty = true; + }); + const GlPreview = Editor._Module.require('PreviewExtends').default; panel.glPreview = new GlPreview('scene:material-preview', 'query-material-preview-data'); @@ -153,6 +162,7 @@ exports.ready = async function() { exports.update = async function(assetList, metaList) { const panel = this; + callMaterialPreviewFunction('resetCamera'); panel.assetList = assetList; panel.metaList = metaList; diff --git a/editor/inspector/assets/mesh-preview.js b/editor/inspector/assets/mesh-preview.js index 36305763307..a69fd881961 100644 --- a/editor/inspector/assets/mesh-preview.js +++ b/editor/inspector/assets/mesh-preview.js @@ -102,7 +102,7 @@ const Elements = { panel.$.canvas.addEventListener('mousedown', async (event) => { // Non-model previews do not respond to events if (panel.$.previewType.value !== previewSelectType.shaded) { return; } - await callMeshPreviewFunction('onMouseDown', { x: event.x, y: event.y }); + await callMeshPreviewFunction('onMouseDown', { x: event.x, y: event.y, button: event.button }); async function mousemove(event) { await callMeshPreviewFunction('onMouseMove', { @@ -131,6 +131,16 @@ const Elements = { panel.isPreviewDataDirty = true; }); + panel.$.canvas.addEventListener('wheel', async (event) => { + // Non-model previews do not respond to events + if (panel.$.previewType.value !== previewSelectType.shaded) { return; } + await callMeshPreviewFunction('onMouseWheel', { + wheelDeltaY: event.wheelDeltaY, + wheelDeltaX: event.wheelDeltaX, + }); + panel.isPreviewDataDirty = true; + }); + const GlPreview = Editor._Module.require('PreviewExtends').default; panel.glPreview = new GlPreview('scene:mesh-preview', 'query-mesh-preview-data'); diff --git a/editor/inspector/assets/skeleton-preview.js b/editor/inspector/assets/skeleton-preview.js index a30033d94dd..f588382f703 100644 --- a/editor/inspector/assets/skeleton-preview.js +++ b/editor/inspector/assets/skeleton-preview.js @@ -49,7 +49,7 @@ const Elements = { const panel = this; panel.$.canvas.addEventListener('mousedown', async (event) => { - await callSkeletonPreviewFunction('onMouseDown', { x: event.x, y: event.y }); + await callSkeletonPreviewFunction('onMouseDown', { x: event.x, y: event.y, button: event.button }); async function mousemove(event) { await callSkeletonPreviewFunction('onMouseMove', { @@ -79,6 +79,15 @@ const Elements = { panel.isPreviewDataDirty = true; }); + panel.$.canvas.addEventListener('wheel', async (event) => { + await callSkeletonPreviewFunction('onMouseWheel', { + wheelDeltaY: event.wheelDeltaY, + wheelDeltaX: event.wheelDeltaX, + }); + panel.isPreviewDataDirty = true; + }); + + const GlPreview = Editor._Module.require('PreviewExtends').default; panel.glPreview = new GlPreview('scene:skeleton-preview', 'query-skeleton-preview-data'); From c63fc769d5d6d5befd41eace5d342aea4c4fe236 Mon Sep 17 00:00:00 2001 From: dogeFu <609075410@qq.com> Date: Tue, 15 Aug 2023 14:30:24 +0800 Subject: [PATCH 101/184] update prefab meta version (#15907) --- editor/assets/default_prefab/2d/Camera.prefab.meta | 2 +- editor/assets/default_prefab/2d/ui/Canvas.prefab.meta | 2 +- editor/assets/default_prefab/3d/Capsule.prefab.meta | 2 +- editor/assets/default_prefab/3d/Cone.prefab.meta | 2 +- editor/assets/default_prefab/3d/Cube.prefab.meta | 2 +- editor/assets/default_prefab/3d/Cylinder.prefab.meta | 2 +- editor/assets/default_prefab/3d/Plane.prefab.meta | 2 +- editor/assets/default_prefab/3d/Quad.prefab.meta | 2 +- editor/assets/default_prefab/3d/Sphere.prefab.meta | 2 +- editor/assets/default_prefab/3d/Torus.prefab.meta | 2 +- editor/assets/default_prefab/Camera.prefab.meta | 2 +- editor/assets/default_prefab/Terrain.prefab.meta | 2 +- editor/assets/default_prefab/light/Point Light.prefab.meta | 2 +- .../default_prefab/light/Ranged Directional Light.prefab.meta | 2 +- editor/assets/default_prefab/light/Reflection Probe.prefab.meta | 2 +- editor/assets/default_prefab/light/Sphere Light.prefab.meta | 2 +- editor/assets/default_prefab/light/Spot Light.prefab.meta | 2 +- editor/assets/default_prefab/ui/Button.prefab.meta | 2 +- editor/assets/default_prefab/ui/Canvas.prefab.meta | 2 +- editor/assets/default_prefab/ui/EditBox.prefab.meta | 2 +- editor/assets/default_prefab/ui/Graphics.prefab.meta | 2 +- editor/assets/default_prefab/ui/Label.prefab.meta | 2 +- editor/assets/default_prefab/ui/Layout.prefab.meta | 2 +- editor/assets/default_prefab/ui/Mask.prefab.meta | 2 +- editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta | 2 +- editor/assets/default_prefab/ui/ProgressBar.prefab.meta | 2 +- editor/assets/default_prefab/ui/RichText.prefab.meta | 2 +- editor/assets/default_prefab/ui/ScrollView.prefab.meta | 2 +- editor/assets/default_prefab/ui/Slider.prefab.meta | 2 +- editor/assets/default_prefab/ui/Sprite.prefab.meta | 2 +- editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta | 2 +- editor/assets/default_prefab/ui/SpriteSplash.prefab.meta | 2 +- editor/assets/default_prefab/ui/TiledMap.prefab.meta | 2 +- editor/assets/default_prefab/ui/Toggle.prefab.meta | 2 +- editor/assets/default_prefab/ui/ToggleContainer.prefab.meta | 2 +- editor/assets/default_prefab/ui/VideoPlayer.prefab.meta | 2 +- editor/assets/default_prefab/ui/WebView.prefab.meta | 2 +- editor/assets/default_prefab/ui/Widget.prefab.meta | 2 +- editor/assets/default_prefab/ui/pageView.prefab.meta | 2 +- editor/assets/tools/debug-view-runtime-control.prefab.meta | 2 +- 40 files changed, 40 insertions(+), 40 deletions(-) diff --git a/editor/assets/default_prefab/2d/Camera.prefab.meta b/editor/assets/default_prefab/2d/Camera.prefab.meta index 43be72409f2..9140b81984e 100644 --- a/editor/assets/default_prefab/2d/Camera.prefab.meta +++ b/editor/assets/default_prefab/2d/Camera.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "3487d118-0158-4983-93fe-c3822790e7c5", diff --git a/editor/assets/default_prefab/2d/ui/Canvas.prefab.meta b/editor/assets/default_prefab/2d/ui/Canvas.prefab.meta index e2403d261e1..955de65ec05 100644 --- a/editor/assets/default_prefab/2d/ui/Canvas.prefab.meta +++ b/editor/assets/default_prefab/2d/ui/Canvas.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "4c33600e-9ca9-483b-b734-946008261697", diff --git a/editor/assets/default_prefab/3d/Capsule.prefab.meta b/editor/assets/default_prefab/3d/Capsule.prefab.meta index 16e79757c68..a5a21cf019f 100644 --- a/editor/assets/default_prefab/3d/Capsule.prefab.meta +++ b/editor/assets/default_prefab/3d/Capsule.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "73ce1f7f-d1f4-4942-ad93-66ca3b3041ab", diff --git a/editor/assets/default_prefab/3d/Cone.prefab.meta b/editor/assets/default_prefab/3d/Cone.prefab.meta index 99f4f574333..5b5113f9f0d 100644 --- a/editor/assets/default_prefab/3d/Cone.prefab.meta +++ b/editor/assets/default_prefab/3d/Cone.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "6350d660-e888-4acf-a552-f3b719ae9110", diff --git a/editor/assets/default_prefab/3d/Cube.prefab.meta b/editor/assets/default_prefab/3d/Cube.prefab.meta index 7c12ed89459..12020ef451a 100644 --- a/editor/assets/default_prefab/3d/Cube.prefab.meta +++ b/editor/assets/default_prefab/3d/Cube.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "30da77a1-f02d-4ede-aa56-403452ee7fde", diff --git a/editor/assets/default_prefab/3d/Cylinder.prefab.meta b/editor/assets/default_prefab/3d/Cylinder.prefab.meta index 71bf262ef47..6c5684fdca6 100644 --- a/editor/assets/default_prefab/3d/Cylinder.prefab.meta +++ b/editor/assets/default_prefab/3d/Cylinder.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "ab3e16f9-671e-48a7-90b7-d0884d9cbb85", diff --git a/editor/assets/default_prefab/3d/Plane.prefab.meta b/editor/assets/default_prefab/3d/Plane.prefab.meta index 7bae40651b3..d38151b7473 100644 --- a/editor/assets/default_prefab/3d/Plane.prefab.meta +++ b/editor/assets/default_prefab/3d/Plane.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "40563723-f8fc-4216-99ea-a81636435c10", diff --git a/editor/assets/default_prefab/3d/Quad.prefab.meta b/editor/assets/default_prefab/3d/Quad.prefab.meta index 32c9ec2aab2..dc8e2b361b2 100644 --- a/editor/assets/default_prefab/3d/Quad.prefab.meta +++ b/editor/assets/default_prefab/3d/Quad.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "34a07346-9f62-4a84-90ae-cb83f7a426c1", diff --git a/editor/assets/default_prefab/3d/Sphere.prefab.meta b/editor/assets/default_prefab/3d/Sphere.prefab.meta index 5a2a2da0fad..ab4f2ec0c6f 100644 --- a/editor/assets/default_prefab/3d/Sphere.prefab.meta +++ b/editor/assets/default_prefab/3d/Sphere.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "655c9519-1a37-472b-bae6-29fefac0b550", diff --git a/editor/assets/default_prefab/3d/Torus.prefab.meta b/editor/assets/default_prefab/3d/Torus.prefab.meta index 7ec5945df32..eb825d2f575 100644 --- a/editor/assets/default_prefab/3d/Torus.prefab.meta +++ b/editor/assets/default_prefab/3d/Torus.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "d47f5d5e-c931-4ff4-987b-cc818a728b82", diff --git a/editor/assets/default_prefab/Camera.prefab.meta b/editor/assets/default_prefab/Camera.prefab.meta index 8f1baf0ca72..c59e4c5e4a4 100644 --- a/editor/assets/default_prefab/Camera.prefab.meta +++ b/editor/assets/default_prefab/Camera.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "bb0a6472-cd67-4afb-a031-94fca8f4cc92", diff --git a/editor/assets/default_prefab/Terrain.prefab.meta b/editor/assets/default_prefab/Terrain.prefab.meta index 2b0c2d2db4d..4cd34a340d4 100644 --- a/editor/assets/default_prefab/Terrain.prefab.meta +++ b/editor/assets/default_prefab/Terrain.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "90e8b0d4-12dc-412d-9156-ea1fdb18c15b", diff --git a/editor/assets/default_prefab/light/Point Light.prefab.meta b/editor/assets/default_prefab/light/Point Light.prefab.meta index 4af906d625c..54d9e7a4705 100644 --- a/editor/assets/default_prefab/light/Point Light.prefab.meta +++ b/editor/assets/default_prefab/light/Point Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "03029371-ee64-4f14-820a-d495ad7cdc29", diff --git a/editor/assets/default_prefab/light/Ranged Directional Light.prefab.meta b/editor/assets/default_prefab/light/Ranged Directional Light.prefab.meta index 27a9e7d9482..9181f35f84d 100644 --- a/editor/assets/default_prefab/light/Ranged Directional Light.prefab.meta +++ b/editor/assets/default_prefab/light/Ranged Directional Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "df72d0f6-49d3-452a-b082-8b23d38b33af", diff --git a/editor/assets/default_prefab/light/Reflection Probe.prefab.meta b/editor/assets/default_prefab/light/Reflection Probe.prefab.meta index ee7309cdab8..872b7155bc6 100644 --- a/editor/assets/default_prefab/light/Reflection Probe.prefab.meta +++ b/editor/assets/default_prefab/light/Reflection Probe.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "d8b49b64-cfba-4cfa-be53-1e469547b28b", diff --git a/editor/assets/default_prefab/light/Sphere Light.prefab.meta b/editor/assets/default_prefab/light/Sphere Light.prefab.meta index 6079668c77f..f6235f6b6d1 100644 --- a/editor/assets/default_prefab/light/Sphere Light.prefab.meta +++ b/editor/assets/default_prefab/light/Sphere Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "4182ee46-ffa0-4de2-b66b-c93cc6c7e9b8", diff --git a/editor/assets/default_prefab/light/Spot Light.prefab.meta b/editor/assets/default_prefab/light/Spot Light.prefab.meta index 1183e7231ef..911d5933b42 100644 --- a/editor/assets/default_prefab/light/Spot Light.prefab.meta +++ b/editor/assets/default_prefab/light/Spot Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "7a49aa24-bd7a-40a8-b31a-b2a9da85abcd", diff --git a/editor/assets/default_prefab/ui/Button.prefab.meta b/editor/assets/default_prefab/ui/Button.prefab.meta index 0083d6b4730..6b0771367ba 100644 --- a/editor/assets/default_prefab/ui/Button.prefab.meta +++ b/editor/assets/default_prefab/ui/Button.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "90bdd2a9-2838-4888-b66c-e94c8b7a5169", diff --git a/editor/assets/default_prefab/ui/Canvas.prefab.meta b/editor/assets/default_prefab/ui/Canvas.prefab.meta index 3fedba353a8..4384e4d0773 100644 --- a/editor/assets/default_prefab/ui/Canvas.prefab.meta +++ b/editor/assets/default_prefab/ui/Canvas.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "f773db21-62b8-4540-956a-29bacf5ddbf5", diff --git a/editor/assets/default_prefab/ui/EditBox.prefab.meta b/editor/assets/default_prefab/ui/EditBox.prefab.meta index fd9818f9ec4..f3ead2aa227 100644 --- a/editor/assets/default_prefab/ui/EditBox.prefab.meta +++ b/editor/assets/default_prefab/ui/EditBox.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "05e79121-8675-4551-9ad7-1b901a4025db", diff --git a/editor/assets/default_prefab/ui/Graphics.prefab.meta b/editor/assets/default_prefab/ui/Graphics.prefab.meta index bd27edc00ed..406c853a9f5 100644 --- a/editor/assets/default_prefab/ui/Graphics.prefab.meta +++ b/editor/assets/default_prefab/ui/Graphics.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "c96e159e-43ea-4a16-8279-05bc39119d1a", diff --git a/editor/assets/default_prefab/ui/Label.prefab.meta b/editor/assets/default_prefab/ui/Label.prefab.meta index e6618c474cf..2c633805df3 100644 --- a/editor/assets/default_prefab/ui/Label.prefab.meta +++ b/editor/assets/default_prefab/ui/Label.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "36008810-7ad3-47c0-8112-e30aee089e45", diff --git a/editor/assets/default_prefab/ui/Layout.prefab.meta b/editor/assets/default_prefab/ui/Layout.prefab.meta index f3eb67a7375..ac6f83cd8ab 100644 --- a/editor/assets/default_prefab/ui/Layout.prefab.meta +++ b/editor/assets/default_prefab/ui/Layout.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "a9ef7dfc-ea8b-4cf8-918e-36da948c4de0", diff --git a/editor/assets/default_prefab/ui/Mask.prefab.meta b/editor/assets/default_prefab/ui/Mask.prefab.meta index 24665d8fb56..2b415c21c59 100644 --- a/editor/assets/default_prefab/ui/Mask.prefab.meta +++ b/editor/assets/default_prefab/ui/Mask.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "7fa63aed-f3e2-46a5-8a7c-c1a1adf6cea6", diff --git a/editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta b/editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta index b9d8833352b..4876341a321 100644 --- a/editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta +++ b/editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "f396261e-3e06-41ec-bdd6-9a8b6d99026f", diff --git a/editor/assets/default_prefab/ui/ProgressBar.prefab.meta b/editor/assets/default_prefab/ui/ProgressBar.prefab.meta index 3611777f751..2f564bd5be8 100644 --- a/editor/assets/default_prefab/ui/ProgressBar.prefab.meta +++ b/editor/assets/default_prefab/ui/ProgressBar.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "0d9353c4-6fb9-49bb-bc62-77f1750078c2", diff --git a/editor/assets/default_prefab/ui/RichText.prefab.meta b/editor/assets/default_prefab/ui/RichText.prefab.meta index 20f31329057..09136191923 100644 --- a/editor/assets/default_prefab/ui/RichText.prefab.meta +++ b/editor/assets/default_prefab/ui/RichText.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "fc6bfcfa-8086-4326-809b-0ba1226bac7d", diff --git a/editor/assets/default_prefab/ui/ScrollView.prefab.meta b/editor/assets/default_prefab/ui/ScrollView.prefab.meta index 181bba25466..a54b724011e 100644 --- a/editor/assets/default_prefab/ui/ScrollView.prefab.meta +++ b/editor/assets/default_prefab/ui/ScrollView.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "c1baa707-78d6-4b89-8d5d-0b7fdf0c39bc", diff --git a/editor/assets/default_prefab/ui/Slider.prefab.meta b/editor/assets/default_prefab/ui/Slider.prefab.meta index d2a1e307889..e74b124a086 100644 --- a/editor/assets/default_prefab/ui/Slider.prefab.meta +++ b/editor/assets/default_prefab/ui/Slider.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "2bd7e5b6-cd8c-41a1-8136-ddb8efbf6326", diff --git a/editor/assets/default_prefab/ui/Sprite.prefab.meta b/editor/assets/default_prefab/ui/Sprite.prefab.meta index 6730fc2d496..da1efd5e39a 100644 --- a/editor/assets/default_prefab/ui/Sprite.prefab.meta +++ b/editor/assets/default_prefab/ui/Sprite.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "9db8cd0b-cbe4-42e7-96a9-a239620c0a9d", diff --git a/editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta b/editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta index 8778f9d8b0b..40cf1cc1d08 100644 --- a/editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta +++ b/editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "279ed042-5a65-4efe-9afb-2fc23c61e15a", diff --git a/editor/assets/default_prefab/ui/SpriteSplash.prefab.meta b/editor/assets/default_prefab/ui/SpriteSplash.prefab.meta index 0d0314abfe6..cbfcc852751 100644 --- a/editor/assets/default_prefab/ui/SpriteSplash.prefab.meta +++ b/editor/assets/default_prefab/ui/SpriteSplash.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "e5f21aad-3a69-4011-ac62-b74352ac025e", diff --git a/editor/assets/default_prefab/ui/TiledMap.prefab.meta b/editor/assets/default_prefab/ui/TiledMap.prefab.meta index bc8c3ce131a..4b1b2c4e25c 100644 --- a/editor/assets/default_prefab/ui/TiledMap.prefab.meta +++ b/editor/assets/default_prefab/ui/TiledMap.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "3139fa4f-8c42-4ce6-98be-15e848d9734c", diff --git a/editor/assets/default_prefab/ui/Toggle.prefab.meta b/editor/assets/default_prefab/ui/Toggle.prefab.meta index 06548ff1b1c..bd92c9057e5 100644 --- a/editor/assets/default_prefab/ui/Toggle.prefab.meta +++ b/editor/assets/default_prefab/ui/Toggle.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "0e89afe7-56de-4f99-96a1-cba8a75bedd2", diff --git a/editor/assets/default_prefab/ui/ToggleContainer.prefab.meta b/editor/assets/default_prefab/ui/ToggleContainer.prefab.meta index 970e885179b..311dc9b3c86 100644 --- a/editor/assets/default_prefab/ui/ToggleContainer.prefab.meta +++ b/editor/assets/default_prefab/ui/ToggleContainer.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "2af73429-41d1-4346-9062-7798e42945dd", diff --git a/editor/assets/default_prefab/ui/VideoPlayer.prefab.meta b/editor/assets/default_prefab/ui/VideoPlayer.prefab.meta index db30f12dd43..9f090bd41eb 100644 --- a/editor/assets/default_prefab/ui/VideoPlayer.prefab.meta +++ b/editor/assets/default_prefab/ui/VideoPlayer.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "7e089eaf-fa97-40d7-8a20-741a152585df", diff --git a/editor/assets/default_prefab/ui/WebView.prefab.meta b/editor/assets/default_prefab/ui/WebView.prefab.meta index e3ea7e3eef3..a5df7884ecc 100644 --- a/editor/assets/default_prefab/ui/WebView.prefab.meta +++ b/editor/assets/default_prefab/ui/WebView.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "9c541fa2-1dc8-4d8b-813a-aec89133f5b1", diff --git a/editor/assets/default_prefab/ui/Widget.prefab.meta b/editor/assets/default_prefab/ui/Widget.prefab.meta index 42a5c51e716..bcf252290f4 100644 --- a/editor/assets/default_prefab/ui/Widget.prefab.meta +++ b/editor/assets/default_prefab/ui/Widget.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "36ed4422-3542-4cc4-bf02-dc4bfc590836", diff --git a/editor/assets/default_prefab/ui/pageView.prefab.meta b/editor/assets/default_prefab/ui/pageView.prefab.meta index 8e7a54907e6..95d4ec9593f 100644 --- a/editor/assets/default_prefab/ui/pageView.prefab.meta +++ b/editor/assets/default_prefab/ui/pageView.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "20a5d8cb-ccad-4543-a937-fccd98c9f3de", diff --git a/editor/assets/tools/debug-view-runtime-control.prefab.meta b/editor/assets/tools/debug-view-runtime-control.prefab.meta index d6157b53851..8ed35ee2c61 100644 --- a/editor/assets/tools/debug-view-runtime-control.prefab.meta +++ b/editor/assets/tools/debug-view-runtime-control.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.46", "importer": "prefab", "imported": true, "uuid": "7f4ddeab-efa9-4b76-bf6a-029520f68461", From 88bad37193fd0ea804ecc48347d0a7091a943bdf Mon Sep 17 00:00:00 2001 From: oahc09 Date: Tue, 15 Aug 2023 15:06:32 +0800 Subject: [PATCH 102/184] improve:xr pico enable detach device thread when use vulkan (#15926) --- native/cocos/renderer/GFXDeviceManager.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/native/cocos/renderer/GFXDeviceManager.h b/native/cocos/renderer/GFXDeviceManager.h index 04fda885a05..15d5d1538dd 100644 --- a/native/cocos/renderer/GFXDeviceManager.h +++ b/native/cocos/renderer/GFXDeviceManager.h @@ -82,10 +82,6 @@ class CC_DLL DeviceManager final { #endif #ifdef CC_USE_VULKAN - #if XR_OEM_PICO - Device::isSupportDetachDeviceThread = false; - #endif - bool skipVulkan = false; #if CC_PLATFORM == CC_PLATFORM_ANDROID auto sdkVersion = BasePlatform::getPlatform()->getSdkVersion(); From 22ab4b2e4485d4b3f4ebd27ae0e38d7bbe5327f4 Mon Sep 17 00:00:00 2001 From: oahc09 Date: Tue, 15 Aug 2023 15:07:37 +0800 Subject: [PATCH 103/184] improve:xr pico use vk1.1 (#15959) --- native/cocos/platform/java/modules/XRInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/cocos/platform/java/modules/XRInterface.cpp b/native/cocos/platform/java/modules/XRInterface.cpp index a9995cbfe55..cc9981801a0 100644 --- a/native/cocos/platform/java/modules/XRInterface.cpp +++ b/native/cocos/platform/java/modules/XRInterface.cpp @@ -481,7 +481,7 @@ void XRInterface::initialize(void *javaVM, void *activity) { #if XR_OEM_PICO std::string graphicsApiName = GraphicsApiOpenglES; #if CC_USE_VULKAN - graphicsApiName = GraphicsApiVulkan_1_0; + graphicsApiName = GraphicsApiVulkan_1_1; #endif xr::XrEntry::getInstance()->createXrInstance(graphicsApiName.c_str()); #endif From 012531ffeb515b8cd97e421178e288ab274b06e5 Mon Sep 17 00:00:00 2001 From: bofeng-song Date: Tue, 15 Aug 2023 16:59:11 +0800 Subject: [PATCH 104/184] Fix logic error of audio's currentTime (#15962) --- pal/audio/minigame/player-minigame.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/pal/audio/minigame/player-minigame.ts b/pal/audio/minigame/player-minigame.ts index cecf6e83231..8f6ed0a67ed 100644 --- a/pal/audio/minigame/player-minigame.ts +++ b/pal/audio/minigame/player-minigame.ts @@ -329,6 +329,7 @@ export class AudioPlayerMinigame implements OperationQueueable { if (this._state === AudioState.PLAYING && !this._seeking) { time = clamp(time, 0, this.duration); this._seeking = true; + this._cacheTime = time; this._eventTarget.once(AudioEvent.SEEKED, resolve); this._innerAudioContext.seek(time); } else { From dfe70e83a4361ad4421521a612faa5e17ed092be Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Wed, 16 Aug 2023 11:20:03 +0800 Subject: [PATCH 105/184] deprecated UIMeshRenderer (#15956) * deprecated UIMeshRenderer * update * add info * fix CI --- cocos/2d/components/ui-mesh-renderer.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cocos/2d/components/ui-mesh-renderer.ts b/cocos/2d/components/ui-mesh-renderer.ts index 9542a49abbd..1cf5f6791f7 100644 --- a/cocos/2d/components/ui-mesh-renderer.ts +++ b/cocos/2d/components/ui-mesh-renderer.ts @@ -34,7 +34,7 @@ import { NativeUIModelProxy } from '../renderer/native-2d'; import { uiRendererManager } from '../framework/ui-renderer-manager'; import { RenderEntity, RenderEntityType } from '../renderer/render-entity'; import { MeshRenderData, RenderData } from '../renderer/render-data'; -import { assert, cclegacy } from '../../core'; +import { assert, cclegacy, warn } from '../../core'; import { RenderDrawInfoType } from '../renderer/render-draw-info'; import type { UIRenderer } from '../framework/ui-renderer'; @@ -47,6 +47,8 @@ import type { UIRenderer } from '../framework/ui-renderer'; * @zh * UI 模型基础组件。 * 当你在 UI 中放置模型或者粒子的时候,必须添加该组件才能渲染。该组件必须放置在带有 [[MeshRenderer]] 或者 [[ParticleSystem]] 组件的节点上。 + * @deprecated This component is not recommended to be used, please use Render Texture instead. + * See [UIMeshRenderer Reference](https://docs.cocos.com/creator/manual/en/ui-system/components/editor/ui-model.html) */ @ccclass('cc.UIMeshRenderer') @help('i18n:cc.UIMeshRenderer') @@ -99,7 +101,7 @@ export class UIMeshRenderer extends Component { this._modelComponent = this.getComponent('cc.ModelRenderer') as ModelRenderer; if (!this._modelComponent) { - console.warn(`node '${this.node && this.node.name}' doesn't have any renderable component`); + warn(`node '${this.node && this.node.name}' doesn't have any renderable component`); return; } if (JSB) { @@ -176,7 +178,7 @@ export class UIMeshRenderer extends Component { } } - private _uploadRenderData (index): void { + private _uploadRenderData (index: number): void { if (JSB) { const renderData = MeshRenderData.add(); // TODO: here we weirdly use UIMeshRenderer as UIRenderer @@ -200,6 +202,7 @@ export class UIMeshRenderer extends Component { * 注意:不要手动调用该函数,除非你理解整个流程。 */ public postUpdateAssembler (render: IBatcher): void { + // No behavior for this component } public update (): void { @@ -251,12 +254,14 @@ export class UIMeshRenderer extends Component { * @deprecated Since v3.7.0, this is an engine private interface that will be removed in the future. */ public setNodeDirty (): void { + // No behavior for this component } /** * @deprecated Since v3.7.0, this is an engine private interface that will be removed in the future. */ public setTextureDirty (): void { + // No behavior for this component } protected _canRender (): boolean { From e2b1e2c3186c3e6621c69248779bcbfe9e1d88a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=A3=AE=E6=96=8C?= Date: Wed, 16 Aug 2023 11:43:39 +0800 Subject: [PATCH 106/184] show node component icon (#15850) --- editor/inspector/contributions/node.js | 1 + 1 file changed, 1 insertion(+) diff --git a/editor/inspector/contributions/node.js b/editor/inspector/contributions/node.js index e454f83b46d..cba64780a8c 100644 --- a/editor/inspector/contributions/node.js +++ b/editor/inspector/contributions/node.js @@ -1211,6 +1211,7 @@ const Elements = {
+ ${component.type}${component.mountedRoot ? '+' : ''} From cdaff8725e9e765cec6cce815abde1dff471322f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Wed, 16 Aug 2023 14:06:34 +0800 Subject: [PATCH 107/184] Optimize general animation performance 3.8.0 (#15582) * Optimize general animation performance 3.8.0 * Fix lint --- cocos/animation/animation-clip.ts | 21 +++++++++++++-------- cocos/animation/tracks/vector-track.ts | 19 +++++++++---------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/cocos/animation/animation-clip.ts b/cocos/animation/animation-clip.ts index 7285e2a1fd9..eca1c287722 100644 --- a/cocos/animation/animation-clip.ts +++ b/cocos/animation/animation-clip.ts @@ -26,7 +26,9 @@ import { ccclass, serializable } from 'cc.decorator'; import { DEBUG } from 'internal:constants'; import { Asset } from '../asset/assets/asset'; import { SpriteFrame } from '../2d/assets/sprite-frame'; -import { errorID, warnID, cclegacy, js, geometry, approx, clamp, Mat4, Quat, Vec3, murmurhash2_32_gc, binarySearchEpsilon, assertIsTrue, RealCurve } from '../core'; +import { errorID, warnID, cclegacy, js, geometry, approx, clamp, Mat4, Quat, + Vec3, murmurhash2_32_gc, binarySearchEpsilon, assertIsTrue, RealCurve, +} from '../core'; import { SkelAnimDataHub } from '../3d/skeletal-animation/skeletal-animation-data-hub'; import { WrapMode as AnimationWrapMode, WrapMode } from './types'; import { Node } from '../scene-graph/node'; @@ -790,9 +792,9 @@ export class AnimationClip extends Asset { ratios: number[]; eventGroups: IAnimationEventGroup[]; } = { - ratios: [], - eventGroups: [], - }; + ratios: [], + eventGroups: [], + }; private _createEvalWithBinder (target: unknown, binder: Binder, rootMotionOptions: RootMotionOptions | undefined): AnimationClipEvaluation { if (this._legacyDataDirty) { @@ -1039,12 +1041,14 @@ class TrackEvalStatus { constructor (binding: RuntimeBinding, trackEval: TrackEval) { this._binding = binding; this._trackEval = trackEval; + this._shouldEvaluateDefault = !!binding.getValue && trackEval.requiresDefault; } public evaluate (time: number): void { const { _binding: binding, _trackEval: trackEval } = this; - const defaultValue = binding.getValue && trackEval.requiresDefault - ? binding.getValue() as TValue extends unknown ? unknown : Readonly + const defaultValue = this._shouldEvaluateDefault + // See `this._shouldEvaluateDefault` for the assertion. + ? (binding.getValue!)() as TValue extends unknown ? unknown : Readonly : undefined; const value = trackEval.evaluate(time, defaultValue); binding.setValue(value); @@ -1052,6 +1056,7 @@ class TrackEvalStatus { private _binding: RuntimeBinding; private _trackEval: TrackEval; + private _shouldEvaluateDefault = true; } interface AnimationClipEvalContext { @@ -1450,7 +1455,7 @@ class RootMotionEvaluation { } function relativeTransform (out: Mat4, from: Mat4, to: Mat4): void { -Mat4.invert(out, from); + Mat4.invert(out, from); Mat4.multiply(out, to, out); } @@ -1533,7 +1538,7 @@ class EventEvaluator { } } - public reset () { + public reset (): void { this._lastFrameIndex = -1; this._lastIterations = 0.0; this._lastDirection = 0; diff --git a/cocos/animation/tracks/vector-track.ts b/cocos/animation/tracks/vector-track.ts index fa71b8263bf..468d71e2a3c 100644 --- a/cocos/animation/tracks/vector-track.ts +++ b/cocos/animation/tracks/vector-track.ts @@ -141,21 +141,20 @@ export class Vec3TrackEval implements TrackEval { } public evaluate (time: number, defaultValue?: Readonly): Vec3 { + const { _x, _y, _z, _result } = this; if (defaultValue) { - Vec3.copy(this._result, defaultValue); + Vec3.copy(_result, defaultValue); } - - if (this._x) { - this._result.x = this._x.evaluate(time); + if (_x) { + _result.x = _x.evaluate(time); } - if (this._y) { - this._result.y = this._y.evaluate(time); + if (_y) { + _result.y = _y.evaluate(time); } - if (this._z) { - this._result.z = this._z.evaluate(time); + if (_z) { + _result.z = _z.evaluate(time); } - - return this._result; + return _result; } private _result: Vec3 = new Vec3(); From 7ed24f87ad21900c0bb68bbfc30062acef0ce915 Mon Sep 17 00:00:00 2001 From: Ling Zhan Date: Wed, 16 Aug 2023 14:10:49 +0800 Subject: [PATCH 108/184] update native/external-config to v3.8.1-10 (#15965) --- native/external-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/external-config.json b/native/external-config.json index 5427b2b8bfa..b16d14480ec 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-9" + "checkout": "v3.8.1-10" } } From a7213c3b6cb0099bb446cf2acd612f954be7033c Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Wed, 16 Aug 2023 14:11:03 +0800 Subject: [PATCH 109/184] RichText: support set default font color (#15669) * add richText default color * doc --- cocos/2d/components/rich-text.ts | 45 ++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/cocos/2d/components/rich-text.ts b/cocos/2d/components/rich-text.ts index 385f5cb2647..a81d5ea8743 100644 --- a/cocos/2d/components/rich-text.ts +++ b/cocos/2d/components/rich-text.ts @@ -236,6 +236,26 @@ export class RichText extends Component { this._updateRichTextStatus(); } + /** + * @en + * Font color of RichText. Works when the text content does not have a color parameter set. Transparency cascade is not supported. + * + * @zh + * 富文本默认文字颜色。在文本内容没有设置颜色参数时生效。暂不支持颜色级联。 + */ + @type(Color) + get fontColor (): Color { + return this._fontColor; + } + set fontColor (value: Color) { + if (this._fontColor === value) { + return; + } + + this._fontColor = value; + this._updateTextDefaultColor(); + } + /** * @en * Custom System font of RichText. @@ -454,6 +474,8 @@ export class RichText extends Component { @serializable protected _fontSize = 40; @serializable + protected _fontColor: Color = Color.WHITE.clone(); + @serializable protected _maxWidth = 0; @serializable protected _fontFamily = 'Arial'; @@ -1023,6 +1045,21 @@ export class RichText extends Component { } } + protected _updateTextDefaultColor (): void { + for (let i = 0; i < this._segments.length; ++i) { + const segment = this._segments[i]; + const label = segment.node.getComponent(Label); + if (!label) { + continue; + } + if (this._textArray[segment.styleIndex]?.style?.color) { + continue; + } + + label.color = this._fontColor; + } + } + protected _updateRichText (): void { if (!this.enabledInHierarchy) { return; @@ -1241,7 +1278,11 @@ export class RichText extends Component { } if (textStyle) { - label.color = this._convertLiteralColorValue(textStyle.color || 'white'); + if (textStyle.color) { + label.color = this._convertLiteralColorValue(textStyle.color); + } else { + label.color = this._fontColor; + } label.isBold = !!textStyle.bold; label.isItalic = !!textStyle.italic; // TODO: temporary implementation, the italic effect should be implemented in the internal of label-assembler. @@ -1293,7 +1334,7 @@ export class RichText extends Component { protected _resetLabelState (label: Label): void { label.fontSize = this._fontSize; - label.color = Color.WHITE; + label.color = this._fontColor; label.isBold = false; label.isItalic = false; label.isUnderline = false; From 02f7d6e8bb7f194d3cfc61176990a2ae4ed6d5f7 Mon Sep 17 00:00:00 2001 From: Ling Zhan Date: Wed, 16 Aug 2023 15:05:06 +0800 Subject: [PATCH 110/184] V3.8.1 mesh collider set mesh (#15520) * bullet mesh-collider supports changing mesh after initialization #15363 * physx mesh-collider supports changing mesh after initialization #15363 * tweak --- .../bullet/shapes/bullet-trimesh-shape.ts | 42 ++++++++++--------- .../physx/shapes/physx-trimesh-shape.ts | 8 ++-- .../physics/physx/shapes/PhysXTrimesh.cpp | 1 + 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/cocos/physics/bullet/shapes/bullet-trimesh-shape.ts b/cocos/physics/bullet/shapes/bullet-trimesh-shape.ts index 8893c1fbffc..935fe7f4b93 100644 --- a/cocos/physics/bullet/shapes/bullet-trimesh-shape.ts +++ b/cocos/physics/bullet/shapes/bullet-trimesh-shape.ts @@ -42,28 +42,30 @@ export class BulletTrimeshShape extends BulletShape implements ITrimeshShape { if (!this._isInitialized) return; if (this._impl && BulletCache.isNotEmptyShape(this._impl)) { - // TODO: change the mesh after initialization - warnID(9620); - } else { - const mesh = v; - if (mesh && mesh.renderingSubMeshes.length > 0) { - if (this.collider.convex) { - const btTriangleMesh = this._getBtTriangleMesh(mesh); - this._impl = bt.ConvexTriangleMeshShape_new(btTriangleMesh); - } else { - this.btBVHMeshShape = BulletBvhTriangleMeshShape.getBulletBvhTriangleMeshShape(mesh.hash, mesh); - this._impl = bt.ScaledBvhTriangleMeshShape_new(this.btBVHMeshShape.bulletBvhTriangleMeshShapePtr, 1, 1, 1); - } - const bt_v3 = BulletCache.instance.BT_V3_0; - cocos2BulletVec3(bt_v3, this._collider.node.worldScale); - bt.CollisionShape_setLocalScaling(this._impl, bt_v3); - bt.CollisionShape_setMargin(this._impl, 0.01); - this.setCompound(this._compound); - this.updateByReAdd(); - this.setWrapper(); + if (this._compound) { bt.CompoundShape_removeChildShape(this._compound, this._impl); } + bt._safe_delete(this._impl, EBulletType.EBulletTypeCollisionShape); + BulletCache.delWrapper(this._impl, BulletShape.TYPE); + this._impl = 0; + } + + const mesh = v; + if (mesh && mesh.renderingSubMeshes.length > 0) { + if (this.collider.convex) { + const btTriangleMesh = this._getBtTriangleMesh(mesh); + this._impl = bt.ConvexTriangleMeshShape_new(btTriangleMesh); } else { - this._impl = bt.EmptyShape_static(); + this.btBVHMeshShape = BulletBvhTriangleMeshShape.getBulletBvhTriangleMeshShape(mesh.hash, mesh); + this._impl = bt.ScaledBvhTriangleMeshShape_new(this.btBVHMeshShape.bulletBvhTriangleMeshShapePtr, 1, 1, 1); } + const bt_v3 = BulletCache.instance.BT_V3_0; + cocos2BulletVec3(bt_v3, this._collider.node.worldScale); + bt.CollisionShape_setLocalScaling(this._impl, bt_v3); + bt.CollisionShape_setMargin(this._impl, 0.01); + this.setCompound(this._compound); + this.updateByReAdd(); + this.setWrapper(); + } else { + this._impl = bt.EmptyShape_static(); } } diff --git a/cocos/physics/physx/shapes/physx-trimesh-shape.ts b/cocos/physics/physx/shapes/physx-trimesh-shape.ts index 77841f09846..bdbd797b326 100644 --- a/cocos/physics/physx/shapes/physx-trimesh-shape.ts +++ b/cocos/physics/physx/shapes/physx-trimesh-shape.ts @@ -27,7 +27,7 @@ import { IVec3Like, Quat, Vec3 } from '../../../core'; import { Mesh } from '../../../3d/assets'; import { MeshCollider, PhysicsMaterial } from '../../framework'; import { ITrimeshShape } from '../../spec/i-physics-shape'; -import { createConvexMesh, createMeshGeometryFlags, createTriangleMesh, PX, _trans, removeReference } from '../physx-adapter'; +import { addReference, createConvexMesh, createMeshGeometryFlags, createTriangleMesh, PX, _trans, removeReference } from '../physx-adapter'; import { EPhysXShapeType, PhysXShape } from './physx-shape'; import { AttributeName } from '../../../gfx'; import { PhysXInstance } from '../physx-instance'; @@ -42,6 +42,7 @@ export class PhysXTrimeshShape extends PhysXShape implements ITrimeshShape { setMesh (v: Mesh | null): void { if (v && v.renderingSubMeshes.length > 0) { if (this._impl != null) { + this.removeFromBody(); removeReference(this, this._impl); this._impl.release(); this._impl = null; @@ -49,7 +50,7 @@ export class PhysXTrimeshShape extends PhysXShape implements ITrimeshShape { const physics = PhysXInstance.physics; const collider = this.collider; - const pxmat = this.getSharedMaterial(collider.sharedMaterial!); + const pxmat = this.getSharedMaterial(collider.sharedMaterial); const meshScale = PhysXShape.MESH_SCALE; meshScale.setScale(Vec3.ONE); meshScale.setRotation(Quat.IDENTITY); @@ -73,7 +74,8 @@ export class PhysXTrimeshShape extends PhysXShape implements ITrimeshShape { } this.updateGeometry(); this._impl = physics.createShape(this.geometry, pxmat, true, this._flags); - this.updateByReAdd(); + this.addToBody(); + addReference(this, this._impl);//in case setMesh is called after initialization } } diff --git a/native/cocos/physics/physx/shapes/PhysXTrimesh.cpp b/native/cocos/physics/physx/shapes/PhysXTrimesh.cpp index f4b0506044c..e8f854d16d4 100644 --- a/native/cocos/physics/physx/shapes/PhysXTrimesh.cpp +++ b/native/cocos/physics/physx/shapes/PhysXTrimesh.cpp @@ -38,6 +38,7 @@ void PhysXTrimesh::setMesh(uint32_t objectID) { uintptr_t handle = PhysXWorld::getInstance().getPXPtrWithPXObjectID(objectID); if (handle == 0) return; if (_mShape) { + getSharedBody().removeShape(*this); eraseFromShapeMap(); _mShape->release(); _mShape = nullptr; From 1256656efd31a85a6770665be81cfac61609158b Mon Sep 17 00:00:00 2001 From: troublemaker52025 Date: Wed, 16 Aug 2023 15:16:43 +0800 Subject: [PATCH 111/184] deferred tone-mapping and fog with float output in custom pipeline (#15968) --- cocos/render-scene/core/pass.ts | 16 +++++++++ ...g-pass.ts => float-output-process-pass.ts} | 10 +++--- cocos/rendering/post-process/passes/index.ts | 2 +- .../post-process/post-process-builder.ts | 9 ++--- .../main-functions/misc/sky-fs.chunk | 2 +- .../render-to-scene/pipeline/forward-fs.chunk | 20 +++++------ ...ing.effect => float-output-process.effect} | 33 ++++++++++++++++--- ....meta => float-output-process.effect.meta} | 0 .../pipeline/post-process/chunks/hbao.chunk | 2 +- native/cocos/scene/Pass.cpp | 15 +++++++++ native/cocos/scene/Pass.h | 1 + 11 files changed, 84 insertions(+), 26 deletions(-) rename cocos/rendering/post-process/passes/{tone-mapping-pass.ts => float-output-process-pass.ts} (89%) rename editor/assets/effects/pipeline/{tone-mapping.effect => float-output-process.effect} (56%) rename editor/assets/effects/pipeline/{tone-mapping.effect.meta => float-output-process.effect.meta} (100%) diff --git a/cocos/render-scene/core/pass.ts b/cocos/render-scene/core/pass.ts index 4345d8c5003..408d5938c5f 100644 --- a/cocos/render-scene/core/pass.ts +++ b/cocos/render-scene/core/pass.ts @@ -546,6 +546,10 @@ export class Pass { this._defines[patch.name] = patch.value; } + if (this._isBlend) { + this._defines.CC_IS_TRANSPARENCY_PASS = 1; + } + let shader: Shader | null = null; if (cclegacy.rendering && cclegacy.rendering.enableEffectImport) { const program = (cclegacy.rendering.programLib as ProgramLibrary) @@ -564,15 +568,27 @@ export class Pass { return shader; } + protected get _isBlend (): boolean { + let bBlend = false; + for (const target of this.blendState.targets) { + if (target.blend) { + bBlend = true; + } + } + return bBlend; + } + // internal use /** * @private */ + // eslint-disable-next-line @typescript-eslint/no-empty-function public beginChangeStatesSilently (): void {} /** * @private */ + // eslint-disable-next-line @typescript-eslint/no-empty-function public endChangeStatesSilently (): void {} protected _doInit (info: IPassInfoFull, copyDefines = false): void { diff --git a/cocos/rendering/post-process/passes/tone-mapping-pass.ts b/cocos/rendering/post-process/passes/float-output-process-pass.ts similarity index 89% rename from cocos/rendering/post-process/passes/tone-mapping-pass.ts rename to cocos/rendering/post-process/passes/float-output-process-pass.ts index 9231c71742b..4570061fe2e 100644 --- a/cocos/rendering/post-process/passes/tone-mapping-pass.ts +++ b/cocos/rendering/post-process/passes/float-output-process-pass.ts @@ -32,10 +32,10 @@ import { passContext } from '../utils/pass-context'; import { SettingPass } from './setting-pass'; import { Root } from '../../../root'; -export class ToneMappingPass extends SettingPass { - name = 'ToneMappingPass'; - effectName = 'pipeline/tone-mapping'; - outputNames = ['ToneMapping']; +export class FloatOutputProcessPass extends SettingPass { + name = 'FloatOutputProcessesPass'; + effectName = 'pipeline/float-output-processes'; + outputNames = ['FloatOutputProcesses']; enableInAllEditorCamera = true; enable = true; @@ -49,6 +49,7 @@ export class ToneMappingPass extends SettingPass { passContext.material = this.material; const input = this.lastPass!.slotName(camera, 0); + const inputDS = passContext.depthSlotName; const output = this.slotName(camera, 0); const layoutName = 'tone-mapping'; const passName = `tone-mapping${cameraID}`; @@ -59,6 +60,7 @@ export class ToneMappingPass extends SettingPass { passContext.updatePassViewPort() .addRenderPass(layoutName, passName) .setPassInput(input, 'u_texSampler') + .setPassInput(inputDS, 'DepthTex') .addRasterView(output, Format.RGBA8) .blitScreen(passIndx) .version(); diff --git a/cocos/rendering/post-process/passes/index.ts b/cocos/rendering/post-process/passes/index.ts index 1c69822da92..00009f2f35a 100644 --- a/cocos/rendering/post-process/passes/index.ts +++ b/cocos/rendering/post-process/passes/index.ts @@ -9,7 +9,7 @@ export * from './bloom-pass'; export * from './fxaa-pass'; export * from './forward-final-pass'; export * from './shadow-pass'; -export * from './tone-mapping-pass'; +export * from './float-output-process-pass'; export * from './forward-transparency-pass'; export * from './forward-transparency-simple-pass'; export * from './skin-pass'; diff --git a/cocos/rendering/post-process/post-process-builder.ts b/cocos/rendering/post-process/post-process-builder.ts index 550d8fa15dd..5dd938caef3 100644 --- a/cocos/rendering/post-process/post-process-builder.ts +++ b/cocos/rendering/post-process/post-process-builder.ts @@ -19,7 +19,8 @@ import { PostProcess } from './components/post-process'; import { director } from '../../game'; import { Camera as CameraComponent } from '../../misc'; -import { BloomPass, ColorGradingPass, ForwardTransparencyPass, ForwardTransparencySimplePass, FxaaPass, SkinPass, ToneMappingPass } from './passes'; +import { BloomPass, ColorGradingPass, FloatOutputProcessPass, ForwardTransparencyPass, + ForwardTransparencySimplePass, FxaaPass, SkinPass } from './passes'; import { PipelineEventType } from '../pipeline-event'; export class PostProcessBuilder implements PipelineBuilder { @@ -50,13 +51,13 @@ export class PostProcessBuilder implements PipelineBuilder { // depth-based shading this.addPass(new HBAOPass()); + // float output related deferred processing: hdr + fog + this.addPass(new FloatOutputProcessPass()); + // transparency should after hdr and depth-based shading // temporary ignore CC_USE_FLOAT_OUTPUT this.addPass(new ForwardTransparencyPass()); - // float output related processing: hdr + fog - this.addPass(new ToneMappingPass()); - // user post-processing this.addPass(new TAAPass()); this.addPass(new FxaaPass()); diff --git a/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk b/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk index ec31cee9515..36e8e4c8eb2 100644 --- a/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk @@ -17,7 +17,7 @@ void main() { #if CC_USE_RGBE_OUTPUT color = packRGBE(color.rgb); - #elif !CC_USE_FLOAT_OUTPUT + #else//todo: change to #elif !CC_USE_FLOAT_OUTPUT when sky render queue has been fixed with custom pipeline color.rgb = HDRToLDR(color.rgb); color.rgb = LinearToSRGB(color.rgb); #endif diff --git a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk index fc75b629d9b..a2c0d94165c 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk @@ -128,26 +128,24 @@ void main() { #endif #endif - // Fog, rgbe and gamma output can't apply fog with forward-add pass - // todo: apply fogColorBrightness to fogColor for supporting scatter lighting with HDR - #if CC_USE_FOG != CC_FOG_NONE - #if CC_USE_FLOAT_OUTPUT - CC_APPLY_FOG_BASE(color, fogFactor); - #elif !CC_FORWARD_ADD - CC_APPLY_FOG_BASE(color, fogFactor); - #endif - #endif - // Color output #if CC_USE_RGBE_OUTPUT color = packRGBE(color.rgb); // for reflection-map #else color = CCSurfacesDebugDisplayInvalidNumber(color); - #if !CC_USE_FLOAT_OUTPUT + #if !CC_USE_FLOAT_OUTPUT || CC_IS_TRANSPARENCY_PASS color.rgb = HDRToLDR(color.rgb); color.rgb = LinearToSRGB(color.rgb); #endif #endif + // Fog, rgbe and gamma output can't apply fog with forward-add pass + // todo: apply fogColorBrightness to fogColor for supporting scatter lighting with HDR + #if CC_USE_FOG != CC_FOG_NONE && (!CC_USE_FLOAT_OUTPUT || CC_IS_TRANSPARENCY_PASS) + #if !CC_FORWARD_ADD + CC_APPLY_FOG_BASE(color, fogFactor); + #endif + #endif + fragColorX = color; } diff --git a/editor/assets/effects/pipeline/tone-mapping.effect b/editor/assets/effects/pipeline/float-output-process.effect similarity index 56% rename from editor/assets/effects/pipeline/tone-mapping.effect rename to editor/assets/effects/pipeline/float-output-process.effect index d280e6b52d6..055d728a4e9 100644 --- a/editor/assets/effects/pipeline/tone-mapping.effect +++ b/editor/assets/effects/pipeline/float-output-process.effect @@ -24,11 +24,15 @@ CCProgram tonemap-fs %{ #include #include #include + #include + #include in vec2 v_uv; #pragma rate u_texSampler pass layout(binding = 0) uniform sampler2D u_texSampler; + #pragma rate DepthTex pass + layout(binding = 1) uniform sampler2D DepthTex; //Sample_Point_Clamp layout(location = 0) out vec4 fragColor; @@ -41,12 +45,33 @@ CCProgram tonemap-fs %{ } vec4 CCFragOutput_PostProcess(vec4 color) { - if (!DebugViewNeedDisplayOriginalData()) { - #if CC_USE_FLOAT_OUTPUT - color.rgb = HDR2LDR_PostProcess(color.rgb); - color.rgb = LinearToSRGB(color.rgb); + + // fog related + vec4 worldPos = vec4(0.0); + #if CC_USE_FOG != CC_FOG_NONE + float depth = texture(DepthTex, v_uv).r; + vec3 posHS = vec3(v_uv, depth) * 2.0 - vec3(1.0); + CC_HANDLE_GET_CLIP_FLIP(posHS.xy); + worldPos = GetWorldPosFromNDCPosRH(posHS, cc_matProj, cc_matViewProjInv); #endif + + // todo: apply fogColorBrightness to fogColor for supporting scatter lighting with HDR + + // tone mapping + if (!DebugViewNeedDisplayOriginalData()) { + #if CC_USE_FLOAT_OUTPUT + color.rgb = HDR2LDR_PostProcess(color.rgb); + color.rgb = LinearToSRGB(color.rgb); + #endif } + + // LDR fog + #if CC_USE_FOG != CC_FOG_NONE + float fogFactor = 1.0; + CC_TRANSFER_FOG_BASE(worldPos, fogFactor); + CC_APPLY_FOG_BASE(color, fogFactor); + #endif + return color; } diff --git a/editor/assets/effects/pipeline/tone-mapping.effect.meta b/editor/assets/effects/pipeline/float-output-process.effect.meta similarity index 100% rename from editor/assets/effects/pipeline/tone-mapping.effect.meta rename to editor/assets/effects/pipeline/float-output-process.effect.meta diff --git a/editor/assets/effects/pipeline/post-process/chunks/hbao.chunk b/editor/assets/effects/pipeline/post-process/chunks/hbao.chunk index 7dbfc531644..ebfa1fcd336 100644 --- a/editor/assets/effects/pipeline/post-process/chunks/hbao.chunk +++ b/editor/assets/effects/pipeline/post-process/chunks/hbao.chunk @@ -296,7 +296,7 @@ float CalculateAO(vec2 uv) ao = 1.0 - ao * INV_NUM_DIRECTIONS * g_Strength; - #if CC_USE_FOG != CC_FOG_NONE + #if CC_USE_FOG != CC_FOG_NONE && !CC_USE_FLOAT_OUTPUT float fogFactor = 1.0; // no fog float depth = texture(DepthTex, uv).r; vec3 posHS = vec3(uv, depth) * 2.0 - vec3(1.0); diff --git a/native/cocos/scene/Pass.cpp b/native/cocos/scene/Pass.cpp index 13518a78464..cc57e887ed1 100644 --- a/native/cocos/scene/Pass.cpp +++ b/native/cocos/scene/Pass.cpp @@ -498,6 +498,10 @@ gfx::Shader *Pass::getShaderVariant(const ccstd::vector &patches) { _defines[patch.name] = patch.value; } + if (isBlend()) { + _defines["CC_IS_TRANSPARENCY_PASS"] = MacroValue(true); + } + gfx::Shader *shader = nullptr; auto *programLib = render::getProgramLibrary(); if (programLib) { @@ -518,6 +522,17 @@ gfx::Shader *Pass::getShaderVariant(const ccstd::vector &patches) { return shader; } +bool Pass::isBlend() { + bool isBlend = false; + for (const auto target : _blendState.targets) { + if (target.blend) { + isBlend = true; + } + } + + return isBlend; +} + IPassInfoFull Pass::getPassInfoFull() const { IPassInfoFull ret; ret.passIndex = _passIndex; diff --git a/native/cocos/scene/Pass.h b/native/cocos/scene/Pass.h index a3324ab4e06..e714e900ad3 100644 --- a/native/cocos/scene/Pass.h +++ b/native/cocos/scene/Pass.h @@ -315,6 +315,7 @@ class Pass : public RefCounted { gfx::BufferViewInfo &bufferViewInfo, ccstd::vector &startOffsets, size_t &count); + bool isBlend(); protected: void setState(const gfx::BlendState &bs, const gfx::DepthStencilState &dss, const gfx::RasterizerState &rs, gfx::DescriptorSet *ds); From b30c076168811e2c28f9cab8cea19b1c1c4a4f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Wed, 16 Aug 2023 15:52:27 +0800 Subject: [PATCH 112/184] optimize the frequency of calls to onUpdateProbes. (#15858) --- cocos/3d/framework/mesh-renderer.ts | 5 +- .../reflection-probe-component.ts | 34 +++++-- .../reflection-probe-manager.ts | 93 +++++++++++++++---- cocos/render-scene/scene/reflection-probe.ts | 3 +- 4 files changed, 106 insertions(+), 29 deletions(-) diff --git a/cocos/3d/framework/mesh-renderer.ts b/cocos/3d/framework/mesh-renderer.ts index ab371efe3d5..9869186e7d1 100644 --- a/cocos/3d/framework/mesh-renderer.ts +++ b/cocos/3d/framework/mesh-renderer.ts @@ -1073,6 +1073,7 @@ export class MeshRenderer extends ModelRenderer { this._onUpdateLocalReflectionProbeData(); } + // eslint-disable-next-line @typescript-eslint/no-empty-function protected _onMeshChanged (old: Mesh | null): void { } @@ -1145,12 +1146,12 @@ export class MeshRenderer extends ModelRenderer { if (this.bakeSettings.reflectionProbe === ReflectionProbeType.BAKED_CUBEMAP || this.bakeSettings.reflectionProbe === ReflectionProbeType.BLEND_PROBES || this.bakeSettings.reflectionProbe === ReflectionProbeType.BLEND_PROBES_AND_SKYBOX) { - cclegacy.internal.reflectionProbeManager.updateUseCubeModels(this._model); + cclegacy.internal.reflectionProbeManager.selectReflectionProbe(this._model); if (!cclegacy.internal.reflectionProbeManager.getUsedReflectionProbe(this._model, false)) { warnID(16302); } } else if (this.bakeSettings.reflectionProbe === ReflectionProbeType.PLANAR_REFLECTION) { - cclegacy.internal.reflectionProbeManager.updateUsePlanarModels(this._model); + cclegacy.internal.reflectionProbeManager.selectPlanarReflectionProbe(this._model); if (!cclegacy.internal.reflectionProbeManager.getUsedReflectionProbe(this._model, true)) { warnID(16302); } diff --git a/cocos/3d/reflection-probe/reflection-probe-component.ts b/cocos/3d/reflection-probe/reflection-probe-component.ts index e5c36ee2fb6..3708c0493a3 100644 --- a/cocos/3d/reflection-probe/reflection-probe-component.ts +++ b/cocos/3d/reflection-probe/reflection-probe-component.ts @@ -101,7 +101,9 @@ export class ReflectionProbe extends Component { protected _previewSphere: Node | null = null; protected _previewPlane: Node | null = null; - protected _sourceCameraPos = new Vec3(0, 0, 0); + private _sourceCameraPos = new Vec3(0, 0, 0); + + private _position = new Vec3(0, 0, 0); /** * @en @@ -114,8 +116,10 @@ export class ReflectionProbe extends Component { absolute(this._size); this.probe.size = this._size; if (this.probe) { - ReflectionProbeManager.probeManager.onUpdateProbes(true); + this.probe.updateBoundingBox(); + ReflectionProbeManager.probeManager.onUpdateProbes(); ReflectionProbeManager.probeManager.updateProbeData(); + ReflectionProbeManager.probeManager.updateProbeOfModels(); } } @type(Vec3) @@ -263,7 +267,7 @@ export class ReflectionProbe extends Component { set cubemap (val: TextureCube | null) { this._cubemap = val; this.probe.cubemap = val; - ReflectionProbeManager.probeManager.onUpdateProbes(true); + ReflectionProbeManager.probeManager.onUpdateProbes(); } get cubemap (): TextureCube | null { @@ -312,7 +316,9 @@ export class ReflectionProbe extends Component { public onLoad (): void { this._createProbe(); - ReflectionProbeManager.probeManager.registerEvent(); + if (EDITOR) { + ReflectionProbeManager.probeManager.registerEvent(); + } } onEnable (): void { @@ -323,7 +329,7 @@ export class ReflectionProbe extends Component { this._probe.updateProbeId(this._probeId); } ReflectionProbeManager.probeManager.register(this._probe); - ReflectionProbeManager.probeManager.onUpdateProbes(true); + ReflectionProbeManager.probeManager.onUpdateProbes(); this._probe.enable(); } } @@ -340,6 +346,7 @@ export class ReflectionProbe extends Component { ReflectionProbeManager.probeManager.filterModelsForPlanarReflection(); } ReflectionProbeManager.probeManager.updateProbeData(); + this._position = this.node.getWorldPosition().clone(); } public onDestroy (): void { @@ -372,13 +379,22 @@ export class ReflectionProbe extends Component { } } - if (this.node.hasChangedFlags) { - this.probe.updateBoundingBox(); - } if (this.node.hasChangedFlags & TransformBit.POSITION) { - ReflectionProbeManager.probeManager.onUpdateProbes(true); + this.probe.updateBoundingBox(); + ReflectionProbeManager.probeManager.onUpdateProbes(); ReflectionProbeManager.probeManager.updateProbeData(); } + + //update probe info for realtime + if (!EDITOR) { + const worldPos = this.node.getWorldPosition(); + if (!this._position.equals(worldPos)) { + this._position = worldPos; + this.probe.updateBoundingBox(); + ReflectionProbeManager.probeManager.updateProbeData(); + ReflectionProbeManager.probeManager.updateProbeOfModels(); + } + } } /** diff --git a/cocos/3d/reflection-probe/reflection-probe-manager.ts b/cocos/3d/reflection-probe/reflection-probe-manager.ts index 88dc20c07d3..c4ac433ee71 100644 --- a/cocos/3d/reflection-probe/reflection-probe-manager.ts +++ b/cocos/3d/reflection-probe/reflection-probe-manager.ts @@ -65,22 +65,26 @@ export class ReflectionProbeManager { set updateForRuntime (val: boolean) { this._updateForRuntime = val; } + get updateForRuntime (): boolean { return this._updateForRuntime; } + /** + * @engineInternal + */ public registerEvent (): void { if (!this._registeredEvent) { cclegacy.director.on(cclegacy.Director.EVENT_BEFORE_UPDATE, this.onUpdateProbes, this); this._registeredEvent = true; } } + /** - * @en refresh all reflection probe - * @zh 刷新所有反射探针 + * @en Refresh all reflection probe. + * @zh 刷新所有反射探针。 */ - public onUpdateProbes (forceUpdate = false): void { - if (!EDITOR && !this._updateForRuntime) return; + public onUpdateProbes (): void { if (this._probes.length === 0) return; const scene = cclegacy.director.getScene(); if (!scene || !scene.renderScene) { @@ -90,16 +94,20 @@ export class ReflectionProbeManager { for (let i = 0; i < models.length; i++) { const model = models[i]; if (!model.node) continue; - if ((model.node.layer & REFLECTION_PROBE_DEFAULT_MASK) && (model.node.hasChangedFlags || forceUpdate)) { + if (model.node.layer & REFLECTION_PROBE_DEFAULT_MASK) { if (model.reflectionProbeType === ReflectionProbeType.BAKED_CUBEMAP || this._isUsedBlending(model)) { - this.updateUseCubeModels(model); + this.selectReflectionProbe(model); } else if (model.reflectionProbeType === ReflectionProbeType.PLANAR_REFLECTION) { - this.updateUsePlanarModels(model); + this.selectPlanarReflectionProbe(model); } } } } + /** + * @en filter models that use planar reflection. + * @zh 筛选使用平面反射的模型 + */ public filterModelsForPlanarReflection (): void { if (this._probes.length === 0) return; const scene = cclegacy.director.getScene(); @@ -111,11 +119,14 @@ export class ReflectionProbeManager { const model = models[i]; if (!model.node) continue; if ((model.node.layer & REFLECTION_PROBE_DEFAULT_MASK) && model.reflectionProbeType === ReflectionProbeType.PLANAR_REFLECTION) { - this.updateUsePlanarModels(model); + this.selectPlanarReflectionProbe(model); } } } + /** + * @engineInternal + */ public clearPlanarReflectionMap (probe: ReflectionProbe): void { for (const entry of this._usePlanarModels.entries()) { if (entry[1] === probe) { @@ -124,6 +135,9 @@ export class ReflectionProbeManager { } } + /** + * @engineInternal + */ public register (probe: ReflectionProbe): void { const index = this._probes.indexOf(probe); if (index === -1) { @@ -132,6 +146,9 @@ export class ReflectionProbeManager { } } + /** + * @engineInternal + */ public unregister (probe: ReflectionProbe): void { for (let i = 0; i < this._probes.length; i++) { if (this._probes[i] === probe) { @@ -145,6 +162,9 @@ export class ReflectionProbeManager { this.updateProbeData(); } + /** + * @engineInternal + */ public exists (probeId: number): boolean { if (this._probes.length === 0) return false; for (let i = 0; i < this._probes.length; i++) { @@ -155,6 +175,9 @@ export class ReflectionProbeManager { return false; } + /** + * @engineInternal + */ public getNewReflectionProbeId (): number { let probeId = 0; // eslint-disable-next-line no-constant-condition @@ -167,10 +190,18 @@ export class ReflectionProbeManager { } } + /** + * @en Get all reflection probes in the scene. + * @zh 获取场景中所有的反射探针 + */ public getProbes (): ReflectionProbe[] { return this._probes; } + /** + * @en Get reflection probe by id. + * @zh 根据id获取反射探针 + */ public getProbeById (probeId: number): ReflectionProbe | null { for (let i = 0; i < this._probes.length; i++) { if (this._probes[i].getProbeId() === probeId) { @@ -180,10 +211,16 @@ export class ReflectionProbeManager { return null; } + /** + * @engineInternal + */ public clearAll (): void { this._probes = []; } + /** + * @engineInternal + */ public getProbeByCamera (camera: Camera): ReflectionProbe | null { for (let i = 0; i < this._probes.length; i++) { if (this._probes[i].camera === camera) { @@ -241,7 +278,7 @@ export class ReflectionProbeManager { * @param probe update the model for reflection probe * @engineInternal */ - public updateUsePlanarModels (model: Model): void { + public selectPlanarReflectionProbe (model: Model): void { if (!model.node || !model.worldBounds || model.reflectionProbeType !== ReflectionProbeType.PLANAR_REFLECTION) return; for (let i = 0; i < this._probes.length; i++) { const probe = this._probes[i]; @@ -272,12 +309,11 @@ export class ReflectionProbeManager { } /** - * @en Update objects using reflection probe for bake cubemap. - * @zh 更新使用反射探针烘焙cubemap的物体。 - * @param model update the model for reflection probe - * @engineInternal + * @en Selecting the appropriate reflection probe for the model, it will use the closest one based on distance. + * @zh 为模型选择适用的反射探针,会使用距离最近的。 + * @param model select for this model */ - public updateUseCubeModels (model: Model): void { + public selectReflectionProbe (model: Model): void { if (model.node && model.worldBounds && ((model.node.layer & REFLECTION_PROBE_DEFAULT_MASK))) { model.updateWorldBound(); const nearest = this._getNearestProbe(model); @@ -441,7 +477,7 @@ export class ReflectionProbeManager { return null; } - /** + /** * @en Set reflection probe used by the model. * @zh 手动设置模型使用的反射探针。 * @param model set the probe for this model @@ -457,6 +493,29 @@ export class ReflectionProbeManager { } } + /** + * @engineInternal + */ + public updateProbeOfModels (): void { + if (this._probes.length === 0) return; + const scene = cclegacy.director.getScene(); + if (!scene || !scene.renderScene) { + return; + } + const models = scene.renderScene.models as Model[]; + for (let i = 0; i < models.length; i++) { + const model = models[i]; + if (!model.node) continue; + if (model.node.layer & REFLECTION_PROBE_DEFAULT_MASK) { + if (model.reflectionProbeType === ReflectionProbeType.BAKED_CUBEMAP + || model.reflectionProbeType === ReflectionProbeType.PLANAR_REFLECTION + || this._isUsedBlending(model)) { + model.updateReflectionProbeId(); + } + } + } + } + /** * @en * select the probe with the nearest distance. @@ -523,14 +582,14 @@ export class ReflectionProbeManager { const p = this._useCubeModels.get(key); if (p !== undefined && p === probe) { this._useCubeModels.delete(key); - this.updateUseCubeModels(key); + this.selectReflectionProbe(key); } } for (const key of this._usePlanarModels.keys()) { const p = this._usePlanarModels.get(key); if (p !== undefined && p === probe) { this._usePlanarModels.delete(key); - this.updateUsePlanarModels(key); + this.selectPlanarReflectionProbe(key); } } } diff --git a/cocos/render-scene/scene/reflection-probe.ts b/cocos/render-scene/scene/reflection-probe.ts index 9c794c75172..8b10802b7ca 100644 --- a/cocos/render-scene/scene/reflection-probe.ts +++ b/cocos/render-scene/scene/reflection-probe.ts @@ -364,8 +364,10 @@ export class ReflectionProbe { this.realtimePlanarTexture = null; } } + // eslint-disable-next-line @typescript-eslint/no-empty-function public enable (): void { } + // eslint-disable-next-line @typescript-eslint/no-empty-function public disable (): void { } @@ -376,7 +378,6 @@ export class ReflectionProbe { public updateBoundingBox (): void { if (this.node) { - this.node.updateWorldTransform(); const pos = this.node.getWorldPosition(); geometry.AABB.set(this._boundingBox!, pos.x, pos.y, pos.z, this._size.x, this._size.y, this._size.z); } From 23f222730a1bc47fe409f89ab3879f1a03a82e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=88=98?= <40414978+PatriceJiang@users.noreply.github.com> Date: Wed, 16 Aug 2023 16:58:42 +0800 Subject: [PATCH 113/184] Android Build Panel: Add `resizeableActivity` Option (#15713) * resizeable activity --- scripts/native-pack-tool/package-lock.json | 34 ++- scripts/native-pack-tool/package.json | 6 +- .../source/platforms/android.ts | 196 ++++++++++++------ scripts/native-pack-tool/source/utils.ts | 22 +- 4 files changed, 182 insertions(+), 76 deletions(-) diff --git a/scripts/native-pack-tool/package-lock.json b/scripts/native-pack-tool/package-lock.json index 43a55b0c26c..029e8e021c6 100644 --- a/scripts/native-pack-tool/package-lock.json +++ b/scripts/native-pack-tool/package-lock.json @@ -18,6 +18,19 @@ "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" }, + "@types/node": { + "version": "20.4.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.1.tgz", + "integrity": "sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==" + }, + "@types/xml2js": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.11.tgz", + "integrity": "sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==", + "requires": { + "@types/node": "*" + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -746,7 +759,7 @@ }, "json5": { "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonfile": { @@ -983,6 +996,11 @@ "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/set-value/-/set-value-2.0.1.tgz", @@ -1288,6 +1306,20 @@ "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "xml2js": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz", + "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, "xxtea-node": { "version": "1.1.4", "resolved": "https://registry.npmmirror.com/xxtea-node/-/xxtea-node-1.1.4.tgz", diff --git a/scripts/native-pack-tool/package.json b/scripts/native-pack-tool/package.json index a525a59ddb8..ec27875c9f0 100644 --- a/scripts/native-pack-tool/package.json +++ b/scripts/native-pack-tool/package.json @@ -12,12 +12,14 @@ "clean": "tsc --clean" }, "dependencies": { + "@types/xml2js": "^0.4.11", "fs-extra": "^10.1.0", "globby": "^8.0.2", "iconv-lite": "^0.4.24", + "json5": "^2.2.1", + "xml2js": "^0.6.0", "xxtea-node": "^1.1.4", "yargs": "^17.5.1", - "zlib": "^1.0.5", - "json5": "^2.2.1" + "zlib": "^1.0.5" } } diff --git a/scripts/native-pack-tool/source/platforms/android.ts b/scripts/native-pack-tool/source/platforms/android.ts index 143559a2e12..212974a8ae1 100644 --- a/scripts/native-pack-tool/source/platforms/android.ts +++ b/scripts/native-pack-tool/source/platforms/android.ts @@ -4,6 +4,7 @@ import { CocosParams, NativePackTool } from "../base/default"; import { cchelper, Paths } from "../utils"; import * as URL from 'url'; import { spawn, spawnSync } from 'child_process'; +import * as xml2js from 'xml2js'; export interface IOrientation { landscapeLeft: boolean; @@ -27,11 +28,15 @@ export interface IAndroidParams { orientation: IOrientation; appBundle: boolean; + resizeableActivity: boolean; } +const DefaultAPILevel = 27; export class AndroidPackTool extends NativePackTool { params!: CocosParams; + private firstTimeBuild: boolean = false; + protected async copyPlatformTemplate() { // 原生工程不重复拷贝 TODO 复用前需要做版本检测 if (!fs.existsSync(this.paths.nativePrjDir)) { @@ -43,8 +48,10 @@ export class AndroidPackTool extends NativePackTool { // 拷贝 lite 仓库的 templates/android/template 文件到构建输出目录 await fs.copy(ps.join(this.paths.nativeTemplateDirInCocos, this.params.platform, 'template'), this.paths.platformTemplateDirInPrj, { overwrite: false }); this.writeEngineVersion(); + this.firstTimeBuild = true; } else { this.validateNativeDir(); + this.firstTimeBuild = false; } } @@ -60,10 +67,9 @@ export class AndroidPackTool extends NativePackTool { await this.generateCMakeConfig(); await this.excuteCocosTemplateTask(); - await this.setOrientation(); - await this.encrypteScripts(); await this.updateAndroidGradleValues(); - await this.configAndroidInstant(); + await this.updateManifest(); + await this.encrypteScripts(); await this.generateAppNameValues(); return true; } @@ -122,40 +128,134 @@ export class AndroidPackTool extends NativePackTool { return await this.copyToDist(); } - protected async setOrientation() { - const cfg = this.params.platformParams.orientation; + private mapOrientationValue() { + const orientation = this.params.platformParams.orientation; + let orientationValue = 'unspecified'; + + if (orientation.landscapeRight && orientation.landscapeLeft && (orientation.portrait || orientation.upsideDown)) { + orientationValue = 'fullSensor'; + } else if ((orientation.landscapeRight || orientation.landscapeLeft) && (orientation.portrait || orientation.upsideDown)) { + orientationValue = 'unspecified'; + } else if (orientation.landscapeRight && !orientation.landscapeLeft) { + orientationValue = 'landscape'; + } else if (!orientation.landscapeRight && orientation.landscapeLeft) { + orientationValue = 'reverseLandscape'; + } else if (orientation.landscapeRight && orientation.landscapeLeft) { + orientationValue = 'sensorLandscape'; + } else if (orientation.portrait && !orientation.upsideDown) { + orientationValue = 'portrait'; + } else if (!orientation.portrait && orientation.upsideDown) { + orientationValue = 'reversePortrait'; + } else if (orientation.portrait && orientation.upsideDown) { + orientationValue = 'sensorPortrait'; + } + return orientationValue; + } + + protected async updateManifest() { + + if (!this.firstTimeBuild) { + console.log(`AndroidManifest.xml has already been updated!`); + return; + } + + const resizeableActivity: boolean = this.params.platformParams.resizeableActivity; const manifestPath = cchelper.join(this.paths.platformTemplateDirInPrj, 'app/AndroidManifest.xml'); const instantManifestPath = cchelper.join(this.paths.platformTemplateDirInPrj, 'instantapp/AndroidManifest.xml'); - if (fs.existsSync(manifestPath) && fs.existsSync(instantManifestPath)) { - const pattern = /android:screenOrientation="[^"]*"/; - let replaceString = 'android:screenOrientation="unspecified"'; - - if (cfg.landscapeRight && cfg.landscapeLeft && (cfg.portrait || cfg.upsideDown)) { - replaceString = 'android:screenOrientation="fullSensor"'; - } else if ((cfg.landscapeRight || cfg.landscapeLeft) && (cfg.portrait || cfg.upsideDown)) { - replaceString = 'android:screenOrientation="unspecified"'; - } else if (cfg.landscapeRight && !cfg.landscapeLeft) { - replaceString = 'android:screenOrientation="landscape"'; - } else if (!cfg.landscapeRight && cfg.landscapeLeft) { - replaceString = 'android:screenOrientation="reverseLandscape"'; - } else if (cfg.landscapeRight && cfg.landscapeLeft) { - replaceString = 'android:screenOrientation="sensorLandscape"'; - } else if (cfg.portrait && !cfg.upsideDown) { - replaceString = 'android:screenOrientation="portrait"'; - } else if (!cfg.portrait && cfg.upsideDown) { - const oriValue = 'reversePortrait'; - replaceString = `android:screenOrientation="${oriValue}"`; - } else if (cfg.portrait && cfg.upsideDown) { - const oriValue = 'sensorPortrait'; - replaceString = `android:screenOrientation="${oriValue}"`; + + const fnParseXml = async (xmlFile: string) => { + const xmlData = await fs.readFile(xmlFile, 'utf8'); + const data = await xml2js.parseStringPromise(xmlData); + return { + data, + save: async () => { + const builder = new xml2js.Builder(); + const dstXML = builder.buildObject(data); + await fs.writeFile(xmlFile, dstXML, 'utf8'); + } + } + }; + const fnUpdateOrientation = (data: any) => { + const attrRef = data.manifest.application[0].activity[0].$; + attrRef['android:screenOrientation'] = this.mapOrientationValue(); + }; + const fnUpdateResizeableActivity = (data: any) => { + const activityRef = data.manifest.application[0].$; + activityRef['android:resizeableActivity'] = resizeableActivity ? 'true' : 'false'; + }; + const fnUpdateMaxAspectRation = (data: any) => { + if (resizeableActivity) return; // disabled + const maxAspectRatio: string = this.params.platformParams.maxAspectRatio; + if (!maxAspectRatio) return; // value not set + const matchFrac = maxAspectRatio.match(/^(\d+):(\d+)$/); + let aspectRatioFloatValue; + try { + if (matchFrac) { + aspectRatioFloatValue = Number.parseInt(matchFrac[1], 10) / Number.parseInt(matchFrac[2], 10); + } else { + aspectRatioFloatValue = Number.parseFloat(maxAspectRatio); + } + } catch (e) { + console.error(e); + console.error(`Error when parsing '${maxAspectRatio}', fallback maxAspectRatio to default value`); + aspectRatioFloatValue = 2.4; + } + + let apiLevel = this.params.platformParams.apiLevel; + if (apiLevel === undefined) apiLevel = DefaultAPILevel; + + + if (apiLevel >= 26) { // Android 8.0 + const activities = data.manifest.application[0].activity; + for (const activity of activities) { + activity.$['android:maxAspectRatio'] = `${aspectRatioFloatValue}`; + } + } else { + const application = data.manifest.application[0]; + //append meta-data + application['meta-data'].push({ + $:{'android:name': 'android.max_aspect', 'android:value': `${aspectRatioFloatValue}`} + }); + } + + }; + const fnUpdateCategory = (data: any) => { + if (!this.params.platformParams.androidInstant) { + console.log('android instant not configured'); + return; + } + const url = this.params.platformParams.remoteUrl; + if (!url) { + return; } + const urlInfo = URL.parse(url); + if (!urlInfo.host) { + throw new Error(`parse url ${url} fail`); + } + const intentFilter: any = data.manifest.application[0].activity[0]['intent-filter'][0]; + if (intentFilter) { + intentFilter.data ||= []; + intentFilter.data = intentFilter.data.concat([ + { $: { 'android:host': urlInfo.host, 'android:pathPattern': urlInfo.path, 'android:scheme': 'https' } }, + { $: { 'android:scheme': 'http' } } + ]); + } + } - let content = await fs.readFile(manifestPath, 'utf8'); - content = content.replace(pattern, replaceString); - let instantContent = await fs.readFile(instantManifestPath, 'utf8'); - instantContent = instantContent.replace(pattern, replaceString); - await fs.writeFile(manifestPath, content); - await fs.writeFile(instantManifestPath, instantContent); + if (fs.existsSync(manifestPath)) { + const app = await fnParseXml(manifestPath); + await fnUpdateOrientation(app.data); + await fnUpdateResizeableActivity(app.data); + await fnUpdateMaxAspectRation(app.data); + await app.save(); + } + if (fs.existsSync(instantManifestPath)) { + const instant = await fnParseXml(instantManifestPath); + await fnUpdateOrientation(instant.data); + await fnUpdateResizeableActivity(instant.data); + await fnUpdateMaxAspectRation(instant.data); + await fnUpdateCategory(instant.data); + await instant.save(); } } @@ -177,7 +277,7 @@ export class AndroidPackTool extends NativePackTool { } let apiLevel = options.apiLevel; if (!apiLevel) { - apiLevel = 27; + apiLevel = DefaultAPILevel; } console.log(`AndroidAPI level ${apiLevel}`); let content = fs.readFileSync(gradlePropertyPath, 'utf-8'); @@ -236,34 +336,6 @@ export class AndroidPackTool extends NativePackTool { } } - protected async configAndroidInstant() { - if (!this.params.platformParams.androidInstant) { - console.log('android instant not configured'); - return; - } - const url = this.params.platformParams.remoteUrl; - if (!url) { - return; - } - const manifestPath = cchelper.join(this.paths.platformTemplateDirInPrj, 'instantapp/AndroidManifest.xml'); - if (!fs.existsSync(manifestPath)) { - throw new Error(`${manifestPath} not found`); - } - const urlInfo = URL.parse(url); - if (!urlInfo.host) { - throw new Error(`parse url ${url} fail`); - } - let manifest = fs.readFileSync(manifestPath, 'utf8'); - manifest = manifest.replace(//, (str) => { - let newStr = ''; - newStr += `\n ` - + `\n `; - return newStr; - }); - - fs.writeFileSync(manifestPath, manifest, 'utf8'); - } - private async generateAppNameValues() { const valuesPath = cchelper.join(this.paths.platformTemplateDirInPrj, 'res/values/strings.xml'); const matchCnt = fs.readFileSync(valuesPath, 'utf8').toString().split('\n').map(x => x.trim()).filter(x => /name=\"app_name\"/.test(x)).length; diff --git a/scripts/native-pack-tool/source/utils.ts b/scripts/native-pack-tool/source/utils.ts index 22e57038415..67eeb88a4dc 100644 --- a/scripts/native-pack-tool/source/utils.ts +++ b/scripts/native-pack-tool/source/utils.ts @@ -416,7 +416,7 @@ export class cchelper { } export const toolHelper = { - getXcodeMajorVerion():number { + getXcodeMajorVerion(): number { try { const output = execSync('xcrun xcodebuild -version').toString('utf8'); return Number.parseInt(output.match(/Xcode\s(\d+)\.\d+/)![1]); @@ -427,15 +427,15 @@ export const toolHelper = { } }, - async runCommand(cmd:string, args:string[], cb?:(code:number, stdout:string, stderr:string)=>void): Promise { + async runCommand(cmd: string, args: string[], cb?: (code: number, stdout: string, stderr: string) => void): Promise { return new Promise((resolve, reject) => { const cp = spawn(cmd, args); - const stdErr:Buffer[] = []; - const stdOut:Buffer[] = []; - cp.stderr.on('data', (d)=>stdErr.push(d)); - cp.stdout.on('data', (d)=>stdOut.push(d)); - cp.on('close', (code, signal)=>{ - if(cb) { + const stdErr: Buffer[] = []; + const stdOut: Buffer[] = []; + cp.stderr.on('data', (d) => stdErr.push(d)); + cp.stdout.on('data', (d) => stdOut.push(d)); + cp.on('close', (code, signal) => { + if (cb) { cb(code as any, Buffer.concat(stdOut).toString('utf8'), Buffer.concat(stdErr).toString('utf8')); } resolve(code === 0); @@ -464,7 +464,7 @@ export const toolHelper = { }); cp.stdout.on('data', (data: any) => { const msg = iconv.decode(data, 'gbk').toString(); - if(/warning/i.test(msg)) { + if (/warning/i.test(msg)) { console.log(`[cmake-warn] ${msg}`); } else { console.log(`[cmake] ${msg}`); @@ -472,9 +472,9 @@ export const toolHelper = { }); cp.stderr.on('data', (data: any) => { const msg = iconv.decode(data, 'gbk').toString(); - if(/CMake Warning/.test(msg) || /warning/i.test(msg)) { + if (/CMake Warning/.test(msg) || /warning/i.test(msg)) { console.log(`[cmake-warn] ${msg}`); - }else{ + } else { console.error(`[cmake-err] ${msg}`); } }); From 544854c9f6fea7b7b69002f65a0fb332cebd2a3d Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Wed, 16 Aug 2023 17:30:28 +0800 Subject: [PATCH 114/184] add model invalidateLocalData interface (#15623) --- cocos/render-scene/scene/model.ts | 9 +++++++++ native/cocos/scene/Model.h | 1 + 2 files changed, 10 insertions(+) diff --git a/cocos/render-scene/scene/model.ts b/cocos/render-scene/scene/model.ts index 3cc86fb88f6..360d856a821 100644 --- a/cocos/render-scene/scene/model.ts +++ b/cocos/render-scene/scene/model.ts @@ -735,6 +735,15 @@ export class Model { } } + /** + * @engineInternal + * @en Invalidate local data + * @zh 使本地数据失效 + */ + public invalidateLocalData (): void { + this._localDataUpdated = true; + } + public showTetrahedron (): boolean { return this.isLightProbeAvailable(); } diff --git a/native/cocos/scene/Model.h b/native/cocos/scene/Model.h index 7085d355383..5a77d27a549 100644 --- a/native/cocos/scene/Model.h +++ b/native/cocos/scene/Model.h @@ -239,6 +239,7 @@ class Model : public RefCounted { _receiveDirLight = value; onMacroPatchesStateChanged(); } + inline void invalidateLocalData() { _localDataUpdated = true; } // For JS inline void setCalledFromJS(bool v) { _isCalledFromJS = v; } From 6afc186c67e4702185b291cd911a65e4a5dddca6 Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Wed, 16 Aug 2023 18:06:47 +0800 Subject: [PATCH 115/184] remove button wrong sprite set (#15949) * remove button wrong sprite set * fix CI --- cocos/ui/button.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/cocos/ui/button.ts b/cocos/ui/button.ts index 2411f97a860..067da5d4525 100644 --- a/cocos/ui/button.ts +++ b/cocos/ui/button.ts @@ -23,7 +23,8 @@ THE SOFTWARE. */ -import { ccclass, help, executionOrder, menu, requireComponent, tooltip, displayOrder, type, rangeMin, rangeMax, serializable, executeInEditMode } from 'cc.decorator'; +import { ccclass, help, executionOrder, menu, requireComponent, tooltip, displayOrder, type, rangeMin, + rangeMax, serializable, executeInEditMode } from 'cc.decorator'; import { EDITOR, EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; import { SpriteFrame } from '../2d/assets'; import { Component, EventHandler as ComponentEventHandler } from '../scene-graph'; @@ -122,7 +123,8 @@ export enum EventType { * - cc.Node.EventType.MOUSE_LEAVE * - cc.Node.EventType.MOUSE_UP * - * The developer can get the current clicked node with `event.target` from event object which is passed as parameter in the callback function of click event. + * The developer can get the current clicked node with `event.target` from event object which is passed as parameter + * in the callback function of click event. * * @zh * 按钮组件。可以被按下,或者点击。
@@ -398,7 +400,8 @@ export class Button extends Component { * @en * When user press the button, the button will zoom to a scale. * The final scale of the button equals (button original scale * zoomScale) - * NOTE: Setting zoomScale less than 1 is not adviced, which could fire the touchCancel event if the touch point is out of touch area after scaling. + * NOTE: Setting zoomScale less than 1 is not adviced, which could fire the touchCancel event + * if the touch point is out of touch area after scaling. * if you need to do so, you should set target as another background node instead of the button node. * * @zh @@ -583,11 +586,6 @@ export class Button extends Component { this.target = this.node; } - const sprite = this.node.getComponent(Sprite); - if (sprite) { - this._normalSprite = sprite.spriteFrame; - } - this._applyTarget(); this._resetState(); } @@ -859,7 +857,7 @@ export class Button extends Component { this.target.setScale(this._originalScale); } } else { - let state; + let state: string; if (hit) { state = State.PRESSED; } else { @@ -940,7 +938,7 @@ export class Button extends Component { return; } - if (EDITOR || state === State.DISABLED) { + if (EDITOR || state === State.DISABLED.toString()) { renderComp.color = color; } else { this._fromColor = renderComp.color.clone(); @@ -962,7 +960,7 @@ export class Button extends Component { return; } - if (state === State.PRESSED) { + if (state === State.PRESSED.toString()) { this._zoomUp(); } else { this._zoomBack(); From 93e397e9f06bda6bfbf3bac0965d1e79ba7b5b84 Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Thu, 17 Aug 2023 10:04:39 +0800 Subject: [PATCH 116/184] Fix sprite size mode change by preload (#15908) * Fix sprite size mode change by preload * fix on runtime --- cocos/2d/components/sprite.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos/2d/components/sprite.ts b/cocos/2d/components/sprite.ts index 4af575e7e5d..e6d958d3814 100644 --- a/cocos/2d/components/sprite.ts +++ b/cocos/2d/components/sprite.ts @@ -27,7 +27,7 @@ import { ccclass, help, executionOrder, menu, tooltip, displayOrder, type, range import { BUILD, EDITOR } from 'internal:constants'; import { SpriteAtlas } from '../assets/sprite-atlas'; import { SpriteFrame } from '../assets/sprite-frame'; -import { Vec2, cclegacy, ccenum, clamp } from '../../core'; +import { Vec2, cclegacy, ccenum, clamp, warn } from '../../core'; import { IBatcher } from '../renderer/i-batcher'; import { UIRenderer, InstanceMaterialType } from '../framework/ui-renderer'; import { PixelFormat } from '../../asset/assets/asset-enum'; @@ -480,9 +480,9 @@ export class Sprite extends UIRenderer { public __preload (): void { this.changeMaterialForDefine(); super.__preload(); + this._applySpriteSize(); if (EDITOR) { - this._resized(); this.node.on(NodeEventType.SIZE_CHANGED, this._resized, this); } } @@ -526,7 +526,7 @@ export class Sprite extends UIRenderer { */ public changeSpriteFrameFromAtlas (name: string): void { if (!this._atlas) { - console.warn('SpriteAtlas is null.'); + warn('SpriteAtlas is null.'); return; } const sprite = this._atlas.getSpriteFrame(name); From 39acb6560f0d47fc7fe4cf3579ad63cab2e354e0 Mon Sep 17 00:00:00 2001 From: zxx43 Date: Thu, 17 Aug 2023 10:17:32 +0800 Subject: [PATCH 117/184] use buffer size instead of capacity to initialize buffer (#15775) * use buffer size instead of capacity to initialize buffer * fix eslint * set min buffer size 16 * remove loop --- cocos/particle/models/particle-batch-model.ts | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/cocos/particle/models/particle-batch-model.ts b/cocos/particle/models/particle-batch-model.ts index 33a611473d1..a302acdeddf 100644 --- a/cocos/particle/models/particle-batch-model.ts +++ b/cocos/particle/models/particle-batch-model.ts @@ -49,6 +49,7 @@ const _uvs_ins = [ export default class ParticleBatchModel extends scene.Model { private _capacity: number; + private _bufferSize: number; private _vertAttrs: Attribute[] | null; private _vertAttribSize: number; private _vBuffer: ArrayBuffer | null; @@ -80,6 +81,7 @@ export default class ParticleBatchModel extends scene.Model { this.type = scene.ModelType.PARTICLE_BATCH; this._capacity = 0; + this._bufferSize = 16; this._vertAttrs = null; this._vertAttribSize = 0; @@ -105,6 +107,7 @@ export default class ParticleBatchModel extends scene.Model { public setCapacity (capacity: number): void { const capChanged = this._capacity !== capacity; this._capacity = capacity; + this._bufferSize = Math.max(this._capacity, 16); if (this._subMeshData && capChanged) { this.rebuild(); } @@ -165,19 +168,25 @@ export default class ParticleBatchModel extends scene.Model { const vertexBuffer = this._device.createBuffer(new BufferInfo( BufferUsageBit.VERTEX | BufferUsageBit.TRANSFER_DST, MemoryUsageBit.HOST | MemoryUsageBit.DEVICE, - this._vertAttribSize * this._capacity * this._vertCount, + this._vertAttribSize * this._bufferSize * this._vertCount, this._vertAttribSize, )); - const vBuffer: ArrayBuffer = new ArrayBuffer(this._vertAttribSize * this._capacity * this._vertCount); + const vBuffer: ArrayBuffer = new ArrayBuffer(this._vertAttribSize * this._bufferSize * this._vertCount); if (this._mesh && this._capacity > 0) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison let vOffset = (this._vertAttrs![this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD)] as any).offset; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this._mesh.copyAttribute(0, AttributeName.ATTR_TEX_COORD, vBuffer, this._vertAttribSize, vOffset); // copy mesh uv to ATTR_TEX_COORD + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison let vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD3); vOffset = (this._vertAttrs![vIdx++] as any).offset; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this._mesh.copyAttribute(0, AttributeName.ATTR_POSITION, vBuffer, this._vertAttribSize, vOffset); // copy mesh position to ATTR_TEX_COORD3 vOffset = (this._vertAttrs![vIdx++] as any).offset; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this._mesh.copyAttribute(0, AttributeName.ATTR_NORMAL, vBuffer, this._vertAttribSize, vOffset); // copy mesh normal to ATTR_NORMAL vOffset = (this._vertAttrs![vIdx++] as any).offset; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument if (!this._mesh.copyAttribute(0, AttributeName.ATTR_COLOR, vBuffer, this._vertAttribSize, vOffset)) { // copy mesh color to ATTR_COLOR1 const vb = new Uint32Array(vBuffer); for (let iVertex = 0; iVertex < this._vertCount; ++iVertex) { @@ -191,7 +200,7 @@ export default class ParticleBatchModel extends scene.Model { } vertexBuffer.update(vBuffer); - const indices: Uint16Array = new Uint16Array(this._capacity * this._indexCount); + const indices: Uint16Array = new Uint16Array(this._bufferSize * this._indexCount); if (this._mesh && this._capacity > 0) { this._mesh.copyIndices(0, indices); for (let i = 1; i < this._capacity; i++) { @@ -215,7 +224,7 @@ export default class ParticleBatchModel extends scene.Model { const indexBuffer: Buffer = this._device.createBuffer(new BufferInfo( BufferUsageBit.INDEX | BufferUsageBit.TRANSFER_DST, MemoryUsageBit.DEVICE, - this._capacity * this._indexCount * Uint16Array.BYTES_PER_ELEMENT, + this._bufferSize * this._indexCount * Uint16Array.BYTES_PER_ELEMENT, Uint16Array.BYTES_PER_ELEMENT, )); @@ -236,11 +245,11 @@ export default class ParticleBatchModel extends scene.Model { const vertexBuffer = this._device.createBuffer(new BufferInfo( BufferUsageBit.VERTEX | BufferUsageBit.TRANSFER_DST, MemoryUsageBit.HOST | MemoryUsageBit.DEVICE, - this._vertAttribSize * this._capacity, + this._vertAttribSize * this._bufferSize, this._vertAttribSize, )); - const vBuffer: ArrayBuffer = new ArrayBuffer(this._vertAttribSize * this._capacity); + const vBuffer: ArrayBuffer = new ArrayBuffer(this._vertAttribSize * this._bufferSize); vertexBuffer.update(vBuffer); this._insBuffers.push(vertexBuffer); @@ -265,15 +274,21 @@ export default class ParticleBatchModel extends scene.Model { const vBuffer: ArrayBuffer = new ArrayBuffer(this._vertAttribSizeStatic * this._vertCount); if (this._mesh) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison let vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD); // find ATTR_TEX_COORD index let vOffset = (this._vertAttrs![vIdx] as any).offset; // find ATTR_TEX_COORD offset + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this._mesh.copyAttribute(0, AttributeName.ATTR_TEX_COORD, vBuffer, this._vertAttribSizeStatic, vOffset); // copy mesh uv to ATTR_TEX_COORD + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD3); // find ATTR_TEX_COORD3 index vOffset = (this._vertAttrs![vIdx++] as any).offset; // find ATTR_TEX_COORD3 offset + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this._mesh.copyAttribute(0, AttributeName.ATTR_POSITION, vBuffer, this._vertAttribSizeStatic, vOffset); // copy mesh position to ATTR_TEX_COORD3 vOffset = (this._vertAttrs![vIdx++] as any).offset; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this._mesh.copyAttribute(0, AttributeName.ATTR_NORMAL, vBuffer, this._vertAttribSizeStatic, vOffset); // copy mesh normal to ATTR_NORMAL vOffset = (this._vertAttrs![vIdx++] as any).offset; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument if (!this._mesh.copyAttribute(0, AttributeName.ATTR_COLOR, vBuffer, this._vertAttribSizeStatic, vOffset)) { // copy mesh color to ATTR_COLOR1 const vb = new Uint32Array(vBuffer); for (let iVertex = 0; iVertex < this._vertCount; ++iVertex) { @@ -412,7 +427,7 @@ export default class ParticleBatchModel extends scene.Model { } } - public addGPUParticleVertexData (p: Particle, num: number, time:number): void { + public addGPUParticleVertexData (p: Particle, num: number, time: number): void { if (!this._useInstance) { let offset = num * this._vertAttrsFloatCount * this._vertCount; for (let i = 0; i < this._vertCount; i++) { @@ -451,7 +466,7 @@ export default class ParticleBatchModel extends scene.Model { } } - private addGPUParticleVertexDataIns (p: Particle, num: number, time:number): void { + private addGPUParticleVertexDataIns (p: Particle, num: number, time: number): void { let offset = num * this._vertAttrsFloatCount; let idx = offset; this._vdataF32![idx++] = p.position.x; From 331fab3c6b341a715f770f28d37103766b1c35ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Thu, 17 Aug 2023 10:21:44 +0800 Subject: [PATCH 118/184] SkeletalAnimation: disable animation baking in pure editor mode (#15977) --- .../skeletal-animation/skeletal-animation.ts | 76 ++++++++++++------- tests/animation/skeletal-animation.test.ts | 39 ++++++++++ 2 files changed, 86 insertions(+), 29 deletions(-) diff --git a/cocos/3d/skeletal-animation/skeletal-animation.ts b/cocos/3d/skeletal-animation/skeletal-animation.ts index a53df4e3ffc..9bba33a2c59 100644 --- a/cocos/3d/skeletal-animation/skeletal-animation.ts +++ b/cocos/3d/skeletal-animation/skeletal-animation.ts @@ -25,8 +25,9 @@ import { ccclass, executeInEditMode, executionOrder, help, menu, type, serializable, editable, } from 'cc.decorator'; +import { EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; import { SkinnedMeshRenderer } from '../skinned-mesh-renderer'; -import { Mat4, cclegacy, js, assertIsTrue } from '../../core'; +import { Mat4, cclegacy, js, assertIsTrue, warn } from '../../core'; import { DataPoolManager } from './data-pool-manager'; import { Node } from '../../scene-graph/node'; import { AnimationClip } from '../../animation/animation-clip'; @@ -37,6 +38,8 @@ import { getWorldTransformUntilRoot } from '../../animation/transform-utils'; import type { AnimationState } from '../../animation/animation-state'; import { getGlobalAnimationManager } from '../../animation/global-animation-manager'; +const FORCE_BAN_BAKED_ANIMATION = EDITOR_NOT_IN_PREVIEW; + /** * @en The socket to synchronize transform from skeletal joint to target node. * @zh 骨骼动画的挂点,用于将骨骼树的挂点节点变化矩阵同步到目标节点上 @@ -113,7 +116,7 @@ export class SkeletalAnimation extends Animation { } set sockets (val) { - if (!this._useBakedAnimation) { + if (!this._useBakedEffectively) { const animMgr = getGlobalAnimationManager(); animMgr.removeSockets(this.node, this._sockets); animMgr.addSockets(this.node, val); @@ -127,33 +130,20 @@ export class SkeletalAnimation extends Animation { * Whether to bake animations. Default to true,
* which substantially increases performance while making all animations completely fixed.
* Dynamically changing this property will take effect when playing the next animation clip. + * Note, in editor(not in preview) mode, this option takes no effect: animation is always non-baked. * @zh * 是否使用预烘焙动画,默认启用,可以大幅提高运行效时率,但所有动画效果会被彻底固定,不支持任何形式的编辑和混合。
* 运行时动态修改此选项会在播放下一条动画片段时生效。 + * 注意,在编辑器(非预览)模式下,此选项不起作用:动画总是非预烘焙的。 */ @editable get useBakedAnimation (): boolean { return this._useBakedAnimation; } - set useBakedAnimation (val) { - this._useBakedAnimation = val; - - for (const stateName in this._nameToState) { - const state = this._nameToState[stateName] as SkeletalAnimationState; - state.setUseBaked(val); - } - - this._users.forEach((user) => { - user.setUseBakedAnimation(val); - }); - - if (this._useBakedAnimation) { - getGlobalAnimationManager().removeSockets(this.node, this._sockets); - } else { - getGlobalAnimationManager().addSockets(this.node, this._sockets); - this._currentBakedState = null; - } + set useBakedAnimation (value) { + this._useBakedAnimation = value; + this._applyBakeFlagChange(); } @serializable @@ -193,12 +183,12 @@ export class SkeletalAnimation extends Animation { public start (): void { this.sockets = this._sockets; - this.useBakedAnimation = this._useBakedAnimation; + this._applyBakeFlagChange(); super.start(); } public pause (): void { - if (!this._useBakedAnimation) { + if (!this._useBakedEffectively) { super.pause(); } else { this._currentBakedState?.pause(); @@ -206,7 +196,7 @@ export class SkeletalAnimation extends Animation { } public resume (): void { - if (!this._useBakedAnimation) { + if (!this._useBakedEffectively) { super.resume(); } else { this._currentBakedState?.resume(); @@ -214,7 +204,7 @@ export class SkeletalAnimation extends Animation { } public stop (): void { - if (!this._useBakedAnimation) { + if (!this._useBakedEffectively) { super.stop(); } else if (this._currentBakedState) { this._currentBakedState.stop(); @@ -276,7 +266,7 @@ export class SkeletalAnimation extends Animation { const socket = this._sockets.find((s) => s.path === path); if (socket) { return socket.target; } const joint = this.node.getChildByPath(path); - if (!joint) { console.warn('illegal socket path'); return null; } + if (!joint) { warn('illegal socket path'); return null; } const target = new Node(); target.parent = this.node; this._sockets.push(new Socket(path, target)); @@ -288,14 +278,14 @@ export class SkeletalAnimation extends Animation { * @internal This method only friends to skinned mesh renderer. */ public notifySkinnedMeshAdded (skinnedMeshRenderer: SkinnedMeshRenderer): void { - const { _useBakedAnimation: useBakedAnimation } = this; + const { _useBakedEffectively } = this; const formerBound = skinnedMeshRenderer.associatedAnimation; if (formerBound) { formerBound._users.delete(skinnedMeshRenderer); } skinnedMeshRenderer.associatedAnimation = this; - skinnedMeshRenderer.setUseBakedAnimation(useBakedAnimation, true); - if (useBakedAnimation) { + skinnedMeshRenderer.setUseBakedAnimation(_useBakedEffectively, true); + if (_useBakedEffectively) { const { _currentBakedState: playingState } = this; if (playingState) { skinnedMeshRenderer.uploadAnimation(playingState.clip); @@ -333,7 +323,7 @@ export class SkeletalAnimation extends Animation { } protected doPlayOrCrossFade (state: AnimationState, duration: number): void { - if (this._useBakedAnimation) { + if (this._useBakedEffectively) { if (this._currentBakedState) { this._currentBakedState.stop(); } @@ -354,4 +344,32 @@ export class SkeletalAnimation extends Animation { this.notifySkinnedMeshRemoved(user); }); } + + private get _useBakedEffectively (): boolean { + if (FORCE_BAN_BAKED_ANIMATION) { + return false; + } else { + return this._useBakedAnimation; + } + } + + private _applyBakeFlagChange (): void { + const useBakedEffectively = this._useBakedEffectively; + + for (const stateName in this._nameToState) { + const state = this._nameToState[stateName] as SkeletalAnimationState; + state.setUseBaked(useBakedEffectively); + } + + this._users.forEach((user) => { + user.setUseBakedAnimation(useBakedEffectively); + }); + + if (useBakedEffectively) { + getGlobalAnimationManager().removeSockets(this.node, this._sockets); + } else { + getGlobalAnimationManager().addSockets(this.node, this._sockets); + this._currentBakedState = null; + } + } } diff --git a/tests/animation/skeletal-animation.test.ts b/tests/animation/skeletal-animation.test.ts index 6c6433b5f41..4c7605be10e 100644 --- a/tests/animation/skeletal-animation.test.ts +++ b/tests/animation/skeletal-animation.test.ts @@ -8,6 +8,9 @@ import { JointAnimationInfo } from '../../cocos/3d/skeletal-animation/skeletal-a import { SkinnedMeshRenderer } from '../../cocos/3d/skinned-mesh-renderer'; import { Node, Scene } from '../../cocos/scene-graph'; import { director, game } from '../../cocos/game'; +import { SkinningModel } from '../../cocos/3d/models/skinning-model'; +import { Mesh, Skeleton } from '../../cocos/3d'; +import { BakedSkinningModel } from '../../cocos/3d/models/baked-skinning-model'; describe('Skeletal animation state', () => { function createSimpleClip(name: string, duration: number, from: number, to: number, path = '') { @@ -220,4 +223,40 @@ describe('Skeletal animation component', () => { skeletalAnimation.enabled = true; expect(state.isPlaying && !state.isPaused).toBe(true); }); + + describe(`useBakedAnimation`, () => { + test.each([ + [true], + [false], + ] as [use: boolean][])(`useBakedAnimation: %s`, ( + use, + ) => { + const clip = new AnimationClip('meow'); + clip.duration = 1.0; + + const node = new Node(); + + const skinnedMeshRenderer = node.addComponent(SkinnedMeshRenderer) as SkinnedMeshRenderer; + skinnedMeshRenderer.mesh = new Mesh(); + skinnedMeshRenderer.skeleton = new Skeleton(); + skinnedMeshRenderer.skinningRoot = node; + + const skeletalAnimation = node.addComponent(SkeletalAnimation) as SkeletalAnimation; + skeletalAnimation.clips = [clip]; + + skeletalAnimation.useBakedAnimation = use; + expect(skeletalAnimation.useBakedAnimation).toBe(use); + + const scene = new Scene('Scene'); + scene.addChild(node); + + director.runSceneImmediate(scene); + + if (use) { + expect(skinnedMeshRenderer.model).toBeInstanceOf(BakedSkinningModel); + } else { + expect(skinnedMeshRenderer.model).toBeInstanceOf(SkinningModel); + } + }); + }); }); \ No newline at end of file From 0a50141a7e87aaa32880d6bc73bdf2095322d46e Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Thu, 17 Aug 2023 10:22:55 +0800 Subject: [PATCH 119/184] add sheen lighting model and substance support for sheen and coat (#15970) --- .../data-structures/lighting-result.chunk | 2 + .../lighting-flow/common-flow.chunk | 9 + .../model-functions/standard.chunk | 3 +- .../surfaces/data-structures/standard.chunk | 1 + .../default-functions/standard-fs.chunk | 20 + .../effect-macros/common-macros.chunk | 5 +- .../module-functions/standard-fs.chunk | 18 + .../assets/effects/advanced/car-paint.effect | 11 +- editor/assets/effects/advanced/fabric.effect | 346 ++++++++++++++++++ .../effects/advanced/fabric.effect.meta | 11 + 10 files changed, 422 insertions(+), 4 deletions(-) create mode 100644 editor/assets/effects/advanced/fabric.effect create mode 100644 editor/assets/effects/advanced/fabric.effect.meta diff --git a/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk b/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk index fd148768dde..11e5a19c741 100644 --- a/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk +++ b/editor/assets/chunks/lighting-models/data-structures/lighting-result.chunk @@ -24,6 +24,8 @@ struct LightingResult #if CC_SURFACES_LIGHTING_TRANSMIT_DIFFUSE vec3 directTransmitDiffuse, environmentTransmitDiffuse; #endif + // used for retro/internal-reflection such as TRT, Dual-Lobe Specular, Sheen... + // multi-layer (coat) just temporary use here, it should be moved to LightingResultPerLayer member #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR vec3 direct2ndSpecular, environment2ndSpecular; vec3 specularColorWithLighting2ndSpecular; diff --git a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk index 4bce62ff3eb..88078372f3a 100644 --- a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk +++ b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk @@ -111,6 +111,10 @@ CCSurfacesLightingCalculateIntermediateData_PerLight(lightingData2ndSpecular, surfaceData, lightDirWithLength); CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, attenuatedLightColorAndIntensity, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF2ndSpecular, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, vec3(1.0)); + #if CC_SURFACES_LIGHTING_SHEEN + vec3 extraF = CCSurfaceLightingCalculateExtraFresnel(lightingData2ndSpecular); + lightingResult.directGF2ndSpecular *= extraF; + #endif lightingResult.direct2ndSpecular *= multiplier; #endif @@ -259,6 +263,11 @@ CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, cc_mainLitColor, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF2ndSpecular, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, lightingResult.environmentGF2ndSpecular); + #if CC_SURFACES_LIGHTING_SHEEN + vec3 extraF = CCSurfaceLightingCalculateExtraFresnel(lightingData2ndSpecular); + lightingResult.environmentGF2ndSpecular *= extraF; + lightingResult.directGF2ndSpecular *= extraF; + #endif #endif #if CC_SURFACES_LIGHTING_TT diff --git a/editor/assets/chunks/lighting-models/model-functions/standard.chunk b/editor/assets/chunks/lighting-models/model-functions/standard.chunk index 74d1afe399f..89f25c75547 100644 --- a/editor/assets/chunks/lighting-models/model-functions/standard.chunk +++ b/editor/assets/chunks/lighting-models/model-functions/standard.chunk @@ -58,13 +58,11 @@ void CCSurfacesLightingCalculateEnvironment(out vec3 lightingDiffuse, out vec3 l #endif } -#if CC_SURFACES_LIGHTING_USE_FRESNEL vec3 CCSurfaceLightingCalculateExtraFresnel(in LightingIntermediateData lightingData) { float fresnel = CalculateFresnelCoefficient(lightingData.ior, lightingData.NoVAbsSat); //NoVSat for single side, and NoVAbsSat for two sided return vec3(fresnel); } -#endif void CCSurfaceLightingCalculateDirectFresnel(out vec3 directGF, in LightingIntermediateData lightingData, vec3 specularColor, in vec3 environmentGF) { @@ -255,6 +253,7 @@ void CCSurfaceLightingCalculateEnvironmentFresnel(out vec3 integratedGF, vec3 in #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND // todo: layer result in LightingResult separate to single structure like LightingResultPerLayer + // todo: after structuring, add TRT/Sheen to eachLayer's direct/environmentSpecular before blending void CCSurfacesLightingCalculateDirectMultiLayerBlending(inout LightingResult lightingResult , in LightingIntermediateData lightingData2ndLayer #if CC_SURFACES_LIGHTING_USE_MULTIPLE_LAYER_BLEND > 1 diff --git a/editor/assets/chunks/surfaces/data-structures/standard.chunk b/editor/assets/chunks/surfaces/data-structures/standard.chunk index a45f0309095..35ad979848b 100644 --- a/editor/assets/chunks/surfaces/data-structures/standard.chunk +++ b/editor/assets/chunks/surfaces/data-structures/standard.chunk @@ -28,6 +28,7 @@ struct SurfacesMaterialData #endif #if CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR // for storage only, copied with CCSurfacesGetSurfacesMaterialData2ndSpecular + // todo: use SurfacesMaterialDataPerLayer instead vec3 baseColor2ndSpecular, color2ndSpecular; float intensity2ndSpecular, roughness2ndSpecular, metallic2ndSpecular; vec3 worldNormal2ndSpecular, worldTangent2ndSpecular, worldBinormal2ndSpecular; diff --git a/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk b/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk index 230cbf6f2bb..038a9e75993 100644 --- a/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk +++ b/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk @@ -215,6 +215,26 @@ vec3 SurfacesFragmentModifyClearCoatWorldNormal() } #endif +#ifndef CC_SURFACES_FRAGMENT_MODIFY_SHEEN_PARAMS +// depends on CC_SURFACES_FRAGMENT_MODIFY_SHEEN_PARAMS +vec4 SurfacesFragmentModifySheenParams() +{ + //x: sheen roughness + //y: sheen ior + //z: sheen opacity + //w: sheen intensity + return vec4(0.7, 1.0, 1.0, 1.0); +} +#endif + +#ifndef CC_SURFACES_FRAGMENT_MODIFY_SHEEN_COLOR +// depends on CC_SURFACES_FRAGMENT_MODIFY_SHEEN_COLOR +vec3 SurfacesFragmentModifySheenColor() +{ + return vec3(1.0, 1.0, 1.0); +} +#endif + #ifndef CC_SURFACES_FRAGMENT_MODIFY_SHARED_DATA // depends on CC_SURFACES_FRAGMENT_MODIFY_SHARED_DATA // some material datas use shared raw data, avoid sample / calculate same raw data multiply times, use this function for better performance diff --git a/editor/assets/chunks/surfaces/effect-macros/common-macros.chunk b/editor/assets/chunks/surfaces/effect-macros/common-macros.chunk index 6c8caca0b8d..dd8d5c245ca 100644 --- a/editor/assets/chunks/surfaces/effect-macros/common-macros.chunk +++ b/editor/assets/chunks/surfaces/effect-macros/common-macros.chunk @@ -71,6 +71,9 @@ #ifndef CC_SURFACES_LIGHTING_DUAL_LOBE_SPECULAR #define CC_SURFACES_LIGHTING_DUAL_LOBE_SPECULAR 0 #endif +#ifndef CC_SURFACES_LIGHTING_SHEEN + #define CC_SURFACES_LIGHTING_SHEEN 0 +#endif #ifndef CC_SURFACES_LIGHTING_CLEAR_COAT #define CC_SURFACES_LIGHTING_CLEAR_COAT 0 #endif @@ -83,7 +86,7 @@ // common 2nd-specular for TRT / Dual-Lobe / Wet / ClearCoat... #ifndef CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR - #if CC_SURFACES_LIGHTING_TRT || CC_SURFACES_LIGHTING_DUAL_LOBE_SPECULAR || CC_SURFACES_LIGHTING_CLEAR_COAT + #if CC_SURFACES_LIGHTING_TRT || CC_SURFACES_LIGHTING_DUAL_LOBE_SPECULAR || CC_SURFACES_LIGHTING_SHEEN || CC_SURFACES_LIGHTING_CLEAR_COAT #define CC_SURFACES_LIGHTING_2ND_LAYER_SPECULAR 1 #endif #endif diff --git a/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk b/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk index 6399cee8adc..6d139729e86 100644 --- a/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk @@ -87,6 +87,24 @@ void CCSurfacesFragmentGetMaterialData(inout SurfacesMaterialData surfaceData) #endif #endif +#if CC_SURFACES_LIGHTING_SHEEN + // skip in shader graph, need extra code + vec4 sheenParams = SurfacesFragmentModifySheenParams(); + surfaceData.roughness2ndSpecular = saturate(sheenParams.x); + surfaceData.ior2ndSpecular = sheenParams.y; + surfaceData.intensity2ndSpecular = sheenParams.z * sheenParams.w; + surfaceData.metallic2ndSpecular = 1.0; + surfaceData.baseColor2ndSpecular = SurfacesFragmentModifySheenColor(); + surfaceData.color2ndSpecular = vec3(1.0); // no extra coloration + surfaceData.worldNormal2ndSpecular = surfaceData.worldNormal; + surfaceData.worldTangent2ndSpecular = surfaceData.worldTangent; + surfaceData.worldBinormal2ndSpecular = surfaceData.worldBinormal; + surfaceData.opacity2ndSpecular = 1.0; // unused + #if CC_SURFACES_LIGHTING_ANISOTROPIC + surfaceData.anisotropyShape2ndSpecular = surfaceData.anisotropyShape; + #endif +#endif + #if CC_SURFACES_LIGHTING_CLEAR_COAT // skip in shader graph, need extra code vec4 clearCoatParams = SurfacesFragmentModifyClearCoatParams(); diff --git a/editor/assets/effects/advanced/car-paint.effect b/editor/assets/effects/advanced/car-paint.effect index 457fd1d97c5..6d7b0a97083 100644 --- a/editor/assets/effects/advanced/car-paint.effect +++ b/editor/assets/effects/advanced/car-paint.effect @@ -30,6 +30,7 @@ CCEffect %{ gradientIntensity: { value: 0.5, target: emissiveScaleParam.y, editor: { parent: USE_GRADIENT_COLOR, slide: true, range: [0, 1.0], step: 0.001 } } mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } normalMap: { value: normal } + coatDataMap: { value: white, editor: { parent: USE_COAT_DATA_MAP, tooltip: 'r: Coat Roughness g: Coat Specular Intensity b: Coat Opacity.' } } coatNormalMap: { value: normal, editor: { parent: USE_FLAKE } } flakeDataMap: { value: white, editor: { parent: USE_FLAKE } } pbrMap: { value: grey } @@ -193,6 +194,9 @@ CCProgram surface-fragment %{ uniform sampler2D coatNormalMap; uniform sampler2D flakeDataMap; #endif + #if USE_COAT_DATA_MAP + uniform sampler2D coatDataMap; + #endif #pragma define OCCLUSION_CHANNEL r #pragma define ROUGHNESS_CHANNEL g @@ -206,7 +210,12 @@ CCProgram surface-fragment %{ #define CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_PARAMS vec4 SurfacesFragmentModifyClearCoatParams() { - return vec4(coatParam.x, coatParam.y - 0.99, coatParam.z, coatParam.w * 2.0); + vec4 params = vec4(coatParam.x, coatParam.y - 0.99, coatParam.z, coatParam.w * 2.0); + #if USE_COAT_DATA_MAP + vec4 coatData = texture(coatDataMap, FSInput_texcoord); + params *= vec4(coatData.r, 1.0, coatData.b, coatData.g); + #endif + return params; } #define CC_SURFACES_FRAGMENT_MODIFY_CLEAR_COAT_COLOR diff --git a/editor/assets/effects/advanced/fabric.effect b/editor/assets/effects/advanced/fabric.effect new file mode 100644 index 00000000000..4803793548b --- /dev/null +++ b/editor/assets/effects/advanced/fabric.effect @@ -0,0 +1,346 @@ +// Copyright (c) 2017-2022 Xiamen Yaji Software Co., Ltd. + +CCEffect %{ + techniques: + - name: opaque + passes: + - vert: standard-vs + frag: standard-fs + properties: &props + tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } + mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, linear: true, editor: { displayName: Albedo, type: color } } + albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } + alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST, slide: true, range: [0, 1.0], step: 0.001 } } + occlusion: { value: 0.0, target: pbrParams.x, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + roughness: { value: 0.5, target: pbrParams.y, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + metallic: { value: 0.0, target: pbrParams.z, editor: { slide: true, range: [0, 1.0], step: 0.001 } } + specularIntensity: { value: 0.5, target: pbrParams.w, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + normalStrength: { value: 1.0, target: emissiveScaleParam.w, editor: { parent: USE_NORMAL_MAP, slide: true, range: [0, 5.0], step: 0.001 } } + anisotropyIntensity: { value: 1.0, target: anisotropyParam.x, editor: { parent: IS_ANISOTROPY, slide : true, range : [0.0, 1.0] , step : 0.0001 } } + anisotropyRotation: { value: 0.0, target: anisotropyParam.y, editor: { parent: IS_ANISOTROPY, slide : true, range : [0, 1.0] , step : 0.0001 } } + anisotropyMapResolutionHeight: { value: 0.0, target: anisotropyParam.w, editor: { parent: FIX_ANISOTROPIC_ROTATION_MAP } } + addOnShadowBias: { value: 0.0, target: anisotropyParam.z } + mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } + normalMap: { value: normal } + pbrMap: { value: grey } + occlusionMap: { value: white } + anisotropyMap: { value: black, editor : { parent: IS_ANISOTROPY } } + sheenColor: { value: [1.0, 1.0, 1.0, 1.0], linear: true, editor: { type: color } } + sheenRoughness: { value: 1.0, target: emissiveScaleParam.x, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + sheenIOR: { value: 1.0, target: emissiveScaleParam.y, editor: { slide: true, range: [1.0, 2.0], step: 0.001 } } + sheenOpacity: { value: 1.0, target: emissiveScaleParam.z, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + sheenMap: { value: white, editor: { parent: USE_SHEEN_MAP, tooltips: 'r: sheen roughness g: sheen opacity' } } + - &forward-add + vert: standard-vs + frag: standard-fs + phase: forward-add + propertyIndex: 0 + embeddedMacros: { CC_FORWARD_ADD: true } + depthStencilState: + depthFunc: equal + depthTest: true + depthWrite: false + blendState: + targets: + - blend: true + blendSrc: one + blendDst: one + blendSrcAlpha: zero + blendDstAlpha: one + - &shadow-caster + vert: shadow-caster-vs + frag: shadow-caster-fs + phase: shadow-caster + propertyIndex: 0 + rasterizerState: + cullMode: front + properties: + tilingOffset: { value: [1.0, 1.0, 0.0, 0.0] } + mainColor: { value: [1.0, 1.0, 1.0, 1.0], target: albedo, editor: { displayName: Albedo, type: color } } + albedoScale: { value: [1.0, 1.0, 1.0], target: albedoScaleAndCutoff.xyz } + alphaThreshold: { value: 0.5, target: albedoScaleAndCutoff.w, editor: { parent: USE_ALPHA_TEST } } + mainTexture: { value: grey, target: albedoMap, editor: { displayName: AlbedoMap } } + - &reflect-map + vert: standard-vs + frag: reflect-map-fs + phase: reflect-map + propertyIndex: 0 + - &planar-shadow + vert: planar-shadow-vs + frag: planar-shadow-fs + phase: planar-shadow + propertyIndex: 0 + depthStencilState: + depthTest: true + depthWrite: false + stencilTestFront: true + stencilFuncFront: not_equal + stencilPassOpFront: replace + stencilRef: 0x80 # only use the leftmost bit + stencilReadMask: 0x80 + stencilWriteMask: 0x80 + blendState: + targets: + - blend: true + blendSrc: src_alpha + blendDst: one_minus_src_alpha + blendDstAlpha: one_minus_src_alpha + - &deferred + vert: standard-vs + frag: standard-fs + pass: gbuffer + phase: gbuffer + embeddedMacros: { CC_PIPELINE_TYPE: 1 } + propertyIndex: 0 + - name: transparent + passes: + - vert: standard-vs + frag: standard-fs + embeddedMacros: { CC_FORCE_FORWARD_SHADING: true } + depthStencilState: &d1 + depthTest: true + depthWrite: false + blendState: &b1 + targets: + - blend: true + blendSrc: src_alpha + blendDst: one_minus_src_alpha + blendDstAlpha: one_minus_src_alpha + properties: *props + - *forward-add + - *shadow-caster + - *planar-shadow + - &deferred-forward + vert: standard-vs + frag: standard-fs + phase: deferred-forward + embeddedMacros: { CC_PIPELINE_TYPE: 0 } + propertyIndex: 0 + depthStencilState: *d1 + blendState: *b1 +}% + +CCProgram shared-ubos %{ + uniform Constants { + vec4 tilingOffset; + vec4 albedo; + vec4 albedoScaleAndCutoff; + vec4 pbrParams; + vec4 sheenColor; + vec4 emissiveScaleParam; + vec4 anisotropyParam; + }; +}% + +CCProgram macro-remapping %{ + // ui displayed macros + #pragma define-meta HAS_SECOND_UV + #pragma define-meta USE_TWOSIDE + #pragma define-meta IS_ANISOTROPY + #pragma define-meta USE_VERTEX_COLOR + + #define CC_SURFACES_USE_SECOND_UV HAS_SECOND_UV + #define CC_SURFACES_USE_TWO_SIDED USE_TWOSIDE + #define CC_SURFACES_LIGHTING_ANISOTROPIC IS_ANISOTROPY + #define CC_SURFACES_USE_VERTEX_COLOR USE_VERTEX_COLOR + #define CC_SURFACES_LIGHTING_SHEEN 1 + + // depend on UI macros +#if IS_ANISOTROPY || USE_NORMAL_MAP + #define CC_SURFACES_USE_TANGENT_SPACE 1 +#endif + + // functionality for each effect + #define CC_SURFACES_LIGHTING_ANISOTROPIC_ENVCONVOLUTION_COUNT 31 +}% + +CCProgram surface-vertex %{ + #define CC_SURFACES_VERTEX_MODIFY_SHADOW_BIAS + vec2 SurfacesVertexModifyShadowBias(in SurfacesStandardVertexIntermediate In, vec2 originShadowBias) + { + return originShadowBias + vec2(anisotropyParam.z, 0.0); + } + + #define CC_SURFACES_VERTEX_MODIFY_UV + void SurfacesVertexModifyUV(inout SurfacesStandardVertexIntermediate In) + { + In.texCoord = In.texCoord * tilingOffset.xy + tilingOffset.zw; + #if CC_SURFACES_USE_SECOND_UV + In.texCoord1 = In.texCoord1 * tilingOffset.xy + tilingOffset.zw; + #endif + } +}% + +CCProgram surface-fragment %{ + #if USE_ALBEDO_MAP + uniform sampler2D albedoMap; + #pragma define-meta ALBEDO_UV options([v_uv, v_uv1]) + #endif + #if USE_NORMAL_MAP + uniform sampler2D normalMap; + #pragma define-meta NORMAL_UV options([v_uv, v_uv1]) + #endif + #pragma define-meta DEFAULT_UV options([v_uv, v_uv1]) + #if USE_PBR_MAP + uniform sampler2D pbrMap; + #endif + #if USE_OCCLUSION_MAP + uniform sampler2D occlusionMap; + #endif + #if IS_ANISOTROPY && USE_ANISOTROPY_MAP + uniform sampler2D anisotropyMap; + #endif + #if USE_SHEEN_MAP + uniform sampler2D sheenMap; + #endif + + #pragma define OCCLUSION_CHANNEL r + #pragma define ROUGHNESS_CHANNEL g + #pragma define METALLIC_CHANNEL b + #pragma define SPECULAR_INTENSITY_CHANNEL a + + #if USE_ALPHA_TEST + #pragma define-meta ALPHA_TEST_CHANNEL options([a, r]) + #endif + + #define CC_SURFACES_FRAGMENT_MODIFY_ANISOTROPY_PARAMS + vec4 SurfacesFragmentModifyAnisotropyParams(out float isRotation) + { + float anisotropyRotation = anisotropyParam.y * PI; + float anisotropyShape = anisotropyParam.x; + #if IS_ANISOTROPY && USE_ANISOTROPY_MAP + // Rotation angle should disable trilinear filtering + vec4 tex = texture(anisotropyMap, DEFAULT_UV); + anisotropyRotation = fract(anisotropyRotation * 0.5 + tex.y) * PI2; + // less value is better for SP exported shape + anisotropyShape *= tex.x; + #endif + + isRotation = 1.0; + return vec4(anisotropyShape, anisotropyRotation, 0.0, 0.0); + } + + #define CC_SURFACES_FRAGMENT_MODIFY_SHEEN_PARAMS + vec4 SurfacesFragmentModifySheenParams() + { + vec4 param = vec4(emissiveScaleParam.x, emissiveScaleParam.y - 0.9, emissiveScaleParam.z, 1.0); + #if USE_SHEEN_MAP + param.xz *= texture(sheenMap, FSInput_texcoord).xy; + #endif + return param; + } + + #define CC_SURFACES_FRAGMENT_MODIFY_SHEEN_COLOR + vec3 SurfacesFragmentModifySheenColor() + { + return sheenColor.rgb; + } + + #include +}% + +CCProgram standard-vs %{ + precision highp float; + + // 1. surface internal macros, for technique usage or remapping some user (material) macros to surface internal macros + #include + #include + + // 2. common include with corresponding shader stage, include before surface functions + #include + + // 3. user surface functions that can use user (effect) parameters (ubo Constants) + // see surfaces/default-functions/xxx.chunk + #include + #include + + // 4. surface include with corresponding shader stage and shading-model (optional) + #include + + // 5. shader entry with corresponding shader stage and technique usage/type + #include +}% + + +CCProgram shadow-caster-vs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram planar-shadow-vs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + + +CCProgram standard-fs %{ + // shading-model : standard + // lighting-model : standard (isotropy / anisotropy pbr) + // shader stage : fs + // technique usage/type : render-to-scene + + precision highp float; + // 1. surface internal macros, for technique usage or remapping some user (material) macros to surface internal macros + #include + #include + + // 2. common include with corresponding shader stage, include before surface functions + #include + + // 3. user surface functions that can use user (effect) parameters (ubo Constants) + // see surfaces/default-functions/xxx.chunk + #include + #include + + // 4. lighting-model (optional) + #include + + // 5. surface include with corresponding shader stage and shading-model (optional) + #include + + // 6. shader entry with corresponding shader stage and technique usage/type + #include +}% + +CCProgram shadow-caster-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram planar-shadow-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include +}% + +CCProgram reflect-map-fs %{ + precision highp float; + #include + #include + #include + #include + #include + #include + #include + #include +}% + diff --git a/editor/assets/effects/advanced/fabric.effect.meta b/editor/assets/effects/advanced/fabric.effect.meta new file mode 100644 index 00000000000..8a62097c4df --- /dev/null +++ b/editor/assets/effects/advanced/fabric.effect.meta @@ -0,0 +1,11 @@ +{ + "ver": "1.7.0", + "importer": "effect", + "imported": true, + "uuid": "b25c7601-1d07-4a56-86c5-62e83ea7c61e", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} From 6e7841fbbbe4a522da88f258a994f6a01dcc4c4f Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Thu, 17 Aug 2023 10:24:49 +0800 Subject: [PATCH 120/184] fixed colorTemperatureRGB jsb binding. (#15972) --- native/tools/swig-config/scene.i | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/tools/swig-config/scene.i b/native/tools/swig-config/scene.i index 39aa6e93646..2a2fff63cae 100644 --- a/native/tools/swig-config/scene.i +++ b/native/tools/swig-config/scene.i @@ -80,7 +80,7 @@ using namespace cc; } }, result); - + SE_PRECONDITION2(ok, false, "Error processing arguments"); %} @@ -337,6 +337,7 @@ using namespace cc; %attribute(cc::scene::Light, ccstd::string&, name, getName, setName); %attribute(cc::scene::Light, cc::scene::RenderScene*, scene, getScene); %attribute(cc::scene::Light, uint32_t, visibility, getVisibility, setVisibility); +%attribute(cc::scene::Light, cc::Vec3&, colorTemperatureRGB, getColorTemperatureRGB, setColorTemperatureRGB); %attribute(cc::scene::LODData, float, screenUsagePercentage, getScreenUsagePercentage, setScreenUsagePercentage); %attribute(cc::scene::LODData, ccstd::vector>&, models, getModels); From c0adb51d36a2c950e76b05f61d5206b1b94436a0 Mon Sep 17 00:00:00 2001 From: zxx43 Date: Thu, 17 Aug 2023 10:38:56 +0800 Subject: [PATCH 121/184] add jsb Slot::getAttachment & Slot::setAttachment (#15964) * add Slot::getAttachment & Slot::setAttachment * Use nativevalue_to_se instead of native_ptr_to_seval in js_spine_Slot_getAttachment * merge into 1 statement --- .../bindings/manual/jsb_spine_manual.cpp | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/native/cocos/bindings/manual/jsb_spine_manual.cpp b/native/cocos/bindings/manual/jsb_spine_manual.cpp index 6e550dc889d..4bc5f5fbb68 100644 --- a/native/cocos/bindings/manual/jsb_spine_manual.cpp +++ b/native/cocos/bindings/manual/jsb_spine_manual.cpp @@ -519,6 +519,42 @@ static bool js_spine_Skin_getAttachments(se::State& s) { } SE_BIND_FUNC(js_spine_Skin_getAttachments) +static bool js_spine_Slot_setAttachment(se::State& s) { + CC_UNUSED bool ok = true; + const auto& args = s.args(); + spine::Slot *slot = (spine::Slot *) NULL ; + + slot = SE_THIS_OBJECT(s); + if (nullptr == slot) return true; + + spine::Attachment* attachment = nullptr; + + ok = sevalue_to_native(args[0], &attachment, s.thisObject()); + SE_PRECONDITION2(ok, false, "Error processing arguments"); + + slot->setAttachment(attachment); + + return true; +} +SE_BIND_FUNC(js_spine_Slot_setAttachment) + +static bool js_spine_Slot_getAttachment(se::State& s) { + CC_UNUSED bool ok = true; + const auto& args = s.args(); + spine::Slot *slot = (spine::Slot *) NULL ; + + slot = SE_THIS_OBJECT(s); + if (nullptr == slot) return true; + + spine::Attachment *attachment = slot->getAttachment(); + if (attachment) { + nativevalue_to_se(attachment, s.rval(), s.thisObject()); + return true; + } + return false; +} +SE_BIND_FUNC(js_spine_Slot_getAttachment) + bool register_all_spine_manual(se::Object *obj) { // Get the ns se::Value nsVal; @@ -545,6 +581,8 @@ bool register_all_spine_manual(se::Object *obj) { __jsb_spine_SwirlVertexEffect_proto->defineFunction("transform", _SE(js_SwirlVertexEffect_transform)); __jsb_spine_JitterVertexEffect_proto->defineFunction("transform", _SE(js_JitterVertexEffect_transform)); __jsb_spine_Skin_proto->defineFunction("getAttachments", _SE(js_spine_Skin_getAttachments)); + __jsb_spine_Slot_proto->defineFunction("setAttachment", _SE(js_spine_Slot_setAttachment)); + __jsb_spine_Slot_proto->defineFunction("getAttachment", _SE(js_spine_Slot_getAttachment)); spine::setSpineObjectDisposeCallback([](void *spineObj) { if (!se::NativePtrToObjectMap::isValid()) { From dd356191613e9cc87c8f93cc98e0fc8095dfa5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Thu, 17 Aug 2023 11:15:43 +0800 Subject: [PATCH 122/184] Revert interface check (#15991) * Revert "Workflow: fix interface check workflow comment (#15795)" This reverts commit 44795e465ff034d3b51338f70f7b538f405db2f9. * Revert "V3.8.0 (#15697)" This reverts commit 1c16ac25d8268f977bcc625d31dea2d775e3afd1. --------- Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com> --- .github/workflows/run_test_cases.yml | 46 +++++-------------- .../workflows/run_test_cases_pr_comment.yml | 36 --------------- .../web-interface-check-pr-comment.yml | 42 ----------------- .github/workflows/web-interface-check.yml | 9 +--- 4 files changed, 13 insertions(+), 120 deletions(-) delete mode 100644 .github/workflows/run_test_cases_pr_comment.yml delete mode 100644 .github/workflows/web-interface-check-pr-comment.yml diff --git a/.github/workflows/run_test_cases.yml b/.github/workflows/run_test_cases.yml index 038ebd04c88..8e15788a1f3 100644 --- a/.github/workflows/run_test_cases.yml +++ b/.github/workflows/run_test_cases.yml @@ -1,12 +1,10 @@ name: run test cases on: - pull_request: + pull_request_target: issue_comment: types: [created, edited] -permissions: read-all - # github.head_ref is only defined on pull_request events concurrency: group: ${{ github.workflow }}-${{ github.actor }}-${{ github.head_ref || github.run_id }} @@ -281,38 +279,16 @@ jobs: JOBID=`cat /usr/local/lib/node_modules/@cctest/scheduler/logs/PR-TEST/nowJobId.log` cd .. python3 -u ./python/main.py --target=job_editor --jobid=$JOBID - - name: Write comment body and issue number to file - uses: actions/github-script@v5 - env: - PR_AUTHOR: ${{ steps.parse_pr.outputs.pr_author }} - EDITOR_VERSION: ${{ steps.run_test_cases.outputs.editor }} - TASK_STATUS: ${{ steps.run_test_cases.outputs.status }} - TASK_REPORT: ${{ steps.run_test_cases.outputs.report }} - JOB_ID: ${{ steps.run_test_cases.outputs.jobid }} - GITHUB_RUN_ID: ${{ github.run_id }} - PR_NUMBER: ${{ steps.get_pr.outputs.pr_number }} + - name: Update Comment + uses: peter-evans/create-or-update-comment@v1 with: - script: | - const fs = require('fs'); - fs.writeFileSync('pr.txt', process.env.PR_NUMBER); - fs.writeFileSync('comment.txt', `@${process.env.PR_AUTHOR}, Please check the result of \`run test cases\`: + issue-number: ${{ steps.get_pr.outputs.pr_number }} + body: | + @${{ steps.parse_pr.outputs.pr_author }}, Please check the result of `run test cases`: - Test Platform: PR-Test - - Editor Version: ${process.env.EDITOR_VERSION} - - Task Result: ${process.env.TASK_STATUS} - - Task URL: http://cctest.cocos.org/#/reportview/PR-TEST/${process.env.JOB_ID}/-1 - - GitHub Action: https://github.com/cocos/cocos-engine/actions/runs/${process.env.GITHUB_RUN_ID} + - Editor Version: ${{ steps.run_test_cases.outputs.editor }} + - Task Result: ${{ steps.run_test_cases.outputs.status }} + - Task URL: http://cctest.cocos.org/#/reportview/PR-TEST/${{ steps.run_test_cases.outputs.jobid }}/-1 + - GitHub Action: https://github.com/cocos/cocos-engine/actions/runs/${{ github.run_id }} ## Task Details - ${process.env.TASK_REPORT}`); - - name: Upload artifact - uses: actions/upload-artifact@v2 - with: - name: pr.txt - path: | - pr.txt - - name: Upload artifact - uses: actions/upload-artifact@v2 - with: - name: comment.txt - path: | - comment.txt - \ No newline at end of file + ${{ steps.run_test_cases.outputs.report }} diff --git a/.github/workflows/run_test_cases_pr_comment.yml b/.github/workflows/run_test_cases_pr_comment.yml deleted file mode 100644 index 7c425fb30c9..00000000000 --- a/.github/workflows/run_test_cases_pr_comment.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: run test cases PR comment -on: - workflow_run: - workflows: ["run test cases"] - types: - - completed - -permissions: - issues: write - pull-requests: write - -jobs: - post-pr-comment: - if: github.event.workflow_run.conclusion == 'success' - runs-on: ubuntu-latest - steps: - - name: Download artifacts - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RUN_ID: ${{ github.event.workflow_run.id }} - run: | - gh run download -R "${{ github.repository }}" --name "pr.txt" "$RUN_ID" - gh run download -R "${{ github.repository }}" --name "comment.txt" "$RUN_ID" - - name: Set PR environment variable - uses: actions/github-script@v4 - with: - script: | - const fs = require('fs'); - const pr = fs.readFileSync('pr.txt', 'utf8').trim(); - core.exportVariable('PR_NUMBER', pr); - - - name: Update Comment - uses: peter-evans/create-or-update-comment@v3 - with: - issue-number: ${{ env.PR_NUMBER }} - body-path: 'comment.txt' \ No newline at end of file diff --git a/.github/workflows/web-interface-check-pr-comment.yml b/.github/workflows/web-interface-check-pr-comment.yml deleted file mode 100644 index 79816558b63..00000000000 --- a/.github/workflows/web-interface-check-pr-comment.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Interface check PR comment -on: - workflow_run: - workflows: [" Interface check"] - types: - - completed - -permissions: - issues: write - pull-requests: write - -jobs: - post-pr-comment: - if: github.event.workflow_run.conclusion == 'success' - runs-on: ubuntu-latest - steps: - - name: 'Get source run informations' - uses: potiuk/get-workflow-origin@v1_1 - id: source_run_info - with: - token: ${{ secrets.GITHUB_TOKEN }} - sourceRunId: ${{ github.event.workflow_run.id }} - - - name: 'Debug' - run: | - Write-Host "Source PR Number: ${{ github.event.workflow_run.pull_requests[0].number }}" - shell: pwsh - - - name: Download artifacts - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RUN_ID: ${{ github.event.workflow_run.id }} - run: | - gh run download -R "${{ github.repository }}" --name "interface-diff.txt" "$RUN_ID" - - - name: Post interface-diff.txt as comment - uses: marocchino/sticky-pull-request-comment@v2 - with: - path: interface-diff.txt - number: ${{ steps.source_run_info.outputs.pullRequestNumber }} - # The following matters, see: https://github.com/orgs/community/discussions/25220 - # number: ${{ github.event.workflow_run.pull_requests[0].number }} \ No newline at end of file diff --git a/.github/workflows/web-interface-check.yml b/.github/workflows/web-interface-check.yml index f96ce3b2235..25f5e3492dd 100644 --- a/.github/workflows/web-interface-check.yml +++ b/.github/workflows/web-interface-check.yml @@ -1,15 +1,13 @@ name: Interface check #on: push -on: [pull_request] +on: [pull_request_target] # github.head_ref is only defined on pull_request events concurrency: group: ${{ github.workflow }}-${{ github.actor }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true -permissions: read-all - jobs: interface_check: if: @@ -81,9 +79,6 @@ jobs: cat ./interface-diff.txt node ./.github/workflows/interface-check-report.js - - name: Upload interface-diff.txt artifact - uses: actions/upload-artifact@v2 + - uses: marocchino/sticky-pull-request-comment@v2 with: - name: interface-diff.txt path: ./engine/interface-diff.txt - \ No newline at end of file From 9b08b34a2b2d6b86f0871492329e5d12e8b52b3b Mon Sep 17 00:00:00 2001 From: pandamicro Date: Thu, 17 Aug 2023 13:15:21 +0800 Subject: [PATCH 123/184] Replace Renderer setMaterial with setSharedMaterial (#15980) * Replace Renderer setMaterial with setSharedMaterial * Fix all usage of Renderer.setMaterial * Soft deprecate Renderer.setMaterial * Remove unnecessary change --- EngineErrorMap.md | 4 ++++ cocos/2d/components/graphics.ts | 6 +++--- cocos/2d/framework/ui-renderer.ts | 8 ++++---- .../skinned-mesh-renderer.ts | 4 ++-- cocos/dragon-bones/ArmatureDisplay.ts | 13 ++++++++++--- cocos/misc/renderer.ts | 19 +++++++++++++------ cocos/particle-2d/particle-system-2d.ts | 2 +- cocos/particle/line.ts | 2 +- .../renderer/particle-system-renderer-data.ts | 4 ++-- cocos/spine/skeleton.ts | 2 +- cocos/terrain/terrain.ts | 2 +- 11 files changed, 42 insertions(+), 24 deletions(-) diff --git a/EngineErrorMap.md b/EngineErrorMap.md index 8d5856b5a24..bf943cfd907 100644 --- a/EngineErrorMap.md +++ b/EngineErrorMap.md @@ -3267,6 +3267,10 @@ PassUtils: illegal uniform handle, accessing uniform at offset %d Pass: setUniform is invoked with incompatible uniform data type for binding %d, expected type is %s +### 12012 + +Can't set a material instance to a sharedMaterial slot + ### 12100 The font size is too big to be fitted into texture atlas. Please switch to other label cache modes or choose a smaller font size. diff --git a/cocos/2d/components/graphics.ts b/cocos/2d/components/graphics.ts index 1f4fb1c8e32..08248a4b935 100644 --- a/cocos/2d/components/graphics.ts +++ b/cocos/2d/components/graphics.ts @@ -34,7 +34,7 @@ import { IAssembler } from '../renderer/base'; import { IBatcher } from '../renderer/i-batcher'; import { LineCap, LineJoin } from '../assembler/graphics/types'; import { Impl } from '../assembler/graphics/webgl/impl'; -import { RenderingSubMesh } from '../../asset/assets'; +import { Material, RenderingSubMesh } from '../../asset/assets'; import { Format, PrimitiveMode, Attribute, Device, BufferUsageBit, BufferInfo, MemoryUsageBit, deviceManager } from '../../gfx'; import { vfmtPosColor, getAttributeStride, getComponentPerVertex } from '../renderer/vertex-format'; import { NativeUIModelProxy } from '../renderer/native-2d'; @@ -528,7 +528,7 @@ export class Graphics extends UIRenderer { * @param h @en The height of the rectangle. * @zh 矩形高度。 */ - public fillRect (x, y, w, h): void { + public fillRect (x: number, y: number, w: number, h: number): void { this.rect(x, y, w, h); this.fill(); } @@ -615,7 +615,7 @@ export class Graphics extends UIRenderer { mat = this.getMaterialInstance(0); } else { mat = builtinResMgr.get('ui-graphics-material'); - this.setMaterial(mat, 0); + this.setSharedMaterial(mat as Material, 0); mat = this.getMaterialInstance(0); mat.recompileShaders({ USE_LOCAL: true }); } diff --git a/cocos/2d/framework/ui-renderer.ts b/cocos/2d/framework/ui-renderer.ts index 440fedc6424..bb4c4a2abd6 100644 --- a/cocos/2d/framework/ui-renderer.ts +++ b/cocos/2d/framework/ui-renderer.ts @@ -151,12 +151,12 @@ export class UIRenderer extends Renderer { set sharedMaterials (val) { for (let i = 0; i < val.length; i++) { if (val[i] !== this._materials[i]) { - this.setMaterial(val[i], i); + this.setSharedMaterial(val[i], i); } } if (val.length < this._materials.length) { for (let i = val.length; i < this._materials.length; i++) { - this.setMaterial(null, i); + this.setSharedMaterial(null, i); } this._materials.splice(val.length); } @@ -450,12 +450,12 @@ export class UIRenderer extends Renderer { public updateMaterial (): void { if (this._customMaterial) { if (this.getSharedMaterial(0) !== this._customMaterial) { - this.setMaterial(this._customMaterial, 0); + this.setSharedMaterial(this._customMaterial, 0); } return; } const mat = this._updateBuiltinMaterial(); - this.setMaterial(mat, 0); + this.setSharedMaterial(mat, 0); if (this.stencilStage === Stage.ENTER_LEVEL || this.stencilStage === Stage.ENTER_LEVEL_INVERTED) { this.getMaterialInstance(0)!.recompileShaders({ USE_ALPHA_TEST: true }); } diff --git a/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts b/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts index 7f3125b3275..84cd794e0a2 100644 --- a/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts +++ b/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts @@ -143,8 +143,8 @@ export class SkinnedMeshRenderer extends MeshRenderer { } } - public setMaterial (material: Material | null, index: number): void { - super.setMaterial(material, index); + public setSharedMaterial (material: Material | null, index: number): void { + super.setSharedMaterial(material, index); if (this._modelType === SkinningModel) { this.getMaterialInstance(index); } diff --git a/cocos/dragon-bones/ArmatureDisplay.ts b/cocos/dragon-bones/ArmatureDisplay.ts index 2e70e6d9660..0c27f29e0cc 100644 --- a/cocos/dragon-bones/ArmatureDisplay.ts +++ b/cocos/dragon-bones/ArmatureDisplay.ts @@ -715,7 +715,7 @@ export class ArmatureDisplay extends UIRenderer { let mat; if (this._customMaterial) mat = this._customMaterial; else mat = this._updateBuiltinMaterial(); - this.setMaterial(mat, 0); + this.setSharedMaterial(mat as Material, 0); this._cleanMaterialCache(); } @@ -732,8 +732,15 @@ export class ArmatureDisplay extends UIRenderer { this._drawIdx = i; const dc = this._drawList.data[i]; if (dc.texture) { - batcher.commitMiddleware(this, meshBuffer, origin + dc.indexOffset, - dc.indexCount, dc.texture, dc.material!, this._enableBatch); + batcher.commitMiddleware( + this, + meshBuffer, + origin + dc.indexOffset, + dc.indexCount, + dc.texture, + dc.material!, + this._enableBatch, + ); } indicesCount += dc.indexCount; } diff --git a/cocos/misc/renderer.ts b/cocos/misc/renderer.ts index 8f5c9dc8e58..f7ccdbd2ca4 100644 --- a/cocos/misc/renderer.ts +++ b/cocos/misc/renderer.ts @@ -26,7 +26,7 @@ import { EDITOR } from 'internal:constants'; import { Material } from '../asset/assets/material'; import { Component } from '../scene-graph'; import { IMaterialInstanceInfo, MaterialInstance } from '../render-scene/core/material-instance'; -import { warnID, _decorator } from '../core'; +import { warnID, _decorator, errorID } from '../core'; const _matInsInfo: IMaterialInstanceInfo = { parent: null!, @@ -78,12 +78,12 @@ export class Renderer extends Component { set sharedMaterials (val) { for (let i = 0; i < val.length; i++) { if (val[i] !== this._materials[i]) { - this.setMaterial(val[i], i); + this.setSharedMaterial(val[i], i); } } if (val.length < this._materials.length) { for (let i = val.length; i < this._materials.length; i++) { - this.setMaterial(null, i); + this.setSharedMaterial(null, i); } this._materials.splice(val.length); } @@ -145,6 +145,13 @@ export class Renderer extends Component { return this.getSharedMaterial(idx); } + /** + * @deprecated Since v3.8.1, please use [[setSharedMaterial]] instead. + */ + public setMaterial (material: Material | null, index: number): void { + this.setSharedMaterial(material, index); + } + /** * @en Get the shared material asset of the specified sub-model. * @zh 获取指定子模型的共享材质资源。 @@ -161,9 +168,9 @@ export class Renderer extends Component { * new material instance will be created automatically if the sub-model is already using one. * @zh 设置指定子模型的 sharedMaterial,如果对应位置有材质实例则会创建一个对应的材质实例。 */ - public setMaterial (material: Material | null, index: number): void { + public setSharedMaterial (material: Material | null, index: number): void { if (material && material instanceof MaterialInstance) { - console.error('Can\'t set a material instance to a sharedMaterial slot'); + errorID(12012); } this._materials[index] = material; const inst = this._materialInstances[index]; @@ -223,7 +230,7 @@ export class Renderer extends Component { // Skip identity check if it's a Material property // Or if there is a MaterialInstance already if (matInst !== this._materials[index] || curInst) { - this.setMaterial(matInst as Material, index); + this.setSharedMaterial(matInst as Material, index); } } diff --git a/cocos/particle-2d/particle-system-2d.ts b/cocos/particle-2d/particle-system-2d.ts index 153d83816f5..2b40985c812 100644 --- a/cocos/particle-2d/particle-system-2d.ts +++ b/cocos/particle-2d/particle-system-2d.ts @@ -1178,7 +1178,7 @@ export class ParticleSystem2D extends UIRenderer { */ public _updateMaterial (): void { if (this._customMaterial) { - this.setMaterial(this._customMaterial, 0); + this.setSharedMaterial(this._customMaterial, 0); const target = this.getRenderMaterial(0)!.passes[0].blendState.targets[0]; this._dstBlendFactor = target.blendDst; this._srcBlendFactor = target.blendSrc; diff --git a/cocos/particle/line.ts b/cocos/particle/line.ts index 7524a2abf94..348dcff09ce 100644 --- a/cocos/particle/line.ts +++ b/cocos/particle/line.ts @@ -73,7 +73,7 @@ export class Line extends ModelRenderer { } set lineMaterial (val) { - this.setMaterial(val, 0); + this.setSharedMaterial(val, 0); } @override diff --git a/cocos/particle/renderer/particle-system-renderer-data.ts b/cocos/particle/renderer/particle-system-renderer-data.ts index 5f3ca4e0b29..f50bcce3c35 100644 --- a/cocos/particle/renderer/particle-system-renderer-data.ts +++ b/cocos/particle/renderer/particle-system-renderer-data.ts @@ -146,7 +146,7 @@ export default class ParticleSystemRenderer { public set particleMaterial (val: Material | null) { if (this._particleSystem) { - this._particleSystem.setMaterial(val, 0); + this._particleSystem.setSharedMaterial(val, 0); } } @@ -226,7 +226,7 @@ export default class ParticleSystemRenderer { public set trailMaterial (val: Material | null) { if (this._particleSystem) { - this._particleSystem.setMaterial(val, 1); + this._particleSystem.setSharedMaterial(val, 1); } } diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index c4e81ab9dab..3c4a77efac7 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -1034,7 +1034,7 @@ export class Skeleton extends UIRenderer { let mat: Material; if (this._customMaterial) mat = this._customMaterial; else mat = this._updateBuiltinMaterial(); - this.setMaterial(mat, 0); + this.setSharedMaterial(mat, 0); this._cleanMaterialCache(); } diff --git a/cocos/terrain/terrain.ts b/cocos/terrain/terrain.ts index d5e3e6c1ff1..e973a6b2e71 100644 --- a/cocos/terrain/terrain.ts +++ b/cocos/terrain/terrain.ts @@ -283,7 +283,7 @@ class TerrainRenderable extends ModelRenderer { this._model.initSubModel(0, this._meshData, this._currentMaterial); } - this.setMaterial(this._currentMaterial, 0); + this.setSharedMaterial(this._currentMaterial, 0); this._currentMaterialLayers = nLayers; this._model.enabled = true; From ed670e7b1b8ca3e20b73b419c987e6d9e61e35bf Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Thu, 17 Aug 2023 15:42:40 +0800 Subject: [PATCH 124/184] NativePipeline external texture (#15946) * NativePipeline external texture * fix lint. * fix format. --- cocos/asset/assets/simple-texture.ts | 2 +- cocos/rendering/custom/pipeline.ts | 33 ++++++- cocos/rendering/custom/render-graph.ts | 3 +- cocos/rendering/custom/web-pipeline.ts | 88 +++++++++++++++++-- native/cocos/core/assets/SimpleTexture.cpp | 2 +- .../pipeline/custom/FrameGraphDispatcher.cpp | 17 ++-- .../pipeline/custom/LayoutGraphUtils.cpp | 29 ++++++ .../pipeline/custom/LayoutGraphUtils.h | 4 + .../pipeline/custom/NativePipeline.cpp | 83 ++++++++++++++++- .../pipeline/custom/NativePipelineTypes.h | 6 ++ .../pipeline/custom/NativeResourceGraph.cpp | 44 ++-------- .../pipeline/custom/RenderGraphTypes.h | 2 + .../pipeline/custom/RenderInterfaceTypes.h | 6 ++ 13 files changed, 263 insertions(+), 56 deletions(-) diff --git a/cocos/asset/assets/simple-texture.ts b/cocos/asset/assets/simple-texture.ts index 9d902b38896..1bd3e8907c0 100644 --- a/cocos/asset/assets/simple-texture.ts +++ b/cocos/asset/assets/simple-texture.ts @@ -310,7 +310,7 @@ export class SimpleTexture extends TextureBase { } } const textureCreateInfo = this._getGfxTextureCreateInfo({ - usage: TextureUsageBit.SAMPLED | TextureUsageBit.TRANSFER_DST, + usage: TextureUsageBit.SAMPLED | TextureUsageBit.TRANSFER_DST | TextureUsageBit.COLOR_ATTACHMENT, format: this._getGFXFormat(), levelCount: this._mipmapLevel, flags, diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index 68e6d54d984..9635183715e 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -32,7 +32,7 @@ import { Material } from '../../asset/assets'; import { Camera } from '../../render-scene/scene/camera'; import { DirectionalLight } from '../../render-scene/scene/directional-light'; import { GeometryRenderer } from '../geometry-renderer'; -import { Buffer, BufferInfo, ClearFlagBit, Color, CommandBuffer, DescriptorSet, DescriptorSetLayout, Device, Format, LoadOp, ResolveMode, SampleCount, Sampler, ShaderStageFlagBit, StoreOp, Swapchain, Texture, TextureInfo, Viewport } from '../../gfx'; +import { Buffer, BufferInfo, ClearFlagBit, Color, CommandBuffer, DescriptorSet, DescriptorSetLayout, Device, Format, LoadOp, ResolveMode, SampleCount, Sampler, ShaderStageFlagBit, StoreOp, Swapchain, Texture, TextureInfo, TextureType, Viewport } from '../../gfx'; import { GlobalDSManager } from '../global-descriptor-set-manager'; import { Mat4, Quat, Vec2, Vec4 } from '../../core/math'; import { MacroRecord } from '../../render-scene/core/pass-utils'; @@ -684,6 +684,37 @@ export interface BasicPipeline extends PipelineRuntime { width: number, height: number, format?: Format): void; + addBuffer ( + name: string, + size: number, + flags: ResourceFlags, + residency: ResourceResidency): number; + updateBuffer ( + name: string, + size: number): void; + addExternalTexture (name: string, texture: Texture, flags: ResourceFlags): number; + updateExternalTexture (name: string, texture: Texture): void; + addTexture ( + name: string, + textureType: TextureType, + format: Format, + width: number, + height: number, + depth: number, + arraySize: number, + mipLevels: number, + sampleCount: SampleCount, + flags: ResourceFlags, + residency: ResourceResidency): number; + updateTexture ( + name: string, + format: Format, + width: number, + height: number, + depth: number, + arraySize: number, + mipLevels: number, + sampleCount: SampleCount): void; addResource ( name: string, dimension: ResourceDimension, diff --git a/cocos/rendering/custom/render-graph.ts b/cocos/rendering/custom/render-graph.ts index 41078871395..fa3f241f839 100644 --- a/cocos/rendering/custom/render-graph.ts +++ b/cocos/rendering/custom/render-graph.ts @@ -31,7 +31,7 @@ import { AdjI, AdjacencyGraph, BidirectionalGraph, ComponentGraph, ED, InEI, MutableGraph, MutableReferenceGraph, NamedGraph, OutE, OutEI, PolymorphicGraph, PropertyGraph, PropertyMap, ReferenceGraph, UuidGraph, VertexListGraph, directional, parallel, reindexEdgeList, traversal } from './graph'; import { Material } from '../../asset/assets'; import { Camera } from '../../render-scene/scene/camera'; -import { AccessFlagBit, Buffer, ClearFlagBit, Color, Format, Framebuffer, LoadOp, RenderPass, SampleCount, Sampler, SamplerInfo, ShaderStageFlagBit, StoreOp, Swapchain, Texture, TextureFlagBit, Viewport } from '../../gfx'; +import { AccessFlagBit, Buffer, ClearFlagBit, Color, Format, Framebuffer, LoadOp, RenderPass, SampleCount, Sampler, SamplerInfo, ShaderStageFlagBit, StoreOp, Swapchain, Texture, TextureFlagBit, Viewport, TextureType } from '../../gfx'; import { AccessType, AttachmentType, ClearValueType, CopyPair, LightInfo, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UploadPair } from './types'; import { RenderScene } from '../../render-scene/core/render-scene'; import { RenderWindow } from '../../render-scene/core/render-window'; @@ -117,6 +117,7 @@ export class ResourceDesc { sampleCount: SampleCount = SampleCount.X1; textureFlags: TextureFlagBit = TextureFlagBit.NONE; flags: ResourceFlags = ResourceFlags.NONE; + viewType: TextureType = TextureType.TEX2D; } export class ResourceTraits { diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index fa46e3dab45..31be6f797d7 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -20,12 +20,12 @@ 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. -****************************************************************************/ + ****************************************************************************/ /* eslint-disable max-len */ import { systemInfo } from 'pal/system-info'; import { DEBUG } from 'internal:constants'; -import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, Sampler, Swapchain, Texture, ClearFlagBit, DescriptorSet, deviceManager, Viewport, API, CommandBuffer, Type, SamplerInfo, Filter, Address, DescriptorSetInfo, LoadOp, StoreOp, ShaderStageFlagBit, BufferInfo, TextureInfo, UniformBlock, ResolveMode, SampleCount, Color } from '../../gfx'; +import { Buffer, DescriptorSetLayout, Device, Feature, Format, FormatFeatureBit, Sampler, Swapchain, Texture, ClearFlagBit, DescriptorSet, deviceManager, Viewport, API, CommandBuffer, Type, SamplerInfo, Filter, Address, DescriptorSetInfo, LoadOp, StoreOp, ShaderStageFlagBit, BufferInfo, TextureInfo, TextureType, UniformBlock, ResolveMode, SampleCount, Color } from '../../gfx'; import { Mat4, Quat, toRadian, Vec2, Vec3, Vec4, assert, macro, cclegacy, IVec4Like, IMat4Like, IVec2Like, Color as CoreColor } from '../../core'; import { AccessType, AttachmentType, CopyPair, LightInfo, LightingMode, MovePair, QueueHint, ResolvePair, ResourceDimension, ResourceFlags, ResourceResidency, SceneFlags, UpdateFrequency } from './types'; import { ComputeView, RasterView, Blit, ClearView, ComputePass, CopyPass, Dispatch, ManagedBuffer, ManagedResource, MovePass, RasterPass, RasterSubpass, RenderData, RenderGraph, RenderGraphComponent, RenderGraphValue, RenderQueue, RenderSwapchain, ResourceDesc, ResourceGraph, ResourceGraphValue, ResourceStates, ResourceTraits, SceneData, Subpass } from './render-graph'; @@ -830,6 +830,39 @@ function getFirstChildLayoutName (lg: LayoutGraphData, parentID: number): string return ''; } +function getTextureType (dimension: ResourceDimension, arraySize: number): TextureType { + switch (dimension) { + case ResourceDimension.TEXTURE1D: + return arraySize > 1 ? TextureType.TEX1D_ARRAY : TextureType.TEX1D; + case ResourceDimension.TEXTURE2D: + return arraySize > 1 ? TextureType.TEX2D_ARRAY : TextureType.TEX2D; + case ResourceDimension.TEXTURE3D: + return TextureType.TEX3D; + case ResourceDimension.BUFFER: + return TextureType.TEX2D; + default: + break; + } + return TextureType.TEX2D; +} + +function getResourceDimension (type: TextureType): ResourceDimension { + switch (type) { + case TextureType.TEX1D: + case TextureType.TEX1D_ARRAY: + return ResourceDimension.TEXTURE1D; + case TextureType.TEX2D: + case TextureType.TEX2D_ARRAY: + case TextureType.CUBE: + return ResourceDimension.TEXTURE2D; + case TextureType.TEX3D: + return ResourceDimension.TEXTURE3D; + default: + break; + } + return ResourceDimension.TEXTURE2D; +} + export class WebRenderQueueBuilder extends WebSetter implements RenderQueueBuilder { constructor (data: RenderData, renderGraph: RenderGraph, layoutGraph: LayoutGraphData, vertID: number, queue: RenderQueue, pipeline: PipelineSceneData) { super(data, layoutGraph); @@ -1477,16 +1510,47 @@ export class WebPipeline implements BasicPipeline { desc.width = width; desc.height = height; } - addResource (name: string, dimension: ResourceDimension, format: Format, width: number, height: number, depth: number, arraySize: number, mipLevels: number, sampleCount: SampleCount, flags: ResourceFlags, residency: ResourceResidency): number { + + public addBuffer (name: string, size: number, flags: ResourceFlags, residency: ResourceResidency): number { + const desc = new ResourceDesc(); + desc.dimension = ResourceDimension.BUFFER; + desc.width = size; + desc.flags = flags; + return this._resourceGraph.addVertex( + ResourceGraphValue.Managed, + new ManagedResource(), + name, + + desc, + new ResourceTraits(residency), + new ResourceStates(), + new SamplerInfo(Filter.LINEAR, Filter.LINEAR, Filter.NONE, Address.CLAMP, Address.CLAMP, Address.CLAMP), + ); + } + + public updateBuffer (name: string, size: number): void { + this.updateResource(name, Format.UNKNOWN, size, 0, 0, 0, 0, SampleCount.X1); + } + + public addExternalTexture (name: string, texture: Texture, flags: ResourceFlags): number { + throw new Error('Method not implemented.'); + } + + public updateExternalTexture (name: string, texture: Texture): void { + throw new Error('Method not implemented.'); + } + + public addTexture (name: string, textureType: TextureType, format: Format, width: number, height: number, depth: number, arraySize: number, mipLevels: number, sampleCount: SampleCount, flags: ResourceFlags, residency: ResourceResidency): number { const desc = new ResourceDesc(); - desc.dimension = dimension; + desc.dimension = getResourceDimension(textureType); desc.width = width; desc.height = height; - desc.depthOrArraySize = dimension === ResourceDimension.TEXTURE3D ? depth : arraySize; + desc.depthOrArraySize = desc.dimension === ResourceDimension.TEXTURE3D ? depth : arraySize; desc.mipLevels = mipLevels; desc.format = format; desc.sampleCount = sampleCount; desc.flags = flags; + desc.viewType = textureType; return this._resourceGraph.addVertex( ResourceGraphValue.Managed, new ManagedResource(), @@ -1498,7 +1562,19 @@ export class WebPipeline implements BasicPipeline { new SamplerInfo(Filter.LINEAR, Filter.LINEAR, Filter.NONE, Address.CLAMP, Address.CLAMP, Address.CLAMP), ); } - updateResource (name: string, format: Format, width: number, height: number, depth: number, arraySize: number, mipLevels: number, sampleCount: SampleCount): void { + + public updateTexture (name: string, format: Format, width: number, height: number, depth: number, arraySize: number, mipLevels: number, sampleCount: SampleCount): void { + this.updateResource(name, format, width, height, depth, arraySize, mipLevels, sampleCount); + } + + public addResource (name: string, dimension: ResourceDimension, format: Format, width: number, height: number, depth: number, arraySize: number, mipLevels: number, sampleCount: SampleCount, flags: ResourceFlags, residency: ResourceResidency): number { + if (dimension === ResourceDimension.BUFFER) { + return this.addBuffer(name, width, flags, residency); + } else { + return this.addTexture(name, getTextureType(dimension, arraySize), format, width, height, depth, arraySize, mipLevels, sampleCount, flags, residency); + } + } + public updateResource (name: string, format: Format, width: number, height: number, depth: number, arraySize: number, mipLevels: number, sampleCount: SampleCount): void { const resId = this.resourceGraph.vertex(name); const desc = this.resourceGraph.getDesc(resId); desc.width = width; diff --git a/native/cocos/core/assets/SimpleTexture.cpp b/native/cocos/core/assets/SimpleTexture.cpp index 145aae30126..74e0018b1fe 100644 --- a/native/cocos/core/assets/SimpleTexture.cpp +++ b/native/cocos/core/assets/SimpleTexture.cpp @@ -140,7 +140,7 @@ void SimpleTexture::createTexture(gfx::Device *device) { } auto textureCreateInfo = getGfxTextureCreateInfo( - gfx::TextureUsageBit::SAMPLED | gfx::TextureUsageBit::TRANSFER_DST, + gfx::TextureUsageBit::SAMPLED | gfx::TextureUsageBit::TRANSFER_DST | gfx::TextureUsageBit::COLOR_ATTACHMENT, getGFXFormat(), _mipmapLevel, flags); diff --git a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp index 60babdea94f..e6087402ac8 100644 --- a/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp +++ b/native/cocos/renderer/pipeline/custom/FrameGraphDispatcher.cpp @@ -189,6 +189,9 @@ ResourceGraph::vertex_descriptor locateSubres(const ccstd::pmr::string& originNa const ResourceGraph &resg, uint32_t basePlane, boost::container::pmr::memory_resource *scratch) { + if (basePlane == 0xFFFFFFFF) { + return findVertex(originName, resg); + } const auto &resName = getSubresNameByPlane(originName, basePlane, resg, scratch); return findVertex(resName, resg); } @@ -909,7 +912,7 @@ void extractNames(const ccstd::pmr::string &resName, // cube // array - + if (names.empty()) { names.emplace_back(resName, 0); } @@ -1002,7 +1005,7 @@ bool checkComputeViews(const Graphs &graphs, ResourceAccessGraph::vertex_descrip tryAddEdge(lastVertId, ragVertID, resourceAccessGraph); tryAddEdge(lastVertId, ragVertID, relationGraph); dependent = lastVertId != EXPECT_START_ID; - + if (out_degree(resID, resourceGraph) && (computeView.plane != 0xFFFFFFFF)) { const auto& subresFullName = getSubresNameByPlane(resName, computeView.plane, resourceGraph, resourceAccessGraph.resource()); resourceAccessGraph.resourceIndex.emplace(subresFullName, vertex(subresFullName, resourceGraph)); @@ -1530,7 +1533,7 @@ gfx::SamplerInfo makePointSamplerInfo() { return gfx::SamplerInfo{gfx::Filter::POINT, gfx::Filter::POINT, gfx::Filter::POINT}; } -SubresourceView makeSubresourceView(const ResourceDesc& desc, const gfx::ResourceRange& range) { +SubresourceView makeSubresourceView(const ResourceDesc& srcDesc, const ResourceDesc &targetDesc, const gfx::ResourceRange& range) { SubresourceView view{}; view.firstArraySlice = range.firstSlice; view.numArraySlices = range.numSlices; @@ -1538,7 +1541,8 @@ SubresourceView makeSubresourceView(const ResourceDesc& desc, const gfx::Resourc view.numMipLevels = range.levelCount; view.firstPlane = range.basePlane; view.numPlanes = range.planeCount; - view.format = desc.format; + view.format = targetDesc.format; + view.viewType = srcDesc.viewType; view.textureView = nullptr; return view; } @@ -1652,7 +1656,10 @@ void subresourceAnalysis(ResourceAccessGraph& rag, ResourceGraph& resg) { } } else { for (const auto &[rangeStr, subres] : subreses) { + auto descResViewID = findVertex(subres, resg); auto targetResID = rag.resourceIndex.at(resName); + + const auto &srcDesc = get(ResourceGraph::DescTag{}, resg, descResViewID); const auto &targetName = get(ResourceGraph::NameTag{}, resg, targetResID); const auto &targetDesc = get(ResourceGraph::DescTag{}, resg, targetResID); const auto &srcResourceRange = rag.movedSourceStatus.at(subres).range; @@ -1660,7 +1667,7 @@ void subresourceAnalysis(ResourceAccessGraph& rag, ResourceGraph& resg) { const auto &indexName = concatResName(targetName, subres, rag.resource()); auto subresID = findVertex(indexName, resg); if (subresID == ResourceGraph::null_vertex()) { - const auto &subView = makeSubresourceView(targetDesc, srcResourceRange); + const auto &subView = makeSubresourceView(srcDesc, targetDesc, srcResourceRange); // register to resourcegraph subresID = addVertex( SubresourceViewTag{}, diff --git a/native/cocos/renderer/pipeline/custom/LayoutGraphUtils.cpp b/native/cocos/renderer/pipeline/custom/LayoutGraphUtils.cpp index 1854385cd5c..74c230b1dba 100644 --- a/native/cocos/renderer/pipeline/custom/LayoutGraphUtils.cpp +++ b/native/cocos/renderer/pipeline/custom/LayoutGraphUtils.cpp @@ -477,6 +477,35 @@ void printLayoutGraphData( } } +gfx::TextureType getTextureType(ResourceDimension dimension, uint32_t arraySize) { + switch (dimension) { + case ResourceDimension::TEXTURE1D: + return arraySize > 1 ? gfx::TextureType::TEX1D_ARRAY : gfx::TextureType::TEX1D; + case ResourceDimension::TEXTURE2D: + return arraySize > 1 ? gfx::TextureType::TEX2D_ARRAY : gfx::TextureType::TEX2D; + case ResourceDimension::TEXTURE3D: + return gfx::TextureType::TEX3D; + case ResourceDimension::BUFFER: + default: + return gfx::TextureType::TEX2D; + } +} + +ResourceDimension getResourceDimension(gfx::TextureType type) { + switch (type) { + case gfx::TextureType::TEX1D: + case gfx::TextureType::TEX1D_ARRAY: + return ResourceDimension::TEXTURE1D; + case gfx::TextureType::TEX3D: + return ResourceDimension::TEXTURE3D; + case gfx::TextureType::TEX2D: + case gfx::TextureType::TEX2D_ARRAY: + case gfx::TextureType::CUBE: + default: + return ResourceDimension::TEXTURE2D; + } +} + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/LayoutGraphUtils.h b/native/cocos/renderer/pipeline/custom/LayoutGraphUtils.h index 389fd95dbd7..acb5780ebe8 100644 --- a/native/cocos/renderer/pipeline/custom/LayoutGraphUtils.h +++ b/native/cocos/renderer/pipeline/custom/LayoutGraphUtils.h @@ -65,6 +65,10 @@ void printLayoutGraphData( const LayoutGraphData& lg, std::ostream& oss, boost::container::pmr::memory_resource* scratch); +gfx::TextureType getTextureType(ResourceDimension dimension, uint32_t arraySize); +ResourceDimension getResourceDimension(gfx::TextureType type); + + } // namespace render } // namespace cc diff --git a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp index f747e151f36..7896ae83828 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipeline.cpp +++ b/native/cocos/renderer/pipeline/custom/NativePipeline.cpp @@ -122,6 +122,47 @@ bool NativePipeline::containsResource(const ccstd::string &name) const { return contains(name.c_str(), resourceGraph); } +uint32_t NativePipeline::addExternalTexture(const ccstd::string &name, gfx::Texture *texture, ResourceFlags flags) { + const auto &texInfo = texture->getInfo(); + ResourceDesc desc{}; + desc.dimension = getResourceDimension(texInfo.type); + desc.width = texInfo.width; + desc.height = texInfo.height; + desc.depthOrArraySize = desc.dimension == ResourceDimension::TEXTURE3D ? texInfo.depth : texInfo.layerCount; + desc.mipLevels = texInfo.levelCount; + desc.format = texture->getFormat(); + desc.sampleCount = gfx::SampleCount::X1; + desc.textureFlags = texture->getInfo().flags; + desc.flags = flags; + desc.viewType = texInfo.type; + + return addVertex( + PersistentTextureTag{}, + std::forward_as_tuple(name.c_str()), + std::forward_as_tuple(desc), + std::forward_as_tuple(ResourceTraits{ResourceResidency::EXTERNAL}), + std::forward_as_tuple(), + std::forward_as_tuple(), + std::forward_as_tuple(texture), + resourceGraph); +} + +void NativePipeline::updateExternalTexture(const ccstd::string &name, gfx::Texture *texture) { + auto resID = findVertex(ccstd::pmr::string(name, get_allocator()), resourceGraph); + if (resID == ResourceGraph::null_vertex()) { + return; + } + auto &desc = get(ResourceGraph::DescTag{}, resourceGraph, resID); + visitObject( + resID, resourceGraph, + [&](IntrusivePtr &tex) { + desc.width = texture->getWidth(); + desc.height = texture->getHeight(); + tex = texture; + }, + [](const auto & /*res*/) {}); +} + // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) uint32_t NativePipeline::addRenderWindow(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, scene::RenderWindow *renderWindow) { ResourceDesc desc{}; @@ -253,10 +294,8 @@ uint32_t NativePipeline::addDepthStencil(const ccstd::string &name, gfx::Format return resID; } -uint32_t NativePipeline::addResource(const ccstd::string& name, ResourceDimension dimension, - gfx::Format format, - uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, - gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) { +uint32_t NativePipeline::addTexture(const ccstd::string &name, gfx::TextureType type, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) { + const auto dimension = getResourceDimension(type); ResourceDesc desc{ dimension, 0, @@ -268,6 +307,7 @@ uint32_t NativePipeline::addResource(const ccstd::string& name, ResourceDimensio sampleCount, residency == ResourceResidency::MEMORYLESS ? gfx::TextureFlagBit::LAZILY_ALLOCATED : gfx::TextureFlagBit::NONE, flags, + type }; return addVertex( ManagedTextureTag{}, @@ -280,6 +320,38 @@ uint32_t NativePipeline::addResource(const ccstd::string& name, ResourceDimensio resourceGraph); } +void NativePipeline::updateTexture(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) { + updateResource(name, format, width, height, depth, arraySize, mipLevels, sampleCount); +} + +uint32_t NativePipeline::addBuffer(const ccstd::string &name, uint32_t size, ResourceFlags flags, ResourceResidency residency) { + ResourceDesc desc = {}; + desc.dimension = ResourceDimension::BUFFER; + desc.width = size; + desc.flags = flags; + return addVertex( + ManagedBufferTag{}, + std::forward_as_tuple(name.c_str()), + std::forward_as_tuple(desc), + std::forward_as_tuple(ResourceTraits{residency}), + std::forward_as_tuple(), + std::forward_as_tuple(), + std::forward_as_tuple(), + resourceGraph); +} + +void NativePipeline::updateBuffer(const ccstd::string &name, uint32_t size) { + updateResource(name, gfx::Format::UNKNOWN, size, 0, 0, 0, 0, gfx::SampleCount::X1); +} + +uint32_t NativePipeline::addResource(const ccstd::string& name, ResourceDimension dimension, + gfx::Format format, + uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, + gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) { + return dimension == ResourceDimension::BUFFER ? addBuffer(name, width, flags, residency) : + addTexture(name, getTextureType(dimension, arraySize), format, width, height, depth, arraySize, mipLevels, sampleCount, flags, residency); +} + void NativePipeline::updateResource(const ccstd::string& name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, // NOLINT(bugprone-easily-swappable-parameters) gfx::SampleCount sampleCount) { @@ -311,6 +383,9 @@ void NativePipeline::updateResource(const ccstd::string& name, gfx::Format forma resourceGraph.invalidatePersistentRenderPassAndFramebuffer(tex.texture.get()); } }, + [&](ManagedBuffer &/*buffer*/) { + desc.width = width; + }, [](const auto & /*res*/) {}); } diff --git a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h index 1fdb0ebed7d..2f5704b28f8 100644 --- a/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h +++ b/native/cocos/renderer/pipeline/custom/NativePipelineTypes.h @@ -1357,12 +1357,18 @@ class NativePipeline final : public Pipeline { void beginSetup() override; void endSetup() override; bool containsResource(const ccstd::string &name) const override; + uint32_t addExternalTexture(const ccstd::string &name, gfx::Texture *texture, ResourceFlags flags) override; + void updateExternalTexture(const ccstd::string &name, gfx::Texture *texture) override; uint32_t addRenderWindow(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, scene::RenderWindow *renderWindow) override; void updateRenderWindow(const ccstd::string &name, scene::RenderWindow *renderWindow) override; uint32_t addRenderTarget(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, ResourceResidency residency) override; uint32_t addDepthStencil(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, ResourceResidency residency) override; void updateRenderTarget(const ccstd::string &name, uint32_t width, uint32_t height, gfx::Format format) override; void updateDepthStencil(const ccstd::string &name, uint32_t width, uint32_t height, gfx::Format format) override; + uint32_t addTexture(const ccstd::string &name, gfx::TextureType type, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; + void updateTexture(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; + uint32_t addBuffer(const ccstd::string &name, uint32_t size, ResourceFlags flags, ResourceResidency residency) override; + void updateBuffer(const ccstd::string &name, uint32_t size) override; uint32_t addResource(const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) override; void updateResource(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) override; void beginFrame() override; diff --git a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp index 1086f449745..750616d549a 100644 --- a/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp +++ b/native/cocos/renderer/pipeline/custom/NativeResourceGraph.cpp @@ -97,35 +97,8 @@ gfx::BufferInfo getBufferInfo(const ResourceDesc& desc) { }; } -gfx::TextureInfo getTextureInfo(const ResourceDesc& desc, bool bCube = false) { +gfx::TextureInfo getTextureInfo(const ResourceDesc& desc) { using namespace gfx; // NOLINT(google-build-using-namespace) - // type - auto type = TextureType::TEX1D; - switch (desc.dimension) { - case ResourceDimension::TEXTURE1D: - if (desc.depthOrArraySize > 1) { - type = TextureType::TEX1D_ARRAY; - } else { - type = TextureType::TEX1D; - } - break; - case ResourceDimension::TEXTURE2D: - if (desc.depthOrArraySize > 1) { - if (bCube) { - type = TextureType::CUBE; - } else { - type = TextureType::TEX2D_ARRAY; - } - } else { - type = TextureType::TEX2D; - } - break; - case ResourceDimension::TEXTURE3D: - type = TextureType::TEX3D; - break; - case ResourceDimension::BUFFER: - CC_EXPECTS(false); - } // usage TextureUsage usage = TextureUsage::NONE; @@ -156,28 +129,26 @@ gfx::TextureInfo getTextureInfo(const ResourceDesc& desc, bool bCube = false) { } return { - type, + desc.viewType, usage, desc.format, desc.width, desc.height, desc.textureFlags, - type == TextureType::TEX3D ? 1U : desc.depthOrArraySize, + desc.viewType == TextureType::TEX3D ? 1U : desc.depthOrArraySize, desc.mipLevels, desc.sampleCount, - type == TextureType::TEX3D ? desc.depthOrArraySize : 1U, + desc.viewType == TextureType::TEX3D ? desc.depthOrArraySize : 1U, nullptr, }; } -gfx::TextureViewInfo getTextureViewInfo(const SubresourceView& subresView, const ResourceDesc& desc, bool bCube = false) { +gfx::TextureViewInfo getTextureViewInfo(const SubresourceView& subresView) { using namespace gfx; // NOLINT(google-build-using-namespace) - const auto& textureInfo = getTextureInfo(desc, bCube); - return { nullptr, - textureInfo.type, + subresView.viewType, subresView.format, subresView.indexOrFirstMipLevel, subresView.numMipLevels, @@ -280,9 +251,8 @@ void ResourceGraph::mount(gfx::Device* device, vertex_descriptor vertID) { CC_ENSURES(!resg.isTextureView(parentID)); mount(device, parentID); // NOLINT(misc-no-recursion) auto* parentTexture = resg.getTexture(parentID); - const auto& desc = get(ResourceGraph::DescTag{}, resg, vertID); if (!view.textureView) { - auto textureViewInfo = getTextureViewInfo(originView, desc); + auto textureViewInfo = getTextureViewInfo(originView); textureViewInfo.texture = parentTexture; view.textureView = device->createTexture(textureViewInfo); } diff --git a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h index acf43826fd8..75abe2d1bf1 100644 --- a/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderGraphTypes.h @@ -169,6 +169,7 @@ struct ResourceDesc { gfx::SampleCount sampleCount{gfx::SampleCount::X1}; gfx::TextureFlagBit textureFlags{gfx::TextureFlagBit::NONE}; ResourceFlags flags{ResourceFlags::NONE}; + gfx::TextureType viewType{gfx::TextureType::TEX2D}; }; struct ResourceTraits { @@ -515,6 +516,7 @@ struct SubresourceView { uint16_t numArraySlices{0}; uint16_t firstPlane{0}; uint16_t numPlanes{0}; + gfx::TextureType viewType; }; struct ResourceGraph { diff --git a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h index 77845fd5c64..29e13290601 100644 --- a/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h +++ b/native/cocos/renderer/pipeline/custom/RenderInterfaceTypes.h @@ -773,6 +773,12 @@ class BasicPipeline : public PipelineRuntime { virtual void updateDepthStencil(const ccstd::string &name, uint32_t width, uint32_t height, gfx::Format format) = 0; virtual uint32_t addResource(const ccstd::string &name, ResourceDimension dimension, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) = 0; virtual void updateResource(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) = 0; + virtual uint32_t addTexture(const ccstd::string &name, gfx::TextureType type, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount, ResourceFlags flags, ResourceResidency residency) = 0; + virtual void updateTexture(const ccstd::string &name, gfx::Format format, uint32_t width, uint32_t height, uint32_t depth, uint32_t arraySize, uint32_t mipLevels, gfx::SampleCount sampleCount) = 0; + virtual uint32_t addBuffer(const ccstd::string &name, uint32_t size, ResourceFlags flags, ResourceResidency residency) = 0; + virtual void updateBuffer(const ccstd::string &name, uint32_t size) = 0; + virtual uint32_t addExternalTexture(const ccstd::string &name, gfx::Texture *texture, ResourceFlags flags) = 0; + virtual void updateExternalTexture(const ccstd::string &name, gfx::Texture *texture) = 0; /** * @engineInternal * @en Begin rendering one frame From d988b2373a4935535c5891cac74c96f57ed4db96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leslie=20Leigh=20=28=E6=9D=8E=E7=9A=84=E5=BA=8F=29?= Date: Thu, 17 Aug 2023 16:16:15 +0800 Subject: [PATCH 125/184] Fix: Inactivated skeletal animation components shall not affect skinned mesh renderers (#13779) --- .../skinned-mesh-renderer.ts | 2 +- tests/animation/skeletal-animation.test.ts | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts b/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts index 84cd794e0a2..c59dfa62b93 100644 --- a/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts +++ b/cocos/3d/skinned-mesh-renderer/skinned-mesh-renderer.ts @@ -173,7 +173,7 @@ export class SkinnedMeshRenderer extends MeshRenderer { } const animation = skinningRoot.getComponent('cc.SkeletalAnimation') as SkeletalAnimation; - if (animation) { + if (animation && animation.enabledInHierarchy) { animation.notifySkinnedMeshAdded(this); } else { this.setUseBakedAnimation(false); diff --git a/tests/animation/skeletal-animation.test.ts b/tests/animation/skeletal-animation.test.ts index 4c7605be10e..a73c9cac0ed 100644 --- a/tests/animation/skeletal-animation.test.ts +++ b/tests/animation/skeletal-animation.test.ts @@ -224,6 +224,26 @@ describe('Skeletal animation component', () => { expect(state.isPlaying && !state.isPaused).toBe(true); }); + test('Bugfix - Inactivated skeletal animation components shall not affect skinned mesh renderers', () => { + const node = new Node(); + const skeletalAnimation = node.addComponent(SkeletalAnimation) as SkeletalAnimation; + skeletalAnimation.enabled = false; + const skinnedMeshRenderer = node.addComponent(SkinnedMeshRenderer) as SkinnedMeshRenderer; + skinnedMeshRenderer.skinningRoot = node; + + const scene = new Scene(''); + scene.addChild(node); + + director.runSceneImmediate(scene); + // The skinned mesh renderer shall not being in baked mode. + expect(skinnedMeshRenderer.model).not.toBeInstanceOf(BakedSkinningModel); + + // While skeletal animation is activated, the skinned mesh renderer should be turned into baked mode. + skeletalAnimation.enabled = true; + director.tick(0.2); + expect(skinnedMeshRenderer.model).toBeInstanceOf(BakedSkinningModel); + }); + describe(`useBakedAnimation`, () => { test.each([ [true], From 7401b55e09cd99ddfcd65fb5bca165df04d6cdc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=88=98?= <40414978+PatriceJiang@users.noreply.github.com> Date: Thu, 17 Aug 2023 16:19:29 +0800 Subject: [PATCH 126/184] add java_home (#15996) --- .../native-pack-tool/source/base/default.ts | 12 +++++----- .../source/platforms/android.ts | 22 +++++++++++++++---- .../source/platforms/openharmony.ts | 4 +++- scripts/native-pack-tool/source/utils.ts | 2 +- 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/scripts/native-pack-tool/source/base/default.ts b/scripts/native-pack-tool/source/base/default.ts index 3f9899653dc..b7e5a994980 100644 --- a/scripts/native-pack-tool/source/base/default.ts +++ b/scripts/native-pack-tool/source/base/default.ts @@ -370,7 +370,7 @@ export abstract class NativePackTool { protected getExcutableNameOrDefault(): string { const en = this.params.executableName; - return en ? en : this.projectNameASCII(); + return en ? en : this.projectNameASCII(); } protected async excuteTemplateTask(tasks: CocosProjectTasks) { @@ -422,7 +422,7 @@ export abstract class NativePackTool { replaceFilesDelay[fp] = replaceFilesDelay[fp] || []; replaceFilesDelay[fp].push({ reg: name, - content: this.params.platformParams.packageName!, + content: (this.params.platformParams as any).packageName!, }); }); delete tasks.projectReplacePackageName; @@ -454,7 +454,7 @@ export abstract class NativePackTool { } }); Object.keys(config).forEach((key: string) => { - if(typeof config[key] !== 'string') { + if (typeof config[key] !== 'string') { console.error(`cMakeConfig.${key} is not a string, "${config[key]}"`); } else { content += config[key] + '\n'; @@ -468,7 +468,7 @@ export abstract class NativePackTool { args.push(`-DRES_DIR="${cchelper.fixPath(this.paths.buildDir)}"`); args.push(`-DAPP_NAME="${this.params.projectName}"`); args.push(`-DLAUNCH_TYPE="${this.buildType}"`); - if (this.params.platformParams?.skipUpdateXcodeProject) { + if ((this.params.platformParams as any).skipUpdateXcodeProject) { args.push(`-DCMAKE_SUPPRESS_REGENERATION=ON`); } } @@ -543,7 +543,7 @@ export abstract class NativePackTool { // cocos.compile.json export class CocosParams { - platformParams!: T | any; + platformParams: T; public debug: boolean; public projectName: string; public cmakePath: string; @@ -602,7 +602,7 @@ export class CocosParams { CC_ENABLE_SWAPPY: false, } - constructor(params: CocosParams) { + constructor(params: CocosParams) { this.buildAssetsDir = params.buildAssetsDir; this.projectName = params.projectName; this.debug = params.debug; diff --git a/scripts/native-pack-tool/source/platforms/android.ts b/scripts/native-pack-tool/source/platforms/android.ts index 212974a8ae1..6cb7d8f1260 100644 --- a/scripts/native-pack-tool/source/platforms/android.ts +++ b/scripts/native-pack-tool/source/platforms/android.ts @@ -5,6 +5,7 @@ import { cchelper, Paths } from "../utils"; import * as URL from 'url'; import { spawn, spawnSync } from 'child_process'; import * as xml2js from 'xml2js'; +import { platform } from 'os'; export interface IOrientation { landscapeLeft: boolean; @@ -17,7 +18,10 @@ export interface IAndroidParams { packageName: string; sdkPath: string; ndkPath: string; + javaHome: string; + javaPath: string; androidInstant: boolean, + maxAspectRatio: string; remoteUrl?: string; apiLevel: number; appABIs: string[]; @@ -25,6 +29,7 @@ export interface IAndroidParams { keystoreAlias: string; keystoreAliasPassword: string; keystorePath: string; + inputSDK: boolean; orientation: IOrientation; appBundle: boolean; @@ -77,6 +82,18 @@ export class AndroidPackTool extends NativePackTool { async make() { const options = this.params.platformParams; + if (options.javaHome) { + if (process.env.JAVA_HOME !== options.javaHome) { + process.env.JAVA_HOME = options.javaHome; + console.log(`Update JAVA_HOME to ${options.javaHome}`); + } + if (!process.env.PATH!.startsWith(options.javaHome)) { + const sep = platform() === 'win32' ? ';' : ':'; + process.env.PATH = ps.join(options.javaHome, 'bin') + sep + process.env.PATH; + console.log(`Add JAVA_HOME/bin to PATH`); + } + } + const projDir: string = this.paths.nativePrjDir; if (!fs.existsSync(projDir)) { throw new Error(`dir ${projDir} not exits`); @@ -93,7 +110,6 @@ export class AndroidPackTool extends NativePackTool { // compile android buildMode = `${this.projectNameASCII()}:assemble${outputMode}`; - // await cchelper.runCmd(gradle, [buildMode /* "--quiet",*/ /*"--build-cache", "--project-cache-dir", nativePrjDir */], false, projDir); // pushd const originDir = process.cwd(); @@ -111,7 +127,6 @@ export class AndroidPackTool extends NativePackTool { // compile android-instant if (options.androidInstant) { buildMode = `instantapp:assemble${outputMode}`; - // await cchelper.runCmd(gradle, [buildMode, /*"--quiet",*/ /*"--build-cache", "--project-cache-dir", nativePrjDir*/], false, projDir); await cchelper.runCmd(gradle, [buildMode], false, projDir); } @@ -122,7 +137,6 @@ export class AndroidPackTool extends NativePackTool { } else { buildMode = `${this.params.projectName}:bundle${outputMode}`; } - // await cchelper.runCmd(gradle, [buildMode, /*"--quiet",*/ /*"--build-cache", "--project-cache-dir", nativePrjDir*/], false, projDir); await cchelper.runCmd(gradle, [buildMode], false, projDir); } return await this.copyToDist(); @@ -214,7 +228,7 @@ export class AndroidPackTool extends NativePackTool { const application = data.manifest.application[0]; //append meta-data application['meta-data'].push({ - $:{'android:name': 'android.max_aspect', 'android:value': `${aspectRatioFloatValue}`} + $: { 'android:name': 'android.max_aspect', 'android:value': `${aspectRatioFloatValue}` } }); } diff --git a/scripts/native-pack-tool/source/platforms/openharmony.ts b/scripts/native-pack-tool/source/platforms/openharmony.ts index b7a18fa9d15..45af3334f3a 100644 --- a/scripts/native-pack-tool/source/platforms/openharmony.ts +++ b/scripts/native-pack-tool/source/platforms/openharmony.ts @@ -20,6 +20,8 @@ export interface OHOSParam { ndkPath: string; orientation: IOrientation; packageName: string; + appABIs: string[]; + apiLevel: number; } export class OpenHarmonyPackTool extends NativePackTool { @@ -143,7 +145,7 @@ export class OpenHarmonyPackTool extends NativePackTool { hdcExe, ['uninstall', packageName], false, hdcCwd); console.debug(`${hdc} install -r ${hapFile}`); await cchelper.runCmd( - hdcExe,['install', '-r', hapFile], false, hdcCwd); + hdcExe, ['install', '-r', hapFile], false, hdcCwd); console.debug(`${hdc} shell aa start -a ${ability} -b ${packageName}`); await cchelper.runCmd( hdcExe, ['shell', 'aa', 'start', '-a', ability, '-b', packageName, '-m', moduleName], false, hdcCwd); diff --git a/scripts/native-pack-tool/source/utils.ts b/scripts/native-pack-tool/source/utils.ts index 67eeb88a4dc..b6559cbd19a 100644 --- a/scripts/native-pack-tool/source/utils.ts +++ b/scripts/native-pack-tool/source/utils.ts @@ -557,7 +557,7 @@ export class Paths { this.buildDir = params.buildDir; this.buildAssetsDir = params.buildAssetsDir; if (params.platform === 'windows') { - this.platformTemplateDirName = params.platformParams.targetPlatform === "win32" ? "win32" : "win64"; + this.platformTemplateDirName = (params.platformParams as any).targetPlatform === "win32" ? "win32" : "win64"; } else { this.platformTemplateDirName = params.platformName ? params.platformName : this.platform; } From 310142ea016bc874d8a955929e3601d5709ba99e Mon Sep 17 00:00:00 2001 From: Cocos Robot <48829427+cocos-robot@users.noreply.github.com> Date: Thu, 17 Aug 2023 16:42:36 +0800 Subject: [PATCH 127/184] [ci skip][AUTO]: Automated code generating update: 9a8c159ac0a52aeaafcf6460a0ea2bc0d9a6b2eb (#15946) (#16002) Co-authored-by: cocos-robot --- native/cocos/core/builtin/DebugInfos.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/native/cocos/core/builtin/DebugInfos.cpp b/native/cocos/core/builtin/DebugInfos.cpp index bb0597c5234..8571eefcfa6 100644 --- a/native/cocos/core/builtin/DebugInfos.cpp +++ b/native/cocos/core/builtin/DebugInfos.cpp @@ -445,6 +445,7 @@ ccstd::unordered_map debugInfos = { { 12009, "GeometryRenderer: too many triangles." }, { 12010, "PassUtils: illegal uniform handle, accessing uniform at offset %d" }, { 12011, "Pass: setUniform is invoked with incompatible uniform data type for binding %d, expected type is %s" }, +{ 12012, "Can't set a material instance to a sharedMaterial slot" }, { 12100, "The font size is too big to be fitted into texture atlas. Please switch to other label cache modes or choose a smaller font size." }, { 12101, "The asset %s has been destroyed!" }, { 12102, "Base pass cannot override states, please use pass instance instead." }, From 4e1ddee39bf29196ce3614a3914bffae28d56d03 Mon Sep 17 00:00:00 2001 From: Cocos Robot <48829427+cocos-robot@users.noreply.github.com> Date: Thu, 17 Aug 2023 17:15:29 +0800 Subject: [PATCH 128/184] [ci skip][AUTO]: Automated code generating update: dec20a47dcf2f1929010ba90c4fec99ded4de3e1 (#15996) (#16007) Co-authored-by: cocos-robot From 52cb79d9eb8d0ba26d62c4530d990202efd9a82c Mon Sep 17 00:00:00 2001 From: Ling Zhan Date: Thu, 17 Aug 2023 17:27:53 +0800 Subject: [PATCH 129/184] [fix] update primitives.fbx: sphere bbx now centerd at zero. #15300 (#15952) --- editor/assets/primitives.fbx | Bin 242784 -> 213184 bytes editor/assets/primitives.fbx.meta | 73 ++++++++++++++++++------------ 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/editor/assets/primitives.fbx b/editor/assets/primitives.fbx index 1ddad73bd082bda2cf04aee3b1cf8516e996080e..f93a097616a8ad8a93a4c72736061aaa7b8fd4b9 100755 GIT binary patch delta 99634 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 diff --git a/editor/assets/primitives.fbx.meta b/editor/assets/primitives.fbx.meta index d749817046b..ea556cdb69f 100644 --- a/editor/assets/primitives.fbx.meta +++ b/editor/assets/primitives.fbx.meta @@ -19,8 +19,8 @@ ], "subMetas": {}, "userData": { - "gltfIndex": 4, - "triangleCount": 2380 + "gltfIndex": 5, + "triangleCount": 1512 } }, "801ec": { @@ -59,12 +59,12 @@ "triangleCount": 200 } }, - "38fd2": { + "40ece": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@40ece", "displayName": "", - "id": "38fd2", - "name": "cone.mesh", + "id": "40ece", + "name": "torus.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -74,15 +74,15 @@ "subMetas": {}, "userData": { "gltfIndex": 2, - "triangleCount": 72 + "triangleCount": 2048 } }, - "40ece": { + "fc873": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@40ece", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@fc873", "displayName": "", - "id": "40ece", - "name": "torus.mesh", + "id": "fc873", + "name": "quad.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -92,15 +92,15 @@ "subMetas": {}, "userData": { "gltfIndex": 3, - "triangleCount": 2048 + "triangleCount": 2 } }, - "fc873": { + "a804a": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@fc873", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@a804a", "displayName": "", - "id": "fc873", - "name": "quad.mesh", + "id": "a804a", + "name": "box.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -109,8 +109,8 @@ ], "subMetas": {}, "userData": { - "gltfIndex": 5, - "triangleCount": 2 + "gltfIndex": 4, + "triangleCount": 12 } }, "8abdc": { @@ -128,15 +128,15 @@ "subMetas": {}, "userData": { "gltfIndex": 6, - "triangleCount": 128 + "triangleCount": 112 } }, - "a804a": { + "38fd2": { "importer": "gltf-mesh", - "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@a804a", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", "displayName": "", - "id": "a804a", - "name": "box.mesh", + "id": "38fd2", + "name": "cone.mesh", "ver": "1.1.1", "imported": true, "files": [ @@ -146,9 +146,25 @@ "subMetas": {}, "userData": { "gltfIndex": 7, - "triangleCount": 12 + "triangleCount": 64 } }, + "7a3ca": { + "importer": "gltf-material", + "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@7a3ca", + "displayName": "", + "id": "7a3ca", + "name": "lambert2.material", + "userData": { + "gltfIndex": 0 + }, + "ver": "1.0.14", + "imported": true, + "files": [ + ".json" + ], + "subMetas": {} + }, "8d883": { "importer": "gltf-material", "uuid": "1263d74c-8167-4928-91a6-4e2672411f47@8d883", @@ -156,7 +172,7 @@ "id": "8d883", "name": "lambert1.material", "userData": { - "gltfIndex": 0 + "gltfIndex": 1 }, "ver": "1.0.14", "imported": true, @@ -203,14 +219,15 @@ "meshes": [ "1263d74c-8167-4928-91a6-4e2672411f47@801ec", "1263d74c-8167-4928-91a6-4e2672411f47@2e76e", - "1263d74c-8167-4928-91a6-4e2672411f47@38fd2", "1263d74c-8167-4928-91a6-4e2672411f47@40ece", - "1263d74c-8167-4928-91a6-4e2672411f47@17020", "1263d74c-8167-4928-91a6-4e2672411f47@fc873", + "1263d74c-8167-4928-91a6-4e2672411f47@a804a", + "1263d74c-8167-4928-91a6-4e2672411f47@17020", "1263d74c-8167-4928-91a6-4e2672411f47@8abdc", - "1263d74c-8167-4928-91a6-4e2672411f47@a804a" + "1263d74c-8167-4928-91a6-4e2672411f47@38fd2" ], "materials": [ + "1263d74c-8167-4928-91a6-4e2672411f47@7a3ca", "1263d74c-8167-4928-91a6-4e2672411f47@8d883" ], "scenes": [ From 1dc3142fbbb4ee93421e3fc2754366c0abcd3517 Mon Sep 17 00:00:00 2001 From: Ling Zhan Date: Thu, 17 Aug 2023 17:34:04 +0800 Subject: [PATCH 130/184] [opt] when move() is called, character controller sync physics position to scene; change default stepOffset; set minimum skinWidth (#15966) * [opt] [character controller] when move() is called, character controller sync physics position to scene immediately; change default stepOffset from 1.0 to 0.5; set minimum skinWidth 0.001 * tweak * native * eslint * eslint * eslint --- cocos/physics/bullet/bullet-world.ts | 107 ++++++++++++------ .../bullet-character-controller.ts | 30 +++-- .../character-controller.ts | 15 ++- cocos/physics/framework/physics-selector.ts | 2 + cocos/physics/physx/physx-world.ts | 8 +- cocos/physics/spec/i-character-controller.ts | 1 + native/cocos/physics/physx/PhysXWorld.cpp | 3 - .../PhysXCharacterController.h | 2 +- .../cocos/physics/sdk/CharacterController.cpp | 4 + .../cocos/physics/sdk/CharacterController.h | 1 + .../cocos/physics/spec/ICharacterController.h | 1 + platforms/native/engine/jsb-physics.js | 1 + 12 files changed, 117 insertions(+), 58 deletions(-) diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index aa4514d28aa..298b1683329 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -45,7 +45,9 @@ const v3_1 = CC_V3_1; const v3_2 = CC_V3_2; const emitHit = new CharacterControllerContact(); export class BulletWorld implements IPhysicsWorld { - setDefaultMaterial (v: PhysicsMaterial): void { } + setDefaultMaterial (v: PhysicsMaterial): void { + //empty + } setAllowSleep (v: boolean): void { bt.ccDiscreteDynamicsWorld_setAllowSleep(this._world, v); @@ -128,9 +130,9 @@ export class BulletWorld implements IPhysicsWorld { readonly oldContactsDic = new TupleDictionary(); readonly cctShapeEventDic = new TupleDictionary(); - private static _sweepBoxGeometry: any; - private static _sweepSphereGeometry: any; - private static _sweepCapsuleGeometry: any; + private static _sweepBoxGeometry: number; + private static _sweepSphereGeometry: number; + private static _sweepCapsuleGeometry: number; constructor () { this._broadphase = bt.DbvtBroadphase_new(); @@ -159,15 +161,9 @@ export class BulletWorld implements IPhysicsWorld { } step (deltaTime: number, timeSinceLastCalled?: number, maxSubStep = 0): void { - if (!this.bodies.length && !this.ghosts.length && !this.ccts.length) return; + if (!this.bodies.length && !this.ghosts.length) return; if (timeSinceLastCalled === undefined) timeSinceLastCalled = deltaTime; bt.DynamicsWorld_stepSimulation(this._world, timeSinceLastCalled, maxSubStep, deltaTime); - - const ccts = this.ccts; - const length = ccts.length; - for (let i = 0; i < length; i++) { - ccts[i].syncPhysicsToScene(); - } } syncSceneToPhysics (): void { @@ -240,8 +236,14 @@ export class BulletWorld implements IPhysicsWorld { return false; } - sweepBox (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepBox ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { // cast shape const hf = BulletCache.instance.BT_V3_0; cocos2BulletVec3(hf, halfExtent); @@ -253,8 +255,13 @@ export class BulletWorld implements IPhysicsWorld { return this.sweep(worldRay, BulletWorld._sweepBoxGeometry, orientation, options, pool, results); } - sweepBoxClosest (worldRay: geometry.Ray, halfExtent: IVec3Like, orientation: IQuatLike, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepBoxClosest ( + worldRay: geometry.Ray, + halfExtent: IVec3Like, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { // cast shape const hf = BulletCache.instance.BT_V3_0; cocos2BulletVec3(hf, halfExtent); @@ -266,8 +273,13 @@ export class BulletWorld implements IPhysicsWorld { return this.sweepClosest(worldRay, BulletWorld._sweepBoxGeometry, orientation, options, result); } - sweepSphere (worldRay: geometry.Ray, radius: number, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepSphere ( + worldRay: geometry.Ray, + radius: number, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { // cast shape if (!BulletWorld._sweepSphereGeometry) { BulletWorld._sweepSphereGeometry = bt.SphereShape_new(radius); @@ -276,8 +288,12 @@ export class BulletWorld implements IPhysicsWorld { return this.sweep(worldRay, BulletWorld._sweepSphereGeometry, Quat.IDENTITY, options, pool, results); } - sweepSphereClosest (worldRay: geometry.Ray, radius: number, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepSphereClosest ( + worldRay: geometry.Ray, + radius: number, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { // cast shape if (!BulletWorld._sweepSphereGeometry) { BulletWorld._sweepSphereGeometry = bt.SphereShape_new(radius); @@ -287,8 +303,15 @@ export class BulletWorld implements IPhysicsWorld { return this.sweepClosest(worldRay, BulletWorld._sweepSphereGeometry, Quat.IDENTITY, options, result); } - sweepCapsule (worldRay: geometry.Ray, radius: number, height: number, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweepCapsule ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { // cast shape if (!BulletWorld._sweepCapsuleGeometry) { BulletWorld._sweepCapsuleGeometry = bt.CapsuleShape_new(radius, height); @@ -297,8 +320,14 @@ export class BulletWorld implements IPhysicsWorld { return this.sweep(worldRay, BulletWorld._sweepCapsuleGeometry, orientation, options, pool, results); } - sweepCapsuleClosest (worldRay: geometry.Ray, radius: number, height: number, orientation: IQuatLike, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepCapsuleClosest ( + worldRay: geometry.Ray, + radius: number, + height: number, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { // cast shape if (!BulletWorld._sweepCapsuleGeometry) { BulletWorld._sweepCapsuleGeometry = bt.CapsuleShape_new(radius, height); @@ -308,8 +337,14 @@ export class BulletWorld implements IPhysicsWorld { return this.sweepClosest(worldRay, BulletWorld._sweepCapsuleGeometry, orientation, options, result); } - sweep (worldRay: geometry.Ray, btShapePtr: any, orientation: IQuatLike, - options: IRaycastOptions, pool: RecyclePool, results: PhysicsRayResult[]): boolean { + sweep ( + worldRay: geometry.Ray, + btShapePtr: number, + orientation: IQuatLike, + options: IRaycastOptions, + pool: RecyclePool, + results: PhysicsRayResult[], + ): boolean { const BT_fromTransform = BulletCache.instance.BT_TRANSFORM_0; const BT_toTransform = BulletCache.instance.BT_TRANSFORM_1; const BT_orientation = BulletCache.instance.BT_QUAT_0; @@ -344,8 +379,13 @@ export class BulletWorld implements IPhysicsWorld { return false; } - sweepClosest (worldRay: geometry.Ray, btShapePtr: any, orientation: IQuatLike, - options: IRaycastOptions, result: PhysicsRayResult): boolean { + sweepClosest ( + worldRay: geometry.Ray, + btShapePtr: number, + orientation: IQuatLike, + options: IRaycastOptions, + result: PhysicsRayResult, + ): boolean { const BT_fromTransform = BulletCache.instance.BT_TRANSFORM_0; const BT_toTransform = BulletCache.instance.BT_TRANSFORM_1; const BT_orientation = BulletCache.instance.BT_QUAT_0; @@ -588,9 +628,9 @@ export class BulletWorld implements IPhysicsWorld { const data = this.cctShapeEventDic.getDataByKey(key); const cct: BulletCharacterController = data.BulletCharacterController; const shape: BulletShape = data.BulletShape; - const worldPos = data.worldPos; - const worldNormal = data.worldNormal; - const motionDir = data.motionDir; + const worldPos = data.worldPos as IVec3Like; + const worldNormal = data.worldNormal as IVec3Like; + const motionDir = data.motionDir as IVec3Like; const motionLength = data.motionLength; emitHit.controller = cct.characterController; emitHit.collider = shape.collider; @@ -623,8 +663,11 @@ export class BulletWorld implements IPhysicsWorld { // current contact let item = this.contactsDic.get(shape0.id, shape1.id); if (!item) { - item = this.contactsDic.set(shape0.id, shape1.id, - { shape0, shape1, contacts: [], impl: manifold }); + item = this.contactsDic.set( + shape0.id, + shape1.id, + { shape0, shape1, contacts: [], impl: manifold }, + ); } item.contacts.push(manifoldPoint);//btManifoldPoint } diff --git a/cocos/physics/bullet/character-controllers/bullet-character-controller.ts b/cocos/physics/bullet/character-controllers/bullet-character-controller.ts index 19135648145..4d6ed88d53b 100644 --- a/cocos/physics/bullet/character-controllers/bullet-character-controller.ts +++ b/cocos/physics/bullet/character-controllers/bullet-character-controller.ts @@ -41,7 +41,7 @@ const v3_2 = new Vec3(0, 0, 0); export abstract class BulletCharacterController implements IBaseCharacterController { readonly wrappedWorld: BulletWorld; private _isEnabled = false; - protected _impl: any = null; //btCapsuleCharacterController + protected _impl: number = 0; //btCapsuleCharacterController protected _comp: CharacterController = null as any; private _btCollisionFlags = 0;//: btControllerCollisionFlag protected _word3 = 0; @@ -50,8 +50,7 @@ export abstract class BulletCharacterController implements IBaseCharacterControl private _collisionFilterMask = -1; get isEnabled (): boolean { return this._isEnabled; } - get impl (): any { - /* eslint-disable @typescript-eslint/no-unsafe-return */ + get impl (): number { return this._impl; } get characterController (): CharacterController { return this._comp; } @@ -61,8 +60,12 @@ export abstract class BulletCharacterController implements IBaseCharacterControl } // virtual - protected onComponentSet (): void { } - protected updateScale (): void { } + protected onComponentSet (): void { + //empty + } + protected updateScale (): void { + //empty + } initialize (comp: CharacterController): boolean { this._comp = comp; @@ -73,7 +76,7 @@ export abstract class BulletCharacterController implements IBaseCharacterControl this.onComponentSet(); - if (this._impl == null) { + if (this._impl === 0) { error('[Physics]: Initialize BulletCharacterController failed'); return false; } else { @@ -106,22 +109,22 @@ export abstract class BulletCharacterController implements IBaseCharacterControl //(this._comp as any) = null; bt._safe_delete(this._impl, EBulletType.EBulletTypeCharacterController); BulletCache.delWrapper(this._impl, bt.CCT_CACHE_NAME); - this._impl = null; + this._impl = 0; //(this.wrappedWorld as any) = null; } onLoad (): void { - + //empty } getPosition (out: IVec3Like): void { if (!this._impl) return; - bullet2CocosVec3(out, bt.CharacterController_getPosition(this.impl)); + bullet2CocosVec3(out, bt.CharacterController_getPosition(this.impl) as number); } setPosition (value: IVec3Like): void { if (!this._impl) return; - cocos2BulletVec3(bt.CharacterController_getPosition(this.impl), value); + cocos2BulletVec3(bt.CharacterController_getPosition(this.impl) as number, value); this.syncPhysicsToScene(); } @@ -257,8 +260,11 @@ export abstract class BulletCharacterController implements IBaseCharacterControl const motionLength = bt.ControllerHit_getHitMotionLength(hit); const s: BulletShape = BulletCache.getWrapper(shapePtr, BulletShape.TYPE); if (s) { - item = bulletWorld.cctShapeEventDic.set(this.impl, shapePtr, - { BulletCharacterController: this, BulletShape: s, worldPos, worldNormal, motionDir, motionLength }); + item = bulletWorld.cctShapeEventDic.set( + this.impl, + shapePtr, + { BulletCharacterController: this, BulletShape: s, worldPos, worldNormal, motionDir, motionLength }, + ); } } } diff --git a/cocos/physics/framework/components/character-controllers/character-controller.ts b/cocos/physics/framework/components/character-controllers/character-controller.ts index f61d683babf..73fa1e0df99 100644 --- a/cocos/physics/framework/components/character-controllers/character-controller.ts +++ b/cocos/physics/framework/components/character-controllers/character-controller.ts @@ -145,7 +145,7 @@ export class CharacterController extends Eventify(Component) { if (this._skinWidth === value) return; this._skinWidth = Math.abs(value); if (this._cct) { - this._cct.setContactOffset(value); + this._cct.setContactOffset(Math.max(0.0001, value)); } } @@ -232,11 +232,11 @@ export class CharacterController extends Eventify(Component) { @serializable private _minMoveDistance = 0.001; //[ 0, infinity ] @serializable - private _stepOffset = 1.0; + private _stepOffset = 0.5; @serializable private _slopeLimit = 45.0; //degree[ 0, 180] @serializable - private _skinWidth = 0.01; + private _skinWidth = 0.01; //[ 0.0001, infinity ] // @serializable // private _detectCollisions = true; // @serializable @@ -307,8 +307,11 @@ export class CharacterController extends Eventify(Component) { /** * @en * Sets world position of center. + * Note: Calling this function will immediately synchronize the position of + * the character controller in the physics world to the node. * @zh * 设置中心的世界坐标。 + * 注意:调用该函数会立刻将角色控制器在物理世界中的位置同步到节点上。 */ public set centerWorldPosition (value: Readonly) { if (this._isInitialized) this._cct!.setPosition(value); @@ -317,8 +320,10 @@ export class CharacterController extends Eventify(Component) { /** * @en * Gets the velocity. + * Note: velocity is only updated after move() is called. * @zh * 获取速度。 + * 注意:velocity 只会在 move() 调用后更新。 */ public get velocity (): Readonly { return this._velocity; @@ -327,8 +332,10 @@ export class CharacterController extends Eventify(Component) { /** * @en * Gets whether the character is on the ground. + * Note: isGrounded is only updated after move() is called. * @zh * 获取是否在地面上。 + * 注意:isGrounded 只会在 move() 调用后更新。 */ public get isGrounded (): boolean { return this._cct!.onGround(); @@ -351,6 +358,8 @@ export class CharacterController extends Eventify(Component) { this._currentPos.set(this.centerWorldPosition); this._velocity = this._currentPos.subtract(this._prevPos).multiplyScalar(1.0 / elapsedTime); + + this._cct!.syncPhysicsToScene(); } /// EVENT INTERFACE /// diff --git a/cocos/physics/framework/physics-selector.ts b/cocos/physics/framework/physics-selector.ts index 4cd1131ce66..306613dc6dc 100644 --- a/cocos/physics/framework/physics-selector.ts +++ b/cocos/physics/framework/physics-selector.ts @@ -39,6 +39,7 @@ import { errorID, IVec3Like, warn, cclegacy } from '../../core'; import { EColliderType, EConstraintType, ECharacterControllerType } from './physics-enum'; import { PhysicsMaterial } from '.'; +// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents export type IPhysicsEngineId = 'builtin' | 'cannon.js' | 'bullet' | 'physx' | string; interface IPhysicsWrapperObject { @@ -524,6 +525,7 @@ const ENTIRE_CHARACTER_CONTROLLER: IEntireCharacterController = { addMask: FUNC, removeMask: FUNC, move: FUNC, + syncPhysicsToScene: FUNC, updateEventListener: FUNC, //IBoxCharacterController setHalfHeight: FUNC, diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index 0916c8b32de..d0ee6c1185a 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -76,7 +76,7 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { } step (deltaTime: number, _timeSinceLastCalled?: number, _maxSubStep = 0): void { - if (this.wrappedBodies.length === 0 && this.ccts.length === 0) return; + if (this.wrappedBodies.length === 0) return; this._simulate(deltaTime); if (!PX.MULTI_THREAD) { this._fetchResults(); @@ -84,12 +84,6 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { const body = this.wrappedBodies[i]; body.syncPhysicsToScene(); } - const ccts = this.ccts; - const length = ccts.length; - for (let i = 0; i < length; i++) { - const cct = ccts[i]; - cct.syncPhysicsToScene(); - } } } diff --git a/cocos/physics/spec/i-character-controller.ts b/cocos/physics/spec/i-character-controller.ts index 6617e58f0fb..5faa80e14a7 100644 --- a/cocos/physics/spec/i-character-controller.ts +++ b/cocos/physics/spec/i-character-controller.ts @@ -40,6 +40,7 @@ export interface IBaseCharacterController extends ILifecycle, IGroupMask { setDetectCollisions (value: boolean): void; setOverlapRecovery (value: boolean): void; move(movement: IVec3Like, minDist: number, elapsedTime: number): void; + syncPhysicsToScene (): void; } export interface ICapsuleCharacterController extends IBaseCharacterController { diff --git a/native/cocos/physics/physx/PhysXWorld.cpp b/native/cocos/physics/physx/PhysXWorld.cpp index 3adedea71f0..96f0d4084f7 100644 --- a/native/cocos/physics/physx/PhysXWorld.cpp +++ b/native/cocos/physics/physx/PhysXWorld.cpp @@ -240,9 +240,6 @@ void PhysXWorld::syncPhysicsToScene() { for (auto const &sb : _mSharedBodies) { sb->syncPhysicsToScene(); } - for (auto const &cct : _mCCTs) { - cct->syncPhysicsToScene(); - } } void PhysXWorld::syncSceneWithCheck() { diff --git a/native/cocos/physics/physx/character-controllers/PhysXCharacterController.h b/native/cocos/physics/physx/character-controllers/PhysXCharacterController.h index 4aba1bbe3f1..5ec9197a655 100644 --- a/native/cocos/physics/physx/character-controllers/PhysXCharacterController.h +++ b/native/cocos/physics/physx/character-controllers/PhysXCharacterController.h @@ -56,7 +56,7 @@ class PhysXCharacterController : virtual public IBaseCharacterController { void syncScale(); void syncSceneToPhysics(); - void syncPhysicsToScene(); + virtual void syncPhysicsToScene() override; //ILifecycle void onEnable() override; diff --git a/native/cocos/physics/sdk/CharacterController.cpp b/native/cocos/physics/sdk/CharacterController.cpp index 1bd9a5569f2..fc53ac4a0fc 100644 --- a/native/cocos/physics/sdk/CharacterController.cpp +++ b/native/cocos/physics/sdk/CharacterController.cpp @@ -68,6 +68,10 @@ void CLASS::move(float x, float y, float z, float minDist, float elapsedTime) { _impl->move(x, y, z, minDist, elapsedTime); \ } \ \ +void CLASS::syncPhysicsToScene() { \ + _impl->syncPhysicsToScene(); \ +} \ + \ void CLASS::setStepOffset(float v) { \ _impl->setStepOffset(v); \ } \ diff --git a/native/cocos/physics/sdk/CharacterController.h b/native/cocos/physics/sdk/CharacterController.h index 90966630923..e87e34dc66d 100644 --- a/native/cocos/physics/sdk/CharacterController.h +++ b/native/cocos/physics/sdk/CharacterController.h @@ -47,6 +47,7 @@ virtual bool onGround() override; \ virtual void move(float x, float y, float z, float minDist, \ float elapsedTime) override; \ + void syncPhysicsToScene() override; \ virtual void setStepOffset(float v) override; \ virtual float getStepOffset() override; \ virtual void setSlopeLimit(float v) override; \ diff --git a/native/cocos/physics/spec/ICharacterController.h b/native/cocos/physics/spec/ICharacterController.h index 1e56bda9b81..26adcfbdbbc 100644 --- a/native/cocos/physics/spec/ICharacterController.h +++ b/native/cocos/physics/spec/ICharacterController.h @@ -51,6 +51,7 @@ class IBaseCharacterController : virtual public ILifecycle { virtual void setPosition(float x, float y, float z) = 0; virtual bool onGround() = 0; virtual void move(float x, float y, float z, float minDist, float elapsedTime) = 0; + virtual void syncPhysicsToScene() = 0; virtual uint32_t getGroup() = 0; virtual void setGroup(uint32_t g) = 0; diff --git a/platforms/native/engine/jsb-physics.js b/platforms/native/engine/jsb-physics.js index fe950775748..49973ef4c94 100644 --- a/platforms/native/engine/jsb-physics.js +++ b/platforms/native/engine/jsb-physics.js @@ -929,6 +929,7 @@ class CharacterController { onGround () { return this._impl.onGround(); } move (v, minDist, dt) { return this._impl.move(v.x, v.y, v.z, minDist, dt); } + syncPhysicsToScene () { this._impl.syncPhysicsToScene(); } setPosition (v) { this._impl.setPosition(v.x, v.y, v.z); } getPosition () { return this._impl.getPosition(); } From 56e00bac7fa968c15b50d3b0bfb93fe9b0ac9aa3 Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Thu, 17 Aug 2023 19:05:02 +0800 Subject: [PATCH 131/184] optimize shader code size, remove unused space (#16011) --- .../chunks/builtin/functionalities/sh.chunk | 2 +- .../builtin/functionalities/shadow-map.chunk | 52 +++++------ .../builtin/uniforms/cc-forward-light.chunk | 2 +- .../common/debug/debug-view-define.chunk | 2 +- .../chunks/common/lighting/attenuation.chunk | 2 +- .../assets/chunks/common/lighting/bxdf.chunk | 2 +- .../chunks/common/lighting/functions.chunk | 6 +- .../assets/chunks/common/math/transform.chunk | 10 +-- .../assets/chunks/common/mesh/material.chunk | 6 +- .../chunks/common/mesh/vat-animation.chunk | 8 +- .../chunks/common/shadow/native-pcf.chunk | 10 +-- editor/assets/chunks/legacy/decode-base.chunk | 4 +- .../legacy/main-functions/outline-vs.chunk | 2 +- .../chunks/legacy/output-standard.chunk | 2 +- .../chunks/legacy/shading-standard-base.chunk | 12 +-- .../assets/chunks/legacy/shading-toon.chunk | 4 +- .../lighting-intermediate-data.chunk | 6 +- .../lighting-flow/common-flow.chunk | 2 +- .../model-functions/standard-common.chunk | 4 +- .../model-functions/standard.chunk | 6 +- .../assets/chunks/post-process/fxaa-hq.chunk | 70 +++++++-------- .../data-structures/vs-intermediate.chunk | 2 +- .../main-functions/misc/sky-fs.chunk | 2 +- .../render-planar-shadow/vs.chunk | 2 +- .../render-to-reflectmap/fs.chunk | 18 ++-- .../main-functions/render-to-scene/fs.chunk | 2 +- .../render-to-scene/pipeline/forward-fs.chunk | 8 +- .../main-functions/render-to-scene/vs.chunk | 2 +- .../render-to-shadowmap/vs.chunk | 2 +- .../surfaces/data-structures/standard.chunk | 4 +- .../surfaces/data-structures/toon.chunk | 2 +- .../surfaces/module-functions/common-vs.chunk | 2 +- .../module-functions/debug-view.chunk | 44 ++++----- .../module-functions/standard-fs.chunk | 6 +- .../surfaces/module-functions/toon-fs.chunk | 4 +- .../surfaces/module-functions/unlit-fs.chunk | 2 +- .../assets/effects/advanced/car-paint.effect | 2 +- .../effects/advanced/common-functions.chunk | 4 +- editor/assets/effects/advanced/eye.chunk | 8 +- editor/assets/effects/advanced/glass.effect | 2 +- editor/assets/effects/advanced/hair.effect | 8 +- .../effects/internal/builtin-wireframe.effect | 4 +- .../internal/editor/box-height-light.effect | 4 +- .../editor/light-probe-visualization.effect | 2 +- .../effects/pipeline/cluster-build.effect | 4 +- .../effects/pipeline/deferred-lighting.effect | 2 +- .../pipeline/post-process/blit-screen.effect | 8 +- .../pipeline/post-process/chunks/fsr.chunk | 6 +- .../pipeline/post-process/chunks/hbao.chunk | 8 +- .../pipeline/post-process/chunks/vs.chunk | 2 +- .../post-process/color-grading.effect | 4 +- .../effects/pipeline/post-process/fsr.effect | 6 +- .../pipeline/post-process/fxaa-hq.effect | 2 +- .../effects/pipeline/post-process/hbao.effect | 8 +- .../effects/pipeline/post-process/taa.effect | 90 +++++++++---------- .../assets/effects/pipeline/ssss-blur.effect | 2 +- .../assets/effects/util/splash-screen.effect | 4 +- 57 files changed, 248 insertions(+), 248 deletions(-) diff --git a/editor/assets/chunks/builtin/functionalities/sh.chunk b/editor/assets/chunks/builtin/functionalities/sh.chunk index 7430c4939f4..a7782e7d4c8 100644 --- a/editor/assets/chunks/builtin/functionalities/sh.chunk +++ b/editor/assets/chunks/builtin/functionalities/sh.chunk @@ -3,7 +3,7 @@ #if CC_USE_LIGHT_PROBE vec3 SHEvaluate(vec3 normal) { - vec3 result; + vec3 result; #if USE_INSTANCING // calculate linear and const terms diff --git a/editor/assets/chunks/builtin/functionalities/shadow-map.chunk b/editor/assets/chunks/builtin/functionalities/shadow-map.chunk index bb744306603..8d77ed8b1bd 100644 --- a/editor/assets/chunks/builtin/functionalities/shadow-map.chunk +++ b/editor/assets/chunks/builtin/functionalities/shadow-map.chunk @@ -34,7 +34,7 @@ float CCGetLinearDepth(vec3 worldPos) { #include #include - + //////////////////////////////////////////////////////////Helper Functions bool GetShadowNDCPos(out vec3 shadowNDCPos, vec4 shadowPosWithDepthBias) @@ -58,9 +58,9 @@ float CCGetLinearDepth(vec3 worldPos) { if (viewNormal.z < 0.1) newShadowPos.xy += viewNormal.xy * projScaleXY * normalBias * clamp(viewNormal.z, 0.001, 0.1); } - return newShadowPos; + return newShadowPos; } - + vec4 ApplyShadowDepthBias_FaceNormal(vec4 shadowPos, vec3 worldNormal, float normalBias, mat4 matLightView, vec2 projScaleXY) { vec4 newShadowPos = shadowPos; @@ -72,7 +72,7 @@ float CCGetLinearDepth(vec3 worldPos) { } return newShadowPos; } - + float GetViewSpaceDepthFromNDCDepth_Orthgraphic(float NDCDepth, float projScaleZ, float projBiasZ) { return (NDCDepth - projBiasZ) / projScaleZ; @@ -88,36 +88,36 @@ float CCGetLinearDepth(vec3 worldPos) { vec3 viewSpacePos; viewSpacePos.xy = shadowPos.xy * cc_shadowProjInfo.zw; viewSpacePos.z = GetViewSpaceDepthFromNDCDepth_Perspective(shadowPos.z, shadowPos.w, cc_shadowInvProjDepthInfo.x, cc_shadowInvProjDepthInfo.y); - + // Apply bias viewSpacePos.xyz += cc_shadowProjDepthInfo.z * normalize(viewSpacePos.xyz) * viewspaceDepthBias; - + // Reconstuct clipspace: cc_matLightProj * viewSpacePos vec4 clipSpacePos; clipSpacePos.xy = viewSpacePos.xy * cc_shadowProjInfo.xy; clipSpacePos.zw = viewSpacePos.z * cc_shadowProjDepthInfo.xz + vec2(cc_shadowProjDepthInfo.y, 0.0); - + // enabled linear depth? #if CC_SHADOWMAP_USE_LINEAR_DEPTH clipSpacePos.z = GetLinearDepthFromViewSpace(viewSpacePos.xyz, cc_shadowNFLSInfo.x, cc_shadowNFLSInfo.y); clipSpacePos.z = (clipSpacePos.z * 2.0 - 1.0) * clipSpacePos.w; #endif - + return clipSpacePos; } - + // (projScaleZ, projBiasZ) = cc_shadowProjDepthInfo.xy vec4 ApplyShadowDepthBias_Orthographic(vec4 shadowPos, float viewspaceDepthBias, float projScaleZ, float projBiasZ) { float coeffA = projScaleZ; float coeffB = projBiasZ; - + // Recover the Z distance in view space: float viewSpacePos_z = GetViewSpaceDepthFromNDCDepth_Orthgraphic(shadowPos.z, projScaleZ, projBiasZ); - + // Apply bias viewSpacePos_z += viewspaceDepthBias; - + // Reconstuct clipspace vec4 result = shadowPos; result.z = viewSpacePos_z * coeffA + coeffB; @@ -140,7 +140,7 @@ float CCGetLinearDepth(vec3 worldPos) { } return NativePCFShadowFactorHard(shadowNDCPos, cc_shadowMap, cc_shadowWHPBInfo.xy); } - + float CCGetDirLightShadowFactorSoft (vec4 shadowPosWithDepthBias) { vec3 shadowNDCPos; if (!GetShadowNDCPos(shadowNDCPos, shadowPosWithDepthBias)) { @@ -148,7 +148,7 @@ float CCGetLinearDepth(vec3 worldPos) { } return NativePCFShadowFactorSoft(shadowNDCPos, cc_shadowMap, cc_shadowWHPBInfo.xy); } - + float CCGetDirLightShadowFactorSoft3X (vec4 shadowPosWithDepthBias) { vec3 shadowNDCPos; if (!GetShadowNDCPos(shadowNDCPos, shadowPosWithDepthBias)) { @@ -156,7 +156,7 @@ float CCGetLinearDepth(vec3 worldPos) { } return NativePCFShadowFactorSoft3X(shadowNDCPos, cc_shadowMap, cc_shadowWHPBInfo.xy); } - + float CCGetDirLightShadowFactorSoft5X (vec4 shadowPosWithDepthBias) { vec3 shadowNDCPos; if (!GetShadowNDCPos(shadowNDCPos, shadowPosWithDepthBias)) { @@ -164,8 +164,8 @@ float CCGetLinearDepth(vec3 worldPos) { } return NativePCFShadowFactorSoft5X(shadowNDCPos, cc_shadowMap, cc_shadowWHPBInfo.xy); } - - + + //////////////////////////////////////////////////////////Spot Light Shadow float CCGetSpotLightShadowFactorHard (vec4 shadowPosWithDepthBias, vec3 worldPos) { vec3 shadowNDCPos; @@ -174,7 +174,7 @@ float CCGetLinearDepth(vec3 worldPos) { } return NativePCFShadowFactorHard(shadowNDCPos, cc_spotShadowMap, cc_shadowWHPBInfo.xy); } - + float CCGetSpotLightShadowFactorSoft (vec4 shadowPosWithDepthBias, vec3 worldPos) { vec3 shadowNDCPos; if (!GetShadowNDCPos(shadowNDCPos, shadowPosWithDepthBias)) { @@ -182,7 +182,7 @@ float CCGetLinearDepth(vec3 worldPos) { } return NativePCFShadowFactorSoft(shadowNDCPos, cc_spotShadowMap, cc_shadowWHPBInfo.xy); } - + float CCGetSpotLightShadowFactorSoft3X (vec4 shadowPosWithDepthBias, vec3 worldPos) { vec3 shadowNDCPos; if (!GetShadowNDCPos(shadowNDCPos, shadowPosWithDepthBias)) { @@ -190,7 +190,7 @@ float CCGetLinearDepth(vec3 worldPos) { } return NativePCFShadowFactorSoft3X(shadowNDCPos, cc_spotShadowMap, cc_shadowWHPBInfo.xy); } - + float CCGetSpotLightShadowFactorSoft5X (vec4 shadowPosWithDepthBias, vec3 worldPos) { vec3 shadowNDCPos; if (!GetShadowNDCPos(shadowNDCPos, shadowPosWithDepthBias)) { @@ -216,21 +216,21 @@ float CCGetLinearDepth(vec3 worldPos) { realtimeShadow = CCGetSpotLightShadowFactorSoft5X(pos, worldPos); }else if (pcf > 1.9) { realtimeShadow = CCGetSpotLightShadowFactorSoft3X(pos, worldPos); - }else if (pcf > 0.9) { + }else if (pcf > 0.9) { realtimeShadow = CCGetSpotLightShadowFactorSoft(pos, worldPos); - }else { + }else { realtimeShadow = CCGetSpotLightShadowFactorHard(pos, worldPos); } shadowPosWithDepthBias = pos; return mix(realtimeShadow, 1.0, cc_shadowNFLSInfo.w); } - + float CCShadowFactorBase(out vec4 shadowPosWithDepthBias, vec4 shadowPos, vec3 N, vec2 shadowBias) { vec4 pos = ApplyShadowDepthBias_FaceNormal(shadowPos, N, shadowBias.y, cc_matLightView, cc_shadowProjInfo.xy); pos = ApplyShadowDepthBias_Orthographic(pos, shadowBias.x, cc_shadowProjDepthInfo.x, cc_shadowProjDepthInfo.y); - + float realtimeShadow = 1.0; #if CC_DIR_SHADOW_PCF_TYPE == CC_SHADOW_PCF_SOFT_5X realtimeShadow = CCGetDirLightShadowFactorSoft5X(pos); @@ -242,13 +242,13 @@ float CCGetLinearDepth(vec3 worldPos) { realtimeShadow = CCGetDirLightShadowFactorSoft(pos); #endif #if CC_DIR_SHADOW_PCF_TYPE == CC_SHADOW_PCF_HARD - realtimeShadow = CCGetDirLightShadowFactorHard(pos); + realtimeShadow = CCGetDirLightShadowFactorHard(pos); #endif shadowPosWithDepthBias = pos; return mix(realtimeShadow, 1.0, cc_shadowNFLSInfo.w); } - + #if CC_SUPPORT_CASCADED_SHADOW_MAP bool CCGetCSMLevelWithTransition(out highp float ratio, vec3 clipPos) { highp float maxRange = 1.0 - cc_csmSplitsInfo.x; diff --git a/editor/assets/chunks/builtin/uniforms/cc-forward-light.chunk b/editor/assets/chunks/builtin/uniforms/cc-forward-light.chunk index 589ca4958f5..fe794dcfbf4 100644 --- a/editor/assets/chunks/builtin/uniforms/cc-forward-light.chunk +++ b/editor/assets/chunks/builtin/uniforms/cc-forward-light.chunk @@ -14,5 +14,5 @@ layout(set = 2, binding = 1) uniform CCForwardLight { vec4 cc_lightSizeRangeAngle[LIGHTS_PER_PASS]; // x: size, y: range, z: cos(half outterAngle), w: enable shadow; ranged dir light: xyz is right vec4 cc_lightDir[LIGHTS_PER_PASS]; // xyz: dir, w: unused vec4 cc_lightBoundingSizeVS[LIGHTS_PER_PASS]; //xyz: ranged dir light node half scale -}; +}; #endif diff --git a/editor/assets/chunks/common/debug/debug-view-define.chunk b/editor/assets/chunks/common/debug/debug-view-define.chunk index c738cdaeb5c..1cb6feffbed 100644 --- a/editor/assets/chunks/common/debug/debug-view-define.chunk +++ b/editor/assets/chunks/common/debug/debug-view-define.chunk @@ -80,7 +80,7 @@ bool equalf_mode(float data1, float data2) { return abs(float(data1) - float(dat // these mode shows non-lighting data, need ignore tone mapping and gamma correction bool DebugViewNeedDisplayOriginalData() { - return + return IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_FRAGMENT_NORMAL) || IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_FRAGMENT_TANGENT) || IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_FRAGMENT_BINORMAL) || IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_TRANSPARENCY) || IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_BASE_COLOR) || IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_DIFFUSE_COLOR) || IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_SPECULAR_COLOR) || IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_ROUGHNESS) || IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_METALLIC) || diff --git a/editor/assets/chunks/common/lighting/attenuation.chunk b/editor/assets/chunks/common/lighting/attenuation.chunk index 44266dc576f..86ab9c10177 100644 --- a/editor/assets/chunks/common/lighting/attenuation.chunk +++ b/editor/assets/chunks/common/lighting/attenuation.chunk @@ -43,7 +43,7 @@ float CalculateDistanceAttenuation(float distToLightSqr, float lightRadius, floa // physical attenuation float attRadiusSqrInv = 1.0 / max(lightRange, 0.01); attRadiusSqrInv *= attRadiusSqrInv; - + // artical soft edge fading float litRadiusSqr = lightRadius * lightRadius; float edgeAttenuation = (IS_POINT_LIGHT(lightType) || IS_RANGED_DIRECTIONAL_LIGHT(lightType)) ? 1.0 : litRadiusSqr / max(litRadiusSqr, distToLightSqr); diff --git a/editor/assets/chunks/common/lighting/bxdf.chunk b/editor/assets/chunks/common/lighting/bxdf.chunk index ba06af07417..478b535caf6 100644 --- a/editor/assets/chunks/common/lighting/bxdf.chunk +++ b/editor/assets/chunks/common/lighting/bxdf.chunk @@ -41,7 +41,7 @@ void InitializeLayerBlending(out vec3 blendedBaseLayerD, out vec3 blendedBaseLay blendedBaseLayerD = baseD; blendedBaseLayerS = baseS; blendedSubLayerD = blendedSubLayerS = vec3(0.0); - lastLayerF = vec3(1.0); + lastLayerF = vec3(1.0); } // use subLayerF instead of subLayerGF for ior-dependent 0-1 range diff --git a/editor/assets/chunks/common/lighting/functions.chunk b/editor/assets/chunks/common/lighting/functions.chunk index cc744e5f7ab..bfedd416ac7 100644 --- a/editor/assets/chunks/common/lighting/functions.chunk +++ b/editor/assets/chunks/common/lighting/functions.chunk @@ -7,7 +7,7 @@ vec3 CalculateRefractDirection(vec3 N, vec3 V, float NoV, float ior) // two sided float sideSign = NoV < 0.0 ? -1.0 : 1.0; N *= sideSign; - + // A: NV B:NR float cosA = abs(NoV); float sinA = sqrt(1.0 - cosA * cosA); @@ -25,7 +25,7 @@ vec3 CalculateRefractDirectionFast(vec3 N, vec3 V, float NoV, float ior) // two sided float sideSign = NoV < 0.0 ? -1.0 : 1.0; N *= sideSign; - + float w = ior * NoV; float k = sqrt(1.0 + (w - ior) * (w + ior)); // 1 + ior2 * (NoV2 - 1) vec3 R = (w - k) * N - ior * V; @@ -54,7 +54,7 @@ vec3 CalculatePlanarReflectPositionOnPlane(vec3 N, vec3 V, vec3 worldPos, vec4 p float sideSignN = dot(N, V) < 0.0 ? -1.0 : 1.0; planeN *= sideSignPlaneN; N *= sideSignN;*/ - vec3 bumpedR = normalize(reflect(-V, N)); //R' + vec3 bumpedR = normalize(reflect(-V, N)); //R' // actually reflected pos alone bumpedR direction, avoid tracing by specified a fake depth vec3 reflectedPointPos = worldPos + probeReflectedDepth * bumpedR; diff --git a/editor/assets/chunks/common/math/transform.chunk b/editor/assets/chunks/common/math/transform.chunk index fd9c9ad9855..c5d906c4ce3 100644 --- a/editor/assets/chunks/common/math/transform.chunk +++ b/editor/assets/chunks/common/math/transform.chunk @@ -167,7 +167,7 @@ void rotateCorner (inout vec2 corner, float angle){ mat3 quatToMat3(vec4 q) { vec3 m0 = vec3( - 1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z, + 1.0 - 2.0 * q.y * q.y - 2.0 * q.z * q.z, 2.0 * q.x * q.y + 2.0 * q.w * q.z, 2.0 * q.x * q.z - 2.0 * q.w * q.y); vec3 m1 = vec3( @@ -176,7 +176,7 @@ mat3 quatToMat3(vec4 q) { 2.0 * q.y * q.z + 2.0 * q.w * q.x); vec3 m2 = vec3( 2.0 * q.x * q.z + 2.0 * q.w * q.y, - 2.0 * q.y * q.z - 2.0 * q.w * q.x, + 2.0 * q.y * q.z - 2.0 * q.w * q.x, 1.0 - 2.0 * q.x * q.x - 2.0 * q.y * q.y); return mat3(m0, m1, m2); } @@ -190,14 +190,14 @@ vec4 mat3ToQuat(mat3 mat) { float tr = mat[0][0] + mat[1][1] + mat[2][2]; float qw, qx, qy, qz; if (tr > 0.0) { - float S = sqrt(tr + 1.0) * 2.0; // S=4*qw + float S = sqrt(tr + 1.0) * 2.0; // S=4*qw float invS = 1.0 / S; qw = 0.25 * S; qx = (mat[1][2] - mat[2][1]) * invS; qy = (mat[2][0] - mat[0][2]) * invS; qz = (mat[0][1] - mat[1][0]) * invS; } else if ((mat[0][0] > mat[1][1])&&(mat[0][0] > mat[2][2])) { - float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0; // S=4*qx + float S = sqrt(1.0 + mat[0][0] - mat[1][1] - mat[2][2]) * 2.0; // S=4*qx float invS = 1.0 / S; qw = (mat[1][2] - mat[2][1]) * invS; qx = 0.25 * S; @@ -224,7 +224,7 @@ vec4 mat3ToQuat(mat3 mat) { vec4 eulerToQuat(vec3 euler) { vec3 er = euler * 0.5; float x = er.x, y = er.y, z = er.z; - + float sx = sin(x); float cx = cos(x); float sy = sin(y); diff --git a/editor/assets/chunks/common/mesh/material.chunk b/editor/assets/chunks/common/mesh/material.chunk index 0f70837976a..435f31a76e7 100644 --- a/editor/assets/chunks/common/mesh/material.chunk +++ b/editor/assets/chunks/common/mesh/material.chunk @@ -7,10 +7,10 @@ bool GetMetallicAlbedoFromDiffuseSpecularMathematic(out float metallic, out vec3 diffuse += vec3(f0 + 0.01); specular += vec3(f0 + 0.01); - vec3 delta = (diffuse + specular) * (diffuse + specular) - 4.0 * f0 * diffuse; + vec3 delta = (diffuse + specular) * (diffuse + specular) - 4.0 * f0 * diffuse; vec3 deltaSqrt = sqrt(max(vec3(0.0), delta)); // solver - vec3 m = (-diffuse - specular + 2.0 * f0 + deltaSqrt) / (2.0 * f0); + vec3 m = (-diffuse - specular + 2.0 * f0 + deltaSqrt) / (2.0 * f0); vec3 weight = diffuse + specular; weight /= dot(weight, vec3(1.0)); float solverMetallic = dot(m, weight); @@ -20,7 +20,7 @@ bool GetMetallicAlbedoFromDiffuseSpecularMathematic(out float metallic, out vec3 && abs(m.x - m.y) < channelFaultTolerant && abs(m.x - m.z) < channelFaultTolerant && m.x >= 0.0 && m.y >= 0.0 && m.z >= 0.0 && m.x <= 1.0 && m.y <= 1.0 && m.z <= 1.0; - + metallic = isValidSolver ? solverMetallic : metallic; albedo = isValidSolver ? solverAlbedo : albedo; return isValidSolver; diff --git a/editor/assets/chunks/common/mesh/vat-animation.chunk b/editor/assets/chunks/common/mesh/vat-animation.chunk index 1d2a20c7a0b..10878821ce7 100644 --- a/editor/assets/chunks/common/mesh/vat-animation.chunk +++ b/editor/assets/chunks/common/mesh/vat-animation.chunk @@ -107,7 +107,7 @@ vec3 VATCalculateFluidVoxelUV(vec3 vatBoundingBoxMin, vec3 vatBoundingBoxMax, ve // bounding box in exported json is unscaled vatBoundingBoxMin *= VAT_FBX_TO_COCOS_COORDINATE_SCALE; vatBoundingBoxMax *= VAT_FBX_TO_COCOS_COORDINATE_SCALE; - + vec3 size = vatBoundingBoxMax - vatBoundingBoxMin; vec3 coef = (localPos - vatBoundingBoxMin) / size; return coef; @@ -119,7 +119,7 @@ vec3 VATCalculateFluidVoxelUV(vec3 vatBoundingBoxMin, vec3 vatBoundingBoxMax, ve ////////////////////////////////////////////////////////////////Rigid-body void VATGetLocalPositionRigidBody20(inout vec3 meshLocalPos, inout vec3 meshLocalNormal, inout vec3 meshLocalTangent, in vec4 meshVertexColor, vec2 thisFrameUV, float pivMax, float pivMin, float posMax, float posMin, sampler2D vatPositionTexture, sampler2D vatPositionSignTexture, sampler2D vatPositionAlphaTexture, sampler2D vatRotationTexture, sampler2D vatRotationSignTexture, sampler2D vatRotationAlphaTexture) -{ +{ // pivot float pivExpand = pivMax - pivMin; float posExpand = posMax - posMin; @@ -127,7 +127,7 @@ void VATGetLocalPositionRigidBody20(inout vec3 meshLocalPos, inout vec3 meshLoca vec3 pivot = meshVertexColor.xyz; pivot.xyz *= pivExpand; pivot.xyz += vec3(pivMin); - + // anim pos vec3 posData = SampleTextureExr(vatPositionTexture, vatPositionSignTexture, thisFrameUV); vec3 texturePos = posData; @@ -203,7 +203,7 @@ void VATGetLocalPositionRigidBody30(inout vec3 meshLocalPos, inout vec3 meshLoca if(isZUp) pivot.xyz = pivot.xzy / VAT_FBX_TO_COCOS_COORDINATE_SCALE; vec3 originPos = meshLocalPos - pivot; - + // rotation offset vec4 posData = SampleTextureExrWithAlpha(vatPositionTexture, vatPositionSignTexture, vatPositionAlphaTexture, thisFrameUV); vec4 XYZW = SampleTextureExrWithAlpha(vatRotationTexture, vatRotationSignTexture, vatRotationAlphaTexture, thisFrameUV); diff --git a/editor/assets/chunks/common/shadow/native-pcf.chunk b/editor/assets/chunks/common/shadow/native-pcf.chunk index 3457167f9a9..ab56782a846 100644 --- a/editor/assets/chunks/common/shadow/native-pcf.chunk +++ b/editor/assets/chunks/common/shadow/native-pcf.chunk @@ -29,7 +29,7 @@ float SampleShadowMapSoft (vec3 shadowNDCPos, highp sampler2D shadowMap, vec2 sh float resultX = mix(block0, block1, coefX); float resultY = mix(block2, block3, coefX); float coefY = mod(shadowNDCPos.y, oneTap.y) * shadowMapResolution.y; - + return mix(resultX, resultY, coefY); } @@ -66,7 +66,7 @@ float NativePCFShadowFactorSoft (vec3 shadowNDCPos, highp sampler2D shadowMap, v float resultX = mix(block0, block1, coefX); float resultY = mix(block2, block3, coefX); float coefY = mod(shadowNDCPos.y, oneTap.y) * shadowMapResolution.y; - + return mix(resultX, resultY, coefY); } @@ -126,9 +126,9 @@ float NativePCFShadowFactorSoft3X (vec3 shadowNDCPos, highp sampler2D shadowMap, float NativePCFShadowFactorSoft5X (vec3 shadowNDCPos, highp sampler2D shadowMap, vec2 shadowMapResolution) { - vec2 oneTap = 1.0 / shadowMapResolution; + vec2 oneTap = 1.0 / shadowMapResolution; vec2 twoTap = oneTap * 2.0; - + vec2 offset1 = shadowNDCPos.xy + vec2(-twoTap.x, -twoTap.y); vec2 offset2 = shadowNDCPos.xy + vec2(-oneTap.x, -twoTap.y); vec2 offset3 = shadowNDCPos.xy + vec2(0.0, -twoTap.y); @@ -154,7 +154,7 @@ float NativePCFShadowFactorSoft5X (vec3 shadowNDCPos, highp sampler2D shadowMap, vec2 offset23 = shadowNDCPos.xy + vec2(0.0, twoTap.y); vec2 offset24 = shadowNDCPos.xy + vec2(oneTap.x, twoTap.y); vec2 offset25 = shadowNDCPos.xy + vec2(twoTap.x, twoTap.y); - + float block1, block2, block3, block4, block5, block6, block7, block8, block9, block10, block11, block12, block13, block14, block15, block16, block17, block18, block19, block20, block21, block22, block23, block24, block25; #if CC_SHADOWMAP_FORMAT == SHADOWMAP_FORMAT_RGBA8 block1 = step(shadowNDCPos.z, unpackRGBAToDepth(texture(shadowMap, offset1))); diff --git a/editor/assets/chunks/legacy/decode-base.chunk b/editor/assets/chunks/legacy/decode-base.chunk index cddbdac9ee8..d23b9596dd9 100644 --- a/editor/assets/chunks/legacy/decode-base.chunk +++ b/editor/assets/chunks/legacy/decode-base.chunk @@ -39,7 +39,7 @@ layout(location = 3) in vec4 a_tangent; #if CC_USE_LIGHTMAP in vec4 a_lightingMapUVParam; #endif - + // TODO (jk20012001) #if CC_USE_REFLECTION_PROBE || CC_RECEIVE_SHADOW // temporary hack for effect-parser: can't detect logic OR. @@ -47,7 +47,7 @@ layout(location = 3) in vec4 a_tangent; #endif in vec4 a_localShadowBiasAndProbeId; // x:shadow bias, y:shadow normal bias, z: reflection probe id, w: reserved for blend reflection probe id #endif - + #if CC_USE_REFLECTION_PROBE in vec4 a_reflectionProbeData; // x:reflection probe blend weight #endif diff --git a/editor/assets/chunks/legacy/main-functions/outline-vs.chunk b/editor/assets/chunks/legacy/main-functions/outline-vs.chunk index 3a24fe065b6..af279490966 100644 --- a/editor/assets/chunks/legacy/main-functions/outline-vs.chunk +++ b/editor/assets/chunks/legacy/main-functions/outline-vs.chunk @@ -28,7 +28,7 @@ vec4 vert () { In.position.xyz += normalize(In.normal) * width; vec4 pos = cc_matProj * (cc_matView * matWorld) * In.position; #endif - + float scaleZ = cc_nearFar.z == 0.0 ? 0.5 : 1.0; pos.z -= outlineParams.y * 0.002 * scaleZ; diff --git a/editor/assets/chunks/legacy/output-standard.chunk b/editor/assets/chunks/legacy/output-standard.chunk index 6ed9b3dd122..44525108a84 100644 --- a/editor/assets/chunks/legacy/output-standard.chunk +++ b/editor/assets/chunks/legacy/output-standard.chunk @@ -12,6 +12,6 @@ vec4 CCFragOutput (vec4 color) { #endif color.rgb = LinearToSRGB(color.rgb); #endif - + return color; } diff --git a/editor/assets/chunks/legacy/shading-standard-base.chunk b/editor/assets/chunks/legacy/shading-standard-base.chunk index 01a3ad3d538..08ed385c87f 100644 --- a/editor/assets/chunks/legacy/shading-standard-base.chunk +++ b/editor/assets/chunks/legacy/shading-standard-base.chunk @@ -125,7 +125,7 @@ struct StandardSurface { vec4 CCStandardShadingBase (StandardSurface s, vec4 shadowPos) { // Calculate diffuse & specular vec3 diffuse = s.albedo.rgb * (1.0 - s.metallic); - + vec3 specular = mix(vec3(0.08 * s.specularIntensity), s.albedo.rgb, s.metallic); vec3 position; @@ -164,20 +164,20 @@ vec4 CCStandardShadingBase (StandardSurface s, vec4 shadowPos) { #endif s.occlusion *= s.lightmap_test; #endif - + #if !CC_DISABLE_DIRECTIONAL_LIGHT float NV = max(abs(dot(N, V)), 0.0); specular = BRDFApprox(specular, s.roughness, NV); - + vec3 H = normalize(L + V); float NH = max(dot(N, H), 0.0); vec3 lightingColor = NL * cc_mainLitColor.rgb * cc_mainLitColor.w; vec3 diffuseContrib = diffuse / PI; - + // Cook-Torrance Microfacet Specular BRDF vec3 specularContrib = specular * CalcSpecular(s.roughness, NH, H, N); vec3 dirlightContrib = (diffuseContrib + specularContrib); - + dirlightContrib *= shadow; finalColor += lightingColor * dirlightContrib; #endif @@ -243,7 +243,7 @@ vec4 CCStandardShadingBase (StandardSurface s, vec4 shadowPos) { vec3 worldPosOffset = CalculatePlanarReflectPositionOnPlane(N, V, s.position, plane, cc_cameraPos.xyz, planarReflectionDepthScale); vec2 screenUV = GetPlanarReflectScreenUV(worldPosOffset, cc_matViewProj, cc_cameraPos.w, V, R); probe = fragTextureLod(cc_reflectionProbePlanarMap, screenUV, mipCount); - } + } env = unpackRGBE(probe); #elif CC_USE_REFLECTION_PROBE == REFLECTION_PROBE_TYPE_BLEND || CC_USE_REFLECTION_PROBE == REFLECTION_PROBE_TYPE_BLEND_AND_SKYBOX if (s.reflectionProbeId < 0.0) { diff --git a/editor/assets/chunks/legacy/shading-toon.chunk b/editor/assets/chunks/legacy/shading-toon.chunk index 655b72018a3..3c6801fba98 100644 --- a/editor/assets/chunks/legacy/shading-toon.chunk +++ b/editor/assets/chunks/legacy/shading-toon.chunk @@ -43,7 +43,7 @@ struct ToonSurface { vec3 SH = normalize(SL + V); float SNL = 0.5 * dot(N, SL) + 0.5; float SNH = 0.5 * dot(N, SH) + 0.5; - + vec3 diffuse = mix(s.shade1, s.shade2, clamp(1.0 + (s.shadeStep - s.shadeFeather - SNL) / s.shadeFeather, 0.0, 1.0)); diffuse = mix(s.baseColor.rgb, diffuse, @@ -87,7 +87,7 @@ struct ToonSurface { vec4 CCToonShading (ToonSurface s) { vec3 position; HIGHP_VALUE_FROM_STRUCT_DEFINED(position, s.position); - + vec3 V = normalize(cc_cameraPos.xyz - position); vec3 N = normalize(s.normal); diff --git a/editor/assets/chunks/lighting-models/data-structures/lighting-intermediate-data.chunk b/editor/assets/chunks/lighting-models/data-structures/lighting-intermediate-data.chunk index 54e54b14bbf..66a9d556070 100644 --- a/editor/assets/chunks/lighting-models/data-structures/lighting-intermediate-data.chunk +++ b/editor/assets/chunks/lighting-models/data-structures/lighting-intermediate-data.chunk @@ -40,7 +40,7 @@ struct LightingIntermediateData // add overrided functions for difference shading-models in void CCSurfacesLightingGetIntermediateData_PerPixel(inout LightingIntermediateData data, vec3 worldNormal, vec3 worldPos, vec3 worldTangent, vec3 worldBinormal #if CC_SURFACES_LIGHTING_ANISOTROPIC - , float anisotropyShape + , float anisotropyShape #endif ) { @@ -85,7 +85,7 @@ void CCSurfacesLightingGetIntermediateData_PerLight(inout LightingIntermediateDa data.L = lightDirWithDist; data.distToLightSqr = dot(data.L, data.L); data.distToLight = sqrt(data.distToLightSqr); - + data.L /= data.distToLight; data.H = normalize(data.L + data.V); @@ -94,7 +94,7 @@ void CCSurfacesLightingGetIntermediateData_PerLight(inout LightingIntermediateDa data.NoL = dot(data.N, data.L); data.NoH = dot(data.N, data.H); data.VoH = dot(data.V, data.H); - + data.NoLSat = max(data.NoL, 0.0); data.NoHSat = max(data.NoH, 0.0); // data.VoHSat = max(data.VoH, 0.0); diff --git a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk index 88078372f3a..0324db26f35 100644 --- a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk +++ b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk @@ -40,7 +40,7 @@ vec3 fresnel = vec3(1.0); #endif lightingResult.fresnel = fresnel; - + float shadow = 1.0; #if CC_RECEIVE_SHADOW && CC_SHADOW_TYPE == CC_SHADOW_MAP diff --git a/editor/assets/chunks/lighting-models/model-functions/standard-common.chunk b/editor/assets/chunks/lighting-models/model-functions/standard-common.chunk index 78ab23eba1f..f2d4c75844b 100644 --- a/editor/assets/chunks/lighting-models/model-functions/standard-common.chunk +++ b/editor/assets/chunks/lighting-models/model-functions/standard-common.chunk @@ -205,14 +205,14 @@ vec3 CalculateEnvironmentSpecular(in LightingIntermediateData lightingData, floa vec3 R = normalize(CalculateReflectDirection(lightingData.N, lightingData.V, lightingData.NoV)); vec4 fixedR = CalculateBoxProjectedDirection(R, worldPos, centerPos, boxHalfSize); envSpec = mix(skyBoxEnv, envSpec, fixedR.w); - #endif + #endif }else{ vec3 centerPosBlend, boxHalfSizeBlend; float mipCountBlend; GetBlendCubeReflectionProbeData(centerPosBlend, boxHalfSizeBlend, mipCountBlend, FSInput_reflectionProbeBlendId); vec3 probeBlend = SampleEnvironmentSpecular(cc_reflectionProbeBlendCubemap, lightingData, mipCountBlend, worldPos, centerPosBlend, boxHalfSizeBlend, isBlendReflectProbeUsingRGBE(FSInput_reflectionProbeBlendId)); envSpec = mix(envSpec, probeBlend, blendFactor); - } + } } #endif #elif CC_USE_IBL diff --git a/editor/assets/chunks/lighting-models/model-functions/standard.chunk b/editor/assets/chunks/lighting-models/model-functions/standard.chunk index 89f25c75547..a0a5054f127 100644 --- a/editor/assets/chunks/lighting-models/model-functions/standard.chunk +++ b/editor/assets/chunks/lighting-models/model-functions/standard.chunk @@ -108,7 +108,7 @@ void CCSurfaceLightingCalculateEnvironmentFresnel(out vec3 integratedGF, vec3 in vec3 R = CalculateRefractDirection(lightingData.N, lightingData.V, lightingData.NoV, lightingData.ior); float RoL = dot(lightingData.L, normalize(R)); float calcSpec = D_GGX(roughness, saturate(RoL)); - + lightingSpecular = irradiance * calcSpec; } void CCSurfacesLightingCalculateEnvironmentTransmitSpecular(out vec3 lightingSpecular, in LightingIntermediateData lightingData, float lightIntensity) @@ -116,7 +116,7 @@ void CCSurfaceLightingCalculateEnvironmentFresnel(out vec3 integratedGF, vec3 in vec3 envSpec = vec3(0.0); vec3 R = CalculateRefractDirection(lightingData.N, lightingData.V, lightingData.NoV, lightingData.ior); float roughness = lightingData.specularParam; - + #if CC_USE_REFLECTION_PROBE #if CC_USE_REFLECTION_PROBE == REFLECTION_PROBE_TYPE_CUBE envSpec = EnvReflection(cc_reflectionProbeCubemap, R, roughness, cc_ambientGround.w); @@ -200,7 +200,7 @@ void CCSurfaceLightingCalculateEnvironmentFresnel(out vec3 integratedGF, vec3 in return vec3(saturate(specBRDF)); } #endif - + void CCSurfacesLightingCalculateDirect2ndSpecular(out vec3 specularLighting, in LightingIntermediateData lightingData, in vec4 lightSourceColorAndIntensity, float intensitySpecular, in vec3 originalSpecular) { #if !CC_SURFACES_LIGHTING_DISABLE_SPECULAR diff --git a/editor/assets/chunks/post-process/fxaa-hq.chunk b/editor/assets/chunks/post-process/fxaa-hq.chunk index 0480aaadae4..96dcb4e1981 100644 --- a/editor/assets/chunks/post-process/fxaa-hq.chunk +++ b/editor/assets/chunks/post-process/fxaa-hq.chunk @@ -110,23 +110,23 @@ float4 FxaaTexOff(FxaaTex tex, float2 pos, int2 off, float2 rcpFrame) { float FxaaLuma(float3 rgb) { - return rgb.y * (0.587/0.299) + rgb.x; } + return rgb.y * (0.587/0.299) + rgb.x; } float3 FxaaLerp3(float3 a, float3 b, float amountOfA) { - return (FxaaToFloat3(-amountOfA) * b) + - ((a * FxaaToFloat3(amountOfA)) + b); } + return (FxaaToFloat3(-amountOfA) * b) + + ((a * FxaaToFloat3(amountOfA)) + b); } float3 FxaaFilterReturn(float3 rgb) { #if FXAA_SRGB_ROP return FxaaSel3( - rgb * FxaaToFloat3(1.0/12.92), + rgb * FxaaToFloat3(1.0/12.92), FxaaPow3( - rgb * FxaaToFloat3(1.0/1.055) + FxaaToFloat3(0.055/1.055), + rgb * FxaaToFloat3(1.0/1.055) + FxaaToFloat3(0.055/1.055), FxaaToFloat3(2.4)), - rgb > FxaaToFloat3(0.04045)); + rgb > FxaaToFloat3(0.04045)); #else return rgb; #endif } - + float3 FxaaPixelShader( float2 pos, @@ -147,7 +147,7 @@ float2 rcpFrame) { float range = rangeMax - rangeMin; #if FXAA_DEBUG float lumaO = lumaM / (1.0 + (0.587/0.299)); - #endif + #endif if(range < max(FXAA_EDGE_THRESHOLD_MIN, rangeMax * FXAA_EDGE_THRESHOLD)) { #if FXAA_DEBUG return FxaaFilterReturn(FxaaToFloat3(lumaO)); @@ -155,27 +155,27 @@ float2 rcpFrame) { return FxaaFilterReturn(rgbM); } #if FXAA_SUBPIX > 0 #if FXAA_SUBPIX_FASTER - float3 rgbL = (rgbN + rgbW + rgbE + rgbS + rgbM) * + float3 rgbL = (rgbN + rgbW + rgbE + rgbS + rgbM) * FxaaToFloat3(1.0/5.0); #else float3 rgbL = rgbN + rgbW + rgbM + rgbE + rgbS; #endif - #endif - + #endif + #if FXAA_SUBPIX != 0 float lumaL = (lumaN + lumaW + lumaE + lumaS) * 0.25; float rangeL = abs(lumaL - lumaM); - #endif + #endif #if FXAA_SUBPIX == 1 - float blendL = max(0.0, - (rangeL / range) - FXAA_SUBPIX_TRIM) * FXAA_SUBPIX_TRIM_SCALE; + float blendL = max(0.0, + (rangeL / range) - FXAA_SUBPIX_TRIM) * FXAA_SUBPIX_TRIM_SCALE; blendL = min(FXAA_SUBPIX_CAP, blendL); #endif #if FXAA_SUBPIX == 2 - float blendL = rangeL / range; + float blendL = rangeL / range; #endif - + float3 rgbNW = FxaaTexOff(tex, pos.xy, FxaaInt2(-1,-1), rcpFrame).xyz; @@ -190,11 +190,11 @@ float2 rcpFrame) { float lumaNE = FxaaLuma(rgbNE); float lumaSW = FxaaLuma(rgbSW); float lumaSE = FxaaLuma(rgbSE); - float edgeVert = + float edgeVert = abs((0.25 * lumaNW) + (-0.5 * lumaN) + (0.25 * lumaNE)) + abs((0.50 * lumaW ) + (-1.0 * lumaM) + (0.50 * lumaE )) + abs((0.25 * lumaSW) + (-0.5 * lumaS) + (0.25 * lumaSE)); - float edgeHorz = + float edgeHorz = abs((0.25 * lumaNW) + (-0.5 * lumaW) + (0.25 * lumaSW)) + abs((0.50 * lumaN ) + (-1.0 * lumaM) + (0.50 * lumaS )) + abs((0.25 * lumaNE) + (-0.5 * lumaE) + (0.25 * lumaSE)); @@ -206,9 +206,9 @@ float2 rcpFrame) { float gradientS = abs(lumaS - lumaM); lumaN = (lumaN + lumaM) * 0.5; lumaS = (lumaS + lumaM) * 0.5; - - + + bool pairN = gradientN >= gradientS; if(!pairN) lumaN = lumaS; if(!pairN) gradientN = gradientS; @@ -216,15 +216,15 @@ float2 rcpFrame) { float2 posN; posN.x = pos.x + (horzSpan ? 0.0 : lengthSign * 0.5); posN.y = pos.y + (horzSpan ? lengthSign * 0.5 : 0.0); - + gradientN *= FXAA_SEARCH_THRESHOLD; - + float2 posP = posN; - float2 offNP = horzSpan ? + float2 offNP = horzSpan ? FxaaFloat2(rcpFrame.x, 0.0) : - FxaaFloat2(0.0, rcpFrame.y); + FxaaFloat2(0.0, rcpFrame.y); float lumaEndN = lumaN; float lumaEndP = lumaN; bool doneN = false; @@ -250,14 +250,14 @@ float2 rcpFrame) { #endif for(int i = 0; i < FXAA_SEARCH_STEPS; i++) { #if FXAA_SEARCH_ACCELERATION == 1 - if(!doneN) lumaEndN = + if(!doneN) lumaEndN = FxaaLuma(FxaaTexLod0(tex, posN.xy).xyz); - if(!doneP) lumaEndP = + if(!doneP) lumaEndP = FxaaLuma(FxaaTexLod0(tex, posP.xy).xyz); #else - if(!doneN) lumaEndN = + if(!doneN) lumaEndN = FxaaLuma(FxaaTexGrad(tex, posN.xy, offNP).xyz); - if(!doneP) lumaEndP = + if(!doneP) lumaEndP = FxaaLuma(FxaaTexGrad(tex, posP.xy, offNP).xyz); #endif doneN = doneN || (abs(lumaEndN - lumaN) >= gradientN); @@ -265,19 +265,19 @@ float2 rcpFrame) { if(doneN && doneP) break; if(!doneN) posN -= offNP; if(!doneP) posP += offNP; } - + float dstN = horzSpan ? pos.x - posN.x : pos.y - posN.y; float dstP = horzSpan ? posP.x - pos.x : posP.y - pos.y; bool directionN = dstN < dstP; lumaEndN = directionN ? lumaEndN : lumaEndP; - - if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0)) + + if(((lumaM - lumaN) < 0.0) == ((lumaEndN - lumaN) < 0.0)) lengthSign = 0.0; - + float spanLength = (dstP + dstN); @@ -287,8 +287,8 @@ float2 rcpFrame) { pos.x + (horzSpan ? 0.0 : subPixelOffset), pos.y + (horzSpan ? subPixelOffset : 0.0))).xyz; #if FXAA_SUBPIX == 0 - return FxaaFilterReturn(rgbF); - #else - return FxaaFilterReturn(FxaaLerp3(rgbL, rgbF, blendL)); + return FxaaFilterReturn(rgbF); + #else + return FxaaFilterReturn(FxaaLerp3(rgbL, rgbF, blendL)); #endif } diff --git a/editor/assets/chunks/shading-entries/data-structures/vs-intermediate.chunk b/editor/assets/chunks/shading-entries/data-structures/vs-intermediate.chunk index c97b12c37de..f464e8da10d 100644 --- a/editor/assets/chunks/shading-entries/data-structures/vs-intermediate.chunk +++ b/editor/assets/chunks/shading-entries/data-structures/vs-intermediate.chunk @@ -6,7 +6,7 @@ struct SurfacesStandardVertexIntermediate #if CC_SURFACES_USE_TANGENT_SPACE vec4 tangent; #endif - + //other data #if CC_SURFACES_USE_VERTEX_COLOR vec4 color; diff --git a/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk b/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk index 36e8e4c8eb2..cd1e3391a55 100644 --- a/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/misc/sky-fs.chunk @@ -28,6 +28,6 @@ void main() { CC_TRANSFER_FOG_BASE(vec4(FSInput_worldPos, 1.0), fogFactor); CC_APPLY_FOG_BASE(color, fogFactor); #endif - + fragColorX = color; } diff --git a/editor/assets/chunks/shading-entries/main-functions/render-planar-shadow/vs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-planar-shadow/vs.chunk index 75f3708624b..6de8688e421 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-planar-shadow/vs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-planar-shadow/vs.chunk @@ -30,7 +30,7 @@ void main() SurfacesVertexModifySharedData(In); // Other Data - CCSurfacesVertexTransformUV(In); + CCSurfacesVertexTransformUV(In); CCSurfacesVertexOutput(In); diff --git a/editor/assets/chunks/shading-entries/main-functions/render-to-reflectmap/fs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-to-reflectmap/fs.chunk index ba2beb4bd2c..4e31ab6d6da 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-to-reflectmap/fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-to-reflectmap/fs.chunk @@ -2,7 +2,7 @@ layout(location = 0) out vec4 fragColorX; #if CC_PIPELINE_TYPE == CC_PIPELINE_TYPE_DEFERRED && !CC_FORCE_FORWARD_SHADING void main() { fragColorX = vec4(0.0, 1.0, 0.0, 1.0); } -#else +#else void main() { #if CC_DISABLE_STRUCTURE_IN_FRAGMENT_SHADER float NoL = dot(-cc_mainLitDir.xyz, FSInput_worldNormal.xyz); //trigger ubo binding @@ -15,14 +15,14 @@ layout(location = 0) out vec4 fragColorX; // Surface SurfacesMaterialData surfaceData; CCSurfacesFragmentGetMaterialData(surfaceData); - + // Shadow parameters vec2 shadowBias = vec2(0.0); #if CC_RECEIVE_SHADOW shadowBias = FSInput_shadowBias; #endif - - + + // Fog factor #if !CC_FORWARD_ADD float fogFactor = 1.0; @@ -34,20 +34,20 @@ layout(location = 0) out vec4 fragColorX; #endif #endif #endif - - + + // Lighting LightingResult lightingResult; CCSurfacesLighting(lightingResult, surfaceData, shadowBias); - + // Shading vec4 color = CCSurfacesShading(surfaceData, lightingResult); #endif - + #if !CC_FORWARD_ADD CC_APPLY_FOG_BASE(color, fogFactor); #endif - + // Color output (RGBE) fragColorX = packRGBE(color.rgb); } diff --git a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/fs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/fs.chunk index 74abf06c26c..044efb76765 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/fs.chunk @@ -2,4 +2,4 @@ #include #elif CC_PIPELINE_TYPE == CC_PIPELINE_TYPE_DEFERRED #include -#endif +#endif diff --git a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk index a2c0d94165c..96fe6789df5 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/pipeline/forward-fs.chunk @@ -1,5 +1,5 @@ layout(location = 0) out vec4 fragColorX; - + void main() { #if CC_DISABLE_STRUCTURE_IN_FRAGMENT_SHADER float NoL = dot(-cc_mainLitDir.xyz, FSInput_worldNormal.xyz); //trigger ubo binding @@ -12,7 +12,7 @@ void main() { // Surface SurfacesMaterialData surfaceData; CCSurfacesFragmentGetMaterialData(surfaceData); - + // Shadow parameters vec2 shadowBias = vec2(0.0); vec3 colDebugCSMLayer = vec3(1.0); @@ -43,7 +43,7 @@ void main() { #endif #endif - + // Fog factor float fogFactor = 1.0; #if !CC_FORWARD_ADD @@ -96,7 +96,7 @@ void main() { // Use material alpha debugColor.a = materialTransparency; - // lighting needs color space conversion + // lighting needs color space conversion #if !CC_USE_FLOAT_OUTPUT debugColor.rgb = HDRToLDR(debugColor.rgb); debugColor.rgb = LinearToSRGB(debugColor.rgb); diff --git a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/vs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/vs.chunk index 1f784d59585..3f09f3b939e 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-to-scene/vs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-to-scene/vs.chunk @@ -29,7 +29,7 @@ void main() SurfacesVertexModifySharedData(In); // Other Data - CCSurfacesVertexTransformUV(In); + CCSurfacesVertexTransformUV(In); CCSurfacesVertexTransferFog(In); CCSurfacesVertexTransferLightMapUV(In); diff --git a/editor/assets/chunks/shading-entries/main-functions/render-to-shadowmap/vs.chunk b/editor/assets/chunks/shading-entries/main-functions/render-to-shadowmap/vs.chunk index cecd57a617e..9af5e4626bc 100644 --- a/editor/assets/chunks/shading-entries/main-functions/render-to-shadowmap/vs.chunk +++ b/editor/assets/chunks/shading-entries/main-functions/render-to-shadowmap/vs.chunk @@ -26,7 +26,7 @@ void main() SurfacesVertexModifySharedData(In); // Other Data - CCSurfacesVertexTransformUV(In); + CCSurfacesVertexTransformUV(In); CCSurfacesVertexOutput(In); diff --git a/editor/assets/chunks/surfaces/data-structures/standard.chunk b/editor/assets/chunks/surfaces/data-structures/standard.chunk index 35ad979848b..d7148f6d3e4 100644 --- a/editor/assets/chunks/surfaces/data-structures/standard.chunk +++ b/editor/assets/chunks/surfaces/data-structures/standard.chunk @@ -14,7 +14,7 @@ struct SurfacesMaterialData // for advanced PBR vec3 worldTangent, worldBinormal; float ior; - + #if CC_SURFACES_LIGHTING_ANISOTROPIC float anisotropyShape; #endif @@ -22,7 +22,7 @@ struct SurfacesMaterialData #if CC_SURFACES_LIGHTING_TRANSMIT_SPECULAR || CC_SURFACES_LIGHTING_TRANSMIT_DIFFUSE vec3 outScatteringColor, inScatteringColor; vec4 transmitScatteringParams; -#endif +#endif #if CC_SURFACES_LIGHTING_TRANSMIT_DIFFUSE vec4 transmitDiffuseParams; #endif diff --git a/editor/assets/chunks/surfaces/data-structures/toon.chunk b/editor/assets/chunks/surfaces/data-structures/toon.chunk index 0fe329c8354..249cbdc1fa7 100644 --- a/editor/assets/chunks/surfaces/data-structures/toon.chunk +++ b/editor/assets/chunks/surfaces/data-structures/toon.chunk @@ -1,7 +1,7 @@ struct SurfacesMaterialData { HIGHP_VALUE_STRUCT_DEFINE(vec3, worldPos); - + vec4 baseColor; vec4 specular; vec3 worldNormal; diff --git a/editor/assets/chunks/surfaces/module-functions/common-vs.chunk b/editor/assets/chunks/surfaces/module-functions/common-vs.chunk index 4e2de4c6c28..a6a68d053af 100644 --- a/editor/assets/chunks/surfaces/module-functions/common-vs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/common-vs.chunk @@ -146,7 +146,7 @@ void CCSurfacesVertexTransferShadow(inout SurfacesStandardVertexIntermediate In) In.shadowBiasAndProbeId.xy += cc_localShadowBias.xy; #endif #endif - + #if CC_USE_REFLECTION_PROBE #if USE_INSTANCING In.shadowBiasAndProbeId.zw = a_localShadowBiasAndProbeId.zw; diff --git a/editor/assets/chunks/surfaces/module-functions/debug-view.chunk b/editor/assets/chunks/surfaces/module-functions/debug-view.chunk index 5f380b79db6..49845f038aa 100644 --- a/editor/assets/chunks/surfaces/module-functions/debug-view.chunk +++ b/editor/assets/chunks/surfaces/module-functions/debug-view.chunk @@ -11,7 +11,7 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) { float index = mod(cc_time.x * 10.0, 2.0); vec4 error = index < 1.0 ? vec4(1.0, 0.0, 0.2, 1.0) : vec4(0.0, 1.0, 0.2, 1.0); - + return (isnans(data) || isinfs(data)) ? error : color; } @@ -21,7 +21,7 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) { vec4 white = vec4(1.0, 1.0, 1.0, 1.0); vec4 black = vec4(0.0, 0.0, 0.0, 1.0); - + // vertex input if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_VERTEX_COLOR)) { @@ -31,10 +31,10 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) color = white; #endif } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_VERTEX_NORMAL)) - color = vec4(FSInput_worldNormal * 0.5 + vec3(0.5), 1.0); - + color = vec4(FSInput_worldNormal * 0.5 + vec3(0.5), 1.0); + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_VERTEX_TANGENT)) { #if CC_SURFACES_USE_TANGENT_SPACE @@ -43,7 +43,7 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) color = black; #endif } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_VERTEX_MIRROR)) { #if CC_SURFACES_USE_TANGENT_SPACE @@ -53,19 +53,19 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) color = black; #endif } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_FACE_SIDE)) { float scalar = clamp(FSInput_faceSideSign, 0.0, 1.0); color = vec4(scalar, scalar, scalar, 1.0); } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_UV0)) color = vec4(FSInput_texcoord.xy, 0.0, 1.0); - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_UV1)) color = vec4(FSInput_texcoord1.xy, 0.0, 1.0); - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_UVLIGHTMAP)) { #if CC_USE_LIGHTMAP && !CC_FORWARD_ADD @@ -74,21 +74,21 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) color = vec4(0.0, 0.0, 0.0, 1.0); #endif } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_PROJ_DEPTH)) { vec4 clipPos = cc_matProj * cc_matView * vec4(FSInput_worldPos.xyz, 1.0); float depth = clipPos.z / clipPos.w; color = vec4(depth, depth, depth, 1.0); } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_LINEAR_DEPTH)) { vec4 viewPos = cc_matView * vec4(FSInput_worldPos.xyz, 1.0); float depth = (-viewPos.z - cc_nearFar.x) / cc_nearFar.y; color = vec4(depth, depth, depth, 1.0); } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_WORLD_POS)) color = vec4(FSInput_worldPos.xyz, 1.0); } @@ -107,55 +107,55 @@ vec4 CCSurfacesDebugDisplayInvalidInputData(vec4 color, vec3 data) color.rgb = lightingResult.directDiffuse * lightingResult.diffuseColorWithLighting; isSRGBColor = true; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_DIRECT_SPECULAR)) { color.rgb = lightingResult.directSpecular * lightingResult.specularColorWithLighting * lightingResult.directGF; isSRGBColor = true; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_DIRECT_ALL)) { color.rgb = lightingResult.directDiffuse * lightingResult.diffuseColorWithLighting + lightingResult.directSpecular * lightingResult.specularColorWithLighting * lightingResult.directGF; isSRGBColor = true; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_ENV_DIFFUSE)) { color.rgb = lightingResult.environmentDiffuse * lightingResult.diffuseColorWithLighting; isSRGBColor = true; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_ENV_SPECULAR)) { color.rgb = lightingResult.environmentSpecular * lightingResult.specularColorWithLighting * lightingResult.environmentGF; isSRGBColor = true; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_ENV_ALL)) { color.rgb = lightingResult.environmentDiffuse * lightingResult.diffuseColorWithLighting + lightingResult.environmentSpecular * lightingResult.specularColorWithLighting * lightingResult.environmentGF; isSRGBColor = true; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_LIGHT_MAP)) { color.rgb = lightingResult.lightmapColor; isSRGBColor = true; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_EMISSIVE)) { color.rgb = lightingResult.emissive; isSRGBColor = true; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_AO)) { color.rgb = vec3(lightingResult.ao); isSRGBColor = false; } - + if (IS_DEBUG_VIEW_SINGLE_MODE(CC_SURFACES_DEBUG_VIEW_SHADOW)) { color.rgb = vec3(lightingResult.shadow); diff --git a/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk b/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk index 6d139729e86..86db9d4f507 100644 --- a/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk @@ -9,7 +9,7 @@ void CCSurfacesFragmentGetMaterialData(inout SurfacesMaterialData surfaceData) surfaceData.worldNormal = SurfacesFragmentModifyWorldNormal(); SurfacesFragmentModifyWorldTangentAndBinormal(surfaceData.worldTangent, surfaceData.worldBinormal, surfaceData.worldNormal); - + surfaceData.ior = SurfacesFragmentModifyIOR(); #if CC_SURFACES_LIGHTING_ANISOTROPIC @@ -348,7 +348,7 @@ vec4 CCSurfacesShading(in SurfacesMaterialData surfaceData, in LightingResult li + lightingResult.directTransmitDiffuse #endif ; - + #else vec3 fresnel = lightingResult.fresnel; vec3 invFresnel = vec3(1.0) - fresnel; @@ -403,7 +403,7 @@ vec4 CCSurfacesShading(in SurfacesMaterialData surfaceData, in LightingResult li + lightingResult.environmentTransmitDiffuse #endif ; - + color.xyz += lightingResult.emissive; #endif diff --git a/editor/assets/chunks/surfaces/module-functions/toon-fs.chunk b/editor/assets/chunks/surfaces/module-functions/toon-fs.chunk index f2019bc22e3..816c5f457f1 100644 --- a/editor/assets/chunks/surfaces/module-functions/toon-fs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/toon-fs.chunk @@ -127,7 +127,7 @@ vec4 CCSurfacesShading(in SurfacesMaterialData surfaceData, in LightingResult li color.xyz += lightingResult.directSpecular * lightingResult.specularColorWithLighting; #else float lightmapCoef = 0.0; - + #if CC_SURFACES_USE_LEGACY_COMPATIBLE_LIGHTING color.xyz += ( mix(lightingResult.directDiffuse, lightingResult.lightmapColor, lightmapCoef) * lightingResult.diffuseColorWithLighting @@ -150,7 +150,7 @@ vec4 CCSurfacesShading(in SurfacesMaterialData surfaceData, in LightingResult li color.xyz += lightingResult.emissive; #endif - + return color; } diff --git a/editor/assets/chunks/surfaces/module-functions/unlit-fs.chunk b/editor/assets/chunks/surfaces/module-functions/unlit-fs.chunk index ed8a5ce578c..c120d38d047 100644 --- a/editor/assets/chunks/surfaces/module-functions/unlit-fs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/unlit-fs.chunk @@ -4,7 +4,7 @@ void CCSurfacesFragmentGetMaterialData(inout SurfacesMaterialData surfaceData) { HIGHP_VALUE_TO_STRUCT_DEFINED(FSInput_worldPos, surfaceData.worldPos); - + surfaceData.baseColor = SurfacesFragmentModifyBaseColorAndTransparency(); SurfacesFragmentModifySharedData(surfaceData); diff --git a/editor/assets/effects/advanced/car-paint.effect b/editor/assets/effects/advanced/car-paint.effect index 6d7b0a97083..e79dfc5047a 100644 --- a/editor/assets/effects/advanced/car-paint.effect +++ b/editor/assets/effects/advanced/car-paint.effect @@ -283,7 +283,7 @@ CCProgram surface-fragment %{ vec4 flakeA = vec4(0.972,0.96,0.915,1); vec4 flakeB = vec4(1.0,0.78,0.344,1); vec4 flakeColor = lerp(flakeA, flakeB, data.r); - + vec4 color = surfaceData.baseColor; color = lerp(color, flakeColor, flakeWeight); color = lerp(surfaceData.baseColor, color, surfaceData.metallic); diff --git a/editor/assets/effects/advanced/common-functions.chunk b/editor/assets/effects/advanced/common-functions.chunk index ac99d9d875d..4c5d71e8ede 100644 --- a/editor/assets/effects/advanced/common-functions.chunk +++ b/editor/assets/effects/advanced/common-functions.chunk @@ -6,7 +6,7 @@ vec4 SurfacesFragmentModifyBaseColorAndTransparency() { vec4 baseColor = albedo; - + #if USE_VERTEX_COLOR baseColor.rgb *= SRGBToLinear(FSInput_vertexColor.rgb); // use linear baseColor.a *= FSInput_vertexColor.a; @@ -39,7 +39,7 @@ #if USE_ALBEDO_MAP alpha = texture(albedoMap, ALBEDO_UV).ALPHA_TEST_CHANNEL; #endif - + if (alpha < albedoScaleAndCutoff.w) discard; #endif } diff --git a/editor/assets/effects/advanced/eye.chunk b/editor/assets/effects/advanced/eye.chunk index 41f5056a345..aba20e3c03c 100644 --- a/editor/assets/effects/advanced/eye.chunk +++ b/editor/assets/effects/advanced/eye.chunk @@ -11,7 +11,7 @@ vec3 lerp_3Color(vec3 A, vec3 B, vec3 C, float alpha) vec3 GetIrisUVMask(float IrisUVRadius) { const float IrisBorderWidth = 0.04, IrisBleedWidth = 0.035, IrisMaskWidth = 0.045; - + vec3 arg3_LimbusUVWidth = vec3(IrisBorderWidth, IrisBleedWidth, IrisMaskWidth); float arg8_IrisUVRadius = IrisUVRadius * 0.03 + 0.15; // vec3 out_IrisUVMask = Custom1(IrisUVRadius,UV,LimbusUVWidth) @@ -30,7 +30,7 @@ vec2 GetIrisUV(vec2 refractedUV, float IrisUVRadius, float PupilScale) { // code between Refract->Parallax, for control pupil size const float PupilShiftX = 0.0, PupilShiftY = 0.0, ScaleIrisWithinMask = 1.0; - + float uvRadius = (IrisUVRadius*0.03+0.15) * 2.0; vec2 UV1 = refractedUV - vec2(0.5); vec2 UV =(UV1 / uvRadius) + vec2(0.5); @@ -91,7 +91,7 @@ vec3 GetGeneratedColorForIris(vec2 irisUV, sampler2D irisColorMap, float IrisCol vec3 a = lerp(desat_col2, desat_col1, alphaRB.y); vec3 lerpedColor = lerp(a, b, RadialStructuralBlendSwitch) * M_Tex.a; vec3 base = lerpedColor * lerp(1.0, M_Tex.g, AOinIris); - + float radius = distance(irisUV - vec2(0.5), vec2(0.0)); float alpha = smoothstep(0.275, 0.5, radius); return lerp(base, pow(base, vec3(LimbusDarkAmount + 1.0)), alpha); @@ -118,7 +118,7 @@ vec3 GetBlendColorForIrisAndSclera(vec3 irisUVMask, vec3 irisGeneratedColor, sam vec3 irisColor = Desaturation(irisGeneratedColor * IrisBrightness, (IrisSaturation - 0.5) * -2.0); vec3 lerpedScleraAndIris = lerp(ScleraColor, irisColor, irisUVMask.r); vec3 cloudyPupilAddColor = SphereMask(FSInput_texcoord, vec2(0.5), CloudyIrisRadius, CloudyIrisHardness) * CloudyIrisColor.rgb; - + float scleraCornerDarkMask = SphereMask(FSInput_texcoord, vec2(0.5), ScleraCornerDarkRadius, ScleraCornerDarkHardness); vec3 ScleraCorner = lerp(ScleraCornerDarkColor.rgb, vec3(1.0), scleraCornerDarkMask); vec3 BaseColor = ScleraCorner * (cloudyPupilAddColor + lerpedScleraAndIris); diff --git a/editor/assets/effects/advanced/glass.effect b/editor/assets/effects/advanced/glass.effect index b1d7fce571a..5194b4fb3b4 100644 --- a/editor/assets/effects/advanced/glass.effect +++ b/editor/assets/effects/advanced/glass.effect @@ -275,7 +275,7 @@ CCProgram surface-fragment %{ if (bright > threshold) result.environmentSpecular = result.environmentSpecular / bright * threshold; #endif - } + } }% CCProgram standard-vs %{ diff --git a/editor/assets/effects/advanced/hair.effect b/editor/assets/effects/advanced/hair.effect index 9c500f38a29..09ea5683a58 100644 --- a/editor/assets/effects/advanced/hair.effect +++ b/editor/assets/effects/advanced/hair.effect @@ -202,7 +202,7 @@ CCProgram macro-remapping %{ #define CC_SURFACES_USE_TWO_SIDED USE_TWOSIDE #define CC_SURFACES_LIGHTING_ANISOTROPIC IS_ANISOTROPY #define CC_SURFACES_USE_VERTEX_COLOR USE_VERTEX_COLOR - + #define CC_SURFACES_LIGHTING_TRANSMIT_DIFFUSE USE_BACK_LIT #define CC_SURFACES_LIGHTING_TRT 1 #define CC_SURFACES_LIGHTING_TT 1 @@ -320,7 +320,7 @@ CCProgram surface-fragment %{ { return vec3(0.0); } - + #define CC_SURFACES_FRAGMENT_MODIFY_TRANSMIT_OUT_SCATTERING_COLOR vec3 SurfacesFragmentModifyTransmitOutScatteringColor() { @@ -331,7 +331,7 @@ CCProgram surface-fragment %{ vec4 SurfacesFragmentModifyBaseColorAndTransparency() { vec4 baseColor = albedo; - + #if USE_VERTEX_COLOR baseColor.rgb *= SRGBToLinear(FSInput_vertexColor.rgb); // use linear baseColor.a *= FSInput_vertexColor.a; @@ -400,7 +400,7 @@ CCProgram surface-fragment %{ isRotation = 1.0; return vec4(anisotropyShape, anisotropyRotation, 0.0, 0.0); } - + #include // definition of SurfacesMaterialData structure with corresponding shading-model diff --git a/editor/assets/effects/internal/builtin-wireframe.effect b/editor/assets/effects/internal/builtin-wireframe.effect index e7a03d9f751..841c062c6ca 100644 --- a/editor/assets/effects/internal/builtin-wireframe.effect +++ b/editor/assets/effects/internal/builtin-wireframe.effect @@ -20,7 +20,7 @@ CCProgram wireframe-vs %{ vec4 lineColor; }; - + out vec2 bary; out vec4 lineCol; @@ -40,7 +40,7 @@ CCProgram wireframe-vs %{ CCProgram wireframe-fs %{ precision mediump float; #include - + in vec2 bary; in vec4 lineCol; diff --git a/editor/assets/effects/internal/editor/box-height-light.effect b/editor/assets/effects/internal/editor/box-height-light.effect index ba347e6f85b..9944578db9e 100644 --- a/editor/assets/effects/internal/editor/box-height-light.effect +++ b/editor/assets/effects/internal/editor/box-height-light.effect @@ -54,13 +54,13 @@ CCProgram line-fs %{ uniform Constant { vec4 mainColor; vec4 selectedColor; - vec4 selectedFaceForward; + vec4 selectedFaceForward; }; vec4 front() { vec4 outputColor = mainColor; - // dot + // dot vec3 d = normal.xyz * selectedFaceForward.xyz; float m = max(max(d.x, d.y), d.z); float selected = step(0.9999,m); diff --git a/editor/assets/effects/internal/editor/light-probe-visualization.effect b/editor/assets/effects/internal/editor/light-probe-visualization.effect index ecb84d1e566..510e0b897bf 100644 --- a/editor/assets/effects/internal/editor/light-probe-visualization.effect +++ b/editor/assets/effects/internal/editor/light-probe-visualization.effect @@ -89,7 +89,7 @@ CCProgram gizmo-fs %{ #if CC_USE_LIGHT_PROBE #include #endif - + vec4 gizmo_fs (float alpha) { #if CC_USE_LIGHT_PROBE vec3 N = normalize(normal_w) * (float(gl_FrontFacing) * 2.0 - 1.0); diff --git a/editor/assets/effects/pipeline/cluster-build.effect b/editor/assets/effects/pipeline/cluster-build.effect index fd4f229455f..40918844c27 100644 --- a/editor/assets/effects/pipeline/cluster-build.effect +++ b/editor/assets/effects/pipeline/cluster-build.effect @@ -36,8 +36,8 @@ CCProgram cluster-main %{ 2.0 * (coord.y - cc_viewPort.y) / cc_viewPort.w - 1.0, 2.0 * coord.z - 1.0); - CC_HANDLE_SAMPLE_NDC_FLIP_STATIC(ndc.y); - + CC_HANDLE_SAMPLE_NDC_FLIP_STATIC(ndc.y); + vec4 eye = ((cc_matProjInv) * (vec4(ndc, 1.0))); eye = eye / eye.w; return eye; diff --git a/editor/assets/effects/pipeline/deferred-lighting.effect b/editor/assets/effects/pipeline/deferred-lighting.effect index bd8ace3b455..7e7da0e4f09 100644 --- a/editor/assets/effects/pipeline/deferred-lighting.effect +++ b/editor/assets/effects/pipeline/deferred-lighting.effect @@ -62,7 +62,7 @@ CCProgram lighting-fs-tiled %{ 2.0 * coord.z - 1.0); #endif - + CC_HANDLE_SAMPLE_NDC_FLIP_STATIC(ndc.y); return GetWorldPosFromNDCPosRH(ndc, cc_matProj, cc_matViewProjInv); } diff --git a/editor/assets/effects/pipeline/post-process/blit-screen.effect b/editor/assets/effects/pipeline/post-process/blit-screen.effect index f7d2c36a554..dd8073e738f 100644 --- a/editor/assets/effects/pipeline/post-process/blit-screen.effect +++ b/editor/assets/effects/pipeline/post-process/blit-screen.effect @@ -23,7 +23,7 @@ CCEffect %{ CCProgram vs %{ #include <./chunks/vs> -}% +}% CCProgram fs %{ @@ -32,7 +32,7 @@ CCProgram fs %{ // #include in vec2 v_uv; - + uniform UBO { vec4 inputViewPort; }; @@ -44,6 +44,6 @@ CCProgram fs %{ void main () { fragColor = texture(inputTexture, v_uv); } - + }% - + diff --git a/editor/assets/effects/pipeline/post-process/chunks/fsr.chunk b/editor/assets/effects/pipeline/post-process/chunks/fsr.chunk index 72cd4d0ae30..c630fb10c18 100644 --- a/editor/assets/effects/pipeline/post-process/chunks/fsr.chunk +++ b/editor/assets/effects/pipeline/post-process/chunks/fsr.chunk @@ -146,7 +146,7 @@ void FsrEasuF( // a b // r g vec2 p0 = fp * con1.xy + con1.zw; - + // These are from p0 to avoid pulling two constants on pre-Navi hardware. vec2 p1 = p0 + con2.xy; vec2 p2 = p0 + con2.zw; @@ -168,7 +168,7 @@ void FsrEasuF( vec3 gC = FsrEasuCF(p2 + off.xz); float gL = gC.g + 0.5 *(gC.r + gC.b); vec3 oC = FsrEasuCF(p3 + off.yz); float oL = oC.g + 0.5 *(oC.r + oC.b); vec3 nC = FsrEasuCF(p3 + off.xz); float nL = nC.g + 0.5 *(nC.r + nC.b); - + //------------------------------------------------------------------------------------------------------------------------------ // Simplest multi-channel approximate luma possible (luma times 2, in 2 FMA/MAD). // Accumulate for bilinear interpolation. @@ -258,7 +258,7 @@ vec3 FsrRcasF( { // Constant generated by RcasSetup(). // Algorithm uses minimal 3x3 pixel neighborhood. - // b + // b // d e f // h vec2 sp = vec2(ip); diff --git a/editor/assets/effects/pipeline/post-process/chunks/hbao.chunk b/editor/assets/effects/pipeline/post-process/chunks/hbao.chunk index ebfa1fcd336..001d85b8011 100644 --- a/editor/assets/effects/pipeline/post-process/chunks/hbao.chunk +++ b/editor/assets/effects/pipeline/post-process/chunks/hbao.chunk @@ -209,13 +209,13 @@ float HorizonOcclusion(vec2 deltaUV, vec3 S = FetchEyePos(uv); float tanS = Tangent(P, S); float d2 = Length2(S - P); - + if ((d2 < g_R2) && (tanS > tanH)) { // Accumulate AO between the horizon and the sample float sinS = tanS / sqrt(1.0 + tanS*tanS); ao += Falloff(d2) * (sinS - sinH); - + // Update the current horizon angle tanH = tanS; sinH = sinS; @@ -261,8 +261,8 @@ float CalculateAO(vec2 uv) // Multiply by 0.5 to scale from [-1,1]^2 to [0,1]^2 vec2 ray_radius_uv = 0.5 * g_R * g_FocalLen / P.z; float ray_radius_pix = ray_radius_uv.x * g_AOResolution.x; - - if (ray_radius_pix < 1.0) + + if (ray_radius_pix < 1.0) { return 1.0; } diff --git a/editor/assets/effects/pipeline/post-process/chunks/vs.chunk b/editor/assets/effects/pipeline/post-process/chunks/vs.chunk index 396287289a6..19c5544f305 100644 --- a/editor/assets/effects/pipeline/post-process/chunks/vs.chunk +++ b/editor/assets/effects/pipeline/post-process/chunks/vs.chunk @@ -1,6 +1,6 @@ precision highp float; - + #include #include #include diff --git a/editor/assets/effects/pipeline/post-process/color-grading.effect b/editor/assets/effects/pipeline/post-process/color-grading.effect index d7d631b7cd0..38195b66a06 100644 --- a/editor/assets/effects/pipeline/post-process/color-grading.effect +++ b/editor/assets/effects/pipeline/post-process/color-grading.effect @@ -82,9 +82,9 @@ CCProgram color-grading-8x8-fs %{ vec2 row = floor(mulB / 8.0 + EPS); vec4 row_col = vec4(row, mulB - row * 8.0); vec4 lookup = orgColor.ggrr * (63.0 / SIZE) + row_col * (TOTAL / SIZE) + (0.5 / SIZE); - + float b1w = bValue - mulB.x; - + vec3 sampled1 = texture(colorGradingMap, lookup.zx).rgb; vec3 sampled2 = texture(colorGradingMap, lookup.wy).rgb; diff --git a/editor/assets/effects/pipeline/post-process/fsr.effect b/editor/assets/effects/pipeline/post-process/fsr.effect index d7afb9fcc6a..5a088ede8c5 100644 --- a/editor/assets/effects/pipeline/post-process/fsr.effect +++ b/editor/assets/effects/pipeline/post-process/fsr.effect @@ -72,18 +72,18 @@ CCProgram fs-easu %{ void main () { vec3 c; vec4 con0, con1, con2, con3; - + // "rendersize" refers to size of source image before upscaling. vec2 rendersize = texSize.xy; FsrEasuCon( - con0, con1, con2, con3, + con0, con1, con2, con3, rendersize, rendersize, texSize.zw ); FsrEasuF(c, gl_FragCoord.xy, con0, con1, con2, con3); float alpha = texture(outputResultMap, v_uv).a; fragColor = vec4(c.xyz, alpha); } - + }% diff --git a/editor/assets/effects/pipeline/post-process/fxaa-hq.effect b/editor/assets/effects/pipeline/post-process/fxaa-hq.effect index 1312f6e0508..720e0506b0f 100644 --- a/editor/assets/effects/pipeline/post-process/fxaa-hq.effect +++ b/editor/assets/effects/pipeline/post-process/fxaa-hq.effect @@ -36,7 +36,7 @@ CCProgram fxaa-edge-fs %{ vec4 frag () { vec3 color = FxaaPixelShader(v_uv, sceneColorMap, texSize.zw); float alpha = texture(sceneColorMap, v_uv).a; - return vec4(color, alpha); + return vec4(color, alpha); } }% diff --git a/editor/assets/effects/pipeline/post-process/hbao.effect b/editor/assets/effects/pipeline/post-process/hbao.effect index adff7297dd3..e82faf6a450 100644 --- a/editor/assets/effects/pipeline/post-process/hbao.effect +++ b/editor/assets/effects/pipeline/post-process/hbao.effect @@ -58,7 +58,7 @@ CCProgram hbao-fs %{ void main () { float ao = CalculateAO(v_uv); - fragColor = vec4(ao, ao, ao, 1.0); + fragColor = vec4(ao, ao, ao, 1.0); } }% @@ -73,7 +73,7 @@ CCProgram blurx-fs %{ void main () { float ao = BlurCore(v_uv, vec2(1.0, 0.0)); - fragColor = vec4(ao, ao, ao, 1.0); + fragColor = vec4(ao, ao, ao, 1.0); } }% @@ -88,7 +88,7 @@ CCProgram blury-fs %{ void main () { float ao = BlurCore(v_uv, vec2(0.0, 1.0)); - fragColor = vec4(ao, ao, ao, 1.0); + fragColor = vec4(ao, ao, ao, 1.0); } }% @@ -103,6 +103,6 @@ CCProgram combine-fs %{ void main () { float ao = Combine(v_uv); - fragColor = vec4(1.0, 1.0, 1.0, ao); + fragColor = vec4(1.0, 1.0, 1.0, ao); } }% diff --git a/editor/assets/effects/pipeline/post-process/taa.effect b/editor/assets/effects/pipeline/post-process/taa.effect index b7ae1196e92..a9f9e49ec02 100644 --- a/editor/assets/effects/pipeline/post-process/taa.effect +++ b/editor/assets/effects/pipeline/post-process/taa.effect @@ -33,7 +33,7 @@ CCEffect %{ CCProgram vs %{ #include <./chunks/vs> -}% +}% CCProgram fs %{ @@ -52,7 +52,7 @@ CCProgram fs %{ vec4 taaParams1; // xy: offset, z: feedback mat4 taaPrevViewProj; }; - + #pragma rate motionMaskTex uniform highp sampler2D motionMaskTex; @@ -73,14 +73,14 @@ CCProgram fs %{ vec2 taaInputTexSize(); vec2 taaPrevTexSize(); - + vec3 Reinhard(in vec3 hdr) { return hdr / (hdr + 1.0); } vec3 ReinhardInverse(in vec3 sdr) { return sdr / max(1.0 - sdr, 1e-5); } - + // metal NDC y up while texture coord y down, // keep ndc and texture coord same y direction. vec2 NDCScToUV(vec4 ndc) { @@ -92,26 +92,26 @@ CCProgram fs %{ } return uv; } - + vec2 getVelocity(vec2 unjittedUV, vec2 uv, out float depth) { // vec3 worldPos = texture(posTex, uv).xyz; - - // use unjitted depth for unjitter matrix + + // use unjitted depth for unjitter matrix depth = texture(depthTex, unjittedUV).r; vec3 worldPos = screen2WS(vec3(uv, depth)); if (abs(worldPos.x) < 0.0001 && abs(worldPos.y) < 0.0001) { return vec2(0.); } - + vec4 historyNDC = taaPrevViewProj * vec4(worldPos, 1.); - + vec2 screenPos = NDCScToUV(historyNDC); return screenPos - uv; } - - + + vec4 clip_aabb(vec3 aabb_min, vec3 aabb_max, vec4 avg, vec4 input_texel) { vec3 p_clip = 0.5 * (aabb_max + aabb_min); vec3 e_clip = 0.5 * (aabb_max - aabb_min) + 5.960464478e-8; @@ -119,64 +119,64 @@ CCProgram fs %{ vec3 v_unit = v_clip.xyz / e_clip; vec3 a_unit = abs(v_unit); float ma_unit = max(a_unit.x, max(a_unit.y, a_unit.z)); - + if (ma_unit > 1.0) return vec4(p_clip, avg.w) + v_clip / ma_unit; else return input_texel; } - + vec3 RGBToYCoCg( vec3 RGB ) { float Y = dot( RGB, vec3( 1, 2, 1 ) ); float Co = dot( RGB, vec3( 2, 0, -2 ) ); float Cg = dot( RGB, vec3( -1, 2, -1 ) ); - + return vec3( Y, Co, Cg ); } - + vec3 YCoCgToRGB( vec3 YCoCg ) { float Y = YCoCg.x * 0.25; float Co = YCoCg.y * 0.25; float Cg = YCoCg.z * 0.25; - + float R = Y + Co - Cg; float G = Y + Cg; float B = Y - Co - Cg; - + return vec3( R, G, B ); } - + vec4 taaSampleTex(sampler2D tex, vec2 uv) { vec4 color = texture(tex, uv); - + color.rgb = RGBToYCoCg(color.rgb); // color.rgb = Reinhard(color.rgb); - + return color; } - + void minmax(sampler2D mainTex, in vec2 uv, out vec4 colorMin, out vec4 colorMax) { vec2 texSize = taaInputTexSize(); - + vec2 du = vec2(texSize.x, 0.0); vec2 dv = vec2(0.0, texSize.y); - + vec4 t = taaSampleTex(mainTex, uv - dv); vec4 l = taaSampleTex(mainTex, uv - du); vec4 c = taaSampleTex(mainTex, uv); vec4 r = taaSampleTex(mainTex, uv + du); vec4 b = taaSampleTex(mainTex, uv + dv); - + colorMin = min(t, min(l, min(c, min(r, b)))); colorMax = max(t, max(l, max(c, max(r, b)))); // colorAvg = (t + l + c + r + b) / 5.0; } - + float HdrWeightY(float Color, float Exposure) { return 1. / (Color * Exposure + 4.0); // return Color; } - + vec2 WeightedLerpFactors(float WeightA, float WeightB, float Blend) { float BlendA = (1.0 - Blend) * WeightA; float BlendB = Blend * WeightB; @@ -185,58 +185,58 @@ CCProgram fs %{ BlendB *= RcpBlend; return vec2(BlendA, BlendB); } - + vec4 temporalAAPS (sampler2D taaPrevTexture, sampler2D inputTexture, vec2 uv) { vec2 unjittedUV = uv - taaParams1.xy / 2.; vec2 scaledUnjittedUV = unjittedUV; // vec2 scaledUnjittedUV = (uv - taaParams1.xy / 2.) * cc_view_pr_parameters.x; // scaledUnjittedUV = min(vec2(cc_view_pr_parameters.x - taaInputTexSize()*2.), scaledUnjittedUV); - + float depth = 0.; vec2 velocity = getVelocity(scaledUnjittedUV, uv, depth); - + vec4 prevColor = taaSampleTex(taaPrevTexture, uv + velocity); - + vec4 color = taaSampleTex(inputTexture, scaledUnjittedUV); - + vec4 colorMin, colorMax; minmax(inputTexture, scaledUnjittedUV, colorMin, colorMax); - + vec3 resultColor; - + // clamp { // if (cc_view_taa_params2.y == 0. && cc_view_taa_params2.z == 1.) { prevColor.rgb = clamp(prevColor.rgb, colorMin.rgb, colorMax.rgb); // } - + float blendFinal = 1. - taaParams1.z; - + float currentWeight = HdrWeightY(color.x, 1.); float historyWeight = HdrWeightY(prevColor.x, 1.); - + vec2 weights = WeightedLerpFactors(historyWeight, currentWeight, blendFinal); resultColor = prevColor.rgb * weights.x + color.rgb * weights.y; - + // resultColor = mix(color.rgb, prevColor.rgb, blendFinal); } - + // clip // { // prevColor = clip_aabb(colorMin.xyz, colorMax.xyz, colorAvg, prevColor); // resultColor = lerp(color.rgb, prevColor.rgb, cc_view_taa_params2.y); // } - + // if (cc_view_taa_params2.y != 0.) { // resultColor = prevColor.rgb; // } - + // resultColor = ReinhardInverse(resultColor); resultColor = YCoCgToRGB(resultColor.rgb); - + return vec4(resultColor, color.a); } - + layout(location = 0) out vec4 fragColor; @@ -253,7 +253,7 @@ CCProgram fs %{ #if USE_TAA_MASK mask = texture(motionMaskTex, v_uv); #endif - + if (mask.r > 0.) { fragColor = texture(inputTexture, v_uv); } @@ -261,6 +261,6 @@ CCProgram fs %{ fragColor = temporalAAPS(taaPrevTexture, inputTexture, v_uv); } } - + }% - + diff --git a/editor/assets/effects/pipeline/ssss-blur.effect b/editor/assets/effects/pipeline/ssss-blur.effect index 4d57aaf8951..8c571a4c25c 100644 --- a/editor/assets/effects/pipeline/ssss-blur.effect +++ b/editor/assets/effects/pipeline/ssss-blur.effect @@ -78,7 +78,7 @@ CCProgram ssssBlur %{ } - /** + /** * @param texcoord The usual quad texture coordinates. * @param dir Direction of the blur: * - First pass: float2(1.0, 0.0) diff --git a/editor/assets/effects/util/splash-screen.effect b/editor/assets/effects/util/splash-screen.effect index 4dfb03b129a..5bb9064451a 100644 --- a/editor/assets/effects/util/splash-screen.effect +++ b/editor/assets/effects/util/splash-screen.effect @@ -26,7 +26,7 @@ CCEffect %{ CCProgram splash-screen-vs %{ precision mediump float; - + #pragma define u_resolution u_buffer0.xy #pragma define u_worldScale u_buffer1.xy #pragma define u_worldTranslate u_buffer1.zw @@ -40,7 +40,7 @@ CCProgram splash-screen-vs %{ mat4 u_projection; }; - vec4 vert () { + vec4 vert () { vec2 worldPos = a_position * u_worldScale + u_worldTranslate; vec2 clipSpace = worldPos / u_resolution * 2.0 - 1.0; vec4 screenPos = u_projection * vec4(clipSpace, 0.0, 1.0); From a51263c66d336fd266d1e0e02ea6acd18faccc63 Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Thu, 17 Aug 2023 19:48:06 +0800 Subject: [PATCH 132/184] fix ScrollView state bug when scrolling with mouse (#15709) * fix ScrollView state bug when scrolling with mouse * fix scroll bar state bug * fix CI * as string --- cocos/ui/scroll-view.ts | 47 +++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/cocos/ui/scroll-view.ts b/cocos/ui/scroll-view.ts index 6087f46b427..7f568589dba 100644 --- a/cocos/ui/scroll-view.ts +++ b/cocos/ui/scroll-view.ts @@ -29,7 +29,7 @@ import { EventHandler as ComponentEventHandler } from '../scene-graph/component- import { UITransform } from '../2d/framework'; import { Event, EventMouse, EventTouch, Touch, SystemEventType, EventHandle, EventGamepad } from '../input/types'; import { errorID, logID } from '../core/platform/debug'; -import { Size, Vec2, Vec3 } from '../core/math'; +import { Size, Vec2, Vec3, approx } from '../core/math'; import { Layout } from './layout'; import { ScrollBar } from './scroll-bar'; import { ViewGroup } from './view-group'; @@ -1067,7 +1067,7 @@ export class ScrollView extends ViewGroup { if (!this._stopMouseWheel) { this._handlePressLogic(); - this.schedule(this._checkMouseWheel, 1.0 / 60, NaN, 0); + this.schedule(this._checkMouseWheel, 1.0 / 60); this._stopMouseWheel = true; } @@ -1282,8 +1282,12 @@ export class ScrollView extends ViewGroup { return a; }, totalMovement); - out.set(totalMovement.x * (1 - this.brake) / totalTime, - totalMovement.y * (1 - this.brake) / totalTime, totalMovement.z); + out.set( + totalMovement.x * (1 - this.brake) / totalTime, + totalMovement.y * (1 - this.brake) / totalTime, + + totalMovement.z, + ); } return out; } @@ -1407,12 +1411,12 @@ export class ScrollView extends ViewGroup { } protected _dispatchEvent (event: string): void { - if (event === EventType.SCROLL_ENDED) { + if (event === EventType.SCROLL_ENDED as string) { this._scrollEventEmitMask = 0; - } else if (event === EventType.SCROLL_TO_TOP - || event === EventType.SCROLL_TO_BOTTOM - || event === EventType.SCROLL_TO_LEFT - || event === EventType.SCROLL_TO_RIGHT) { + } else if (event === EventType.SCROLL_TO_TOP as string + || event === EventType.SCROLL_TO_BOTTOM as string + || event === EventType.SCROLL_TO_LEFT as string + || event === EventType.SCROLL_TO_RIGHT as string) { const flag = (1 << eventMap[event]); if (this._scrollEventEmitMask & flag) { return; @@ -1431,8 +1435,9 @@ export class ScrollView extends ViewGroup { } this._outOfBoundaryAmountDirty = true; - if (this._isOutOfBoundary()) { - const outOfBoundary = this._getHowMuchOutOfBoundary(); + const outOfBoundary = this._getHowMuchOutOfBoundary(); + const _isOutOfBoundary = !outOfBoundary.equals(Vec3.ZERO, EPSILON); + if (_isOutOfBoundary) { _tempVec3.set(this._getContentPosition()); _tempVec3.add(outOfBoundary); this._setContentPosition(_tempVec3); @@ -1457,7 +1462,7 @@ export class ScrollView extends ViewGroup { const viewTrans = this.view; const uiTrans = this._content._uiProps.uiTransformComp!; if (this._verticalScrollBar && this._verticalScrollBar.isValid) { - if (uiTrans.height < viewTrans.height) { + if (uiTrans.height < viewTrans.height || approx(uiTrans.height, viewTrans.height)) { this._verticalScrollBar.hide(); } else { this._verticalScrollBar.show(); @@ -1465,7 +1470,7 @@ export class ScrollView extends ViewGroup { } if (this._horizontalScrollBar && this._horizontalScrollBar.isValid) { - if (uiTrans.width < viewTrans.width) { + if (uiTrans.width < viewTrans.width || approx(uiTrans.width, viewTrans.width)) { this._horizontalScrollBar.hide(); } else { this._horizontalScrollBar.show(); @@ -1760,8 +1765,13 @@ export class ScrollView extends ViewGroup { if (!currentOutOfBoundary.equals(Vec3.ZERO, EPSILON)) { this._processInertiaScroll(); + if (this._scrolling) { + this._scrolling = false; + if (!this._autoScrolling) { + this._dispatchEvent(EventType.SCROLL_ENDED); + } + } this.unschedule(this._checkMouseWheel); - this._dispatchEvent(EventType.SCROLL_ENDED); this._stopMouseWheel = false; return; } @@ -1771,8 +1781,13 @@ export class ScrollView extends ViewGroup { // mouse wheel event is ended if (this._mouseWheelEventElapsedTime > maxElapsedTime) { this._onScrollBarTouchEnded(); + if (this._scrolling) { + this._scrolling = false; + if (!this._autoScrolling) { + this._dispatchEvent(EventType.SCROLL_ENDED); + } + } this.unschedule(this._checkMouseWheel); - this._dispatchEvent(EventType.SCROLL_ENDED); this._stopMouseWheel = false; } } @@ -1865,7 +1880,7 @@ export class ScrollView extends ViewGroup { } else if (event instanceof EventHandle) { handleInputDevice = event.handleInputDevice; } - let value; + let value: Vec2; if (!this.enabledInHierarchy || this._hoverIn === XrhoverType.NONE) { return; } From 1df6a1095af9ddeb89cf2e2fbf6ea6b4d3a426a5 Mon Sep 17 00:00:00 2001 From: GengineJS <476393671@qq.com> Date: Fri, 18 Aug 2023 01:23:18 +0800 Subject: [PATCH 133/184] [Restore] additive light (#16016) --- cocos/rendering/custom/executor.ts | 106 +++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 22 deletions(-) diff --git a/cocos/rendering/custom/executor.ts b/cocos/rendering/custom/executor.ts index 445a712e1ed..2ba97a70061 100644 --- a/cocos/rendering/custom/executor.ts +++ b/cocos/rendering/custom/executor.ts @@ -122,13 +122,12 @@ import { UpdateFrequency, } from './types'; import { PipelineUBO } from '../pipeline-ubo'; -import { RenderInfo, RenderObject, WebSceneTask, WebSceneTransversal } from './web-scene'; +import { WebSceneTask, WebSceneTransversal } from './web-scene'; import { WebSceneVisitor } from './web-scene-visitor'; import { RenderAdditiveLightQueue } from '../render-additive-light-queue'; import { DefaultVisitor, depthFirstSearch, ReferenceGraphView } from './graph'; import { VectorGraphColorMap } from './effect'; import { - getDescBindingFromName, getDescriptorSetDataFromLayout, getDescriptorSetDataFromLayoutId, getRenderArea, @@ -137,8 +136,6 @@ import { validPunctualLightsCulling, } from './define'; import { RenderReflectionProbeQueue } from '../render-reflection-probe-queue'; -import { builtinResMgr } from '../../asset/asset-manager/builtin-res-mgr'; -import { Texture2D } from '../../asset/assets/texture-2d'; import { SceneCulling } from './scene-culling'; class ResourceVisitor implements ResourceGraphVisitor { @@ -163,6 +160,7 @@ class ResourceVisitor implements ResourceGraphVisitor { // noop } persistentBuffer (value: Buffer): void { + // noop } persistentTexture (value: Texture): void { this.createDeviceTex(value); @@ -174,8 +172,10 @@ class ResourceVisitor implements ResourceGraphVisitor { this.createDeviceTex(value); } formatView (value: FormatView): void { + // noop } subresourceView (value: SubresourceView): void { + // noop } } @@ -1106,6 +1106,16 @@ class DevicePreSceneTask extends WebSceneTask { public start (): void { if (this.graphScene.blit) { this._currentQueue.createBlitDesc(this.graphScene.blit); + return; + } + if (!this.camera) { + return; + } + const sceneFlag = this._graphScene.scene!.flags; + if (sceneFlag & SceneFlags.DEFAULT_LIGHTING) { + this._sceneCulling(); + validPunctualLightsCulling(context.pipeline, this.camera); + context.additiveLight.gatherLightPasses(this.camera, this._cmdBuff, this._currentQueue.devicePass.layoutName); } } @@ -1147,7 +1157,9 @@ class DeviceSceneTask extends WebSceneTask { } } get graphScene (): GraphScene { return this._graphScene; } - public start (): void {} + public start (): void { + // noop + } protected _recordUI (): void { const batches = this.camera!.scene!.batches; @@ -1283,6 +1295,14 @@ class DeviceSceneTask extends WebSceneTask { } } + private _recordAdditiveLights (): void { + context.additiveLight?.recordCommandBuffer( + context.device, + this._renderPass, + context.commandBuffer, + ); + } + public submit (): void { const devicePass = this._currentQueue.devicePass; const sceneCulling = context.culling; @@ -1298,6 +1318,14 @@ class DeviceSceneTask extends WebSceneTask { const graphSceneData = this.graphScene.scene!; renderQueue.opaqueQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); renderQueue.opaqueInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); + if (graphSceneData.flags & SceneFlags.DEFAULT_LIGHTING) { + this._recordAdditiveLights(); + this.visitor.bindDescriptorSet( + SetIndex.GLOBAL, + context.pipeline.descriptorSet, + ); + } + renderQueue.transparentInstancingQueue.recordCommandBuffer(this._renderPass, context.commandBuffer); renderQueue.transparentQueue.recordCommandBuffer(deviceManager.gfxDevice, this._renderPass, context.commandBuffer); if (graphSceneData.flags & SceneFlags.GEOMETRY) { @@ -1729,13 +1757,27 @@ class PreRenderVisitor extends BaseRenderVisitor implements RenderGraphVisitor { this.currPass.resetResource(this.passID, pass); } } - rasterSubpass (value: RasterSubpass): void {} - computeSubpass (value: ComputeSubpass): void {} - compute (value: ComputePass): void {} - resolve (value: ResolvePass): void {} - copy (value: CopyPass): void {} - move (value: MovePass): void {} - raytrace (value: RaytracePass): void {} + rasterSubpass (value: RasterSubpass): void { + // noop + } + computeSubpass (value: ComputeSubpass): void { + // noop + } + compute (value: ComputePass): void { + // noop + } + resolve (value: ResolvePass): void { + // noop + } + copy (value: CopyPass): void { + // noop + } + move (value: MovePass): void { + // noop + } + raytrace (value: RaytracePass): void { + // noop + } queue (value: RenderQueue): void { if (!this.rg.getValid(this.queueID)) return; const deviceQueue = context.pools.addDeviceQueue(); @@ -1763,7 +1805,9 @@ class PreRenderVisitor extends BaseRenderVisitor implements RenderGraphVisitor { graphScene.init(null, value, -1); this.currQueue!.addSceneTask(graphScene); } - dispatch (value: Dispatch): void {} + dispatch (value: Dispatch): void { + // noop + } } class PostRenderVisitor extends BaseRenderVisitor implements RenderGraphVisitor { @@ -1786,21 +1830,39 @@ class PostRenderVisitor extends BaseRenderVisitor implements RenderGraphVisitor this.currPass.record(); this.currPass.postPass(); } - rasterSubpass (value: RasterSubpass): void {} - computeSubpass (value: ComputeSubpass): void {} - resolve (value: ResolvePass): void {} - compute (value: ComputePass): void {} - copy (value: CopyPass): void {} - move (value: MovePass): void {} - raytrace (value: RaytracePass): void {} + rasterSubpass (value: RasterSubpass): void { + // noop + } + computeSubpass (value: ComputeSubpass): void { + // noop + } + resolve (value: ResolvePass): void { + // noop + } + compute (value: ComputePass): void { + // noop + } + copy (value: CopyPass): void { + // noop + } + move (value: MovePass): void { + // noop + } + raytrace (value: RaytracePass): void { + // noop + } queue (value: RenderQueue): void { // collect scene results } scene (value: SceneData): void { // scene command list finished } - blit (value: Blit): void {} - dispatch (value: Dispatch): void {} + blit (value: Blit): void { + // noop + } + dispatch (value: Dispatch): void { + // noop + } } export class RenderVisitor extends DefaultVisitor { From 7a3a4f1dfbe97f741e3ec690a0310e9f8843a293 Mon Sep 17 00:00:00 2001 From: zxx43 Date: Fri, 18 Aug 2023 02:08:30 +0800 Subject: [PATCH 134/184] add missed spine api (#16010) * add missed spine api * readSkeletonData return point --- native/tools/swig-config/spine.i | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/native/tools/swig-config/spine.i b/native/tools/swig-config/spine.i index 4d92e47b311..9ffeb32ccbf 100644 --- a/native/tools/swig-config/spine.i +++ b/native/tools/swig-config/spine.i @@ -136,6 +136,7 @@ using namespace spine; %ignore spine::Skeleton::getBounds; %ignore spine::Bone::updateWorldTransform(float, float, float, float, float, float, float); %ignore spine::Skin::findAttachmentsForSlot; +%ignore spine::SkeletonBinary::readSkeletonData(const unsigned char*, int); // ----- Rename Section ------ // Brief: Classes, methods or attributes needs to be renamed @@ -203,6 +204,7 @@ using namespace spine; %rename(slotIndex) spine::Skin::AttachmentMap::Entry::_slotIndex; %rename(name) spine::Skin::AttachmentMap::Entry::_name; %rename(attachment) spine::Skin::AttachmentMap::Entry::_attachment; +%rename(signum) spine::MathUtil::sign(float); // ----- Module Macro Section ------ // Brief: Generated code should be wrapped inside a macro @@ -745,4 +747,14 @@ using namespace spine; spine::String attachment(attachmentName.data()); return *($self->getAttachment(slot, attachment)); } +} + +%extend spine::SkeletonBinary { + SkeletonData *readSkeletonData(const std::vector& binary) { + std::vector input; + for (int i = 0; i < binary.size(); ++i) { + input.push_back(binary[i]); + } + return $self->readSkeletonData(input.data(), input.size()); + } } \ No newline at end of file From 006bc6254ea51e1971a6b1a4f725df4a342a321e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E5=85=B5?= <49358166+xubing0906@users.noreply.github.com> Date: Fri, 18 Aug 2023 10:10:38 +0800 Subject: [PATCH 135/184] fix planar reflection error under the native custom pipeline (#16014) --- .../pipeline/reflection-probe/ReflectionProbeStage.cpp | 4 ++-- native/cocos/scene/ReflectionProbe.cpp | 2 +- native/cocos/scene/ReflectionProbe.h | 2 +- native/tools/swig-config/scene.i | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/native/cocos/renderer/pipeline/reflection-probe/ReflectionProbeStage.cpp b/native/cocos/renderer/pipeline/reflection-probe/ReflectionProbeStage.cpp index 54af9f38a54..7b08a491cc0 100644 --- a/native/cocos/renderer/pipeline/reflection-probe/ReflectionProbeStage.cpp +++ b/native/cocos/renderer/pipeline/reflection-probe/ReflectionProbeStage.cpp @@ -69,8 +69,8 @@ void ReflectionProbeStage::render(scene::Camera *camera) { _renderArea.x = 0; _renderArea.y = 0; - _renderArea.width = _probe->getRenderArea().x; - _renderArea.height = _probe->getRenderArea().y; + _renderArea.width = _probe->renderArea().x; + _renderArea.height = _probe->renderArea().y; if (hasFlag(static_cast(_probe->getCamera()->getClearFlag()), gfx::ClearFlagBit::COLOR)) { _clearColors[0] = _probe->getCamera()->getClearColor(); diff --git a/native/cocos/scene/ReflectionProbe.cpp b/native/cocos/scene/ReflectionProbe.cpp index 179029732d4..58fe46f8ef2 100644 --- a/native/cocos/scene/ReflectionProbe.cpp +++ b/native/cocos/scene/ReflectionProbe.cpp @@ -267,7 +267,7 @@ void ReflectionProbe::updateCameraDir(int32_t faceIdx) { _camera->update(true); } -Vec2 ReflectionProbe::getRenderArea() const { +Vec2 ReflectionProbe::renderArea() const { if (_probeType == ProbeType::PLANAR) { return Vec2(_realtimePlanarTexture->getWidth(), _realtimePlanarTexture->getHeight()); } diff --git a/native/cocos/scene/ReflectionProbe.h b/native/cocos/scene/ReflectionProbe.h index c7f50b57824..8a17a5e06be 100644 --- a/native/cocos/scene/ReflectionProbe.h +++ b/native/cocos/scene/ReflectionProbe.h @@ -135,7 +135,7 @@ class ReflectionProbe final { inline const ccstd::vector>& getBakedCubeTextures() const { return _bakedCubeTextures; } void resetCameraParams(); void updateCameraDir(int32_t faceIdx); - Vec2 getRenderArea() const; + Vec2 renderArea() const; void packBackgroundColor(); bool isRGBE() const; diff --git a/native/tools/swig-config/scene.i b/native/tools/swig-config/scene.i index 2a2fff63cae..f80fd18cece 100644 --- a/native/tools/swig-config/scene.i +++ b/native/tools/swig-config/scene.i @@ -603,6 +603,7 @@ using namespace cc; %attribute(cc::scene::ReflectionProbe, cc::TextureCube*, cubemap, getCubeMap, setCubeMap); %attribute(cc::scene::ReflectionProbe, cc::Node*, node, getNode); %attribute(cc::scene::ReflectionProbe, cc::RenderTexture*, realtimePlanarTexture, getRealtimePlanarTexture); +%attribute(cc::scene::ReflectionProbe, cc::scene::Camera*, camera, getCamera); %attribute(cc::SceneGlobals, bool, bakedWithStationaryMainLight, getBakedWithStationaryMainLight, setBakedWithStationaryMainLight); %attribute(cc::SceneGlobals, bool, bakedWithHighpLightmap, getBakedWithHighpLightmap, setBakedWithHighpLightmap); From 0b8b6981b687ad4850ce0b7c7075b5ad414a38d2 Mon Sep 17 00:00:00 2001 From: zxx43 Date: Fri, 18 Aug 2023 10:22:12 +0800 Subject: [PATCH 136/184] fix uimeshrender in native (#15879) * fix uimeshrender in native * fix eslint --- cocos/2d/components/ui-mesh-renderer.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cocos/2d/components/ui-mesh-renderer.ts b/cocos/2d/components/ui-mesh-renderer.ts index 1cf5f6791f7..62bc1de4628 100644 --- a/cocos/2d/components/ui-mesh-renderer.ts +++ b/cocos/2d/components/ui-mesh-renderer.ts @@ -170,8 +170,10 @@ export class UIMeshRenderer extends Component { this._UIModelNativeProxy.clearModels(); this._renderEntity.clearDynamicRenderDrawInfos(); for (let i = 0; i < models.length; i++) { - this._uploadRenderData(i); - this._UIModelNativeProxy.updateModels(models[i]); + if (models[i].enabled) { + this._uploadRenderData(i); + this._UIModelNativeProxy.updateModels(models[i]); + } } this._UIModelNativeProxy.attachDrawInfo(); } @@ -189,6 +191,7 @@ export class UIMeshRenderer extends Component { // please fix the type @holycanvas // issue: https://github.com/cocos/cocos-engine/issues/14637 this._renderData = renderData as unknown as RenderData; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this._renderData.material = this._modelComponent!.getMaterialInstance(index); } } @@ -201,6 +204,7 @@ export class UIMeshRenderer extends Component { * 它可能会组装额外的渲染数据到顶点数据缓冲区,也可能只是重置一些渲染状态。 * 注意:不要手动调用该函数,除非你理解整个流程。 */ + // eslint-disable-next-line @typescript-eslint/no-empty-function public postUpdateAssembler (render: IBatcher): void { // No behavior for this component } @@ -253,6 +257,7 @@ export class UIMeshRenderer extends Component { /** * @deprecated Since v3.7.0, this is an engine private interface that will be removed in the future. */ + // eslint-disable-next-line @typescript-eslint/no-empty-function public setNodeDirty (): void { // No behavior for this component } @@ -260,6 +265,7 @@ export class UIMeshRenderer extends Component { /** * @deprecated Since v3.7.0, this is an engine private interface that will be removed in the future. */ + // eslint-disable-next-line @typescript-eslint/no-empty-function public setTextureDirty (): void { // No behavior for this component } From cf8ceed66124a94b71b881337c209812accddc4a Mon Sep 17 00:00:00 2001 From: Ling Zhan Date: Fri, 18 Aug 2023 10:47:59 +0800 Subject: [PATCH 137/184] V3.8.1 cct trigger (#15613) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * physx ts 支持 # Conflicts: # cocos/physics/framework/components/character-controllers/character-controller.ts # cocos/physics/framework/components/colliders/collider.ts # cocos/physics/physx/physx-world.ts * add bullet-character-controller trigger events * physx c++ add cct trigger * tweaks * tweaks * tweaks * tweak * tweaks * physics jsb: emitCCTShapeEvent --> emitCCTCollisionEvent --- cocos/physics/bullet/bullet-cache.ts | 10 +- cocos/physics/bullet/bullet-world.ts | 413 ++++++++++++------ .../bullet-character-controller.ts | 4 + .../character-controller.ts | 30 +- .../components/colliders/collider.ts | 19 +- cocos/physics/framework/physics-interface.ts | 8 + .../physx-box-character-controller.ts | 6 +- .../physx-capsule-character-controller.ts | 6 +- .../physx-character-controller.ts | 7 + cocos/physics/physx/physx-world.ts | 117 ++++- cocos/physics/utils/util.ts | 9 +- exports/physics-framework.ts | 1 + .../bindings/manual/jsb_conversions_spec.cpp | 12 + .../bindings/manual/jsb_conversions_spec.h | 1 + .../cocos/physics/physx/PhysXEventManager.cpp | 98 ++++- .../cocos/physics/physx/PhysXEventManager.h | 2 + native/cocos/physics/physx/PhysXWorld.h | 3 + .../PhysXCharacterController.cpp | 13 +- .../PhysXCharacterController.h | 3 + native/cocos/physics/sdk/World.cpp | 4 + native/cocos/physics/sdk/World.h | 1 + native/cocos/physics/spec/IWorld.h | 12 + platforms/native/engine/jsb-physics.js | 87 +++- 23 files changed, 673 insertions(+), 193 deletions(-) diff --git a/cocos/physics/bullet/bullet-cache.ts b/cocos/physics/bullet/bullet-cache.ts index 3d9e0f9b3f1..fe8c0567173 100644 --- a/cocos/physics/bullet/bullet-cache.ts +++ b/cocos/physics/bullet/bullet-cache.ts @@ -22,8 +22,9 @@ THE SOFTWARE. */ -import { Collider, TriggerEventType, CollisionEventType, IContactEquation } from '../../../exports/physics-framework'; +import { Collider, TriggerEventType, CollisionEventType, IContactEquation, CharacterController } from '../../../exports/physics-framework'; import { Vec3, Quat, Mat4 } from '../../core'; +import { CharacterTriggerEventType } from '../framework'; import { bt } from './instantiated'; export const TriggerEventObject = { @@ -41,6 +42,13 @@ export const CollisionEventObject = { impl: null, }; +export const CharacterTriggerEventObject = { + type: 'onControllerTriggerEnter' as unknown as CharacterTriggerEventType, + collider: null as unknown as Collider, + characterController: null as unknown as CharacterController, + impl: null, +}; + export class BulletCache { private static _instance: BulletCache; static get instance (): BulletCache { diff --git a/cocos/physics/bullet/bullet-world.ts b/cocos/physics/bullet/bullet-world.ts index 298b1683329..431158135f4 100644 --- a/cocos/physics/bullet/bullet-world.ts +++ b/cocos/physics/bullet/bullet-world.ts @@ -28,7 +28,7 @@ import { BulletRigidBody } from './bullet-rigid-body'; import { BulletShape } from './shapes/bullet-shape'; import { ArrayCollisionMatrix } from '../utils/array-collision-matrix'; import { TupleDictionary } from '../utils/tuple-dictionary'; -import { TriggerEventObject, CollisionEventObject, CC_V3_0, CC_V3_1, CC_V3_2, BulletCache } from './bullet-cache'; +import { TriggerEventObject, CollisionEventObject, CC_V3_0, CC_V3_1, CC_V3_2, BulletCache, CharacterTriggerEventObject } from './bullet-cache'; import { bullet2CocosVec3, cocos2BulletQuat, cocos2BulletVec3 } from './bullet-utils'; import { IRaycastOptions, IPhysicsWorld } from '../spec/i-physics-world'; import { PhysicsRayResult, PhysicsMaterial, CharacterControllerContact } from '../framework'; @@ -129,7 +129,8 @@ export class BulletWorld implements IPhysicsWorld { readonly contactsDic = new TupleDictionary(); readonly oldContactsDic = new TupleDictionary(); readonly cctShapeEventDic = new TupleDictionary(); - + readonly cctContactsDic = new TupleDictionary(); + readonly cctOldContactsDic = new TupleDictionary(); private static _sweepBoxGeometry: number; private static _sweepSphereGeometry: number; private static _sweepCapsuleGeometry: number; @@ -493,66 +494,127 @@ export class BulletWorld implements IPhysicsWorld { if (this._needEmitEvents) { this.gatherConatactData(); - // is enter or stay - let dicL = this.contactsDic.getLength(); - while (dicL--) { - contactsPool.push.apply(contactsPool, CollisionEventObject.contacts as BulletContactData[]); - CollisionEventObject.contacts.length = 0; - const key = this.contactsDic.getKeyByIndex(dicL); - const data = this.contactsDic.getDataByKey(key); - const shape0: BulletShape = data.shape0; - const shape1: BulletShape = data.shape1; - this.oldContactsDic.set(shape0.id, shape1.id, data); - const collider0 = shape0.collider; - const collider1 = shape1.collider; - if (collider0 && collider1) { - const isTrigger = collider0.isTrigger || collider1.isTrigger; - if (isTrigger) { - if (this.triggerArrayMat.get(shape0.id, shape1.id)) { - TriggerEventObject.type = 'onTriggerStay'; - } else { - TriggerEventObject.type = 'onTriggerEnter'; - this.triggerArrayMat.set(shape0.id, shape1.id, true); - } - TriggerEventObject.impl = data.impl; //btPersistentManifold - TriggerEventObject.selfCollider = collider0; - TriggerEventObject.otherCollider = collider1; - collider0.emit(TriggerEventObject.type, TriggerEventObject); - - TriggerEventObject.selfCollider = collider1; - TriggerEventObject.otherCollider = collider0; - collider1.emit(TriggerEventObject.type, TriggerEventObject); - this._needSyncAfterEvents = true; + + this.emitCollisionAndTriggerEvent(); + // emit cct trigger events + this.emitCCTTriggerEvent(); + } + + // emit cct collision events + if (this._needEmitCCTEvents) { + this.emitCCTCollisionEvent(); + } + } + + private emitCollisionAndTriggerEvent (): void { + // is enter or stay + let dicL = this.contactsDic.getLength(); + while (dicL--) { + contactsPool.push.apply(contactsPool, CollisionEventObject.contacts as BulletContactData[]); + CollisionEventObject.contacts.length = 0; + const key = this.contactsDic.getKeyByIndex(dicL); + const data = this.contactsDic.getDataByKey(key); + const shape0: BulletShape = data.shape0; + const shape1: BulletShape = data.shape1; + this.oldContactsDic.set(shape0.id, shape1.id, data); + const collider0 = shape0.collider; + const collider1 = shape1.collider; + if (collider0 && collider1) { + const isTrigger = collider0.isTrigger || collider1.isTrigger; + if (isTrigger) { + if (this.triggerArrayMat.get(shape0.id, shape1.id)) { + TriggerEventObject.type = 'onTriggerStay'; } else { - const body0 = collider0.attachedRigidBody; - const body1 = collider1.attachedRigidBody; - if (body0 && body1) { - if (body0.isSleeping && body1.isSleeping) continue; - } else if (!body0 && body1) { - if (body1.isSleeping) continue; - } else if (!body1 && body0) { - if (body0.isSleeping) continue; - } - if (this.collisionArrayMat.get(shape0.id, shape1.id)) { - CollisionEventObject.type = 'onCollisionStay'; + TriggerEventObject.type = 'onTriggerEnter'; + this.triggerArrayMat.set(shape0.id, shape1.id, true); + } + TriggerEventObject.impl = data.impl; //btPersistentManifold + TriggerEventObject.selfCollider = collider0; + TriggerEventObject.otherCollider = collider1; + collider0.emit(TriggerEventObject.type, TriggerEventObject); + + TriggerEventObject.selfCollider = collider1; + TriggerEventObject.otherCollider = collider0; + collider1.emit(TriggerEventObject.type, TriggerEventObject); + this._needSyncAfterEvents = true; + } else { + const body0 = collider0.attachedRigidBody; + const body1 = collider1.attachedRigidBody; + if (body0 && body1) { + if (body0.isSleeping && body1.isSleeping) continue; + } else if (!body0 && body1) { + if (body1.isSleeping) continue; + } else if (!body1 && body0) { + if (body0.isSleeping) continue; + } + if (this.collisionArrayMat.get(shape0.id, shape1.id)) { + CollisionEventObject.type = 'onCollisionStay'; + } else { + CollisionEventObject.type = 'onCollisionEnter'; + this.collisionArrayMat.set(shape0.id, shape1.id, true); + } + + for (let i = 0; i < data.contacts.length; i++) { + const cq = data.contacts[i]; //btManifoldPoint + if (contactsPool.length > 0) { + const c = contactsPool.pop(); + c!.impl = cq; //btManifoldPoint + CollisionEventObject.contacts.push(c!); } else { - CollisionEventObject.type = 'onCollisionEnter'; - this.collisionArrayMat.set(shape0.id, shape1.id, true); + const c = new BulletContactData(CollisionEventObject); + c.impl = cq; //btManifoldPoint + CollisionEventObject.contacts.push(c); } + } + CollisionEventObject.impl = data.impl; //btPersistentManifold + CollisionEventObject.selfCollider = collider0; + CollisionEventObject.otherCollider = collider1; + collider0.emit(CollisionEventObject.type, CollisionEventObject); + + CollisionEventObject.selfCollider = collider1; + CollisionEventObject.otherCollider = collider0; + collider1.emit(CollisionEventObject.type, CollisionEventObject); + this._needSyncAfterEvents = true; + } - for (let i = 0; i < data.contacts.length; i++) { - const cq = data.contacts[i]; //btManifoldPoint - if (contactsPool.length > 0) { - const c = contactsPool.pop(); - c!.impl = cq; //btManifoldPoint - CollisionEventObject.contacts.push(c!); - } else { - const c = new BulletContactData(CollisionEventObject); - c.impl = cq; //btManifoldPoint - CollisionEventObject.contacts.push(c); - } + if (this.oldContactsDic.get(shape0.id, shape1.id) == null) { + this.oldContactsDic.set(shape0.id, shape1.id, data); + } + } + } + + // is exit + let oldDicL = this.oldContactsDic.getLength(); + while (oldDicL--) { + const key = this.oldContactsDic.getKeyByIndex(oldDicL); + const data = this.oldContactsDic.getDataByKey(key); + const shape0: BulletShape = data.shape0; + const shape1: BulletShape = data.shape1; + const collider0 = shape0.collider; + const collider1 = shape1.collider; + if (collider0 && collider1) { + const isTrigger = collider0.isTrigger || collider1.isTrigger; + if (this.contactsDic.getDataByKey(key) == null) { + if (isTrigger) { + if (this.triggerArrayMat.get(shape0.id, shape1.id)) { + TriggerEventObject.type = 'onTriggerExit'; + TriggerEventObject.selfCollider = collider0; + TriggerEventObject.otherCollider = collider1; + collider0.emit(TriggerEventObject.type, TriggerEventObject); + + TriggerEventObject.selfCollider = collider1; + TriggerEventObject.otherCollider = collider0; + collider1.emit(TriggerEventObject.type, TriggerEventObject); + + this.triggerArrayMat.set(shape0.id, shape1.id, false); + this.oldContactsDic.set(shape0.id, shape1.id, null); + this._needSyncAfterEvents = true; } - CollisionEventObject.impl = data.impl; //btPersistentManifold + } else if (this.collisionArrayMat.get(shape0.id, shape1.id)) { + contactsPool.push.apply(contactsPool, CollisionEventObject.contacts as BulletContactData[]); + CollisionEventObject.contacts.length = 0; + + CollisionEventObject.type = 'onCollisionExit'; CollisionEventObject.selfCollider = collider0; CollisionEventObject.otherCollider = collider1; collider0.emit(CollisionEventObject.type, CollisionEventObject); @@ -560,89 +622,111 @@ export class BulletWorld implements IPhysicsWorld { CollisionEventObject.selfCollider = collider1; CollisionEventObject.otherCollider = collider0; collider1.emit(CollisionEventObject.type, CollisionEventObject); - this._needSyncAfterEvents = true; - } - if (this.oldContactsDic.get(shape0.id, shape1.id) == null) { - this.oldContactsDic.set(shape0.id, shape1.id, data); + this.collisionArrayMat.set(shape0.id, shape1.id, false); + this.oldContactsDic.set(shape0.id, shape1.id, null); + this._needSyncAfterEvents = true; } } } + } - // is exit - let oldDicL = this.oldContactsDic.getLength(); - while (oldDicL--) { - const key = this.oldContactsDic.getKeyByIndex(oldDicL); - const data = this.oldContactsDic.getDataByKey(key); - const shape0: BulletShape = data.shape0; - const shape1: BulletShape = data.shape1; - const collider0 = shape0.collider; - const collider1 = shape1.collider; - if (collider0 && collider1) { - const isTrigger = collider0.isTrigger || collider1.isTrigger; - if (this.contactsDic.getDataByKey(key) == null) { - if (isTrigger) { - if (this.triggerArrayMat.get(shape0.id, shape1.id)) { - TriggerEventObject.type = 'onTriggerExit'; - TriggerEventObject.selfCollider = collider0; - TriggerEventObject.otherCollider = collider1; - collider0.emit(TriggerEventObject.type, TriggerEventObject); - - TriggerEventObject.selfCollider = collider1; - TriggerEventObject.otherCollider = collider0; - collider1.emit(TriggerEventObject.type, TriggerEventObject); - - this.triggerArrayMat.set(shape0.id, shape1.id, false); - this.oldContactsDic.set(shape0.id, shape1.id, null); - this._needSyncAfterEvents = true; - } - } else if (this.collisionArrayMat.get(shape0.id, shape1.id)) { - contactsPool.push.apply(contactsPool, CollisionEventObject.contacts as BulletContactData[]); - CollisionEventObject.contacts.length = 0; - - CollisionEventObject.type = 'onCollisionExit'; - CollisionEventObject.selfCollider = collider0; - CollisionEventObject.otherCollider = collider1; - collider0.emit(CollisionEventObject.type, CollisionEventObject); + this.contactsDic.reset(); + } + + private emitCCTTriggerEvent (): void { + // is enter or stay + let dicL = this.cctContactsDic.getLength(); + while (dicL--) { + const key = this.cctContactsDic.getKeyByIndex(dicL); + const data = this.cctContactsDic.getDataByKey(key); + const shape: BulletShape = data.shape; + const cct: BulletCharacterController = data.cct; + this.cctOldContactsDic.set(shape.id, cct.id, data); + const collider = shape.collider; + const characterController = cct.characterController; + if (collider && characterController) { + const isTrigger = collider.isTrigger; + if (isTrigger) { + if (this.triggerArrayMat.get(shape.id, cct.id)) { + CharacterTriggerEventObject.type = 'onControllerTriggerStay'; + } else { + CharacterTriggerEventObject.type = 'onControllerTriggerEnter'; + this.triggerArrayMat.set(shape.id, cct.id, true); + } + CharacterTriggerEventObject.impl = data.impl; //btPersistentManifold + CharacterTriggerEventObject.collider = collider; + CharacterTriggerEventObject.characterController = characterController; + collider.emit(CharacterTriggerEventObject.type, CharacterTriggerEventObject); + + CharacterTriggerEventObject.collider = collider; + CharacterTriggerEventObject.characterController = characterController; + characterController.emit(CharacterTriggerEventObject.type, CharacterTriggerEventObject); + this._needSyncAfterEvents = true; + } - CollisionEventObject.selfCollider = collider1; - CollisionEventObject.otherCollider = collider0; - collider1.emit(CollisionEventObject.type, CollisionEventObject); + if (this.cctOldContactsDic.get(shape.id, cct.id) == null) { + this.cctOldContactsDic.set(shape.id, cct.id, data); + } + } + } - this.collisionArrayMat.set(shape0.id, shape1.id, false); - this.oldContactsDic.set(shape0.id, shape1.id, null); + // is exit + let oldDicL = this.cctOldContactsDic.getLength(); + while (oldDicL--) { + const key = this.cctOldContactsDic.getKeyByIndex(oldDicL); + const data = this.cctOldContactsDic.getDataByKey(key); + const shape: BulletShape = data.shape; + const cct: BulletCharacterController = data.cct; + const collider = shape.collider; + const characterController = cct.characterController; + if (collider && characterController) { + const isTrigger = collider.isTrigger; + if (this.cctContactsDic.getDataByKey(key) == null) { + if (isTrigger) { + if (this.triggerArrayMat.get(shape.id, cct.id)) { + CharacterTriggerEventObject.type = 'onControllerTriggerExit'; + CharacterTriggerEventObject.collider = collider; + CharacterTriggerEventObject.characterController = characterController; + collider.emit(CharacterTriggerEventObject.type, CharacterTriggerEventObject); + + CharacterTriggerEventObject.collider = collider; + CharacterTriggerEventObject.characterController = characterController; + characterController.emit(CharacterTriggerEventObject.type, CharacterTriggerEventObject); + + this.triggerArrayMat.set(shape.id, cct.id, false); + this.cctOldContactsDic.set(shape.id, cct.id, null); this._needSyncAfterEvents = true; } } } } - - this.contactsDic.reset(); } - // emit cct events - if (this._needEmitCCTEvents) { - let dicL = this.cctShapeEventDic.getLength(); - while (dicL--) { - const key = this.cctShapeEventDic.getKeyByIndex(dicL); - const data = this.cctShapeEventDic.getDataByKey(key); - const cct: BulletCharacterController = data.BulletCharacterController; - const shape: BulletShape = data.BulletShape; - const worldPos = data.worldPos as IVec3Like; - const worldNormal = data.worldNormal as IVec3Like; - const motionDir = data.motionDir as IVec3Like; - const motionLength = data.motionLength; - emitHit.controller = cct.characterController; - emitHit.collider = shape.collider; - emitHit.worldPosition.set(worldPos.x, worldPos.y, worldPos.z); - emitHit.worldNormal.set(worldNormal.x, worldNormal.y, worldNormal.z); - emitHit.motionDirection.set(motionDir.x, motionDir.y, motionDir.z); - emitHit.motionLength = motionLength; - emitHit.controller?.emit('onControllerColliderHit', emitHit); - this._needSyncAfterEvents = true; - } - this.cctShapeEventDic.reset(); + this.cctContactsDic.reset(); + } + + private emitCCTCollisionEvent (): void { + let dicL = this.cctShapeEventDic.getLength(); + while (dicL--) { + const key = this.cctShapeEventDic.getKeyByIndex(dicL); + const data = this.cctShapeEventDic.getDataByKey(key); + const cct: BulletCharacterController = data.BulletCharacterController; + const shape: BulletShape = data.BulletShape; + const worldPos = data.worldPos as IVec3Like; + const worldNormal = data.worldNormal as IVec3Like; + const motionDir = data.motionDir as IVec3Like; + const motionLength = data.motionLength; + emitHit.controller = cct.characterController; + emitHit.collider = shape.collider; + emitHit.worldPosition.set(worldPos.x, worldPos.y, worldPos.z); + emitHit.worldNormal.set(worldNormal.x, worldNormal.y, worldNormal.z); + emitHit.motionDirection.set(motionDir.x, motionDir.y, motionDir.z); + emitHit.motionLength = motionLength; + emitHit.controller?.emit('onControllerColliderHit', emitHit); + this._needSyncAfterEvents = true; } + this.cctShapeEventDic.reset(); } gatherConatactData (): void { @@ -654,22 +738,71 @@ export class BulletWorld implements IPhysicsWorld { const manifoldPoint = bt.PersistentManifold_getContactPoint(manifold, j);//btManifoldPoint const s0 = bt.ManifoldPoint_getShape0(manifoldPoint); const s1 = bt.ManifoldPoint_getShape1(manifoldPoint); - const shape0: BulletShape = BulletCache.getWrapper(s0, BulletShape.TYPE); - const shape1: BulletShape = BulletCache.getWrapper(s1, BulletShape.TYPE); - if (shape0 && shape1) { - if (shape0.collider.needTriggerEvent || shape1.collider.needTriggerEvent - || shape0.collider.needCollisionEvent || shape1.collider.needCollisionEvent - ) { - // current contact - let item = this.contactsDic.get(shape0.id, shape1.id); - if (!item) { - item = this.contactsDic.set( - shape0.id, - shape1.id, - { shape0, shape1, contacts: [], impl: manifold }, - ); + + let processed = false; + + if (!processed) { + const shape0: BulletShape = BulletCache.getWrapper(s0, BulletShape.TYPE); + const shape1: BulletShape = BulletCache.getWrapper(s1, BulletShape.TYPE); + if (shape0 && shape1) { + processed = true; + if (shape0.collider.needTriggerEvent || shape1.collider.needTriggerEvent + || shape0.collider.needCollisionEvent || shape1.collider.needCollisionEvent) { + // current contact + let item = this.contactsDic.get(shape0.id, shape1.id); + if (!item) { + item = this.contactsDic.set( + shape0.id, + shape1.id, + { shape0, shape1, contacts: [], impl: manifold }, + ); + } + item.contacts.push(manifoldPoint);//btManifoldPoint + } + } + } + + //cct - collider trigger event + if (!processed) { + const shape: BulletShape = BulletCache.getWrapper(s0, BulletShape.TYPE); + const cct: BulletCharacterController = BulletCache.getWrapper(s1, bt.CCT_CACHE_NAME); + if (shape && cct) { + processed = true; + if (shape.collider.needTriggerEvent) { + // current contact + let item = this.cctContactsDic.get(shape.id, cct.id); + if (!item) { + item = this.cctContactsDic.set( + shape.id, + cct.id, + { shape, cct, contacts: [], impl: manifold }, + ); + } + item.contacts.push(manifoldPoint);//btManifoldPoint + processed = true; + } + } + } + + //cct - collider trigger event + if (!processed) { + const cct: BulletCharacterController = BulletCache.getWrapper(s0, bt.CCT_CACHE_NAME); + const shape: BulletShape = BulletCache.getWrapper(s1, BulletShape.TYPE); + if (shape && cct) { + processed = true; + if (shape.collider.needTriggerEvent) { + // current contact + let item = this.cctContactsDic.get(shape.id, cct.id); + if (!item) { + item = this.cctContactsDic.set( + shape.id, + cct.id, + { shape, cct, contacts: [], impl: manifold }, + ); + } + item.contacts.push(manifoldPoint);//btManifoldPoint + processed = true; } - item.contacts.push(manifoldPoint);//btManifoldPoint } } } diff --git a/cocos/physics/bullet/character-controllers/bullet-character-controller.ts b/cocos/physics/bullet/character-controllers/bullet-character-controller.ts index 4d6ed88d53b..7c50e656fd5 100644 --- a/cocos/physics/bullet/character-controllers/bullet-character-controller.ts +++ b/cocos/physics/bullet/character-controllers/bullet-character-controller.ts @@ -48,6 +48,8 @@ export abstract class BulletCharacterController implements IBaseCharacterControl protected _dirty = false; private _collisionFilterGroup: number = PhysicsGroup.DEFAULT; private _collisionFilterMask = -1; + private static idCounter = 0; + readonly id = BulletCharacterController.idCounter++; get isEnabled (): boolean { return this._isEnabled; } get impl (): number { @@ -86,6 +88,8 @@ export abstract class BulletCharacterController implements IBaseCharacterControl setWrapper (): void { BulletCache.setWrapper(this._impl, bt.CCT_CACHE_NAME, this); + const cctCollisionShapeImpl = bt.CharacterController_getCollisionShape(this.impl); + BulletCache.setWrapper(cctCollisionShapeImpl, bt.CCT_CACHE_NAME, this); } onEnable (): void { diff --git a/cocos/physics/framework/components/character-controllers/character-controller.ts b/cocos/physics/framework/components/character-controllers/character-controller.ts index 73fa1e0df99..ef6a0509058 100644 --- a/cocos/physics/framework/components/character-controllers/character-controller.ts +++ b/cocos/physics/framework/components/character-controllers/character-controller.ts @@ -30,7 +30,7 @@ import { Vec3, warn, CCFloat, Eventify } from '../../../../core'; import { Component } from '../../../../scene-graph'; import { IBaseCharacterController } from '../../../spec/i-character-controller'; import { ECharacterControllerType } from '../../physics-enum'; -import { CharacterCollisionEventType } from '../../physics-interface'; +import { CharacterCollisionEventType, CharacterTriggerEventType, TriggerEventType } from '../../physics-interface'; import { selector, createCharacterController } from '../../physics-selector'; import { PhysicsSystem } from '../../physics-system'; @@ -251,6 +251,7 @@ export class CharacterController extends Eventify(Component) { private _centerWorldPosition: Vec3 = new Vec3(); protected _needCollisionEvent = false; + protected _needTriggerEvent = false; protected get _isInitialized (): boolean { if (this._cct === null || !this._initialized) { @@ -285,6 +286,7 @@ export class CharacterController extends Eventify(Component) { protected onDestroy (): void { if (this._cct) { this._needCollisionEvent = false; + this._needTriggerEvent = false; this._cct.updateEventListener(); this._cct.onDestroy!(); this._cct = null; @@ -372,7 +374,8 @@ export class CharacterController extends Eventify(Component) { * @param callback - The event callback, signature:`(event?:ICollisionEvent|ITriggerEvent)=>void`. * @param target - The event callback target. */ - public on void>(type: CharacterCollisionEventType, callback: TFunction, target?, once?: boolean): any { + public on void>(type: CharacterTriggerEventType | CharacterCollisionEventType, + callback: TFunction, target?, once?: boolean): any { const ret = super.on(type, callback, target, once); this._updateNeedEvent(type); return ret; @@ -387,7 +390,7 @@ export class CharacterController extends Eventify(Component) { * @param callback - The event callback, signature:`(event?:ICollisionEvent|ITriggerEvent)=>void`. * @param target - The event callback target. */ - public off (type: CharacterCollisionEventType, callback?: (...any) => void, target?): void { + public off (type: CharacterTriggerEventType | CharacterCollisionEventType, callback?: (...any) => void, target?): void { super.off(type, callback, target); this._updateNeedEvent(); } @@ -401,7 +404,8 @@ export class CharacterController extends Eventify(Component) { * @param callback - The event callback, signature:`(event?:ICollisionEvent|ITriggerEvent)=>void`. * @param target - The event callback target. */ - public once void>(type: CharacterCollisionEventType, callback: TFunction, target?): any { + public once void>(type: CharacterTriggerEventType | CharacterCollisionEventType, + callback: TFunction, target?): any { // TODO: callback invoker now is a entity, after `once` will not calling the upper `off`. const ret = super.once(type, callback, target); this._updateNeedEvent(type); @@ -504,14 +508,28 @@ export class CharacterController extends Eventify(Component) { return this._needCollisionEvent; } + public get needTriggerEvent (): boolean { + return this._needTriggerEvent; + } + private _updateNeedEvent (type?: string): void { if (this.isValid) { if (type !== undefined) { if (type === 'onControllerColliderHit') { this._needCollisionEvent = true; } - } else if (!this.hasEventListener('onControllerColliderHit')) { - this._needCollisionEvent = false; + if (type === 'onControllerTriggerEnter' || type === 'onControllerTriggerStay' || type === 'onControllerTriggerExit') { + this._needTriggerEvent = true; + } + } else { + if (!this.hasEventListener('onControllerColliderHit')) { + this._needCollisionEvent = false; + } + if (!(this.hasEventListener('onControllerTriggerEnter') + || this.hasEventListener('onControllerTriggerStay') + || this.hasEventListener('onControllerTriggerExit'))) { + this._needTriggerEvent = false; + } } if (this._cct) this._cct.updateEventListener(); } diff --git a/cocos/physics/framework/components/colliders/collider.ts b/cocos/physics/framework/components/colliders/collider.ts index 2c8ef0ce264..8caffad63e7 100644 --- a/cocos/physics/framework/components/colliders/collider.ts +++ b/cocos/physics/framework/components/colliders/collider.ts @@ -26,7 +26,7 @@ import { ccclass, tooltip, displayOrder, displayName, readOnly, type, serializable } from 'cc.decorator'; import { EDITOR } from 'internal:constants'; import { Eventify, Vec3, error, geometry } from '../../../../core'; -import { CollisionEventType, TriggerEventType } from '../../physics-interface'; +import { CharacterTriggerEventType, CollisionEventType, TriggerEventType } from '../../physics-interface'; import { RigidBody } from '../rigid-body'; import { PhysicsMaterial } from '../../assets/physics-material'; import { Component, Node } from '../../../../scene-graph'; @@ -248,7 +248,8 @@ export class Collider extends Eventify(Component) { * @param callback - The event callback, signature:`(event?:ICollisionEvent|ITriggerEvent)=>void`. * @param target - The event callback target. */ - public on void>(type: TriggerEventType | CollisionEventType, callback: TFunction, target?, once?: boolean): any { + public on void>(type: TriggerEventType | CollisionEventType | CharacterTriggerEventType, + callback: TFunction, target?, once?: boolean): any { const ret = super.on(type, callback, target, once); this._updateNeedEvent(type); return ret; @@ -263,7 +264,7 @@ export class Collider extends Eventify(Component) { * @param callback - The event callback, signature:`(event?:ICollisionEvent|ITriggerEvent)=>void`. * @param target - The event callback target. */ - public off (type: TriggerEventType | CollisionEventType, callback?: (...any) => void, target?): void { + public off (type: TriggerEventType | CollisionEventType | CharacterTriggerEventType, callback?: (...any) => void, target?): void { super.off(type, callback, target); this._updateNeedEvent(); } @@ -277,7 +278,8 @@ export class Collider extends Eventify(Component) { * @param callback - The event callback, signature:`(event?:ICollisionEvent|ITriggerEvent)=>void`. * @param target - The event callback target. */ - public once void>(type: TriggerEventType | CollisionEventType, callback: TFunction, target?): any { + public once void>(type: TriggerEventType | CollisionEventType | CharacterTriggerEventType, + callback: TFunction, target?): any { // TODO: callback invoker now is a entity, after `once` will not calling the upper `off`. const ret = super.once(type, callback, target); this._updateNeedEvent(type); @@ -448,13 +450,18 @@ export class Collider extends Eventify(Component) { if (type === 'onCollisionEnter' || type === 'onCollisionStay' || type === 'onCollisionExit') { this._needCollisionEvent = true; } - if (type === 'onTriggerEnter' || type === 'onTriggerStay' || type === 'onTriggerExit') { + if (type === 'onTriggerEnter' || type === 'onTriggerStay' || type === 'onTriggerExit' + || type === 'onControllerTriggerEnter' || type === 'onControllerTriggerStay' || type === 'onControllerTriggerExit') { this._needTriggerEvent = true; } } else { if (!(this.hasEventListener('onTriggerEnter') || this.hasEventListener('onTriggerStay') - || this.hasEventListener('onTriggerExit'))) { + || this.hasEventListener('onTriggerExit') + || this.hasEventListener('onControllerTriggerEnter') + || this.hasEventListener('onControllerTriggerStay') + || this.hasEventListener('onControllerTriggerExit') + )) { this._needTriggerEvent = false; } if (!(this.hasEventListener('onCollisionEnter') diff --git a/cocos/physics/framework/physics-interface.ts b/cocos/physics/framework/physics-interface.ts index e113dee2128..452ee6e63d0 100644 --- a/cocos/physics/framework/physics-interface.ts +++ b/cocos/physics/framework/physics-interface.ts @@ -242,6 +242,14 @@ export type CollisionEventType = 'onCollisionEnter' | 'onCollisionStay' | 'onCol */ export type CollisionCallback = (event?: ICollisionEvent) => void; +/** + * @en + * The definition of the trigger event of the character controller. + * @zh + * 角色控制器触发事件的值类型定义。 + */ +export type CharacterTriggerEventType = 'onControllerTriggerEnter' | 'onControllerTriggerStay' | 'onControllerTriggerExit'; + /** * @en * Value type definitions fot the collision events of character controller. diff --git a/cocos/physics/physx/character-controllers/physx-box-character-controller.ts b/cocos/physics/physx/character-controllers/physx-box-character-controller.ts index b8c96ee72f1..3d58ac36e8e 100644 --- a/cocos/physics/physx/character-controllers/physx-box-character-controller.ts +++ b/cocos/physics/physx/character-controllers/physx-box-character-controller.ts @@ -67,7 +67,11 @@ export class PhysXBoxCharacterController extends PhysXCharacterController implem controllerDesc.setReportCallback(PX.PxUserControllerHitReport.implement(physxWorld.callback.controllerHitReportCB)); this._impl = PX.createBoxCharacterController(physxWorld.controllerManager, controllerDesc); - if (this._impl.$$) PX.IMPL_PTR[this._impl.$$.ptr] = this; + if (this._impl.$$) { + PX.IMPL_PTR[this._impl.$$.ptr] = this; + const shapePtr = this._impl.getShape().$$.ptr; + PX.IMPL_PTR[shapePtr] = this; + } this.updateScale(); } diff --git a/cocos/physics/physx/character-controllers/physx-capsule-character-controller.ts b/cocos/physics/physx/character-controllers/physx-capsule-character-controller.ts index c2c7e202622..9e4dfdd2b50 100644 --- a/cocos/physics/physx/character-controllers/physx-capsule-character-controller.ts +++ b/cocos/physics/physx/character-controllers/physx-capsule-character-controller.ts @@ -68,7 +68,11 @@ export class PhysXCapsuleCharacterController extends PhysXCharacterController im controllerDesc.setReportCallback(PX.PxUserControllerHitReport.implement(physxWorld.callback.controllerHitReportCB)); this._impl = PX.createCapsuleCharacterController(physxWorld.controllerManager, controllerDesc); - if (this._impl.$$) PX.IMPL_PTR[this._impl.$$.ptr] = this; + if (this._impl.$$) { + PX.IMPL_PTR[this._impl.$$.ptr] = this; + const shapePtr = this._impl.getShape().$$.ptr; + PX.IMPL_PTR[shapePtr] = this; + } this.updateScale(); } diff --git a/cocos/physics/physx/character-controllers/physx-character-controller.ts b/cocos/physics/physx/character-controllers/physx-character-controller.ts index da7d3e9d703..a5361c282ec 100644 --- a/cocos/physics/physx/character-controllers/physx-character-controller.ts +++ b/cocos/physics/physx/character-controllers/physx-character-controller.ts @@ -45,6 +45,9 @@ export class PhysXCharacterController implements IBaseCharacterController { protected _word3 = 0; protected _overlapRecovery = true; + readonly id: number; + private static idCounter = 0; + get isEnabled (): boolean { return this._isEnabled; } get impl (): any { /* eslint-disable @typescript-eslint/no-unsafe-return */ @@ -63,6 +66,7 @@ export class PhysXCharacterController implements IBaseCharacterController { } constructor () { + this.id = PhysXCharacterController.idCounter++; this._filterData = { word0: 1, word1: 1, word2: 1, word3: 0 }; } @@ -116,6 +120,9 @@ export class PhysXCharacterController implements IBaseCharacterController { if (this._impl.$$) { PX.IMPL_PTR[this._impl.$$.ptr] = null; delete PX.IMPL_PTR[this._impl.$$.ptr]; + const shapePtr = this._impl.getShape().$$.ptr; + PX.IMPL_PTR[shapePtr] = null; + delete PX.IMPL_PTR[shapePtr]; } this._impl.release(); this._impl = null; diff --git a/cocos/physics/physx/physx-world.ts b/cocos/physics/physx/physx-world.ts index d0ee6c1185a..6ffe301e263 100644 --- a/cocos/physics/physx/physx-world.ts +++ b/cocos/physics/physx/physx-world.ts @@ -24,7 +24,8 @@ /* eslint-disable @typescript-eslint/no-unsafe-return */ import { IPhysicsWorld, IRaycastOptions } from '../spec/i-physics-world'; -import { PhysicsMaterial, PhysicsRayResult, CollisionEventType, TriggerEventType, CharacterControllerContact } from '../framework'; +import { PhysicsMaterial, PhysicsRayResult, CollisionEventType, TriggerEventType, CharacterTriggerEventType, + CharacterControllerContact } from '../framework'; import { error, RecyclePool, js, IVec3Like, geometry, IQuatLike, Vec3, Quat } from '../../core'; import { IBaseConstraint } from '../spec/i-physics-constraint'; import { PhysXRigidBody } from './physx-rigid-body'; @@ -35,7 +36,7 @@ import { import { PhysXSharedBody } from './physx-shared-body'; import { TupleDictionary } from '../utils/tuple-dictionary'; import { PhysXContactEquation } from './physx-contact-equation'; -import { CollisionEventObject, TriggerEventObject, VEC3_0 } from '../utils/util'; +import { CollisionEventObject, TriggerEventObject, CharacterTriggerEventObject, VEC3_0 } from '../utils/util'; import { PhysXShape } from './shapes/physx-shape'; import { EFilterDataWord3 } from './physx-enum'; import { PhysXInstance } from './physx-instance'; @@ -244,7 +245,8 @@ export class PhysXWorld extends PhysXInstance implements IPhysicsWorld { gatherEvents(this); PhysXCallback.emitTriggerEvent(); PhysXCallback.emitCollisionEvent(); - PhysXCallback.emitCCTShapeEvent(); + PhysXCallback.emitCCTCollisionEvent(); + PhysXCallback.emitCCTTriggerEvent(); } } @@ -267,6 +269,12 @@ interface ICollisionEventItem { offset: number, } +interface ITriggerEventItemCCT { + a: PhysXShape, + b: PhysXCharacterController, + times: number, +} + const triggerEventBeginDic = new TupleDictionary(); const triggerEventEndDic = new TupleDictionary(); const triggerEventsPool: ITriggerEventItem[] = []; @@ -275,6 +283,9 @@ const contactEventsPool: ICollisionEventItem[] = []; const contactsPool: [] = []; const cctShapeEventDic = new TupleDictionary(); const emitHit = new CharacterControllerContact(); +const cctTriggerEventBeginDic = new TupleDictionary(); +const cctTriggerEventEndDic = new TupleDictionary(); +const cctTriggerEventsPool: ITriggerEventItemCCT[] = []; const PhysXCallback = { eventCallback: { @@ -294,14 +305,26 @@ const PhysXCallback = { PhysXCallback.onCollision('onCollisionStay', wpa, wpb, c, d, o); }, onTriggerBegin: (a: any, b: any): void => { - const wpa = getWrapShape(a); - const wpb = getWrapShape(b); - PhysXCallback.onTrigger('onTriggerEnter', wpa, wpb, true); + const wpa = getWrapShape(a); + const wpb = getWrapShape(b); + if (wpa instanceof PhysXShape && wpb instanceof PhysXShape) { + PhysXCallback.onTrigger('onTriggerEnter', wpa, wpb, true); + } else if (wpa instanceof PhysXShape && wpb instanceof PhysXCharacterController) { + PhysXCallback.onTriggerCCT('onControllerTriggerEnter', wpa, wpb, true); + } else if (wpa instanceof PhysXCharacterController && wpb instanceof PhysXShape) { + PhysXCallback.onTriggerCCT('onControllerTriggerEnter', wpb, wpa, true); + } }, onTriggerEnd: (a: any, b: any): void => { - const wpa = getWrapShape(a); - const wpb = getWrapShape(b); - PhysXCallback.onTrigger('onTriggerExit', wpa, wpb, false); + const wpa = getWrapShape(a); + const wpb = getWrapShape(b); + if (wpa instanceof PhysXShape && wpb instanceof PhysXShape) { + PhysXCallback.onTrigger('onTriggerExit', wpa, wpb, false); + } else if (wpa instanceof PhysXShape && wpb instanceof PhysXCharacterController) { + PhysXCallback.onTriggerCCT('onControllerTriggerExit', wpa, wpb, false); + } else if (wpa instanceof PhysXCharacterController && wpb instanceof PhysXShape) { + PhysXCallback.onTriggerCCT('onControllerTriggerExit', wpb, wpa, false); + } }, }, @@ -347,6 +370,25 @@ const PhysXCallback = { } }, + onTriggerCCT (type: CharacterTriggerEventType, wpa: PhysXShape, cct: PhysXCharacterController, isEnter: boolean): void { + if (wpa && cct) { + if (wpa.collider.needTriggerEvent) { + let tE: ITriggerEventItemCCT; + if (cctTriggerEventsPool.length > 0) { + tE = cctTriggerEventsPool.pop() as ITriggerEventItemCCT; + tE.a = wpa; tE.b = cct; tE.times = 0; + } else { + tE = { a: wpa, b: cct, times: 0 }; + } + if (isEnter) { + cctTriggerEventBeginDic.set(wpa.id, cct.id, tE); + } else { + cctTriggerEventEndDic.set(wpa.id, cct.id, tE); + } + } + } + }, + emitTriggerEvent (): void { let len = triggerEventEndDic.getLength(); while (len--) { @@ -483,7 +525,7 @@ const PhysXCallback = { onControllerHit (hit: any): void { //PX.ControllersHit }, }, - emitCCTShapeEvent (): void { + emitCCTCollisionEvent (): void { let dicL = cctShapeEventDic.getLength(); while (dicL--) { const key = cctShapeEventDic.getKeyByIndex(dicL); @@ -502,4 +544,59 @@ const PhysXCallback = { } cctShapeEventDic.reset(); }, + emitCCTTriggerEvent (): void { + let len = cctTriggerEventEndDic.getLength(); + while (len--) { + const key = cctTriggerEventEndDic.getKeyByIndex(len); + const data = cctTriggerEventEndDic.getDataByKey(key); + cctTriggerEventsPool.push(data); + const dataBeg = cctTriggerEventBeginDic.getDataByKey(key); + if (dataBeg) { + cctTriggerEventsPool.push(dataBeg); + cctTriggerEventBeginDic.set(data.a.id, data.b.id, null); + } + const collider = data.a.collider; + const characterController = data.b.characterController; + if (collider && characterController) { + const type: CharacterTriggerEventType = 'onControllerTriggerExit'; + CharacterTriggerEventObject.type = type; + if (collider.needTriggerEvent) { + CharacterTriggerEventObject.collider = collider; + CharacterTriggerEventObject.characterController = characterController; + collider.emit(type, CharacterTriggerEventObject); + } + if (characterController.needTriggerEvent) { + CharacterTriggerEventObject.collider = collider; + CharacterTriggerEventObject.characterController = characterController; + characterController.emit(type, CharacterTriggerEventObject); + } + } + } + cctTriggerEventEndDic.reset(); + + len = cctTriggerEventBeginDic.getLength(); + while (len--) { + const key = cctTriggerEventBeginDic.getKeyByIndex(len); + const data = cctTriggerEventBeginDic.getDataByKey(key); + const collider = data.a.collider; + const characterController = data.b.characterController; + if (!collider || !collider.isValid || !characterController || !characterController.isValid) { + cctTriggerEventsPool.push(data); + cctTriggerEventBeginDic.set(data.a.id, data.b.id, null); + } else { + const type: CharacterTriggerEventType = data.times++ ? 'onControllerTriggerStay' : 'onControllerTriggerEnter'; + CharacterTriggerEventObject.type = type; + if (collider.needTriggerEvent) { + CharacterTriggerEventObject.collider = collider; + CharacterTriggerEventObject.characterController = characterController; + collider.emit(type, CharacterTriggerEventObject); + } + if (characterController.needTriggerEvent) { + CharacterTriggerEventObject.collider = collider; + CharacterTriggerEventObject.characterController = characterController; + characterController.emit(type, CharacterTriggerEventObject); + } + } + } + }, }; diff --git a/cocos/physics/utils/util.ts b/cocos/physics/utils/util.ts index ad8e0135a9a..ead93adcf0e 100644 --- a/cocos/physics/utils/util.ts +++ b/cocos/physics/utils/util.ts @@ -23,7 +23,7 @@ */ import { equals, Vec3, IVec3Like } from '../../core'; -import { Collider, CollisionEventType, IContactEquation, TriggerEventType } from '../framework'; +import { CharacterController, CharacterTriggerEventType, Collider, CollisionEventType, IContactEquation, TriggerEventType } from '../framework'; export { cylinder } from '../../primitive'; @@ -52,6 +52,13 @@ export const TriggerEventObject = { impl: null as any, }; +export const CharacterTriggerEventObject = { + type: 'onControllerTriggerEnter' as CharacterTriggerEventType, + collider: null as Collider | null, + characterController: null as CharacterController | null, + impl: null as any, +}; + export const CollisionEventObject = { type: 'onCollisionEnter' as CollisionEventType, selfCollider: null as unknown as Collider, diff --git a/exports/physics-framework.ts b/exports/physics-framework.ts index 3d5704b9088..cbadf86dfa5 100644 --- a/exports/physics-framework.ts +++ b/exports/physics-framework.ts @@ -77,6 +77,7 @@ export type { TriggerCallback, CharacterCollisionEventType, CharacterControllerContact, + CharacterTriggerEventType, } from '../cocos/physics/framework'; export * from '../cocos/physics/framework/deprecated'; diff --git a/native/cocos/bindings/manual/jsb_conversions_spec.cpp b/native/cocos/bindings/manual/jsb_conversions_spec.cpp index 91620cd2c13..8af8ffc8273 100644 --- a/native/cocos/bindings/manual/jsb_conversions_spec.cpp +++ b/native/cocos/bindings/manual/jsb_conversions_spec.cpp @@ -1619,6 +1619,18 @@ bool nativevalue_to_se(const ccstd::vector> &from, se::Value &to, se::Object * /*ctx*/) { + se::HandleObject array(se::Object::createArrayObject(from.size() * cc::physics::CCTTriggerEventPair::COUNT)); + for (size_t i = 0; i < from.size(); i++) { + auto t = i * cc::physics::CCTTriggerEventPair::COUNT; + array->setArrayElement(static_cast(t + 0), se::Value(from[i]->cct)); + array->setArrayElement(static_cast(t + 1), se::Value(from[i]->shape)); + array->setArrayElement(static_cast(t + 2), se::Value(static_cast(from[i]->state))); + } + to.setObject(array); + return true; +} + bool nativevalue_to_se(const cc::physics::RaycastResult &from, se::Value &to, se::Object *ctx) { se::HandleObject obj(se::Object::createPlainObject()); obj->setProperty("shape", se::Value(from.shape)); diff --git a/native/cocos/bindings/manual/jsb_conversions_spec.h b/native/cocos/bindings/manual/jsb_conversions_spec.h index 09ef024954b..86ff9065793 100644 --- a/native/cocos/bindings/manual/jsb_conversions_spec.h +++ b/native/cocos/bindings/manual/jsb_conversions_spec.h @@ -628,6 +628,7 @@ bool nativevalue_to_se(const ccstd::vector &from, se: bool nativevalue_to_se(const ccstd::vector> &from, se::Value &to, se::Object *ctx); bool nativevalue_to_se(const cc::physics::RaycastResult &from, se::Value &to, se::Object *ctx); bool nativevalue_to_se(const ccstd::vector> &from, se::Value &to, se::Object *ctx); +bool nativevalue_to_se(const ccstd::vector> &from, se::Value &to, se::Object * /*ctx*/); bool sevalue_to_native(const se::Value &from, cc::physics::ConvexDesc *to, se::Object *ctx); bool sevalue_to_native(const se::Value &from, cc::physics::TrimeshDesc *to, se::Object *ctx); diff --git a/native/cocos/physics/physx/PhysXEventManager.cpp b/native/cocos/physics/physx/PhysXEventManager.cpp index 0e20cb500a8..97338197471 100644 --- a/native/cocos/physics/physx/PhysXEventManager.cpp +++ b/native/cocos/physics/physx/PhysXEventManager.cpp @@ -34,27 +34,71 @@ namespace physics { void PhysXEventManager::SimulationEventCallback::onTrigger(physx::PxTriggerPair *pairs, physx::PxU32 count) { for (physx::PxU32 i = 0; i < count; i++) { - const physx::PxTriggerPair &tp = pairs[i]; - if (tp.flags & (physx::PxTriggerPairFlag::eREMOVED_SHAPE_TRIGGER | physx::PxTriggerPairFlag::eREMOVED_SHAPE_OTHER)) { + const physx::PxTriggerPair &triggerPair = pairs[i]; + if (triggerPair.flags & (physx::PxTriggerPairFlag::eREMOVED_SHAPE_TRIGGER | physx::PxTriggerPairFlag::eREMOVED_SHAPE_OTHER)) { continue; } - const auto &selfIter = getPxShapeMap().find(reinterpret_cast(tp.triggerShape)); - const auto &otherIter = getPxShapeMap().find(reinterpret_cast(tp.otherShape)); - if (selfIter == getPxShapeMap().end() || otherIter == getPxShapeMap().end()) { - continue; + bool processed = false; + + //collider trigger event + if (!processed) { + const auto &selfIter = getPxShapeMap().find(reinterpret_cast(triggerPair.triggerShape)); + const auto &otherIter = getPxShapeMap().find(reinterpret_cast(triggerPair.otherShape)); + if (selfIter != getPxShapeMap().end() && otherIter != getPxShapeMap().end()) { + processed = true; + const auto &self = selfIter->second; + const auto &other = otherIter->second; + auto &pairs = mManager->getTriggerPairs(); + const auto &iter = std::find_if(pairs.begin(), pairs.end(), [self, other](std::shared_ptr &pair) { + return (pair->shapeA == self || pair->shapeA == other) && (pair->shapeB == self || pair->shapeB == other); + }); + if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) { + if (iter == pairs.end()) pairs.push_back(std::shared_ptr(ccnew TriggerEventPair{self, other})); + } else if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_LOST) { + if (iter != pairs.end()) iter->get()->state = ETouchState::EXIT; + } + } } - const auto &self = selfIter->second; - const auto &other = otherIter->second; - auto &pairs = mManager->getTriggerPairs(); - const auto &iter = std::find_if(pairs.begin(), pairs.end(), [self, other](std::shared_ptr &pair) { - return (pair->shapeA == self || pair->shapeA == other) && (pair->shapeB == self || pair->shapeB == other); - }); - if (tp.status & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) { - if (iter == pairs.end()) pairs.push_back(std::shared_ptr(ccnew TriggerEventPair{self, other})); - } else if (tp.status & physx::PxPairFlag::eNOTIFY_TOUCH_LOST) { - if (iter != pairs.end()) iter->get()->state = ETouchState::EXIT; + //cct trigger event + if (!processed) { + const auto &shapeIter = getPxShapeMap().find(reinterpret_cast(triggerPair.triggerShape)); + const auto &cctIter = getPxCCTMap().find(reinterpret_cast(triggerPair.otherShape)); + if (shapeIter != getPxShapeMap().end() && cctIter != getPxCCTMap().end()) { + processed = true; + const auto &shape = shapeIter->second; + const auto &cct = cctIter->second; + auto &pairs = mManager->getCCTTriggerPairs(); + const auto &iter = std::find_if(pairs.begin(), pairs.end(), [shape, cct](std::shared_ptr &pair) { + return (pair->shape == shape && pair->cct == cct); + }); + if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) { + if (iter == pairs.end()) pairs.push_back(std::shared_ptr(ccnew CCTTriggerEventPair{cct, shape})); + } else if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_LOST) { + if (iter != pairs.end()) iter->get()->state = ETouchState::EXIT; + } + } + } + + //cct trigger event + if (!processed) { + const auto &cctIter = getPxCCTMap().find(reinterpret_cast(triggerPair.triggerShape)); + const auto &shapeIter = getPxShapeMap().find(reinterpret_cast(triggerPair.otherShape)); + if (shapeIter != getPxShapeMap().end() && cctIter != getPxCCTMap().end()) { + processed = true; + const auto &shape = shapeIter->second; + const auto &cct = cctIter->second; + auto &pairs = mManager->getCCTTriggerPairs(); + const auto &iter = std::find_if(pairs.begin(), pairs.end(), [shape, cct](std::shared_ptr &pair) { + return (pair->shape == shape && pair->cct == cct); + }); + if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_FOUND) { + if (iter == pairs.end()) pairs.push_back(std::shared_ptr(ccnew CCTTriggerEventPair{cct, shape})); + } else if (triggerPair.status & physx::PxPairFlag::eNOTIFY_TOUCH_LOST) { + if (iter != pairs.end()) iter->get()->state = ETouchState::EXIT; + } + } } } } @@ -121,6 +165,28 @@ void PhysXEventManager::refreshPairs() { } } + for (auto iter = getCCTTriggerPairs().begin(); iter != getCCTTriggerPairs().end();) { + uintptr_t wrapperPtrCCT = PhysXWorld::getInstance().getWrapperPtrWithObjectID(iter->get()->cct); + uintptr_t wrapperPtrShape = PhysXWorld::getInstance().getWrapperPtrWithObjectID(iter->get()->shape); + if (wrapperPtrCCT == 0 || wrapperPtrShape == 0) { + iter = getCCTTriggerPairs().erase(iter); + continue; + } + + const auto& cctIter = getPxCCTMap().find(reinterpret_cast(&(reinterpret_cast(wrapperPtrCCT)->getCCT()))); + const auto& shapeIter = getPxShapeMap().find(reinterpret_cast(&(reinterpret_cast(wrapperPtrShape)->getShape()))); + if (cctIter == getPxCCTMap().end() || shapeIter == getPxShapeMap().end()) { + iter = getCCTTriggerPairs().erase(iter); + } + else if (iter->get()->state == ETouchState::EXIT) { + iter = getCCTTriggerPairs().erase(iter); + } + else { + iter->get()->state = ETouchState::STAY; + iter++; + } + } + getConatctPairs().clear(); getCCTShapePairs().clear(); } diff --git a/native/cocos/physics/physx/PhysXEventManager.h b/native/cocos/physics/physx/PhysXEventManager.h index 36a3f4f2dd0..6cc2f0d0006 100644 --- a/native/cocos/physics/physx/PhysXEventManager.h +++ b/native/cocos/physics/physx/PhysXEventManager.h @@ -61,12 +61,14 @@ class PhysXEventManager final { inline ccstd::vector> &getTriggerPairs() { return _mTriggerPairs; } inline ccstd::vector>& getConatctPairs() { return _mConatctPairs; } inline ccstd::vector>& getCCTShapePairs() { return _mCCTShapePairs; } + inline ccstd::vector> &getCCTTriggerPairs() { return _mCCTTriggerPairs; } void refreshPairs(); private: ccstd::vector> _mTriggerPairs; ccstd::vector> _mConatctPairs; ccstd::vector> _mCCTShapePairs; + ccstd::vector> _mCCTTriggerPairs; SimulationEventCallback *_mCallback; }; diff --git a/native/cocos/physics/physx/PhysXWorld.h b/native/cocos/physics/physx/PhysXWorld.h index 007b648d163..08cfa6a9d43 100644 --- a/native/cocos/physics/physx/PhysXWorld.h +++ b/native/cocos/physics/physx/PhysXWorld.h @@ -88,6 +88,9 @@ class PhysXWorld final : virtual public IPhysicsWorld { inline ccstd::vector>& getCCTShapeEventPairs() override { return _mEventMgr->getCCTShapePairs(); } + inline ccstd::vector> &getCCTTriggerEventPairs() override { + return _mEventMgr->getCCTTriggerPairs(); + } void syncSceneToPhysics() override; void syncSceneWithCheck() override; void destroy() override; diff --git a/native/cocos/physics/physx/character-controllers/PhysXCharacterController.cpp b/native/cocos/physics/physx/character-controllers/PhysXCharacterController.cpp index 37483bc95f3..66635d23445 100644 --- a/native/cocos/physics/physx/character-controllers/PhysXCharacterController.cpp +++ b/native/cocos/physics/physx/character-controllers/PhysXCharacterController.cpp @@ -259,12 +259,14 @@ void PhysXCharacterController::syncPhysicsToScene() { void PhysXCharacterController::insertToCCTMap() { if (_impl) { getPxCCTMap().insert(std::pair(reinterpret_cast(_impl), getObjectID())); + getPxCCTMap().insert(std::pair(reinterpret_cast(getShape()), getObjectID())); } } void PhysXCharacterController::eraseFromCCTMap() { if (_impl) { getPxCCTMap().erase(reinterpret_cast(_impl)); + getPxCCTMap().erase(reinterpret_cast(getShape())); } } @@ -272,6 +274,15 @@ cc::Vec3 PhysXCharacterController::scaledCenter() { return _mNode->getWorldScale() * _mCenter; } - +physx::PxShape* PhysXCharacterController::getShape() { + if (_impl) { + //cct's shape + physx::PxRigidDynamic* actor = _impl->getActor(); + physx::PxShape* shape; + actor->getShapes(&shape, 1); + return shape; + } + return nullptr; +} } // namespace physics } // namespace cc diff --git a/native/cocos/physics/physx/character-controllers/PhysXCharacterController.h b/native/cocos/physics/physx/character-controllers/PhysXCharacterController.h index 5ec9197a655..da11603ea10 100644 --- a/native/cocos/physics/physx/character-controllers/PhysXCharacterController.h +++ b/native/cocos/physics/physx/character-controllers/PhysXCharacterController.h @@ -88,6 +88,8 @@ class PhysXCharacterController : virtual public IBaseCharacterController { uint32_t getObjectID() const override { return _mObjectID; }; //ICharacterController END + inline physx::PxController& getCCT() { return *_impl; }; + protected: physx::PxController* _impl{ nullptr }; uint8_t _mFlag{ 0 }; @@ -114,6 +116,7 @@ class PhysXCharacterController : virtual public IBaseCharacterController { void insertToCCTMap(); void eraseFromCCTMap(); cc::Vec3 scaledCenter(); + physx::PxShape* getShape(); }; } // namespace physics diff --git a/native/cocos/physics/sdk/World.cpp b/native/cocos/physics/sdk/World.cpp index cf0dbba7cfb..6849def1576 100644 --- a/native/cocos/physics/sdk/World.cpp +++ b/native/cocos/physics/sdk/World.cpp @@ -82,6 +82,10 @@ ccstd::vector>& World::getCCTShapeEventPairs( return _impl->getCCTShapeEventPairs(); } +ccstd::vector> &World::getCCTTriggerEventPairs() { + return _impl->getCCTTriggerEventPairs(); +} + void World::setCollisionMatrix(uint32_t i, uint32_t m) { _impl->setCollisionMatrix(i, m); } diff --git a/native/cocos/physics/sdk/World.h b/native/cocos/physics/sdk/World.h index 64661216602..33be08ac30c 100644 --- a/native/cocos/physics/sdk/World.h +++ b/native/cocos/physics/sdk/World.h @@ -44,6 +44,7 @@ class CC_DLL World final : public IPhysicsWorld { ccstd::vector> &getTriggerEventPairs() override; ccstd::vector>& getContactEventPairs() override; ccstd::vector>& getCCTShapeEventPairs() override; + ccstd::vector>& getCCTTriggerEventPairs() override; bool raycast(RaycastOptions &opt) override; bool raycastClosest(RaycastOptions &opt) override; ccstd::vector &raycastResult() override; diff --git a/native/cocos/physics/spec/IWorld.h b/native/cocos/physics/spec/IWorld.h index ea69d7d7f15..062b8d37cdc 100644 --- a/native/cocos/physics/spec/IWorld.h +++ b/native/cocos/physics/spec/IWorld.h @@ -90,6 +90,17 @@ struct CCTShapeEventPair { } }; +struct CCTTriggerEventPair { + uint32_t cct; //wrapper object ID + uint32_t shape; //wrapper object ID + ETouchState state; + static constexpr uint8_t COUNT = 3; + CCTTriggerEventPair(const uint32_t cct, const uint32_t shape) + : cct(cct), + shape(shape), + state(ETouchState::ENTER) {} +}; + struct ConvexDesc { void *positions; uint32_t positionLength; @@ -138,6 +149,7 @@ class IPhysicsWorld { virtual ccstd::vector> &getTriggerEventPairs() = 0; virtual ccstd::vector>& getContactEventPairs() = 0; virtual ccstd::vector>& getCCTShapeEventPairs() = 0; + virtual ccstd::vector> &getCCTTriggerEventPairs() = 0; virtual bool raycast(RaycastOptions &opt) = 0; virtual bool raycastClosest(RaycastOptions &opt) = 0; virtual ccstd::vector &raycastResult() = 0; diff --git a/platforms/native/engine/jsb-physics.js b/platforms/native/engine/jsb-physics.js index 49973ef4c94..8b92d375ea9 100644 --- a/platforms/native/engine/jsb-physics.js +++ b/platforms/native/engine/jsb-physics.js @@ -52,6 +52,13 @@ const CCTShapeEventObject = { motionLength: 0, }; +const CharacterTriggerEventObject = { + type: 'onControllerTriggerEnter', + characterController: null, + collider: null, + impl: null, +}; + function emitTriggerEvent (t, c0, c1, impl) { TriggerEventObject.type = t; TriggerEventObject.impl = impl; @@ -67,6 +74,19 @@ function emitTriggerEvent (t, c0, c1, impl) { } } +function emitCCTTriggerEvent (t, cct, collider, impl) { + CharacterTriggerEventObject.type = t; + CharacterTriggerEventObject.impl = impl; + CharacterTriggerEventObject.characterController = cct; + CharacterTriggerEventObject.collider = collider; + if (collider.needTriggerEvent) { + collider.emit(t, CharacterTriggerEventObject); + } + if (cct.needTriggerEvent) { + cct.emit(t, CharacterTriggerEventObject); + } +} + const quat = new cc.Quat(); const contactsPool = []; const contactBufferElementLength = 12; @@ -138,7 +158,7 @@ function emitCollisionEvent (t, c0, c1, impl, b) { } } -function emitCCTShapeEvent (t, cct, collider, b) { +function emitCCTCollisionEvent (t, cct, collider, b) { CCTShapeEventObject.type = t; const contactCount = b.length / 10; @@ -211,8 +231,16 @@ class PhysicsWorld { raycastOptions.mask = options.mask >>> 0; raycastOptions.distance = options.maxDistance; raycastOptions.queryTrigger = !!options.queryTrigger; - const isHit = this._impl.sweepBox(raycastOptions, halfExtent.x, halfExtent.y, halfExtent.z, - orientation.w, orientation.x, orientation.y, orientation.z); + const isHit = this._impl.sweepBox( + raycastOptions, + halfExtent.x, + halfExtent.y, + halfExtent.z, + orientation.w, + orientation.x, + orientation.y, + orientation.z, + ); if (isHit) { const hits = this._impl.sweepResult(); for (let i = 0; i < hits.length; i++) { @@ -231,8 +259,16 @@ class PhysicsWorld { raycastOptions.mask = options.mask >>> 0; raycastOptions.distance = options.maxDistance; raycastOptions.queryTrigger = !!options.queryTrigger; - const isHit = this._impl.sweepBoxClosest(raycastOptions, halfExtent.x, halfExtent.y, halfExtent.z, - orientation.w, orientation.x, orientation.y, orientation.z); + const isHit = this._impl.sweepBoxClosest( + raycastOptions, + halfExtent.x, + halfExtent.y, + halfExtent.z, + orientation.w, + orientation.x, + orientation.y, + orientation.z, + ); if (isHit) { const hit = this._impl.sweepClosestResult(); result._assign(hit.hitPoint, hit.distance, ptrToObj[hit.shape].collider, hit.hitNormal); @@ -298,8 +334,15 @@ class PhysicsWorld { raycastOptions.mask = options.mask >>> 0; raycastOptions.distance = options.maxDistance; raycastOptions.queryTrigger = !!options.queryTrigger; - const isHit = this._impl.sweepCapsuleClosest(raycastOptions, radius, height, - orientation.w, orientation.x, orientation.y, orientation.z); + const isHit = this._impl.sweepCapsuleClosest( + raycastOptions, + radius, + height, + orientation.w, + orientation.x, + orientation.y, + orientation.z, + ); if (isHit) { const hit = this._impl.sweepClosestResult(); result._assign(hit.hitPoint, hit.distance, ptrToObj[hit.shape].collider, hit.hitNormal); @@ -310,7 +353,8 @@ class PhysicsWorld { emitEvents () { this.emitTriggerEvent(); this.emitCollisionEvent(); - this.emitCCTShapeEvent(); + this.emitCCTCollisionEvent(); + this.emitCCTTriggerEvent(); this._impl.emitEvents(); } @@ -366,7 +410,7 @@ class PhysicsWorld { } } - emitCCTShapeEvent () { + emitCCTCollisionEvent () { const events = this._impl.getCCTShapeEventPairs(); const len2 = events.length / 3; for (let i = 0; i < len2; i++) { @@ -375,7 +419,30 @@ class PhysicsWorld { if (!cct || !shape) continue; const c0 = cct.characterController; const c1 = shape.collider; if (!(c0 && c0.isValid && c1 && c1.isValid)) continue; - emitCCTShapeEvent('onControllerColliderHit', c0, c1, events[t + 2]); + emitCCTCollisionEvent('onControllerColliderHit', c0, c1, events[t + 2]); + } + } + + emitCCTTriggerEvent () { + const teps = this._impl.getCCTTriggerEventPairs(); + const len = teps.length / 3; + for (let i = 0; i < len; i++) { + const t = i * 3; + const sa = ptrToObj[teps[t + 0]]; + const sb = ptrToObj[teps[t + 1]]; + if (!sa || !sb) continue; + const cct = sa.characterController; + const collider = sb.collider; + if (!(cct && cct.isValid && collider && collider.isValid)) continue; + if (!collider.needTriggerEvent) continue; + const state = teps[t + 2]; + if (state === 1) { + emitCCTTriggerEvent('onControllerTriggerStay', cct, collider, teps); + } else if (state === 0) { + emitCCTTriggerEvent('onControllerTriggerEnter', cct, collider, teps); + } else { + emitCCTTriggerEvent('onControllerTriggerExit', cct, collider, teps); + } } } } From a77a6c94884e19dfb2bb97ae57f89d5a77dfaff1 Mon Sep 17 00:00:00 2001 From: Zach Lee Date: Fri, 18 Aug 2023 11:05:53 +0800 Subject: [PATCH 138/184] fix instanced buffer. (#16017) --- native/cocos/renderer/pipeline/InstancedBuffer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/native/cocos/renderer/pipeline/InstancedBuffer.cpp b/native/cocos/renderer/pipeline/InstancedBuffer.cpp index bd5f02f1d4b..a26cc71c0b7 100644 --- a/native/cocos/renderer/pipeline/InstancedBuffer.cpp +++ b/native/cocos/renderer/pipeline/InstancedBuffer.cpp @@ -157,6 +157,7 @@ void InstancedBuffer::uploadBuffers(gfx::CommandBuffer *cmdBuff) const { if (!instance.drawInfo.instanceCount) continue; cmdBuff->updateBuffer(instance.vb, instance.data, instance.vb->getSize()); + instance.ia->setInstanceCount(instance.drawInfo.instanceCount); } } From 541ef96eb8ca01dc0a654121c97f94011fd85fbf Mon Sep 17 00:00:00 2001 From: Gin Date: Fri, 18 Aug 2023 11:27:21 +0800 Subject: [PATCH 139/184] update: i18n text of CurveRange (#16019) --- editor/i18n/en/localization.js | 13 +++++++++++++ editor/i18n/zh/localization.js | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/editor/i18n/en/localization.js b/editor/i18n/en/localization.js index ac6f45fe483..c3b05125f0a 100755 --- a/editor/i18n/en/localization.js +++ b/editor/i18n/en/localization.js @@ -49,6 +49,19 @@ module.exports = link(mixin({ }, }, }, + CurveRange: { + properties: { + spline: { + displayName: 'Spline', + }, + splineMin: { + displayName: 'Spline Min', + }, + splineMax: { + displayName: 'Spline Max', + }, + }, + }, }, }, diff --git a/editor/i18n/zh/localization.js b/editor/i18n/zh/localization.js index a2c1052c6fb..cd3a0881867 100755 --- a/editor/i18n/zh/localization.js +++ b/editor/i18n/zh/localization.js @@ -50,6 +50,19 @@ module.exports = link(mixin({ }, }, }, + CurveRange: { + properties: { + spline: { + displayName: 'Spline', + }, + splineMin: { + displayName: 'Spline Min', + }, + splineMax: { + displayName: 'Spline Max', + }, + }, + }, }, help: { From c589518f3d6764d2dcdac63c881117b5ca6f242a Mon Sep 17 00:00:00 2001 From: Jiujiang Liu <37231523+moshuying@users.noreply.github.com> Date: Fri, 18 Aug 2023 13:48:21 +0800 Subject: [PATCH 140/184] disable show probe (#15887) --- cocos/scene-graph/scene-globals.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/cocos/scene-graph/scene-globals.ts b/cocos/scene-graph/scene-globals.ts index f3d97b259d5..4907c9e0d2f 100644 --- a/cocos/scene-graph/scene-globals.ts +++ b/cocos/scene-graph/scene-globals.ts @@ -1312,8 +1312,6 @@ export class LightProbeInfo { * @en Whether to show light probe * @zh 是否显示光照探针 */ - @editable - @tooltip('i18n:light_probe.showProbe') set showProbe (val: boolean) { if (this._showProbe === val) return; this._showProbe = val; From f4a7b9576739ddba77d030502feb3de619a1ca0d Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Fri, 18 Aug 2023 14:32:30 +0800 Subject: [PATCH 141/184] fix sprite world matrix update bug (#15978) * fix sprite world matrix update bug * fix by flag Changed Version * add test * CI & more test --- cocos/2d/assembler/sprite/bar-filled.ts | 3 +- cocos/2d/assembler/sprite/radial-filled.ts | 63 ++++++--- cocos/2d/assembler/sprite/simple.ts | 3 +- cocos/2d/assembler/sprite/sliced.ts | 7 +- cocos/2d/assembler/sprite/tiled.ts | 14 +- cocos/2d/framework/ui-renderer.ts | 16 ++- tests/ui/sprite.test.ts | 145 +++++++++++++++++++++ 7 files changed, 218 insertions(+), 33 deletions(-) create mode 100644 tests/ui/sprite.test.ts diff --git a/cocos/2d/assembler/sprite/bar-filled.ts b/cocos/2d/assembler/sprite/bar-filled.ts index b0244832800..9d1088c62b0 100644 --- a/cocos/2d/assembler/sprite/bar-filled.ts +++ b/cocos/2d/assembler/sprite/bar-filled.ts @@ -236,9 +236,10 @@ export const barFilled: IAssembler = { fillBuffers (sprite: Sprite, renderer: IBatcher) { const renderData: RenderData = sprite.renderData!; const chunk = renderData.chunk; - if (sprite.node.hasChangedFlags || renderData.vertDirty) { + if (sprite._flagChangedVersion !== sprite.node.flagChangedVersion || renderData.vertDirty) { this.updateWorldVertexData(sprite, chunk); renderData.vertDirty = false; + sprite._flagChangedVersion = sprite.node.flagChangedVersion; } const bid = chunk.bufferId; diff --git a/cocos/2d/assembler/sprite/radial-filled.ts b/cocos/2d/assembler/sprite/radial-filled.ts index c7d0685e5c1..aa869b0ee17 100644 --- a/cocos/2d/assembler/sprite/radial-filled.ts +++ b/cocos/2d/assembler/sprite/radial-filled.ts @@ -27,7 +27,7 @@ import { SpriteFrame } from '../../assets'; import { Mat4, Vec2 } from '../../../core'; import { IRenderData, RenderData } from '../../renderer/render-data'; import { IBatcher } from '../../renderer/i-batcher'; -import { Sprite, UIOpacity } from '../../components'; +import { Sprite } from '../../components'; import { IAssembler } from '../../renderer/base'; import { dynamicAtlasManager } from '../../utils/dynamic-atlas/atlas-manager'; import { StaticVBChunk } from '../../renderer/static-vb-accessor'; @@ -43,9 +43,9 @@ const _intersectPoint_1: Vec2[] = [new Vec2(), new Vec2(), new Vec2(), new Vec2( const _intersectPoint_2: Vec2[] = [new Vec2(), new Vec2(), new Vec2(), new Vec2()]; const _center = new Vec2(); const _triangles: Vec2[] = [new Vec2(), new Vec2(), new Vec2(), new Vec2()]; -let QUAD_INDICES; +let QUAD_INDICES: Uint16Array | null = null; -function _calcIntersectedPoints (left, right, bottom, top, center: Vec2, angle, intersectPoints: Vec2[]): void { +function _calcIntersectedPoints (left, right, bottom, top, center: Vec2, angle: number, intersectPoints: Vec2[]): void { // left bottom, right, top let sinAngle = Math.sin(angle); sinAngle = Math.abs(sinAngle) > EPSILON ? sinAngle : 0; @@ -269,14 +269,22 @@ export const radialFilled: IAssembler = { // build uvs _calculateUVs(frame); _calcIntersectedPoints( - _vertices[0], _vertices[2], - _vertices[1], _vertices[3], - _center, fillStart, _intersectPoint_1, + _vertices[0], + _vertices[2], + _vertices[1], + _vertices[3], + _center, + fillStart, + _intersectPoint_1, ); _calcIntersectedPoints( - _vertices[0], _vertices[2], - _vertices[1], _vertices[3], - _center, fillStart + fillRange, _intersectPoint_2, + _vertices[0], + _vertices[2], + _vertices[1], + _vertices[3], + _center, + fillStart + fillRange, + _intersectPoint_2, ); let offset = 0; @@ -307,14 +315,21 @@ export const radialFilled: IAssembler = { if (endAngle >= fillEnd) { // startAngle to fillEnd _generateTriangle( - dataList, offset, _center, + dataList, + offset, + _center, _vertPos[triangle.x], _intersectPoint_2[triangleIndex], ); } else { // startAngle to endAngle - _generateTriangle(dataList, offset, _center, - _vertPos[triangle.x], _vertPos[triangle.y]); + _generateTriangle( + dataList, + offset, + _center, + _vertPos[triangle.x], + _vertPos[triangle.y], + ); } offset += 3; } else if (endAngle > fillStart) { @@ -322,16 +337,24 @@ export const radialFilled: IAssembler = { if (endAngle <= fillEnd) { renderData.dataLength = offset + 3; // fillStart to endAngle - _generateTriangle(dataList, offset, _center, + _generateTriangle( + dataList, + offset, + _center, _intersectPoint_1[triangleIndex], - _vertPos[triangle.y]); + _vertPos[triangle.y], + ); offset += 3; } else { renderData.dataLength = offset + 3; // fillStart to fillEnd - _generateTriangle(dataList, offset, _center, + _generateTriangle( + dataList, + offset, + _center, _intersectPoint_1[triangleIndex], - _intersectPoint_2[triangleIndex]); + _intersectPoint_2[triangleIndex], + ); offset += 3; } } @@ -348,7 +371,7 @@ export const radialFilled: IAssembler = { if (JSB) { const indexCount = renderData.indexCount; this.createQuadIndices(indexCount); - renderData.chunk.setIndexBuffer(QUAD_INDICES); + renderData.chunk.setIndexBuffer(QUAD_INDICES!); // may can update color & uv here // need dirty this.updateWorldUVData(sprite); @@ -359,7 +382,7 @@ export const radialFilled: IAssembler = { } }, - createQuadIndices (indexCount) { + createQuadIndices (indexCount: number) { QUAD_INDICES = null; QUAD_INDICES = new Uint16Array(indexCount); let offset = 0; @@ -372,9 +395,10 @@ export const radialFilled: IAssembler = { const node = comp.node; const renderData: RenderData = comp.renderData!; const chunk = renderData.chunk; - if (node.hasChangedFlags || renderData.vertDirty) { + if (comp._flagChangedVersion !== node.flagChangedVersion || renderData.vertDirty) { this.updateWorldVertexAndUVData(comp, chunk); renderData.vertDirty = false; + comp._flagChangedVersion = node.flagChangedVersion; } // forColor @@ -464,5 +488,6 @@ export const radialFilled: IAssembler = { // Too early updateColor (sprite: Sprite) { + // Update color by updateColorLate }, }; diff --git a/cocos/2d/assembler/sprite/simple.ts b/cocos/2d/assembler/sprite/simple.ts index c214a2a31e6..cd3d03048ef 100644 --- a/cocos/2d/assembler/sprite/simple.ts +++ b/cocos/2d/assembler/sprite/simple.ts @@ -99,10 +99,11 @@ export const simple: IAssembler = { const renderData = sprite.renderData!; const chunk = renderData.chunk; - if (sprite.node.hasChangedFlags || renderData.vertDirty) { + if (sprite._flagChangedVersion !== sprite.node.flagChangedVersion || renderData.vertDirty) { // const vb = chunk.vertexAccessor.getVertexBuffer(chunk.bufferId); this.updateWorldVerts(sprite, chunk); renderData.vertDirty = false; + sprite._flagChangedVersion = sprite.node.flagChangedVersion; } // quick version diff --git a/cocos/2d/assembler/sprite/sliced.ts b/cocos/2d/assembler/sprite/sliced.ts index 0d4be8aef0c..942d6f62038 100644 --- a/cocos/2d/assembler/sprite/sliced.ts +++ b/cocos/2d/assembler/sprite/sliced.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { Color, Mat4, Vec3 } from '../../../core'; +import { Color, Mat4 } from '../../../core'; import { IRenderData, RenderData } from '../../renderer/render-data'; import { IBatcher } from '../../renderer/i-batcher'; import { Sprite } from '../../components'; @@ -51,7 +51,7 @@ export const sliced: IAssembler = { renderData.vertexCol = 4; this.QUAD_INDICES = new Uint16Array(54); this.createQuadIndices(4, 4); - renderData.chunk.setIndexBuffer(this.QUAD_INDICES); + renderData.chunk.setIndexBuffer(this.QUAD_INDICES as Uint16Array); return renderData; }, @@ -156,9 +156,10 @@ export const sliced: IAssembler = { fillBuffers (sprite: Sprite, renderer: IBatcher) { const renderData: RenderData = sprite.renderData!; const chunk = renderData.chunk; - if (sprite.node.hasChangedFlags || renderData.vertDirty) { + if (sprite._flagChangedVersion !== sprite.node.flagChangedVersion || renderData.vertDirty) { this.updateWorldVertexData(sprite, chunk); renderData.vertDirty = false; + sprite._flagChangedVersion = sprite.node.flagChangedVersion; } const bid = chunk.bufferId; diff --git a/cocos/2d/assembler/sprite/tiled.ts b/cocos/2d/assembler/sprite/tiled.ts index 502ebb5fe4f..8c271e500b5 100644 --- a/cocos/2d/assembler/sprite/tiled.ts +++ b/cocos/2d/assembler/sprite/tiled.ts @@ -24,7 +24,7 @@ import { JSB } from 'internal:constants'; import { IUV, SpriteFrame } from '../../assets/sprite-frame'; -import { Mat4, Vec3, Color } from '../../../core'; +import { Mat4, Vec3, Color, error } from '../../../core'; import { IRenderData, RenderData } from '../../renderer/render-data'; import { IBatcher } from '../../renderer/i-batcher'; import { Sprite } from '../../components/sprite'; @@ -43,7 +43,7 @@ let topInner: IUV; let topOuter: IUV; let tempRenderDataLength = 0; const tempRenderData: IRenderData[] = []; -let QUAD_INDICES; +let QUAD_INDICES: Uint16Array | null = null; function has9SlicedOffsetVertexCount (spriteFrame: SpriteFrame): number { if (spriteFrame) { @@ -109,7 +109,7 @@ export const tiled: IAssembler = { if (JSB) { const indexCount = renderData.indexCount; this.createQuadIndices(indexCount); - renderData.chunk.setIndexBuffer(QUAD_INDICES); + renderData.chunk.setIndexBuffer(QUAD_INDICES!); // may can update color & uv here // need dirty this.updateWorldUVData(sprite); @@ -119,9 +119,9 @@ export const tiled: IAssembler = { renderData.updateRenderData(sprite, frame); }, - createQuadIndices (indexCount) { + createQuadIndices (indexCount: number) { if (indexCount % 6 !== 0) { - console.error('illegal index count!'); + error('illegal index count!'); return; } const quadCount = indexCount / 6; @@ -150,9 +150,10 @@ export const tiled: IAssembler = { const node = sprite.node; const renderData: RenderData = sprite.renderData!; const chunk = renderData.chunk; - if (node.hasChangedFlags || renderData.vertDirty) { + if (sprite._flagChangedVersion !== node.flagChangedVersion || renderData.vertDirty) { this.updateWorldVertexAndUVData(sprite, chunk); renderData.vertDirty = false; + sprite._flagChangedVersion = node.flagChangedVersion; } // forColor @@ -512,5 +513,6 @@ export const tiled: IAssembler = { // Too early updateColor (sprite: Sprite) { + // Update color by updateColorLate }, }; diff --git a/cocos/2d/framework/ui-renderer.ts b/cocos/2d/framework/ui-renderer.ts index bb4c4a2abd6..d79a81d315f 100644 --- a/cocos/2d/framework/ui-renderer.ts +++ b/cocos/2d/framework/ui-renderer.ts @@ -278,6 +278,10 @@ export class UIRenderer extends Renderer { * @deprecated Since v3.7.0, this is an engine private interface that will be removed in the future. */ public _internalId = -1; + /** + * @engineInternal + */ + public _flagChangedVersion = -1; /** * @deprecated Since v3.7.0, this is an engine private interface that will be removed in the future. @@ -429,9 +433,13 @@ export class UIRenderer extends Renderer { } } - protected _render (render: IBatcher): void { } + protected _render (render: IBatcher): void { + // Implemented by subclasses + } - protected _postRender (render: IBatcher): void { } + protected _postRender (render: IBatcher): void { + // Implemented by subclasses + } protected _canRender (): boolean { if (DEBUG) { @@ -442,7 +450,9 @@ export class UIRenderer extends Renderer { && this._color.a > 0; } - protected _postCanRender (): void { } + protected _postCanRender (): void { + // Implemented by subclasses + } /** * @engineInternal diff --git a/tests/ui/sprite.test.ts b/tests/ui/sprite.test.ts new file mode 100644 index 00000000000..b05a02d2ee8 --- /dev/null +++ b/tests/ui/sprite.test.ts @@ -0,0 +1,145 @@ +import { Canvas, SpriteFrame, UITransform } from "../../cocos/2d"; +import { Sprite, UIOpacity } from "../../cocos/2d/components"; +import { Texture2D } from "../../cocos/asset/assets"; +import { Node } from "../../cocos/scene-graph/node"; +import { Camera, Scene, Size, Vec3, director, game } from "../../exports/base"; +import { Batcher2D } from "../../cocos/2d/renderer/batcher-2d"; + +test('sprite.updateWorldMatrix', () => { + + // @ts-expect-error + director.root!._batcher = new Batcher2D(director.root!); + + const scene = new Scene('test'); + director.runSceneImmediate(scene); + + let canvasNode = new Node("Canvas"); + scene.addChild(canvasNode); + let canvas = canvasNode.addComponent(Canvas) as Canvas; + let uitrs = canvasNode.addComponent(UITransform) as UITransform; + uitrs.contentSize = new Size(600, 600); + + let uiCamera = new Node('UICamera'); + let camera = uiCamera.addComponent(Camera) as Camera; + uiCamera.parent = canvasNode; + canvas.cameraComponent = camera; + // camera._createCamera(); + // camera.onEnable(); + + let node = new Node('root'); + let spriteFrame = new SpriteFrame(); + let texture = new Texture2D(); + spriteFrame.texture = texture; + + node.setParent(canvasNode); + + let node1 = new Node('sprite1'); + node1.addComponent(Sprite); + let sprite1 = node1.getComponent(Sprite) as Sprite; + node1.parent = node; + + let node2 = new Node('sprite2'); + node2.addComponent(Sprite); + let sprite2 = node2.getComponent(Sprite) as Sprite; + node2.parent = node; + + let node3 = new Node('sprite3'); + node3.addComponent(Sprite); + let sprite3 = node3.getComponent(Sprite) as Sprite; + node3.parent = node; + + let node4 = new Node('sprite4'); + node4.addComponent(Sprite); + let sprite4 = node4.getComponent(Sprite) as Sprite; + node4.parent = node; + + let node5 = new Node('sprite5'); + node5.addComponent(Sprite); + let sprite5 = node5.getComponent(Sprite) as Sprite; + node5.parent = node; + + sprite1.spriteFrame = spriteFrame; + sprite2.spriteFrame = spriteFrame; + sprite3.spriteFrame = spriteFrame; + sprite4.spriteFrame = spriteFrame; + sprite5.spriteFrame = spriteFrame; + + sprite1.type = Sprite.Type.SIMPLE; + sprite2.type = Sprite.Type.SLICED; + sprite3.type = Sprite.Type.TILED; + sprite4.type = Sprite.Type.FILLED; + sprite5.type = Sprite.Type.FILLED; + sprite4.fillType = Sprite.FillType.HORIZONTAL; + sprite5.fillType = Sprite.FillType.RADIAL; + + sprite5.fillRange = 1; + + let opacity = node.addComponent(UIOpacity) as UIOpacity; + + // normal part + node.setPosition(100, 100, 0); + game.step(); + expect(sprite1.node._pos).toStrictEqual(new Vec3(100, 100, 0)); + expect(sprite2.node._pos).toStrictEqual(new Vec3(100, 100, 0)); + expect(sprite3.node._pos).toStrictEqual(new Vec3(100, 100, 0)); + expect(sprite4.node._pos).toStrictEqual(new Vec3(100, 100, 0)); + expect(sprite5.node._pos).toStrictEqual(new Vec3(100, 100, 0)); + + // disabled part + node.active = false; + node.setPosition(200, 200, 0); + game.step(); + node.active = true; + game.step(); + expect(sprite1.node._pos).toStrictEqual(new Vec3(200, 200, 0)); + expect(sprite2.node._pos).toStrictEqual(new Vec3(200, 200, 0)); + expect(sprite3.node._pos).toStrictEqual(new Vec3(200, 200, 0)); + expect(sprite4.node._pos).toStrictEqual(new Vec3(200, 200, 0)); + expect(sprite5.node._pos).toStrictEqual(new Vec3(200, 200, 0)); + + // opacity part + opacity.opacity = 0; + node.setPosition(300, 300, 0); + game.step(); + opacity.opacity = 255; + game.step(); + expect(sprite1.node._pos).toStrictEqual(new Vec3(300, 300, 0)); + expect(sprite2.node._pos).toStrictEqual(new Vec3(300, 300, 0)); + expect(sprite3.node._pos).toStrictEqual(new Vec3(300, 300, 0)); + expect(sprite4.node._pos).toStrictEqual(new Vec3(300, 300, 0)); + expect(sprite5.node._pos).toStrictEqual(new Vec3(300, 300, 0)); + + // disabled & after node change part + node.active = false; + node.setPosition(200, 200, 0); + game.step(); + sprite1.node.worldMatrix; + sprite2.node.worldMatrix; + sprite3.node.worldMatrix; + sprite4.node.worldMatrix; + sprite5.node.worldMatrix; + node.active = true; + game.step(); + expect(sprite1.renderData!.chunk.vb[0]).toStrictEqual(200 - 0.5); + expect(sprite2.renderData!.chunk.vb[0]).toStrictEqual(200 - 0.5); + expect(sprite3.renderData!.chunk.vb[0]).toStrictEqual(200 - 0.5); + expect(sprite4.renderData!.chunk.vb[0]).toStrictEqual(200 - 0.5); + expect(sprite5.renderData!.chunk.vb[0]).toStrictEqual(200 - 0.5); + + // opacity & after node change part + opacity.opacity = 0; + node.setPosition(300, 300, 0); + game.step(); + sprite1.node.worldMatrix; + sprite2.node.worldMatrix; + sprite3.node.worldMatrix; + sprite4.node.worldMatrix; + sprite5.node.worldMatrix; + opacity.opacity = 255; + game.step(); + expect(sprite1.renderData!.chunk.vb[0]).toStrictEqual(300 - 0.5); + expect(sprite2.renderData!.chunk.vb[0]).toStrictEqual(300 - 0.5); + expect(sprite3.renderData!.chunk.vb[0]).toStrictEqual(300 - 0.5); + expect(sprite4.renderData!.chunk.vb[0]).toStrictEqual(300 - 0.5); + expect(sprite5.renderData!.chunk.vb[0]).toStrictEqual(300 - 0.5); +}); \ No newline at end of file From daa4a4ffbc114702f09eb3bac79e64dbc6783394 Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Fri, 18 Aug 2023 14:40:26 +0800 Subject: [PATCH 142/184] remove unnecessary code (#15687) * Revert "Revert "remove useless code (#15682)" (#15683)" This reverts commit b318b39eb97584c890249755d68b9f729061b9bb. * fix lint * Revert "fix lint" This reverts commit 269acd1715a93d59f61286d336afa9a03f07f805. * revert some change * fix lint --- cocos/2d/assembler/label/ttf.ts | 4 +-- cocos/2d/assembler/sprite/bar-filled.ts | 2 -- cocos/2d/assembler/sprite/simple.ts | 45 ++++++++++--------------- cocos/2d/assembler/sprite/sliced.ts | 8 ++--- 4 files changed, 22 insertions(+), 37 deletions(-) diff --git a/cocos/2d/assembler/label/ttf.ts b/cocos/2d/assembler/label/ttf.ts index 73c3b2b255a..68e3a4580fc 100644 --- a/cocos/2d/assembler/label/ttf.ts +++ b/cocos/2d/assembler/label/ttf.ts @@ -60,8 +60,6 @@ export const ttf: IAssembler = { Color.toArray(vData, WHITE, offset); offset += 9; } - renderData.vertexRow = 2; - renderData.vertexCol = 2; renderData.chunk.setIndexBuffer(QUAD_INDICES); return renderData; }, @@ -149,7 +147,7 @@ export const ttf: IAssembler = { }, updateColor (comp: Label) { - + // no needs to update color }, }; diff --git a/cocos/2d/assembler/sprite/bar-filled.ts b/cocos/2d/assembler/sprite/bar-filled.ts index 9d1088c62b0..31e164023ad 100644 --- a/cocos/2d/assembler/sprite/bar-filled.ts +++ b/cocos/2d/assembler/sprite/bar-filled.ts @@ -196,8 +196,6 @@ export const barFilled: IAssembler = { // 0-4 for local vertex renderData.dataLength = 4; renderData.resize(4, 6); - renderData.vertexRow = 2; - renderData.vertexCol = 2; renderData.chunk.setIndexBuffer(QUAD_INDICES); // not need diff --git a/cocos/2d/assembler/sprite/simple.ts b/cocos/2d/assembler/sprite/simple.ts index cd3d03048ef..879d13d9266 100644 --- a/cocos/2d/assembler/sprite/simple.ts +++ b/cocos/2d/assembler/sprite/simple.ts @@ -45,8 +45,6 @@ export const simple: IAssembler = { const renderData = sprite.requestRenderData(); renderData.dataLength = 4; renderData.resize(4, 6); - renderData.vertexRow = 2; - renderData.vertexCol = 2; renderData.chunk.setIndexBuffer(QUAD_INDICES); return renderData; }, @@ -107,36 +105,29 @@ export const simple: IAssembler = { } // quick version - const bid = chunk.bufferId; const vidOrigin = chunk.vertexOffset; const meshBuffer = chunk.meshBuffer; const ib = chunk.meshBuffer.iData; let indexOffset = meshBuffer.indexOffset; - // rect count = vertex count - 1 - for (let curRow = 0; curRow < renderData.vertexRow - 1; curRow++) { - for (let curCol = 0; curCol < renderData.vertexCol - 1; curCol++) { - // vid is the index of the left bottom vertex in each rect. - const vid = vidOrigin + curRow * renderData.vertexCol + curCol; - - // left bottom - ib[indexOffset++] = vid; - // right bottom - ib[indexOffset++] = vid + 1; - // left top - ib[indexOffset++] = vid + renderData.vertexCol; - - // right bottom - ib[indexOffset++] = vid + 1; - // right top - ib[indexOffset++] = vid + 1 + renderData.vertexCol; - // left top - ib[indexOffset++] = vid + renderData.vertexCol; - - // IndexOffset should add 6 when vertices of a rect are visited. - meshBuffer.indexOffset += 6; - } - } + const vid = vidOrigin; + + // left bottom + ib[indexOffset++] = vid; + // right bottom + ib[indexOffset++] = vid + 1; + // left top + ib[indexOffset++] = vid + 2; + + // right bottom + ib[indexOffset++] = vid + 1; + // right top + ib[indexOffset++] = vid + 3; + // left top + ib[indexOffset++] = vid + 2; + + // IndexOffset should add 6 when vertices of a rect are visited. + meshBuffer.indexOffset += 6; // slow version // renderer.switchBufferAccessor().appendIndices(chunk); }, diff --git a/cocos/2d/assembler/sprite/sliced.ts b/cocos/2d/assembler/sprite/sliced.ts index 942d6f62038..e7164a077cb 100644 --- a/cocos/2d/assembler/sprite/sliced.ts +++ b/cocos/2d/assembler/sprite/sliced.ts @@ -47,8 +47,6 @@ export const sliced: IAssembler = { // 0-4 for local vertex renderData.dataLength = 16; renderData.resize(16, 54); - renderData.vertexRow = 4; - renderData.vertexCol = 4; this.QUAD_INDICES = new Uint16Array(54); this.createQuadIndices(4, 4); renderData.chunk.setIndexBuffer(this.QUAD_INDICES as Uint16Array); @@ -140,9 +138,9 @@ export const sliced: IAssembler = { tempRenderData[3].x = width - appX; tempRenderData[3].y = height - appY; - for (let curRow = 0; curRow < renderData.vertexRow; curRow++) { - for (let curCol = 0; curCol < renderData.vertexCol; curCol++) { - const curIndex = curRow * renderData.vertexCol + curCol; + for (let curRow = 0; curRow < 4; curRow++) { + for (let curCol = 0; curCol < 4; curCol++) { + const curIndex = curRow * 4 + curCol; if (curIndex < renderData.dataLength && curRow < tempRenderData.length && curCol < tempRenderData.length) { From 92c37fc921357dacbe6118d5db67668d1769c81d Mon Sep 17 00:00:00 2001 From: Canvas Date: Fri, 18 Aug 2023 14:44:17 +0800 Subject: [PATCH 143/184] fix the animation name is a number and is equal to the index. (#15871) * fix the case where the animation name is a number and is equal to the index. * revert onRestore code. * fix code format. * change internal -> engineInternal. * fix code format. --- cocos/spine/skeleton.ts | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index 3c4a77efac7..08c61481ddd 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -95,7 +95,7 @@ interface AnimationItem { } /** - * @internal Since v3.7.2, this is an engine private enum, only used in editor. + * @engineInternal */ export enum DefaultSkinsEnum { default = 0, @@ -103,7 +103,7 @@ export enum DefaultSkinsEnum { ccenum(DefaultSkinsEnum); /** - * @internal Since v3.7.2, this is an engine private enum, only used in editor. + * @engineInternal */ export enum DefaultAnimsEnum { '' = 0 @@ -111,7 +111,7 @@ export enum DefaultAnimsEnum { ccenum(DefaultAnimsEnum); /** - * @internal Since v3.7.2, this is an engine private enum. + * @engineInternal */ export enum SpineMaterialType { COLORED_TEXTURED = 0, @@ -125,7 +125,7 @@ interface AnimationItem { } /** - * @engineInternal Since v3.7.2, this is an engine private interface. + * @engineInternal */ export interface SkeletonDrawData { material: Material | null; @@ -253,11 +253,11 @@ export class Skeleton extends UIRenderer { protected _cachedSockets: Map = new Map(); /** - * @internal + * @engineInternal */ public _startEntry: spine.TrackEntry; /** - * @internal + * @engineInternal */ public _endEntry: spine.TrackEntry; // Paused or playing state @@ -306,7 +306,7 @@ export class Skeleton extends UIRenderer { } /** - * @engineInternal Since v3.7.2, this is an engine private interface. + * @engineInternal */ get drawList (): RecyclePool { return this._drawList; } @@ -342,7 +342,7 @@ export class Skeleton extends UIRenderer { } /** - * @internal Since v3.7.2, this is an engine private interface + * @engineInternal */ @displayName('Default Skin') @type(DefaultSkinsEnum) @@ -368,7 +368,7 @@ export class Skeleton extends UIRenderer { return 0; } /** - * @internal Since v3.7.2, this is an engine private interface. + * @engineInternal */ set _defaultSkinIndex (value: number) { let skinsEnum; @@ -393,7 +393,7 @@ export class Skeleton extends UIRenderer { // value of 0 represents no animation /** - * @internal + * @engineInternal */ @displayName('Animation') @type(DefaultAnimsEnum) @@ -416,7 +416,7 @@ export class Skeleton extends UIRenderer { return 0; } /** - * @internal + * @engineInternal */ set _animationIndex (value: number) { let animsEnum; @@ -427,7 +427,7 @@ export class Skeleton extends UIRenderer { error(`${this.name} animation enums are invalid`); return; } - const animName = animsEnum[value]; + const animName = String(animsEnum[value]); if (animName !== undefined) { this.animation = animName; if (EDITOR_NOT_IN_PREVIEW) { @@ -626,10 +626,16 @@ export class Skeleton extends UIRenderer { this._updateDebugDraw(); } - // eslint-disable-next-line @typescript-eslint/no-empty-function + // For Redo, Undo + // call markForUpdateRenderData to make sure renderData will be re-built. + /** + * @engineInternal + */ public onRestore (): void { - + this.updateMaterial(); + this.markForUpdateRenderData(); } + /** * @en Gets the animation state object. * @zh 获取动画状态。 @@ -697,7 +703,7 @@ export class Skeleton extends UIRenderer { if (!this._runtimeData) return; this.setSkeletonData(this._runtimeData); this._refreshInspector(); - if (this.defaultAnimation) this.animation = this.defaultAnimation; + if (this.defaultAnimation) this.animation = this.defaultAnimation.toString(); if (this.defaultSkin) this.setSkin(this.defaultSkin); this._updateUseTint(); this._indexBoneSockets(); @@ -1052,7 +1058,7 @@ export class Skeleton extends UIRenderer { } /** - * @engineInternal Since v3.7.2, this is an engine private interface. + * @engineInternal */ public getMaterialForBlendAndTint (src: BlendFactor, dst: BlendFactor, type: SpineMaterialType): MaterialInstance { const key = `${type}/${src}/${dst}`; @@ -1157,7 +1163,7 @@ export class Skeleton extends UIRenderer { } /** - * @engineInternal since v3.7.2 this is an engine private function. + * @engineInternal */ public syncAttachedNode (): void { // sync attached node matrix From 56417f35b06e7aa88c4bdc7a4bf70998c0082bb0 Mon Sep 17 00:00:00 2001 From: oahc09 Date: Fri, 18 Aug 2023 15:11:35 +0800 Subject: [PATCH 144/184] improve:adjust xr begin/end render frame call's position (#16021) (Calculate the correct delta time) --- native/cocos/engine/Engine.cpp | 5 +++-- native/cocos/engine/Engine.h | 3 +++ native/cocos/platform/android/AndroidPlatform.cpp | 2 -- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/native/cocos/engine/Engine.cpp b/native/cocos/engine/Engine.cpp index 50d34212923..86d7f48e69e 100644 --- a/native/cocos/engine/Engine.cpp +++ b/native/cocos/engine/Engine.cpp @@ -206,6 +206,7 @@ void Engine::destroy() { int32_t Engine::run() { BasePlatform *platform = BasePlatform::getPlatform(); + _xr = CC_GET_XR_INTERFACE(); platform->runInPlatformThread([&]() { tick(); }); @@ -284,7 +285,7 @@ void Engine::tick() { #endif prevTime = std::chrono::steady_clock::now(); - + if (_xr) _xr->beginRenderFrame(); _scheduler->update(dt); se::ScriptEngine::getInstance()->handlePromiseExceptions(); @@ -292,7 +293,7 @@ void Engine::tick() { se::ScriptEngine::getInstance()->mainLoopUpdate(); cc::DeferredReleasePool::clear(); - + if (_xr) _xr->endRenderFrame(); now = std::chrono::steady_clock::now(); dtNS = dtNS * 0.1 + 0.9 * static_cast(std::chrono::duration_cast(now - prevTime).count()); dt = static_cast(dtNS) / NANOSECONDS_PER_SECOND; diff --git a/native/cocos/engine/Engine.h b/native/cocos/engine/Engine.h index ff6281faa1c..74c989c56aa 100644 --- a/native/cocos/engine/Engine.h +++ b/native/cocos/engine/Engine.h @@ -48,6 +48,7 @@ class DebugRenderer; class Profiler; class BuiltinResMgr; class ProgramLib; +class IXRInterface; #define NANOSECONDS_PER_SECOND 1000000000 #define NANOSECONDS_60FPS 16666667L @@ -132,6 +133,8 @@ class CC_DLL Engine : public BaseEngine { events::WindowEvent::Listener _windowEventListener; CC_DISALLOW_COPY_MOVE_ASSIGN(Engine); + + IXRInterface *_xr{nullptr}; }; } // namespace cc diff --git a/native/cocos/platform/android/AndroidPlatform.cpp b/native/cocos/platform/android/AndroidPlatform.cpp index fc8d213420a..b14f3e2732f 100644 --- a/native/cocos/platform/android/AndroidPlatform.cpp +++ b/native/cocos/platform/android/AndroidPlatform.cpp @@ -843,9 +843,7 @@ int32_t AndroidPlatform::loop() { if (xr && !xr->platformLoopStart()) continue; _inputProxy->handleInput(); if (_inputProxy->isAnimating() && (xr ? xr->getXRConfig(xr::XRConfigKey::SESSION_RUNNING).getBool() : true)) { - if (xr) xr->beginRenderFrame(); runTask(); - if (xr) xr->endRenderFrame(); if (_inputProxy->isActive()) { flushTasksOnGameThreadAtForegroundJNI(); } From d8e75b225de15e90fee4b2bab140a6a48f4ff16c Mon Sep 17 00:00:00 2001 From: Cocos Robot <48829427+cocos-robot@users.noreply.github.com> Date: Fri, 18 Aug 2023 16:02:41 +0800 Subject: [PATCH 145/184] [ci skip][AUTO]: Automated code generating update: bc27ce06eb5f4f8922ed479ea00c9cc46011c61d (#16021) (#16029) Co-authored-by: cocos-robot --- cocos/native-binding/decorators.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/cocos/native-binding/decorators.ts b/cocos/native-binding/decorators.ts index cfdfc74d5c9..d2ab61a942b 100644 --- a/cocos/native-binding/decorators.ts +++ b/cocos/native-binding/decorators.ts @@ -515,7 +515,6 @@ export function patch_cc_LightProbeInfo(ctx: cc_LightProbeInfo_Context_Args, app const giSamplesDescriptor = Object.getOwnPropertyDescriptor(LightProbeInfo.prototype, 'giSamples'); const bouncesDescriptor = Object.getOwnPropertyDescriptor(LightProbeInfo.prototype, 'bounces'); const reduceRingingDescriptor = Object.getOwnPropertyDescriptor(LightProbeInfo.prototype, 'reduceRinging'); - const showProbeDescriptor = Object.getOwnPropertyDescriptor(LightProbeInfo.prototype, 'showProbe'); const showWireframeDescriptor = Object.getOwnPropertyDescriptor(LightProbeInfo.prototype, 'showWireframe'); const showConvexDescriptor = Object.getOwnPropertyDescriptor(LightProbeInfo.prototype, 'showConvex'); const lightProbeSphereVolumeDescriptor = Object.getOwnPropertyDescriptor(LightProbeInfo.prototype, 'lightProbeSphereVolume'); @@ -538,8 +537,6 @@ export function patch_cc_LightProbeInfo(ctx: cc_LightProbeInfo_Context_Args, app apply(() => { $.slide(LightProbeInfo.prototype, 'reduceRinging', reduceRingingDescriptor); }, 'slide', 'reduceRinging'); apply(() => { $.range([0.0, 0.05, 0.001])(LightProbeInfo.prototype, 'reduceRinging', reduceRingingDescriptor); }, 'range', 'reduceRinging'); apply(() => { $.editable(LightProbeInfo.prototype, 'reduceRinging', reduceRingingDescriptor); }, 'editable', 'reduceRinging'); - apply(() => { $.tooltip('i18n:light_probe.showProbe')(LightProbeInfo.prototype, 'showProbe', showProbeDescriptor); }, 'tooltip', 'showProbe'); - apply(() => { $.editable(LightProbeInfo.prototype, 'showProbe', showProbeDescriptor); }, 'editable', 'showProbe'); apply(() => { $.tooltip('i18n:light_probe.showWireframe')(LightProbeInfo.prototype, 'showWireframe', showWireframeDescriptor); }, 'tooltip', 'showWireframe'); apply(() => { $.editable(LightProbeInfo.prototype, 'showWireframe', showWireframeDescriptor); }, 'editable', 'showWireframe'); apply(() => { $.tooltip('i18n:light_probe.showConvex')(LightProbeInfo.prototype, 'showConvex', showConvexDescriptor); }, 'tooltip', 'showConvex'); From b0745d50bee84835a54866e8ae84ff0d6f5d0c1c Mon Sep 17 00:00:00 2001 From: mmyduckx <308303735@qq.com> Date: Fri, 18 Aug 2023 16:16:47 +0800 Subject: [PATCH 146/184] add bytedance videoplayer support (#16031) * add bytedance videoplayer support * refine --- .../bytedance/wrapper/engine/VideoPlayer.js | 391 ++++++++++++++++++ .../bytedance/wrapper/engine/index.js | 3 +- 2 files changed, 393 insertions(+), 1 deletion(-) create mode 100644 platforms/minigame/platforms/bytedance/wrapper/engine/VideoPlayer.js diff --git a/platforms/minigame/platforms/bytedance/wrapper/engine/VideoPlayer.js b/platforms/minigame/platforms/bytedance/wrapper/engine/VideoPlayer.js new file mode 100644 index 00000000000..16c572f4e30 --- /dev/null +++ b/platforms/minigame/platforms/bytedance/wrapper/engine/VideoPlayer.js @@ -0,0 +1,391 @@ +/**************************************************************************** + Copyright (c) 2023 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. +****************************************************************************/ + +if (cc.internal.VideoPlayer) { + const { EventType } = cc.internal.VideoPlayer; + + const vec3 = cc.Vec3; + const _mat4_temp = cc.mat4(); + + const _topLeft = new vec3(); + const _bottomRight = new vec3(); + + const dpr = tt.getSystemInfoSync().pixelRatio; + + cc.internal.VideoPlayerImplManager.getImpl = function (componenet) { + return new VideoPlayerImplMiniGame(componenet); + }; + + class VideoPlayerImplMiniGame extends cc.internal.VideoPlayerImpl { + constructor (componenet) { + super(componenet); + } + + syncClip (clip) { + this.removeVideoPlayer(); + if (!clip) { + return; + } + this.createVideoPlayer(clip._nativeAsset); + } + + syncURL (url) { + this.removeVideoPlayer(); + if (!url) { + return; + } + this.createVideoPlayer(url); + } + + onCanplay () { + if (this._loaded) { + return; + } + this._loaded = true; + this.setVisible(this._visible); + this.dispatchEvent(EventType.READY_TO_PLAY); + this.delayedPlay(); + } + + _bindEvent () { + const video = this._video; + const self = this; + + if (!video) { + return; + } + video.onCanplay(() => { + if (self._video !== video) return; + self._loaded = true; + self.setVisible(self._visible); + self.dispatchEvent(EventType.READY_TO_PLAY); + video.play(); + const initRect = self._getInitRect(); + function drawVideo () { + requestAnimationFrame(drawVideo); + video.paintTo(cc.game.canvas, initRect.x, initRect.y, 0, 0, initRect.width, initRect.height); + } + drawVideo(video); + }); + video.onPlay(() => { + if (self._video !== video) return; + self._playing = true; + self.dispatchEvent(EventType.PLAYING); + }); + video.onEnded(() => { + if (self._video !== video) return; + self._playing = false; + self._currentTime = self._duration; // ensure currentTime is at the end of duration + self.dispatchEvent(EventType.COMPLETED); + }); + video.onPause(() => { + if (self._video !== video) return; + self._playing = false; + self.dispatchEvent(EventType.PAUSED); + }); + video.onTimeUpdate((res) => { + self._duration = res.duration; + self._currentTime = res.position; + }); + video.onStop(() => { + if (self._video !== video) return; + self._playing = false; + self.dispatchEvent(EventType.STOPPED); + }); + } + + _unbindEvent () { + const video = this._video; + if (!video) { + return; + } + + video.offPlay(); + video.offEnded(); + video.offPause(); + video.offTimeUpdate(); + video.offStop(); + } + + createVideoPlayer (url) { + if (!tt.createVideo) { + console.warn('VideoPlayer not supported'); + return; + } + + if (!this._video) { + this._video = tt.createOffscreenVideo(); + this._duration = 0; + this._currentTime = 0; + this._loaded = false; + this.setVisible(this._visible); + this._bindEvent(); + this._forceUpdate = true; + } + + this.setURL(url); + this._forceUpdate = true; + } + + setURL (path) { + const video = this._video; + if (!video || video.src === path) { + return; + } + video.stop(); + this._unbindEvent(); + video.autoplay = true; + video.src = path; + video.muted = true; + const self = this; + this._loaded = false; + function loadedCallback () { + self._bindEvent(); + video.muted = false; + self._loaded = true; + self.dispatchEvent(EventType.READY_TO_PLAY); + } + function endedCallback () { + video.offPlay(); + video.stop(); + self._playing = false; + self._currentTime = 0; + self.dispatchEvent(EventType.COMPLETED); + } + video.onPlay(loadedCallback); + video.onEnded(endedCallback); + } + + removeVideoPlayer () { + const video = this.video; + if (video) { + video.stop(); + video.destroy(); + this._playing = false; + this._loaded = false; + this._loadedMeta = false; + this._ignorePause = false; + this._cachedCurrentTime = 0; + this._video = null; + } + } + + setVisible (value) { + const video = this._video; + if (!video || this._visible === value) { + return; + } + if (value) { + video.width = this._actualWidth || 0; + } else { + video.width = 0; // hide video + } + this._visible = value; + } + + getDuration () { + return this.duration(); + } + + duration () { + return this._duration; + } + + syncPlaybackRate (value) { + const video = this._video; + if (video && value !== video.playbackRate) { + if (value === 0.5 | value === 0.8 | value === 1.0 | value === 1.25 | value === 1.5) { + video.playbackRate = value; + } else { + console.warn('The platform does not support this PlaybackRate!'); + } + } + } + + syncVolume () { + console.warn('The platform does not support'); + } + + syncMute (enable) { + const video = this._video; + if (video && video.muted !== enable) { + video.muted = enable; + } + } + + syncLoop (enable) { + const video = this._video; + if (video && video.loop !== enable) { + video.loop = enable; + } + } + + syncStayOnBottom () { + console.warn('The platform does not support'); + } + + getCurrentTime () { + if (this.video) { + return this.currentTime(); + } + return -1; + } + + currentTime () { + return this._currentTime; + } + + seekTo (time) { + const video = this._video; + if (!video || !this._loaded) return; + video.seek(time); + } + + disable (noPause) { + if (this._video) { + if (!noPause) { + this._video.pause(); + } + this.setVisible(false); + this._visible = false; + } + } + + enable () { + if (this._video) { + this.setVisible(true); + this._visible = true; + } + } + + canPlay () { + this._video.play(); + this.syncCurrentTime(); + } + + resume () { + const video = this._video; + if (this._playing || !video) return; + + video.play(); + } + + pause () { + const video = this._video; + if (!this._playing || !video) return; + + video.pause(); + } + + stop () { + const self = this; + const video = this._video; + if (!video || !this._visible) return; + video.stop().then((res) => { + if (res.errMsg && !res.errMsg.includes('ok')) { + console.error('failed to stop video player'); + return; + } + self._currentTime = 0; + self._playing = false; + self.dispatchEvent(EventType.STOPPED); + }); + } + + canFullScreen (enabled) { + if (this._video) { + this.setFullScreenEnabled(enabled); + } + } + + setFullScreenEnabled (enable) { + const video = this._video; + if (!video || this._fullScreenEnabled === enable) { + return; + } + if (enable) { + video.requestFullScreen(); + } else { + video.exitFullScreen(); + } + this._fullScreenEnabled = enable; + } + + syncKeepAspectRatio (enabled) { + console.warn('On bytedance game videoPlayer is always keep the aspect ratio'); + } + + syncMatrix () { + // DO NOTHING... + } + + _getInitRect () { + if (!this._component || !this._uiTrans) return; + + const camera = this.UICamera; + if (!camera) { + return; + } + + this._component.node.getWorldMatrix(_mat4_temp); + const uiWidth = this._uiTrans.contentSize.width; + const uiHeight = this._uiTrans.contentSize.height; + + this._m00 = _mat4_temp.m00; + this._m01 = _mat4_temp.m01; + this._m04 = _mat4_temp.m04; + this._m05 = _mat4_temp.m05; + this._m12 = _mat4_temp.m12; + this._m13 = _mat4_temp.m13; + this._w = uiWidth; + this._h = uiHeight; + + const canvas_width = cc.game.canvas.width; + const canvas_height = cc.game.canvas.height; + + const ap = this._uiTrans.anchorPoint; + // Vectors in node space + vec3.set(_topLeft, -ap.x * this._w, (1.0 - ap.y) * this._h, 0); + vec3.set(_bottomRight, (1 - ap.x) * this._w, -ap.y * this._h, 0); + // Convert to world space + vec3.transformMat4(_topLeft, _topLeft, _mat4_temp); + vec3.transformMat4(_bottomRight, _bottomRight, _mat4_temp); + // Convert to Screen space + camera.worldToScreen(_topLeft, _topLeft); + camera.worldToScreen(_bottomRight, _bottomRight); + + const finalWidth = _bottomRight.x - _topLeft.x; + const finalHeight = _topLeft.y - _bottomRight.y; + + const x = _topLeft.x; + const y = canvas_height - _topLeft.y; + const width = finalWidth; + const height = finalHeight; + return { + x, y, width, height, + }; + } + } +} diff --git a/platforms/minigame/platforms/bytedance/wrapper/engine/index.js b/platforms/minigame/platforms/bytedance/wrapper/engine/index.js index bcb93ce2a33..26624d377e0 100644 --- a/platforms/minigame/platforms/bytedance/wrapper/engine/index.js +++ b/platforms/minigame/platforms/bytedance/wrapper/engine/index.js @@ -1,4 +1,5 @@ require('../fs-utils'); require('../../../../common/engine/index'); +require('./VideoPlayer'); require('./Label'); -require('./ImageAsset'); \ No newline at end of file +require('./ImageAsset'); From be9a52dc36c00a2cbfa14c84e5bd17a110714c28 Mon Sep 17 00:00:00 2001 From: pandamicro Date: Fri, 18 Aug 2023 17:32:05 +0800 Subject: [PATCH 147/184] export ISpriteFrameInitInfo for SpriteFrame reset (#16005) --- cocos/2d/assets/sprite-frame.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos/2d/assets/sprite-frame.ts b/cocos/2d/assets/sprite-frame.ts index abc7d4194f3..4f9394aaa4a 100644 --- a/cocos/2d/assets/sprite-frame.ts +++ b/cocos/2d/assets/sprite-frame.ts @@ -105,7 +105,7 @@ interface ISpriteFrameOriginal { * @en Information object interface for initialize a [[SpriteFrame]] asset. * @zh 用于初始化 [[SpriteFrame]] 资源的对象接口描述。 */ -interface ISpriteFrameInitInfo { +export interface ISpriteFrameInitInfo { /** * @en The texture of the sprite frame, could be `TextureBase`. * @zh 贴图对象资源,可以是 `TextureBase` 类型。 From ae9b42740b9647bce0e50581ec7ea18488efdda5 Mon Sep 17 00:00:00 2001 From: Yiwen <15225434259xue@gmail.com> Date: Fri, 18 Aug 2023 18:01:55 +0800 Subject: [PATCH 148/184] deprecate conetwsit constraint, use configurable constraint instead (#15987) --- cocos/physics/framework/deprecated.ts | 7 +++++++ cocos/physics/framework/physics-enum.ts | 1 + cocos/physics/framework/physics-selector.ts | 6 ++++++ cocos/physics/physx/instantiate.ts | 3 --- cocos/physics/spec/i-physics-constraint.ts | 3 +++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/cocos/physics/framework/deprecated.ts b/cocos/physics/framework/deprecated.ts index 9473bf7a3d8..6a9d9519d11 100644 --- a/cocos/physics/framework/deprecated.ts +++ b/cocos/physics/framework/deprecated.ts @@ -33,6 +33,7 @@ import { RigidBody } from './components/rigid-body'; import { Collider } from './components/colliders/collider'; import { PhysicsMaterial } from './assets/physics-material'; import { Constraint } from './components/constraints/constraint'; +import { EConstraintType } from './physics-enum'; replaceProperty(PhysicsSystem, 'PhysicsSystem', [ { @@ -147,6 +148,12 @@ removeProperty(RigidBody.prototype, 'RigidBody.prototype', [ }, ]); +removeProperty(EConstraintType, 'EConstraintType.prototype', [ + { + name: 'CONE_TWIST', + }, +]); + /** * Alias of [[RigidBody]] * @deprecated Since v1.2 diff --git a/cocos/physics/framework/physics-enum.ts b/cocos/physics/framework/physics-enum.ts index 4ea4538a92f..a84d210aa48 100644 --- a/cocos/physics/framework/physics-enum.ts +++ b/cocos/physics/framework/physics-enum.ts @@ -275,6 +275,7 @@ export enum EConstraintType { * Cone twist constraint. * @zh * 锥形扭转约束。 + * @deprecated coneTwist is deprecated, please use configurable instead */ CONE_TWIST, /** diff --git a/cocos/physics/framework/physics-selector.ts b/cocos/physics/framework/physics-selector.ts index 306613dc6dc..9be81501389 100644 --- a/cocos/physics/framework/physics-selector.ts +++ b/cocos/physics/framework/physics-selector.ts @@ -58,6 +58,9 @@ interface IPhysicsWrapperObject { PlaneShape?: Constructor, PointToPointConstraint?: Constructor, HingeConstraint?: Constructor, + /** + * @deprecated cone twist constraint is deprecated, please use configurable instead + */ ConeTwistConstraint?: Constructor, FixedConstraint?: Constructor, ConfigurableConstraint?: Constructor, @@ -233,6 +236,9 @@ enum ECheckType { // JOINT // PointToPointConstraint, HingeConstraint, + /** + * @deprecated cone twist constraint is deprecated, please use configurable instead + */ ConeTwistConstraint, FixedConstraint, ConfigurableConstraint, diff --git a/cocos/physics/physx/instantiate.ts b/cocos/physics/physx/instantiate.ts index 3a083bba0b1..6e89eff9701 100644 --- a/cocos/physics/physx/instantiate.ts +++ b/cocos/physics/physx/instantiate.ts @@ -58,17 +58,14 @@ game.once(Game.EVENT_PRE_SUBSYSTEM_INIT, () => { CylinderShape: PhysXCylinderShape, ConeShape: PhysXConeShape, TerrainShape: PhysXTerrainShape, - // SimplexShape: PhysXSimplexShape, PlaneShape: PhysXPlaneShape, PointToPointConstraint: PhysXSphericalJoint, - // PointToPointConstraint: PhysXFixedJoint, HingeConstraint: PhysXRevoluteJoint, FixedConstraint: PhysXFixedJoint, ConfigurableConstraint: PhysXConfigurableJoint, BoxCharacterController: PhysXBoxCharacterController, CapsuleCharacterController: PhysXCapsuleCharacterController, - }); }); diff --git a/cocos/physics/spec/i-physics-constraint.ts b/cocos/physics/spec/i-physics-constraint.ts index 76985a0df63..91664b25717 100644 --- a/cocos/physics/spec/i-physics-constraint.ts +++ b/cocos/physics/spec/i-physics-constraint.ts @@ -97,4 +97,7 @@ export interface IConfigurableConstraint extends IBaseConstraint { setBreakTorque(v: number): void; } +/** + * @deprecated ConeTwistConstraint is deprecated, please use ConfigurableConstraint instead + */ export type IConeTwistConstraint = IBaseConstraint From e5488b7d32189c498b70a9931538940025454646 Mon Sep 17 00:00:00 2001 From: Ling Zhan Date: Fri, 18 Aug 2023 19:30:14 +0800 Subject: [PATCH 149/184] V3.8.1 box2d wasm experimental (#15979) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * init * tsconfig.json * add box2d-wasm backend to cocos engine. not crash now in 3.8.0. * rigid-body, collider, and joint works now. * back * Joint: SetLinearFrequencyAndDampingRatio * PhysicsRayCastCallback, PhysicsAABBQueryCallback * box2d wasm debugDraw * asm.js * B2PolygonShape uses B2.ConvexPartition * box2d wasm contact disabled works now. * add unit test for physics2d. * b2ContactListenerWrapper::registerContactFixture * tweak * drawPolygon transfer array data from wasm to ts * tweak * contact event performance opt * revert to polygon collider 2d to original implementation. no need for libtess any more. * PostSolve ContactImpulse use raw pointer. * TransformVector2; debugDraw supports transform * enable rtti * WASM_OBJECT_PTR_2_TS_OBJECT, WASM_OBJECT_PTR_2_WASM_OBJECT * fix PreSolve parameter oldManifold error * B2.TransformVector2 --> b2Mul(in ts) * tweaks: code format. * eslint * eslint * remove physics-2d-box2d-wasm from render-config.json * comment tweaks * [opt] debug draw performance opt * tweaks --- cc.config.json | 3 + cocos/physics-2d/box2d-wasm/box2d.asmjs.ts | 30 ++ cocos/physics-2d/box2d-wasm/box2d.null.ts | 28 ++ cocos/physics-2d/box2d-wasm/box2d.wasmjs.ts | 31 ++ cocos/physics-2d/box2d-wasm/instantiate.ts | 60 +++ cocos/physics-2d/box2d-wasm/instantiated.ts | 148 ++++++ .../box2d-wasm/joints/distance-joint.ts | 46 ++ .../box2d-wasm/joints/fixed-joint.ts | 58 +++ .../box2d-wasm/joints/hinge-joint.ts | 83 ++++ .../physics-2d/box2d-wasm/joints/joint-2d.ts | 129 +++++ .../box2d-wasm/joints/mouse-joint.ts | 138 ++++++ .../box2d-wasm/joints/relative-joint.ts | 73 +++ .../box2d-wasm/joints/slider-joint.ts | 85 ++++ .../box2d-wasm/joints/spring-joint.ts | 63 +++ .../box2d-wasm/joints/wheel-joint.ts | 80 ++++ .../physics-2d/box2d-wasm/physics-contact.ts | 289 ++++++++++++ cocos/physics-2d/box2d-wasm/physics-world.ts | 441 ++++++++++++++++++ .../platform/physics-aabb-query-callback.ts | 73 +++ .../platform/physics-contact-listener.ts | 72 +++ .../box2d-wasm/platform/physics-debug-draw.ts | 199 ++++++++ .../platform/physics-ray-cast-callback.ts | 98 ++++ cocos/physics-2d/box2d-wasm/rigid-body.ts | 362 ++++++++++++++ .../box2d-wasm/shapes/box-shape-2d.ts | 76 +++ .../box2d-wasm/shapes/circle-shape-2d.ts | 59 +++ .../box2d-wasm/shapes/polygon-shape-2d.ts | 115 +++++ .../physics-2d/box2d-wasm/shapes/shape-2d.ts | 228 +++++++++ cocos/physics-2d/box2d/physics-world.ts | 20 +- cocos/physics-2d/builtin/builtin-world.ts | 32 +- cocos/physics-2d/framework/index.ts | 2 + .../physics-2d/framework/physics-selector.ts | 11 +- cocos/physics-2d/framework/physics-system.ts | 13 +- editor/engine-features/schema.json | 6 + editor/engine-features/types.ts | 1 + exports/physics-2d-box2d-wasm.ts | 26 ++ exports/wait-for-box2d-instantiation.ts | 27 ++ native/external-config.json | 2 +- scripts/build-engine/.vscode/launch.json | 1 + .../tests/stats-query/cc.config.json | 1 + tests/init.ts | 8 + tests/physics2d/collider.ts | 43 ++ tests/physics2d/events.ts | 49 ++ tests/physics2d/physics2d.test.ts | 50 ++ tests/physics2d/rigid-body.ts | 142 ++++++ tests/physics2d/scene-query.ts | 96 ++++ tsconfig.json | 1 + 45 files changed, 3567 insertions(+), 31 deletions(-) create mode 100644 cocos/physics-2d/box2d-wasm/box2d.asmjs.ts create mode 100644 cocos/physics-2d/box2d-wasm/box2d.null.ts create mode 100644 cocos/physics-2d/box2d-wasm/box2d.wasmjs.ts create mode 100644 cocos/physics-2d/box2d-wasm/instantiate.ts create mode 100644 cocos/physics-2d/box2d-wasm/instantiated.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/distance-joint.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/fixed-joint.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/hinge-joint.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/joint-2d.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/mouse-joint.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/relative-joint.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/slider-joint.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/spring-joint.ts create mode 100644 cocos/physics-2d/box2d-wasm/joints/wheel-joint.ts create mode 100644 cocos/physics-2d/box2d-wasm/physics-contact.ts create mode 100644 cocos/physics-2d/box2d-wasm/physics-world.ts create mode 100644 cocos/physics-2d/box2d-wasm/platform/physics-aabb-query-callback.ts create mode 100644 cocos/physics-2d/box2d-wasm/platform/physics-contact-listener.ts create mode 100644 cocos/physics-2d/box2d-wasm/platform/physics-debug-draw.ts create mode 100644 cocos/physics-2d/box2d-wasm/platform/physics-ray-cast-callback.ts create mode 100644 cocos/physics-2d/box2d-wasm/rigid-body.ts create mode 100644 cocos/physics-2d/box2d-wasm/shapes/box-shape-2d.ts create mode 100644 cocos/physics-2d/box2d-wasm/shapes/circle-shape-2d.ts create mode 100644 cocos/physics-2d/box2d-wasm/shapes/polygon-shape-2d.ts create mode 100644 cocos/physics-2d/box2d-wasm/shapes/shape-2d.ts create mode 100644 exports/physics-2d-box2d-wasm.ts create mode 100644 exports/wait-for-box2d-instantiation.ts create mode 100644 tests/physics2d/collider.ts create mode 100644 tests/physics2d/events.ts create mode 100644 tests/physics2d/rigid-body.ts create mode 100644 tests/physics2d/scene-query.ts diff --git a/cc.config.json b/cc.config.json index f4d4da87658..ad9f279be52 100644 --- a/cc.config.json +++ b/cc.config.json @@ -98,6 +98,9 @@ "physics-2d-builtin": { "modules": ["physics-2d-builtin", "physics-2d-framework"] }, + "physics-2d-box2d-wasm": { + "modules": ["physics-2d-box2d-wasm", "physics-2d-framework"] + }, "intersection-2d": { "modules": ["intersection-2d"] }, diff --git a/cocos/physics-2d/box2d-wasm/box2d.asmjs.ts b/cocos/physics-2d/box2d-wasm/box2d.asmjs.ts new file mode 100644 index 00000000000..a4304945dc0 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/box2d.asmjs.ts @@ -0,0 +1,30 @@ +/* + Copyright (c) 2023 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 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. +*/ + +/** + * export box2d from internal module + */ +import asmFactory from 'external:emscripten/box2d/box2d.release.asm.js'; + +export { asmFactory }; diff --git a/cocos/physics-2d/box2d-wasm/box2d.null.ts b/cocos/physics-2d/box2d-wasm/box2d.null.ts new file mode 100644 index 00000000000..ad885b3845a --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/box2d.null.ts @@ -0,0 +1,28 @@ +/* + Copyright (c) 2023 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 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. +*/ + +/** + * export null for module elimination + */ +export const asmFactory = null; diff --git a/cocos/physics-2d/box2d-wasm/box2d.wasmjs.ts b/cocos/physics-2d/box2d-wasm/box2d.wasmjs.ts new file mode 100644 index 00000000000..78c64b77406 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/box2d.wasmjs.ts @@ -0,0 +1,31 @@ +/* + Copyright (c) 2023 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 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. +*/ + +/** + * export box2d from internal module + */ +import wasmFactory from 'external:emscripten/box2d/box2d.release.wasm.js'; +import box2dWasmUrl from 'external:emscripten/box2d/box2d.release.wasm.wasm'; + +export { wasmFactory, box2dWasmUrl }; diff --git a/cocos/physics-2d/box2d-wasm/instantiate.ts b/cocos/physics-2d/box2d-wasm/instantiate.ts new file mode 100644 index 00000000000..2de0f968ed4 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/instantiate.ts @@ -0,0 +1,60 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { selector } from '../framework/physics-selector'; +import { B2PhysicsWorld } from './physics-world'; +import { B2RigidBody2D } from './rigid-body'; +import { B2BoxShape } from './shapes/box-shape-2d'; +import { B2CircleShape } from './shapes/circle-shape-2d'; +import { B2PolygonShape } from './shapes/polygon-shape-2d'; +import { B2MouseJoint } from './joints/mouse-joint'; +import { B2DistanceJoint } from './joints/distance-joint'; +import { B2SpringJoint } from './joints/spring-joint'; +import { B2RelativeJoint } from './joints/relative-joint'; +import { B2SliderJoint } from './joints/slider-joint'; +import { B2FixedJoint } from './joints/fixed-joint'; +import { B2WheelJoint } from './joints/wheel-joint'; +import { B2HingeJoint } from './joints/hinge-joint'; + +import { Game, game } from '../../game'; + +game.once(Game.EVENT_PRE_SUBSYSTEM_INIT, () => { + selector.register('box2d-wasm', { + PhysicsWorld: B2PhysicsWorld, + RigidBody: B2RigidBody2D, + + BoxShape: B2BoxShape, + CircleShape: B2CircleShape, + PolygonShape: B2PolygonShape, + + MouseJoint: B2MouseJoint, + DistanceJoint: B2DistanceJoint, + SpringJoint: B2SpringJoint, + RelativeJoint: B2RelativeJoint, + SliderJoint: B2SliderJoint, + FixedJoint: B2FixedJoint, + WheelJoint: B2WheelJoint, + HingeJoint: B2HingeJoint, + }); +}); diff --git a/cocos/physics-2d/box2d-wasm/instantiated.ts b/cocos/physics-2d/box2d-wasm/instantiated.ts new file mode 100644 index 00000000000..5156374fd49 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/instantiated.ts @@ -0,0 +1,148 @@ +/* + Copyright (c) 2023 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 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. +*/ + +import { instantiateWasm, fetchBuffer } from 'pal/wasm'; +import { JSB, WASM_SUPPORT_MODE, CULL_ASM_JS_MODULE, EDITOR, TEST } from 'internal:constants'; +import { wasmFactory, box2dWasmUrl } from './box2d.wasmjs'; +import { asmFactory } from './box2d.asmjs'; + +import { game } from '../../game'; +import { getError, error, sys, debug, IVec2Like } from '../../core'; +import { WebAssemblySupportMode } from '../../misc/webassembly-support'; + +export const B2 = {} as any; + +export function getImplPtr (wasmObject: any): number { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return (wasmObject).$$.ptr; +} + +/** +* mapping wasm-object-ptr to ts-object +* B2.Fixture pointer -->B2Shape2D +* B2.Body pointer --> B2RigidBody2D +* B2.Contact pointer --> PhysicsContact +* B2.Joint pointer --> B2Joint +* ... +*/ +const WASM_OBJECT_PTR_2_TS_OBJECT = {}; +export function addImplPtrReference (TSObject: any, implPtr: number): void { + if (implPtr) { WASM_OBJECT_PTR_2_TS_OBJECT[implPtr] = TSObject; } +} +export function removeImplPtrReference (implPtr: number): void { + if (implPtr) { + delete WASM_OBJECT_PTR_2_TS_OBJECT[implPtr]; + } +} +export function getTSObjectFromWASMObjectPtr (implPtr: number): T { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return WASM_OBJECT_PTR_2_TS_OBJECT[implPtr]; +} +export function getTSObjectFromWASMObject (impl: any): T { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return WASM_OBJECT_PTR_2_TS_OBJECT[getImplPtr(impl)]; +} + +/** +* mapping wasm-object-ptr to wasm-object +* B2.Fixture pointer -->B2.Fixture +* B2.Body pointer --> B2.Body +* B2.Contact pointer --> B2.Contact +* B2.Joint pointer --> B2.Joint +* ... +*/ +const WASM_OBJECT_PTR_2_WASM_OBJECT = {}; +export function addImplPtrReferenceWASM (WASMObject: any, implPtr: number): void { + if (implPtr) { WASM_OBJECT_PTR_2_WASM_OBJECT[implPtr] = WASMObject; } +} + +export function removeImplPtrReferenceWASM (implPtr: number): void { + if (implPtr) { + delete WASM_OBJECT_PTR_2_WASM_OBJECT[implPtr]; + } +} + +export function getWASMObjectFromWASMObjectPtr (implPtr: number): T { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return WASM_OBJECT_PTR_2_WASM_OBJECT[implPtr]; +} + +/** +* ts implementation of c++ b2Mul +*/ +export function b2Mul (T: any, v: IVec2Like, out: IVec2Like): void { + out.x = (T.q.c * v.x - T.q.s * v.y) + T.p.x; + out.y = (T.q.s * v.x + T.q.c * v.y) + T.p.y; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +function initWasm (wasmUrl: string): Promise { + return new Promise((resolve, reject) => { + const errorMessage = (err: any): string => `[box2d]: box2d wasm lib load failed: ${err}`; + wasmFactory({ + instantiateWasm ( + importObject: WebAssembly.Imports, + receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void, + ) { + // NOTE: the Promise return by instantiateWasm hook can't be caught. + instantiateWasm(wasmUrl, importObject).then((result: any) => { + receiveInstance(result.instance as WebAssembly.Instance, result.module as WebAssembly.Module); + }).catch((err) => reject(errorMessage(err))); + }, + }).then((Instance: any) => { + if (!EDITOR && !TEST) debug('[box2d]:box2d wasm lib loaded.'); + Object.assign(B2, Instance); + }).then(resolve).catch((err: any) => reject(errorMessage(err))); + }); +} + +function initAsm (): Promise { + if (asmFactory != null) { + return asmFactory().then((instance: any) => { + if (!EDITOR && !TEST) debug('[box2d]:box2d asm lib loaded.'); + Object.assign(B2, instance); + }); + } else { + return new Promise((resolve, reject) => { + resolve(); + }); + } +} + +export function waitForBox2dWasmInstantiation (): Promise { + const errorReport = (msg: any): void => { error(msg); }; + if ((WASM_SUPPORT_MODE as WebAssemblySupportMode) === WebAssemblySupportMode.MAYBE_SUPPORT) { + if (sys.hasFeature(sys.Feature.WASM)) { + return initWasm(box2dWasmUrl).catch(errorReport); + } else { + return initAsm().catch(errorReport); + } + } else if ((WASM_SUPPORT_MODE as WebAssemblySupportMode) === WebAssemblySupportMode.SUPPORT) { + return initWasm(box2dWasmUrl).catch(errorReport); + } else { + return initAsm().catch(errorReport); + } +} + +game.onPostInfrastructureInitDelegate.add(waitForBox2dWasmInstantiation); diff --git a/cocos/physics-2d/box2d-wasm/joints/distance-joint.ts b/cocos/physics-2d/box2d-wasm/joints/distance-joint.ts new file mode 100644 index 00000000000..79484881da8 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/distance-joint.ts @@ -0,0 +1,46 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { IDistanceJoint } from '../../spec/i-physics-joint'; +import { B2Joint } from './joint-2d'; +import { DistanceJoint2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; + +export class B2DistanceJoint extends B2Joint implements IDistanceJoint { + setMaxLength (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.RopeJoint).SetMaxLength(v); + } + } + + _createJointDef (): any { + const comp = this._jointComp as DistanceJoint2D; + const def = new B2.RopeJointDef(); + def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; + def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + def.maxLength = comp.maxLength / PHYSICS_2D_PTM_RATIO; + return def; + } +} diff --git a/cocos/physics-2d/box2d-wasm/joints/fixed-joint.ts b/cocos/physics-2d/box2d-wasm/joints/fixed-joint.ts new file mode 100644 index 00000000000..d5de28d963a --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/fixed-joint.ts @@ -0,0 +1,58 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { IFixedJoint } from '../../spec/i-physics-joint'; +import { B2Joint } from './joint-2d'; +import { FixedJoint2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; + +export class B2FixedJoint extends B2Joint implements IFixedJoint { + setFrequency (v: number): void { + this.updateStiffnessAndDamping(); + } + setDampingRatio (v: number): void { + this.updateStiffnessAndDamping(); + } + updateStiffnessAndDamping (): void { + if (this._b2joint) { + B2.SetLinearFrequencyAndDampingRatio( + this._b2joint, + (this._jointComp as FixedJoint2D).frequency, + (this._jointComp as FixedJoint2D).dampingRatio, + ); + } + } + + _createJointDef (): any { + const comp = this._jointComp as FixedJoint2D; + const def = new B2.WeldJointDef(); + def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; + def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + def.referenceAngle = 0; + def.damping = 0;//comp.dampingRatio; + def.stiffness = 1;//comp.frequency; + return def; + } +} diff --git a/cocos/physics-2d/box2d-wasm/joints/hinge-joint.ts b/cocos/physics-2d/box2d-wasm/joints/hinge-joint.ts new file mode 100644 index 00000000000..dedde81f871 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/hinge-joint.ts @@ -0,0 +1,83 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { IHingeJoint } from '../../spec/i-physics-joint'; +import { HingeJoint2D } from '../../framework'; +import { B2Joint } from './joint-2d'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; +import { toRadian } from '../../../core'; + +export class B2HingeJoint extends B2Joint implements IHingeJoint { + enableLimit (v: boolean): void { + if (this._b2joint) { + (this._b2joint as B2.RevoluteJoint).EnableLimit(v); + } + } + setLowerAngle (v: number): void { + this.updateLimits(); + } + setUpperAngle (v: number): void { + this.updateLimits(); + } + updateLimits (): void { + if (this._b2joint) { + const comp = this._jointComp as HingeJoint2D; + (this._b2joint as B2.RevoluteJoint).SetLimits(toRadian(comp.lowerAngle), toRadian(comp.upperAngle)); + } + } + + // motor + enableMotor (v: boolean): void { + if (this._b2joint) { + (this._b2joint as B2.RevoluteJoint).EnableMotor(v); + } + } + setMaxMotorTorque (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.RevoluteJoint).SetMaxMotorTorque(v); + } + } + setMotorSpeed (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.RevoluteJoint).SetMotorSpeed(v); + } + } + + _createJointDef (): any { + const comp = this._jointComp as HingeJoint2D; + const def = new B2.RevoluteJointDef(); + def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; + def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + + def.enableMotor = comp.enableMotor; + def.maxMotorTorque = comp.maxMotorTorque; + def.motorSpeed = toRadian(comp.motorSpeed); + + def.enableLimit = comp.enableLimit; + def.lowerAngle = toRadian(comp.lowerAngle); + def.upperAngle = toRadian(comp.upperAngle); + return def; + } +} diff --git a/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts b/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts new file mode 100644 index 00000000000..2f0990e0d6b --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/joint-2d.ts @@ -0,0 +1,129 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2, addImplPtrReference, addImplPtrReferenceWASM, getImplPtr } from '../instantiated'; +import { IJoint2D } from '../../spec/i-physics-joint'; +import { Joint2D, PhysicsSystem2D, RigidBody2D } from '../../framework'; +import { B2PhysicsWorld } from '../physics-world'; +import { Vec2, warn } from '../../../core'; + +export class B2Joint implements IJoint2D { + get impl (): B2.Joint | null { + return this._b2joint; + } + get comp (): Joint2D | null { + return this._jointComp; + } + get body (): RigidBody2D | null { + return this._body; + } + + protected _b2joint: B2.Joint | null = null; + protected _jointComp: Joint2D | null = null; + protected _body: RigidBody2D | null = null; + + private _inited = false; + + initialize (comp: Joint2D): void { + this._jointComp = comp; + } + + onEnable (): void { + PhysicsSystem2D.instance._callAfterStep(this, this._init); + } + + onDisable (): void { + PhysicsSystem2D.instance._callAfterStep(this, this._destroy); + } + + // need init after body and connected body init + start (): void { + PhysicsSystem2D.instance._callAfterStep(this, this._init); + } + + _init (): void { + if (this._inited) return; + + const comp = this._jointComp!; + if (!comp.isValid) { + return; + } + + this._body = comp.getComponent(RigidBody2D); + if (!this._body) { + warn(`Joint2D: Body is not found, can not create joint. Node Name: ${comp.node.name}`); + return; + } + + const def = this._createJointDef(); + if (!def) { + return; + } + + def.SetBodyA(this._body.impl!.impl as B2.Body); + const connectedBody = comp.connectedBody; + //if connected body is set but not active, return + if (connectedBody && !connectedBody.enabledInHierarchy) { + return; + } + + //if connected body is not set, use scene origin as connected body + if (!connectedBody) { + def.SetBodyB((PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).groundBodyImpl); + } else { + def.SetBodyB(connectedBody.impl!.impl as B2.Body); + } + + def.collideConnected = comp.collideConnected; + + this._b2joint = (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).impl.CreateJoint(def); + addImplPtrReference(this, getImplPtr(this._b2joint)); + addImplPtrReferenceWASM(this._b2joint, getImplPtr(this._b2joint)); + + this.updateStiffnessAndDamping(); + + this._inited = true; + } + + _destroy (): void { + if (!this._inited) return; + + (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).impl.DestroyJoint(this._b2joint!); + + this._b2joint = null; + this._inited = false; + } + + _createJointDef (): B2.JointDef | null { + return null; + } + + isValid (): Joint2D | null { + return this._b2joint && this._body && this._body.impl && this._jointComp; + } + + updateStiffnessAndDamping (): void { + // do nothing + } +} diff --git a/cocos/physics-2d/box2d-wasm/joints/mouse-joint.ts b/cocos/physics-2d/box2d-wasm/joints/mouse-joint.ts new file mode 100644 index 00000000000..f5d359056da --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/mouse-joint.ts @@ -0,0 +1,138 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { IMouseJoint } from '../../spec/i-physics-joint'; +import { B2Joint } from './joint-2d'; +import { MouseJoint2D, PhysicsSystem2D, Joint2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; +import { IVec2Like, Vec2 } from '../../../core'; +import { Touch } from '../../../input/types'; +import { B2PhysicsWorld } from '../physics-world'; +import { NodeEventType } from '../../../scene-graph/node-event'; +import { find } from '../../../scene-graph'; + +const tempB2Vec2 = { x: 0, y: 0 };//new b2.Vec2(); + +export class B2MouseJoint extends B2Joint implements IMouseJoint { + _touchPoint = new Vec2(); + _isTouched = false; + + setTarget (v: IVec2Like): void { + if (this._b2joint) { + tempB2Vec2.x = v.x / PHYSICS_2D_PTM_RATIO; + tempB2Vec2.y = v.y / PHYSICS_2D_PTM_RATIO; + (this._b2joint as B2.MouseJoint).SetTarget(tempB2Vec2); + } + } + setFrequency (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.MouseJoint).SetFrequency(v); + } + } + setDampingRatio (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.MouseJoint).SetDampingRatio(v); + } + } + setMaxForce (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.MouseJoint).SetMaxForce(v); + } + } + + _createJointDef (): any { + const def = new B2.MouseJointDef(); + const comp = this._jointComp as MouseJoint2D; + def.target = { x: this._touchPoint.x / PHYSICS_2D_PTM_RATIO, y: this._touchPoint.y / PHYSICS_2D_PTM_RATIO }; + def.maxForce = comp.maxForce; + def.dampingRatio = comp.dampingRatio; + def.frequencyHz = comp.frequency; + return def; + } + + initialize (comp: Joint2D): void { + super.initialize(comp); + + const canvas = find('Canvas'); + if (canvas) { + canvas.on(NodeEventType.TOUCH_START, this.onTouchBegan, this); + canvas.on(NodeEventType.TOUCH_MOVE, this.onTouchMove, this); + canvas.on(NodeEventType.TOUCH_END, this.onTouchEnd, this); + canvas.on(NodeEventType.TOUCH_CANCEL, this.onTouchEnd, this); + } + } + + onEnable (): void { + //empty + } + + start (): void { + //empty + } + + onTouchBegan (event: Touch): void { + this._isTouched = true; + + const target = this._touchPoint.set(event.getUILocation()); + + const world = (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld); + const colliders = world.testPoint(target); + if (colliders.length <= 0) return; + + const body = colliders[0].body; + body!.wakeUp(); + + const comp = this._jointComp as MouseJoint2D; + comp.connectedBody = body; + + this._init(); + + this.setMaxForce(comp.maxForce * body!.getMass()); + this.setTarget(target); + } + + onTouchMove (event: Touch): void { + this._touchPoint = event.getUILocation(); + } + + onTouchEnd (event: Touch): void { + this._destroy(); + this._isTouched = false; + } + + update (): void { + if (!this._isTouched || !this.isValid()) { + return; + } + + // let camera = cc.Camera.findCamera(this.node); + // if (camera) { + // this.target = camera.getScreenToWorldPoint(this._touchPoint); + // } + // else { + this.setTarget(this._touchPoint); + // } + } +} diff --git a/cocos/physics-2d/box2d-wasm/joints/relative-joint.ts b/cocos/physics-2d/box2d-wasm/joints/relative-joint.ts new file mode 100644 index 00000000000..9b3fea118e6 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/relative-joint.ts @@ -0,0 +1,73 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { IRelativeJoint } from '../../spec/i-physics-joint'; +import { B2Joint } from './joint-2d'; +import { RelativeJoint2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; +import { Vec2, toRadian } from '../../../core'; + +const tempB2Vec2 = { x: 0, y: 0 };//new b2.Vec2(); + +export class B2RelativeJoint extends B2Joint implements IRelativeJoint { + setMaxForce (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.MotorJoint).SetMaxForce(v); + } + } + setAngularOffset (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.MotorJoint).SetAngularOffset(toRadian(v)); + } + } + setLinearOffset (v: Vec2): void { + if (this._b2joint) { + tempB2Vec2.x = v.x / PHYSICS_2D_PTM_RATIO; + tempB2Vec2.y = v.y / PHYSICS_2D_PTM_RATIO; + (this._b2joint as B2.MotorJoint).SetLinearOffset(tempB2Vec2); + } + } + setCorrectionFactor (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.MotorJoint).SetCorrectionFactor(v); + } + } + setMaxTorque (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.MotorJoint).SetMaxTorque(v); + } + } + + _createJointDef (): any { + const comp = this._jointComp as RelativeJoint2D; + const def = new B2.MotorJointDef(); + def.linearOffset = { x: comp.linearOffset.x / PHYSICS_2D_PTM_RATIO, y: comp.linearOffset.y / PHYSICS_2D_PTM_RATIO }; + def.angularOffset = toRadian(comp.angularOffset); + def.maxForce = comp.maxForce; + def.maxTorque = comp.maxTorque; + def.correctionFactor = comp.correctionFactor; + return def; + } +} diff --git a/cocos/physics-2d/box2d-wasm/joints/slider-joint.ts b/cocos/physics-2d/box2d-wasm/joints/slider-joint.ts new file mode 100644 index 00000000000..0d22aa4ee23 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/slider-joint.ts @@ -0,0 +1,85 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { ISliderJoint } from '../../spec/i-physics-joint'; +import { B2Joint } from './joint-2d'; +import { SliderJoint2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; +import { toRadian } from '../../../core'; + +export class B2SliderJoint extends B2Joint implements ISliderJoint { + // limit + enableLimit (v: boolean): void { + if (this._b2joint) { + (this._b2joint as B2.PrismaticJoint).EnableLimit(v); + } + } + setLowerLimit (v: number): void { + this.updateLimits(); + } + setUpperLimit (v: number): void { + this.updateLimits(); + } + updateLimits (): void { + if (this._b2joint) { + const comp = this._jointComp as SliderJoint2D; + (this._b2joint as B2.PrismaticJoint).SetLimits(comp.lowerLimit / PHYSICS_2D_PTM_RATIO, comp.upperLimit / PHYSICS_2D_PTM_RATIO); + } + } + + // motor + enableMotor (v: boolean): void { + if (this._b2joint) { + (this._b2joint as B2.PrismaticJoint).EnableMotor(v); + } + } + setMaxMotorForce (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.PrismaticJoint).SetMaxMotorForce(v); + } + } + setMotorSpeed (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.PrismaticJoint).SetMotorSpeed(v); + } + } + + _createJointDef (): any { + const comp = this._jointComp as SliderJoint2D; + const def = new B2.PrismaticJointDef(); + def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; + def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const angle = toRadian(comp.angle); + def.localAxisA = { x: Math.cos(angle), y: Math.sin(angle) }; + def.referenceAngle = 0; + def.enableLimit = comp.enableLimit; + def.lowerTranslation = comp.lowerLimit / PHYSICS_2D_PTM_RATIO; + def.upperTranslation = comp.upperLimit / PHYSICS_2D_PTM_RATIO; + def.enableMotor = comp.enableMotor; + def.maxMotorForce = comp.maxMotorForce; + def.motorSpeed = comp.motorSpeed; + return def; + } +} diff --git a/cocos/physics-2d/box2d-wasm/joints/spring-joint.ts b/cocos/physics-2d/box2d-wasm/joints/spring-joint.ts new file mode 100644 index 00000000000..d8faa118417 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/spring-joint.ts @@ -0,0 +1,63 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { ISpringJoint } from '../../spec/i-physics-joint'; +import { B2Joint } from './joint-2d'; +import { SpringJoint2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; + +export class B2SpringJoint extends B2Joint implements ISpringJoint { + setFrequency (v: number): void { + this.updateStiffnessAndDamping(); + } + setDampingRatio (v: number): void { + this.updateStiffnessAndDamping(); + } + updateStiffnessAndDamping (): void { + if (this._b2joint) { + B2.SetLinearFrequencyAndDampingRatio( + this._b2joint, + (this._jointComp as SpringJoint2D).frequency, + (this._jointComp as SpringJoint2D).dampingRatio, + ); + } + } + setDistance (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.DistanceJoint).SetLength(v); + } + } + + _createJointDef (): any { + const comp = this._jointComp as SpringJoint2D; + const def = new B2.DistanceJointDef(); + def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; + def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + def.length = comp.distance / PHYSICS_2D_PTM_RATIO; + def.damping = 0;//comp.dampingRatio; + def.stiffness = 1;//comp.frequency; + return def; + } +} diff --git a/cocos/physics-2d/box2d-wasm/joints/wheel-joint.ts b/cocos/physics-2d/box2d-wasm/joints/wheel-joint.ts new file mode 100644 index 00000000000..72be5356593 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/joints/wheel-joint.ts @@ -0,0 +1,80 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { IWheelJoint } from '../../spec/i-physics-joint'; +import { WheelJoint2D } from '../../framework'; +import { B2Joint } from './joint-2d'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; +import { toRadian } from '../../../core'; + +export class B2WheelJoint extends B2Joint implements IWheelJoint { + setFrequency (v: number): void { + this.updateStiffnessAndDamping(); + } + setDampingRatio (v: number): void { + this.updateStiffnessAndDamping(); + } + updateStiffnessAndDamping (): void { + if (this._b2joint) { + B2.SetLinearFrequencyAndDampingRatio( + this._b2joint, + (this._jointComp as WheelJoint2D).frequency, + (this._jointComp as WheelJoint2D).dampingRatio, + ); + } + } + + // motor + enableMotor (v: boolean): void { + if (this._b2joint) { + (this._b2joint as B2.WheelJoint).EnableMotor(v); + } + } + setMaxMotorTorque (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.WheelJoint).SetMaxMotorTorque(v); + } + } + setMotorSpeed (v: number): void { + if (this._b2joint) { + (this._b2joint as B2.WheelJoint).SetMotorSpeed(v); + } + } + + _createJointDef (): any { + const comp = this._jointComp as WheelJoint2D; + const def = new B2.WheelJointDef(); + def.localAnchorA = { x: comp.anchor.x / PHYSICS_2D_PTM_RATIO, y: comp.anchor.y / PHYSICS_2D_PTM_RATIO }; + def.localAnchorB = { x: comp.connectedAnchor.x / PHYSICS_2D_PTM_RATIO, y: comp.connectedAnchor.y / PHYSICS_2D_PTM_RATIO }; + const angle = toRadian(comp.angle); + def.localAxisA = { x: Math.cos(angle), y: Math.sin(angle) }; + def.maxMotorTorque = comp.maxMotorTorque; + def.motorSpeed = toRadian(comp.motorSpeed); + def.enableMotor = comp.enableMotor; + def.damping = 0;//comp.dampingRatio; + def.stiffness = 1;//comp.frequency; + return def; + } +} diff --git a/cocos/physics-2d/box2d-wasm/physics-contact.ts b/cocos/physics-2d/box2d-wasm/physics-contact.ts new file mode 100644 index 00000000000..85f180a9a0e --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/physics-contact.ts @@ -0,0 +1,289 @@ +/* + Copyright (c) 2017-2023 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 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. +*/ + +import { B2, addImplPtrReference, getTSObjectFromWASMObjectPtr, removeImplPtrReference } from './instantiated'; +import { Vec2 } from '../../core'; +import { PHYSICS_2D_PTM_RATIO } from '../framework/physics-types'; +import { Collider2D, Contact2DType, PhysicsSystem2D } from '../framework'; +import { B2Shape2D } from './shapes/shape-2d'; +import { IPhysics2DContact, IPhysics2DImpulse, IPhysics2DManifoldPoint, IPhysics2DWorldManifold } from '../spec/i-physics-contact'; +import { B2PhysicsWorld } from './physics-world'; + +const pools: PhysicsContact[] = []; + +// temp world manifold +const pointCache = [new Vec2(), new Vec2()]; + +const worldmanifold: IPhysics2DWorldManifold = { + points: [] as Vec2[], + separations: [] as number[], + normal: new Vec2(), +}; + +class ManifoldPoint implements IPhysics2DManifoldPoint { + localPoint = new Vec2(); + normalImpulse = 0; + tangentImpulse = 0; +} + +const manifoldPointCache = [new ManifoldPoint(), new ManifoldPoint()]; + +const manifold = { + type: 0, + localPoint: new Vec2(), + localNormal: new Vec2(), + points: [] as ManifoldPoint[], +}; + +const impulse: IPhysics2DImpulse = { + normalImpulses: [] as number[], + tangentImpulses: [] as number[], +}; + +export class PhysicsContact implements IPhysics2DContact { + static get (b2contact: number): PhysicsContact { + let c = pools.pop(); + + if (!c) { + c = new PhysicsContact(); + } + + c.init(b2contact); + return c; + } + + static put (b2contact: number): void { + const c = getTSObjectFromWASMObjectPtr(b2contact); + if (!c) return; + + pools.push(c); + c.reset(); + } + + colliderA: Collider2D | null = null; + colliderB: Collider2D | null = null; + + disabled = false; + disabledOnce = false; + + private _impulsePtr: number = 0; + private _inverted = false; + private _implPtr: number = 0; //wasm object pointer + private _b2WorldmanifoldPtr: number = 0; //wasm object pointer + + _setImpulse (impulse: number): void { + this._impulsePtr = impulse; + } + + init (b2contact: number): void { + this.colliderA = (getTSObjectFromWASMObjectPtr(B2.ContactGetFixtureA(b2contact) as number)).collider; + this.colliderB = (getTSObjectFromWASMObjectPtr(B2.ContactGetFixtureB(b2contact) as number)).collider; + this.disabled = false; + this.disabledOnce = false; + this._impulsePtr = 0; + this._inverted = false; + + this._implPtr = b2contact; + addImplPtrReference(this, this._implPtr); + this._b2WorldmanifoldPtr = B2.WorldManifoldNew(); + } + + reset (): void { + this.setTangentSpeed(0); + this.resetFriction(); + this.resetRestitution(); + + this.colliderA = null; + this.colliderB = null; + this.disabled = false; + this._impulsePtr = 0; + + removeImplPtrReference(this._implPtr); + this._implPtr = 0; + + B2.WorldManifoldDelete(this._b2WorldmanifoldPtr); + this._b2WorldmanifoldPtr = 0; + } + + getWorldManifold (): IPhysics2DWorldManifold { + const points = worldmanifold.points; + const separations = worldmanifold.separations; + const normal = worldmanifold.normal; + + B2.ContactGetWorldManifold(this._implPtr, this._b2WorldmanifoldPtr); + const b2Manifold = B2.ContactGetManifold(this._implPtr); + const count = B2.ManifoldGetPointCount(b2Manifold); + points.length = separations.length = count; + + for (let i = 0; i < count; i++) { + const p = pointCache[i]; + p.x = B2.WorldManifoldGetPointValueX(this._b2WorldmanifoldPtr, i) * PHYSICS_2D_PTM_RATIO; + p.y = B2.WorldManifoldGetPointValueY(this._b2WorldmanifoldPtr, i) * PHYSICS_2D_PTM_RATIO; + points[i] = p; + separations[i] = B2.WorldManifoldGetSeparationValue(this._b2WorldmanifoldPtr, i) * PHYSICS_2D_PTM_RATIO; + } + + normal.x = B2.WorldManifoldGetNormalValueX(this._b2WorldmanifoldPtr); + normal.y = B2.WorldManifoldGetNormalValueY(this._b2WorldmanifoldPtr); + + if (this._inverted) { + normal.x *= -1; + normal.y *= -1; + } + + return worldmanifold; + } + + getManifold (): { type: number; localPoint: Vec2; localNormal: Vec2; points: ManifoldPoint[]; } { + const points = manifold.points; + const localNormal = manifold.localNormal; + const localPoint = manifold.localPoint; + + const b2Manifold = B2.ContactGetManifold(this._implPtr); + const count = points.length = B2.ManifoldGetPointCount(b2Manifold); + + for (let i = 0; i < count; i++) { + const p = manifoldPointCache[i]; + const b2p = B2.ManifoldGetManifoldPointPtr(b2Manifold, i);//B2.ManifoldPoint + p.localPoint.x = B2.ManifoldPointGetLocalPointX(b2p) * PHYSICS_2D_PTM_RATIO; + p.localPoint.y = B2.ManifoldPointGetLocalPointY(b2p) * PHYSICS_2D_PTM_RATIO; + p.normalImpulse = B2.ManifoldPointGetNormalImpulse(b2p) * PHYSICS_2D_PTM_RATIO; + p.tangentImpulse = B2.ManifoldPointGetTangentImpulse(b2p); //* PHYSICS_2D_PTM_RATIO;? + points[i] = p; + } + + localPoint.x = B2.ManifoldGetLocalPointValueX(b2Manifold) * PHYSICS_2D_PTM_RATIO; + localPoint.y = B2.ManifoldGetLocalPointValueY(b2Manifold) * PHYSICS_2D_PTM_RATIO; + localNormal.x = B2.ManifoldGetLocalNormalValueX(b2Manifold); + localNormal.y = B2.ManifoldGetLocalNormalValueY(b2Manifold); + manifold.type = B2.ManifoldGetType(b2Manifold); + + if (this._inverted) { + localNormal.x *= -1; + localNormal.y *= -1; + } + + return manifold; + } + + getImpulse (): IPhysics2DImpulse | null { + const b2impulse = this._impulsePtr; + if (!b2impulse) return null; + + const normalImpulses = impulse.normalImpulses; + const tangentImpulses = impulse.tangentImpulses; + const count = B2.ContactImpulseGetCount(b2impulse); + for (let i = 0; i < count; i++) { + normalImpulses[i] = B2.ContactImpulseGetNormalImpulse(b2impulse, i) * PHYSICS_2D_PTM_RATIO; + tangentImpulses[i] = B2.ContactImpulseGetTangentImpulse(b2impulse, i); + } + + tangentImpulses.length = normalImpulses.length = count; + + return impulse; + } + + emit (contactType: string): void { + let func = ''; + switch (contactType) { + case Contact2DType.BEGIN_CONTACT: + func = 'onBeginContact'; + break; + case Contact2DType.END_CONTACT: + func = 'onEndContact'; + break; + case Contact2DType.PRE_SOLVE: + func = 'onPreSolve'; + break; + case Contact2DType.POST_SOLVE: + func = 'onPostSolve'; + break; + default: + break; + } + + const colliderA = this.colliderA; + const colliderB = this.colliderB; + + const bodyA = colliderA!.body; + const bodyB = colliderB!.body; + + if (bodyA!.enabledContactListener) { + colliderA?.emit(contactType, colliderA, colliderB, this); + } + + if (bodyB!.enabledContactListener) { + colliderB?.emit(contactType, colliderB, colliderA, this); + } + + if (bodyA!.enabledContactListener || bodyB!.enabledContactListener) { + PhysicsSystem2D.instance.emit(contactType, colliderA, colliderB, this); + } + + if (this.disabled || this.disabledOnce) { + this.setEnabled(false); + this.disabledOnce = false; + } + } + + setEnabled (value: boolean): void { + B2.ContactSetEnabled(this._implPtr, value); + } + + isTouching (): boolean { + return B2.ContactIsTouching(this._implPtr) as boolean; + } + + setTangentSpeed (value: number): void { + B2.ContactSetTangentSpeed(this._implPtr, value); + } + + getTangentSpeed (): number { + return B2.ContactGetTangentSpeed(this._implPtr) as number; + } + + setFriction (value: number): void { + B2.ContactSetFriction(this._implPtr, value); + } + + getFriction (): number { + return B2.ContactGetFriction(this._implPtr) as number; + } + + resetFriction (): void { + B2.ContactResetFriction(this._implPtr); + } + + setRestitution (value: number): void { + B2.ContactSetRestitution(this._implPtr, value); + } + + getRestitution (): number { + return B2.ContactGetRestitution(this._implPtr) as number; + } + + resetRestitution (): void { + B2.ContactResetRestitution(this._implPtr); + } +} diff --git a/cocos/physics-2d/box2d-wasm/physics-world.ts b/cocos/physics-2d/box2d-wasm/physics-world.ts new file mode 100644 index 00000000000..c0997b14915 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/physics-world.ts @@ -0,0 +1,441 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; +import { B2, getImplPtr, addImplPtrReference, addImplPtrReferenceWASM, getTSObjectFromWASMObject, + getTSObjectFromWASMObjectPtr, removeImplPtrReference, removeImplPtrReferenceWASM } from './instantiated'; +import { IPhysicsWorld } from '../spec/i-physics-world'; +import { IVec2Like, Vec3, Quat, toRadian, Vec2, toDegree, Rect, CCObject, js } from '../../core'; +import { PHYSICS_2D_PTM_RATIO, ERaycast2DType, ERigidBody2DType } from '../framework/physics-types'; +import { Canvas } from '../../2d/framework'; +import { Graphics } from '../../2d/components'; + +import { B2RigidBody2D } from './rigid-body'; +import { PhysicsContactListener } from './platform/physics-contact-listener'; +import { PhysicsAABBQueryCallback } from './platform/physics-aabb-query-callback'; +import { PhysicsRayCastCallback } from './platform/physics-ray-cast-callback'; +import { PhysicsContact } from './physics-contact'; +import { Contact2DType, Collider2D, RaycastResult2D } from '../framework'; +import { B2Shape2D } from './shapes/shape-2d'; +import { PhysicsDebugDraw } from './platform/physics-debug-draw'; +import { Node, find, Layers } from '../../scene-graph'; +import { director } from '../../game'; + +const tempVec3 = new Vec3(); +const tempVec2_1 = new Vec2(); +const tempVec2_2 = new Vec2(); +const tempB2Vec2_1 = { x: 0, y: 0 }; + +// const tempB2AABB = null;//new B2.AABB(); + +const testResults: Collider2D[] = []; + +export class B2PhysicsWorld implements IPhysicsWorld { + protected _world: B2.World; + protected _bodies: B2RigidBody2D[] = []; + protected _animatedBodies: B2RigidBody2D[] = []; + protected _rotationAxis: Vec3 = new Vec3(); + protected _physicsGroundBody: B2.Body; + + protected _contactListener: B2.ContactListener; + protected _aabbQueryCallback: B2.QueryCallback; + protected _raycastQueryCallback: B2.RayCastCallback; + + private _temoBodyDef: B2.BodyDef; + private _tempB2AABB: B2.AABB; + + get impl (): B2.World { + return this._world; + } + + get groundBodyImpl (): B2.Body { + return this._physicsGroundBody; + } + + constructor () { + this._world = new B2.World({ x: 0, y: -10 }); + this._physicsGroundBody = this._world.CreateBody(new B2.BodyDef() as B2.BodyDef); + PhysicsContactListener._BeginContact = this._onBeginContact; + PhysicsContactListener._EndContact = this._onEndContact; + PhysicsContactListener._PreSolve = this._onPreSolve; + PhysicsContactListener._PostSolve = this._onPostSolve; + this._contactListener = B2.ContactListener.implement(PhysicsContactListener.callback); + this._world.SetContactListener(this._contactListener); + + this._aabbQueryCallback = B2.QueryCallback.implement(PhysicsAABBQueryCallback.callback); + this._raycastQueryCallback = B2.RayCastCallback.implement(PhysicsRayCastCallback.callback); + + this._temoBodyDef = new B2.BodyDef(); + this._tempB2AABB = new B2.AABB(); + } + + _debugGraphics: Graphics | null = null; + _b2DebugDrawer: B2.Draw | null = null; + + _debugDrawFlags = 0; + get debugDrawFlags (): number { + return this._debugDrawFlags; + } + set debugDrawFlags (v) { + if (EDITOR_NOT_IN_PREVIEW) return; + + if (!v) { + if (this._debugGraphics) { + this._debugGraphics.node.parent = null; + } + } + + this._debugDrawFlags = v; + } + + _checkDebugDrawValid (): void { + if (EDITOR_NOT_IN_PREVIEW) return; + if (!this._debugGraphics || !this._debugGraphics.isValid) { + let canvas = find('Canvas'); + if (!canvas) { + const scene = director.getScene(); + if (!scene) { + return; + } + + canvas = new Node('Canvas'); + canvas.addComponent(Canvas); + canvas.parent = scene; + } + + const node = new Node('PHYSICS_2D_DEBUG_DRAW'); + // node.zIndex = cc.macro.MAX_ZINDEX; + node.hideFlags |= CCObject.Flags.DontSave; + node.parent = canvas; + node.worldPosition = Vec3.ZERO; + node.layer = Layers.Enum.UI_2D; + + this._debugGraphics = node.addComponent(Graphics); + this._debugGraphics.lineWidth = 3; + + PhysicsDebugDraw._drawer = this._debugGraphics; + const debugDraw = B2.Draw.implement(PhysicsDebugDraw.callback);//new PhysicsDebugDraw(); + + this._b2DebugDrawer = debugDraw; + this._world.SetDebugDraw(debugDraw as B2.Draw); + } + + const parent = this._debugGraphics.node.parent!; + this._debugGraphics.node.setSiblingIndex(parent.children.length - 1); + + if (this._b2DebugDrawer) { + this._b2DebugDrawer.SetFlags(this.debugDrawFlags); + } + } + + setGravity (v: IVec2Like): void { + this._world.SetGravity(v as B2.Vec2); + } + + setAllowSleep (v: boolean): void { + this._world.SetAllowSleeping(true); + } + + step (deltaTime: number, velocityIterations = 10, positionIterations = 10): void { + const animatedBodies = this._animatedBodies; + for (let i = 0, l = animatedBodies.length; i < l; i++) { + animatedBodies[i].animate(deltaTime); + } + this._world.Step(deltaTime, velocityIterations, positionIterations); + } + + raycast (p1: Vec2, p2: Vec2, type: ERaycast2DType, mask: number): RaycastResult2D[] { + if (p1.equals(p2)) { + return []; + } + + type = type || ERaycast2DType.Closest; + + tempVec2_1.x = p1.x / PHYSICS_2D_PTM_RATIO; + tempVec2_1.y = p1.y / PHYSICS_2D_PTM_RATIO; + tempVec2_2.x = p2.x / PHYSICS_2D_PTM_RATIO; + tempVec2_2.y = p2.y / PHYSICS_2D_PTM_RATIO; + + PhysicsRayCastCallback.init(type, mask); + this._world.RayCast(this._raycastQueryCallback, tempVec2_1, tempVec2_2); + + const fixtures = PhysicsRayCastCallback.getFixtures(); + if (fixtures.length > 0) { + const points = PhysicsRayCastCallback.getPoints(); + const normals = PhysicsRayCastCallback.getNormals(); + const fractions = PhysicsRayCastCallback.getFractions(); + + const results: RaycastResult2D[] = []; + for (let i = 0, l = fixtures.length; i < l; i++) { + const fixture = fixtures[i]; + const shape = getTSObjectFromWASMObject(fixture); + const collider = shape.collider; + + if (type === ERaycast2DType.AllClosest) { + let result; + for (let j = 0; j < results.length; j++) { + if (results[j].collider === collider) { + result = results[j]; + } + } + + if (result) { + if (fractions[i] < result.fraction) { + result.fixtureIndex = shape.getFixtureIndex(fixture); + result.point.x = points[i].x * PHYSICS_2D_PTM_RATIO; + result.point.y = points[i].y * PHYSICS_2D_PTM_RATIO; + result.normal.x = normals[i].x; + result.normal.y = normals[i].y; + result.fraction = fractions[i]; + } + continue; + } + } + + results.push({ + collider, + fixtureIndex: shape.getFixtureIndex(fixture), + point: new Vec2(points[i].x * PHYSICS_2D_PTM_RATIO, points[i].y * PHYSICS_2D_PTM_RATIO), + normal: new Vec2(normals[i].x, normals[i].y), + fraction: fractions[i], + }); + } + + return results; + } + + return []; + } + + syncPhysicsToScene (): void { + const bodies = this._bodies; + for (let i = 0, l = bodies.length; i < l; i++) { + const body = bodies[i]; + const bodyComp = body.rigidBody; + if (bodyComp.type === ERigidBody2DType.Animated) { + body.resetVelocity(); + continue; + } + + const node = bodyComp.node; + const b2body = body.impl!; + + // position + const pos = b2body.GetPosition(); + tempVec3.x = pos.x * PHYSICS_2D_PTM_RATIO; + tempVec3.y = pos.y * PHYSICS_2D_PTM_RATIO; + tempVec3.z = 0; + node.worldPosition = tempVec3; + + // rotation + const angle = toDegree(b2body.GetAngle()); + node.setWorldRotationFromEuler(0, 0, angle); + } + } + syncSceneToPhysics (): void { + const bodies = this._bodies; + for (let i = 0; i < bodies.length; i++) { + bodies[i].syncSceneToPhysics(); + } + } + + addBody (body: B2RigidBody2D): void { + const bodies = this._bodies; + if (bodies.includes(body)) { + return; + } + + const bodyDef = this._temoBodyDef; + + const comp = body.rigidBody; + + bodyDef.allowSleep = comp.allowSleep; + bodyDef.gravityScale = comp.gravityScale; + bodyDef.linearDamping = comp.linearDamping; + bodyDef.angularDamping = comp.angularDamping; + + bodyDef.fixedRotation = comp.fixedRotation; + bodyDef.bullet = comp.bullet; + + const node = comp.node; + const pos = node.worldPosition; + bodyDef.position = { x: pos.x / PHYSICS_2D_PTM_RATIO, y: pos.y / PHYSICS_2D_PTM_RATIO }; + tempVec3.z = Quat.getAxisAngle(this._rotationAxis, node.worldRotation); + if (this._rotationAxis.z < 0.0) { + tempVec3.z = Math.PI * 2 - tempVec3.z; + } + bodyDef.angle = tempVec3.z; + + bodyDef.awake = comp.awakeOnLoad; + + if (comp.type === ERigidBody2DType.Animated) { + bodyDef.type = B2.BodyType.b2_kinematicBody; + this._animatedBodies.push(body); + body._animatedPos.set(bodyDef.position.x, bodyDef.position.y); + body._animatedAngle = bodyDef.angle; + } else { + switch (comp.type) { + case ERigidBody2DType.Dynamic: + bodyDef.type = B2.BodyType.b2_dynamicBody; + break; + case ERigidBody2DType.Static: + bodyDef.type = B2.BodyType.b2_staticBody; + break; + case ERigidBody2DType.Kinematic: + bodyDef.type = B2.BodyType.b2_kinematicBody; + break; + default: + bodyDef.type = B2.BodyType.b2_staticBody; + break; + } + } + + // read private property + const compPrivate = comp as any; + const linearVelocity = compPrivate._linearVelocity; + bodyDef.linearVelocity = { x: linearVelocity.x, y: linearVelocity.y }; + + bodyDef.angularVelocity = toRadian(compPrivate._angularVelocity as number); + + const b2Body = this._world.CreateBody(bodyDef); + addImplPtrReference(body, getImplPtr(b2Body)); + addImplPtrReferenceWASM(b2Body, getImplPtr(b2Body)); + body._imp = b2Body; + + this._bodies.push(body); + } + + removeBody (body: B2RigidBody2D): void { + if (!this._bodies.includes(body)) { + return; + } + if (body.impl) { + removeImplPtrReference(getImplPtr(body.impl)); + removeImplPtrReferenceWASM(getImplPtr(body.impl)); + this._world.DestroyBody(body.impl); + body._imp = null; + } + js.array.remove(this._bodies, body); + + const comp = body.rigidBody; + if (comp.type === ERigidBody2DType.Animated) { + js.array.remove(this._animatedBodies, body); + } + } + + registerContactFixture (fixture: B2.Fixture): void { + this._contactListener.registerContactFixture(getImplPtr(fixture)); + } + unregisterContactFixture (fixture: B2.Fixture): void { + this._contactListener.unregisterContactFixture(getImplPtr(fixture)); + } + + testPoint (point: Vec2): readonly Collider2D[] { + const x = tempVec2_1.x = point.x / PHYSICS_2D_PTM_RATIO; + const y = tempVec2_1.y = point.y / PHYSICS_2D_PTM_RATIO; + + const d = 0.2 / PHYSICS_2D_PTM_RATIO; + this._tempB2AABB.lowerBound = { x: x - d, y: y - d }; + this._tempB2AABB.upperBound = { x: x + d, y: y + d }; + + const callback = this._aabbQueryCallback; + PhysicsAABBQueryCallback.init(tempVec2_1); + this._world.QueryAABB(callback, this._tempB2AABB); + + const fixtures = PhysicsAABBQueryCallback.getFixtures(); + testResults.length = 0; + for (let i = 0; i < fixtures.length; i++) { + const collider = getTSObjectFromWASMObject(fixtures[i]).collider; + if (!testResults.includes(collider)) { + testResults.push(collider); + } + } + return testResults; + } + + testAABB (rect: Rect): readonly Collider2D[] { + this._tempB2AABB.lowerBound = { x: rect.xMin / PHYSICS_2D_PTM_RATIO, y: rect.yMin / PHYSICS_2D_PTM_RATIO }; + this._tempB2AABB.upperBound = { x: rect.xMax / PHYSICS_2D_PTM_RATIO, y: rect.yMax / PHYSICS_2D_PTM_RATIO }; + + const callback = this._aabbQueryCallback; + PhysicsAABBQueryCallback.init(); + this._world.QueryAABB(callback, this._tempB2AABB); + + const fixtures = PhysicsAABBQueryCallback.getFixtures(); + testResults.length = 0; + for (let i = 0; i < fixtures.length; i++) { + const collider = getTSObjectFromWASMObject(fixtures[i]).collider; + if (!testResults.includes(collider)) { + testResults.push(collider); + } + } + return testResults; + } + + drawDebug (): void { + this._checkDebugDrawValid(); + + if (!this._debugGraphics) { + return; + } + this._debugGraphics.clear(); + this._world.DebugDraw(); + } + + _onBeginContact (b2contact: number): void { + const c = PhysicsContact.get(b2contact); + c.emit(Contact2DType.BEGIN_CONTACT); + } + + _onEndContact (b2contact: number): void { + const c = getTSObjectFromWASMObjectPtr(b2contact); + if (!c) { + return; + } + c.emit(Contact2DType.END_CONTACT); + + PhysicsContact.put(b2contact); + } + + _onPreSolve (b2contact: number): void { + const c = getTSObjectFromWASMObjectPtr(b2contact); + if (!c) { + return; + } + + c.emit(Contact2DType.PRE_SOLVE); + } + + _onPostSolve (b2contact: number, impulse: number): void { + const c = getTSObjectFromWASMObjectPtr(b2contact); + if (!c) { + return; + } + + // impulse only survive during post sole callback + c._setImpulse(impulse); + c.emit(Contact2DType.POST_SOLVE); + c._setImpulse(0); + } +} diff --git a/cocos/physics-2d/box2d-wasm/platform/physics-aabb-query-callback.ts b/cocos/physics-2d/box2d-wasm/platform/physics-aabb-query-callback.ts new file mode 100644 index 00000000000..657dcc2b407 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/platform/physics-aabb-query-callback.ts @@ -0,0 +1,73 @@ +/* + Copyright (c) 2017-2023 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 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. +*/ + +import { B2, getTSObjectFromWASMObject, getWASMObjectFromWASMObjectPtr } from '../instantiated'; +import { Vec2 } from '../../../core'; +import { B2RigidBody2D } from '../rigid-body'; + +export class PhysicsAABBQueryCallback { + static _point = { x: 0, y: 0 }; + static _isPoint = false; + static _fixtures: B2.Fixture[] = []; + + static init (point?: Vec2): void { + if (point) { + this._isPoint = true; + this._point.x = point.x; + this._point.y = point.y; + } else { + this._isPoint = false; + } + + this._fixtures.length = 0; + } + + static ReportFixture (fixture: B2.Fixture): boolean { + if (this._isPoint) { + if (fixture.TestPoint(this._point)) { + this._fixtures.push(fixture); + } + } else { + this._fixtures.push(fixture); + } + + // True to continue the query, false to terminate the query. + return true; + } + + static getFixture (): any { + return this._fixtures[0]; + } + + static getFixtures (): any[] { + return this._fixtures; + } + + static callback = { + ReportFixture (fixture: number): boolean { + const f = getWASMObjectFromWASMObjectPtr(fixture); + return PhysicsAABBQueryCallback.ReportFixture(f); + }, + }; +} diff --git a/cocos/physics-2d/box2d-wasm/platform/physics-contact-listener.ts b/cocos/physics-2d/box2d-wasm/platform/physics-contact-listener.ts new file mode 100644 index 00000000000..088620079c3 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/platform/physics-contact-listener.ts @@ -0,0 +1,72 @@ +/* + Copyright (c) 2017-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { js, warn } from '../../../core'; + +export class PhysicsContactListener { + static _BeginContact: Function | null = null; + static _EndContact: Function | null = null; + static _PreSolve: Function | null = null; + static _PostSolve: Function | null = null; + + static BeginContact (contact: number): void { + if (this._BeginContact) { + this._BeginContact(contact); + } + } + + static EndContact (contact: number): void { + if (this._EndContact) { + this._EndContact(contact); + } + } + + static PreSolve (contact: number, oldManifold: number): void { + if (this._PreSolve) { + this._PreSolve(contact, oldManifold); + } + } + + static PostSolve (contact: number, impulse: number): void { + if (this._PostSolve) { + this._PostSolve(contact, impulse); + } + } + + static callback = { + BeginContact (contact: number): void { + PhysicsContactListener.BeginContact(contact); + }, + EndContact (contact: number): void { + PhysicsContactListener.EndContact(contact); + }, + PreSolve (contact: number, oldManifold: number): void { + PhysicsContactListener.PreSolve(contact, oldManifold); + }, + PostSolve (contact: number, impulse: number): void { + PhysicsContactListener.PostSolve(contact, impulse); + }, + }; +} diff --git a/cocos/physics-2d/box2d-wasm/platform/physics-debug-draw.ts b/cocos/physics-2d/box2d-wasm/platform/physics-debug-draw.ts new file mode 100644 index 00000000000..9127274bdb5 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/platform/physics-debug-draw.ts @@ -0,0 +1,199 @@ +/* + Copyright (c) 2017-2023 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 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. +*/ + +import { B2, b2Mul } from '../instantiated'; +import { Color, warn } from '../../../core'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework'; +import { Graphics } from '../../../2d'; + +const _tmp_vec2 = { x: 0, y: 0 }; +const _tmp_vec3 = { x: 0, y: 0 }; +const _tmp_color = new Color(); + +const GREEN_COLOR = Color.GREEN; +const RED_COLOR = Color.RED; + +export class PhysicsDebugDraw {// extends B2.Draw { + static callback = { + DrawPolygon (vertices: number, vertexCount: number, color: B2.Color): void { + PhysicsDebugDraw.DrawPolygon(vertices, vertexCount, color); + }, + DrawSolidPolygon (vertices: number, vertexCount: number, color: B2.Color): void { + PhysicsDebugDraw.DrawSolidPolygon(vertices, vertexCount, color); + }, + DrawCircle (center: B2.Vec2, radius: number, color: B2.Color): void { + PhysicsDebugDraw.DrawCircle(center, radius, color); + }, + DrawSolidCircle (center: B2.Vec2, radius: number, axis, color: B2.Color): void { + PhysicsDebugDraw.DrawSolidCircle(center, radius, axis, color); + }, + DrawSegment (p1: B2.Vec2, p2: B2.Vec2, color: B2.Color): void { + PhysicsDebugDraw.DrawSegment(p1, p2, color); + }, + DrawTransform (xf: B2.Transform): void { + PhysicsDebugDraw.DrawTransform(xf); + }, + DrawPoint (center: B2.Vec2, size: number, color: B2.Color): void { + PhysicsDebugDraw.DrawPoint(center, size, color); + }, + }; + + static _drawer: Graphics | null = null; + + static _xf = { p: { x: 0, y: 0 }, q: { s: 0, c: 1 } };//new B2.Transform(); + static _dxf = { p: { x: 0, y: 0 }, q: { s: 0, c: 1 } };//new B2.Transform(); + + static _DrawPolygon (vertices: number, vertexCount: number): void { + const drawer = PhysicsDebugDraw._drawer!; + const rawVertexBuffer = B2.HEAPF32.subarray(vertices / 4, vertices / 4 + vertexCount * 2); + + for (let i = 0; i < vertexCount; i++) { + _tmp_vec2.x = rawVertexBuffer[i * 2 + 0]; + _tmp_vec2.y = rawVertexBuffer[i * 2 + 1]; + b2Mul(PhysicsDebugDraw._xf, _tmp_vec2, _tmp_vec3); + const x = _tmp_vec3.x * PHYSICS_2D_PTM_RATIO; + const y = _tmp_vec3.y * PHYSICS_2D_PTM_RATIO; + if (i === 0) drawer.moveTo(x, y); + else { + drawer.lineTo(x, y); + } + } + + drawer.close(); + } + + static DrawPolygon (vertices: number, vertexCount: number, color: B2.Color): void { + PhysicsDebugDraw._applyStrokeColor(color); + PhysicsDebugDraw._DrawPolygon(vertices, vertexCount); + PhysicsDebugDraw._drawer!.stroke(); + } + + static DrawSolidPolygon (vertices: number, vertexCount: number, color: B2.Color): void { + PhysicsDebugDraw._applyFillColor(color); + PhysicsDebugDraw._DrawPolygon(vertices, vertexCount); + PhysicsDebugDraw._drawer!.fill(); + PhysicsDebugDraw._drawer!.stroke(); + } + + static _DrawCircle (center: B2.Vec2, radius: number): void { + const p = PhysicsDebugDraw._xf.p; + PhysicsDebugDraw._drawer!.circle( + (center.x + p.x) * PHYSICS_2D_PTM_RATIO, + (center.y + p.y) * PHYSICS_2D_PTM_RATIO, + radius * PHYSICS_2D_PTM_RATIO, + ); + } + + static DrawCircle (center: B2.Vec2, radius: number, color: B2.Color): void { + PhysicsDebugDraw._applyStrokeColor(color); + PhysicsDebugDraw._DrawCircle(center, radius); + PhysicsDebugDraw._drawer!.stroke(); + } + + static DrawSolidCircle (center: B2.Vec2, radius: number, axis, color: B2.Color): void { + PhysicsDebugDraw._applyFillColor(color); + PhysicsDebugDraw._DrawCircle(center, radius); + PhysicsDebugDraw._drawer!.fill(); + } + + static DrawSegment (p1: B2.Vec2, p2: B2.Vec2, color: B2.Color): void { + const drawer = PhysicsDebugDraw._drawer!; + + if (p1.x === p2.x && p1.y === p2.y) { + PhysicsDebugDraw._applyFillColor(color); + PhysicsDebugDraw._DrawCircle(p1, 2 / PHYSICS_2D_PTM_RATIO); + drawer.fill(); + return; + } + PhysicsDebugDraw._applyStrokeColor(color); + + b2Mul(PhysicsDebugDraw._xf, p1, _tmp_vec2); + drawer.moveTo(_tmp_vec2.x * PHYSICS_2D_PTM_RATIO, _tmp_vec2.y * PHYSICS_2D_PTM_RATIO); + b2Mul(PhysicsDebugDraw._xf, p2, _tmp_vec2); + drawer.lineTo(_tmp_vec2.x * PHYSICS_2D_PTM_RATIO, _tmp_vec2.y * PHYSICS_2D_PTM_RATIO); + drawer.stroke(); + } + + static DrawTransform (xf: B2.Transform): void { + const drawer = PhysicsDebugDraw._drawer!; + + drawer.strokeColor = RED_COLOR; + + _tmp_vec2.x = _tmp_vec2.y = 0; + b2Mul(xf, _tmp_vec2, _tmp_vec3); + drawer.moveTo(_tmp_vec3.x * PHYSICS_2D_PTM_RATIO, _tmp_vec3.y * PHYSICS_2D_PTM_RATIO); + + _tmp_vec2.x = 1; _tmp_vec2.y = 0; + b2Mul(xf, _tmp_vec2, _tmp_vec3); + drawer.lineTo(_tmp_vec3.x * PHYSICS_2D_PTM_RATIO, _tmp_vec3.y * PHYSICS_2D_PTM_RATIO); + + drawer.stroke(); + + drawer.strokeColor = GREEN_COLOR; + + _tmp_vec2.x = _tmp_vec2.y = 0; + b2Mul(xf, _tmp_vec2, _tmp_vec3); + drawer.moveTo(_tmp_vec3.x * PHYSICS_2D_PTM_RATIO, _tmp_vec3.y * PHYSICS_2D_PTM_RATIO); + + _tmp_vec2.x = 0; _tmp_vec2.y = 1; + b2Mul(xf, _tmp_vec2, _tmp_vec3); + drawer.lineTo(_tmp_vec3.x * PHYSICS_2D_PTM_RATIO, _tmp_vec3.y * PHYSICS_2D_PTM_RATIO); + + drawer.stroke(); + } + + static DrawPoint (center, size, color): void { + // TODO + } + + static DrawParticles (): void { + // TODO + } + + static _applyStrokeColor (color: B2.Color): void { + PhysicsDebugDraw._drawer!.strokeColor = _tmp_color.set( + color.r * 255, + color.g * 255, + color.b * 255, + 150, + ); + } + + static _applyFillColor (color: B2.Color): void { + PhysicsDebugDraw._drawer!.fillColor = _tmp_color.set( + color.r * 255, + color.g * 255, + color.b * 255, + 150, + ); + } + + PushTransform (xf): void { + PhysicsDebugDraw._xf = xf; + } + + PopTransform (): void { + PhysicsDebugDraw._xf = PhysicsDebugDraw._dxf; + } +} diff --git a/cocos/physics-2d/box2d-wasm/platform/physics-ray-cast-callback.ts b/cocos/physics-2d/box2d-wasm/platform/physics-ray-cast-callback.ts new file mode 100644 index 00000000000..3c067a73da2 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/platform/physics-ray-cast-callback.ts @@ -0,0 +1,98 @@ +/* + Copyright (c) 2017-2023 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 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. +*/ + +import { B2, getTSObjectFromWASMObject, getWASMObjectFromWASMObjectPtr } from '../instantiated'; +import { Vec2 } from '../../../core'; +import { ERaycast2DType } from '../../framework'; +import { B2Shape2D } from '../shapes/shape-2d'; +import { B2RigidBody2D } from '../rigid-body'; + +export class PhysicsRayCastCallback {// extends B2.RayCastCallback { + static _type = ERaycast2DType.Closest; + static _fixtures: B2.Fixture[] = []; + static _points: Vec2[] = []; + static _normals: Vec2[] = []; + static _fractions: number[] = []; + + static _mask = 0xffffffff; + + static init (type: ERaycast2DType, mask: number): void { + PhysicsRayCastCallback._type = type; + PhysicsRayCastCallback._mask = mask; + PhysicsRayCastCallback._fixtures.length = 0; + PhysicsRayCastCallback._points.length = 0; + PhysicsRayCastCallback._normals.length = 0; + PhysicsRayCastCallback._fractions.length = 0; + } + + static ReportFixture (fixture: B2.Fixture, point: B2.Vec2, normal: B2.Vec2, fraction: number): any { + if ((fixture.GetFilterData().categoryBits & PhysicsRayCastCallback._mask) === 0) { + return 0; + } + + if (PhysicsRayCastCallback._type === ERaycast2DType.Closest) { + PhysicsRayCastCallback._fixtures[0] = fixture; + PhysicsRayCastCallback._points[0] = point as Vec2; + PhysicsRayCastCallback._normals[0] = normal as Vec2; + PhysicsRayCastCallback._fractions[0] = fraction; + return fraction; + } + + PhysicsRayCastCallback._fixtures.push(fixture); + PhysicsRayCastCallback._points.push(new Vec2(point.x, point.y)); + PhysicsRayCastCallback._normals.push(new Vec2(normal.x, normal.y)); + PhysicsRayCastCallback._fractions.push(fraction); + + if (PhysicsRayCastCallback._type === ERaycast2DType.Any) { + return 0; + } else if (PhysicsRayCastCallback._type >= ERaycast2DType.All) { + return 1; + } + + return fraction; + } + + static getFixtures (): B2.Fixture[] { + return PhysicsRayCastCallback._fixtures; + } + + static getPoints (): Vec2[] { + return PhysicsRayCastCallback._points; + } + + static getNormals (): Vec2[] { + return PhysicsRayCastCallback._normals; + } + + static getFractions (): number[] { + return PhysicsRayCastCallback._fractions; + } + + static callback = { + ReportFixture (fixture: number, point: B2.Vec2, normal: B2.Vec2, fraction: number): any { + const f = getWASMObjectFromWASMObjectPtr(fixture); + return PhysicsRayCastCallback.ReportFixture(f, point, normal, fraction); + }, + }; +} diff --git a/cocos/physics-2d/box2d-wasm/rigid-body.ts b/cocos/physics-2d/box2d-wasm/rigid-body.ts new file mode 100644 index 00000000000..feb13037e4c --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/rigid-body.ts @@ -0,0 +1,362 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from './instantiated'; +import { IRigidBody2D } from '../spec/i-rigid-body'; +import { RigidBody2D } from '../framework/components/rigid-body-2d'; +import { PhysicsSystem2D } from '../framework/physics-system'; +import { B2PhysicsWorld } from './physics-world'; +import { Vec2, toRadian, Vec3, Quat, IVec2Like, toDegree, TWO_PI, HALF_PI } from '../../core'; +import { PHYSICS_2D_PTM_RATIO, ERigidBody2DType } from '../framework/physics-types'; + +import { Node } from '../../scene-graph/node'; +import { Collider2D } from '../framework'; +import { NodeEventType } from '../../scene-graph/node-event'; + +const tempVec3 = new Vec3(); +const tempVec2_1 = { x: 0, y: 0 };//new B2.Vec2(0, 0); +let tempVec2_2 = { x: 0, y: 0 }; +export class B2RigidBody2D implements IRigidBody2D { + get impl (): B2.Body | null { + return this._body; + } + set _imp (v: B2.Body | null) { + this._body = v; + } + + get rigidBody (): RigidBody2D { + return this._rigidBody; + } + get isAwake (): boolean { + return this._body!.IsAwake(); + } + get isSleeping (): boolean { + return !(this._body!.IsAwake()); + } + + _animatedPos = new Vec2(); + _animatedAngle = 0; + + private _body: B2.Body | null = null; + private _rigidBody!: RigidBody2D; + + private _inited = false; + + initialize (com: RigidBody2D): void { + this._rigidBody = com; + + PhysicsSystem2D.instance._callAfterStep(this, this._init); + } + + onDestroy (): void { + PhysicsSystem2D.instance._callAfterStep(this, this._destroy); + } + + onEnable (): void { + this.setActive(true); + } + + onDisable (): void { + this.setActive(false); + } + + nodeTransformChanged (type): void { + if (PhysicsSystem2D.instance.stepping) { + return; + } + + if (type & Node.TransformBit.SCALE) { + const colliders = this.rigidBody.getComponents(Collider2D); + for (let i = 0; i < colliders.length; i++) { + colliders[i].apply(); + } + } + if (type & Node.TransformBit.POSITION) { + this.syncPositionToPhysics(true); + } + if (type & Node.TransformBit.ROTATION) { + this.syncRotationToPhysics(true); + } + } + + _init (): void { + if (this._inited) { + return; + } + + (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).addBody(this); + this.setActive(false); + + this._inited = true; + } + + _destroy (): void { + if (!this._inited) return; + + (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).removeBody(this); + + this._inited = false; + } + + animate (dt: number): void { + const b2body = this._body; + if (!b2body) return; + const b2Pos = b2body.GetPosition(); + + b2body.SetAwake(true); + + const timeStep = 1 / dt; + tempVec2_1.x = (this._animatedPos.x - b2Pos.x) * timeStep; + tempVec2_1.y = (this._animatedPos.y - b2Pos.y) * timeStep; + b2body.SetLinearVelocity(tempVec2_1); + + //convert b2Rotation to [-PI~PI], which is the same as this._animatedAngle + let b2Rotation = b2body.GetAngle() % (TWO_PI); + if (b2Rotation > Math.PI) { + b2Rotation -= TWO_PI; + } + + //calculate angular velocity + let angularVelocity = (this._animatedAngle - b2Rotation) * timeStep; + if (this._animatedAngle < -HALF_PI && b2Rotation > HALF_PI) { //ccw, crossing PI + angularVelocity = (this._animatedAngle + TWO_PI - b2Rotation) * timeStep; + } if (this._animatedAngle > HALF_PI && b2Rotation < -HALF_PI) { //cw, crossing PI + angularVelocity = (this._animatedAngle - TWO_PI - b2Rotation) * timeStep; + } + + b2body.SetAngularVelocity(angularVelocity); + } + + syncSceneToPhysics (): void { + const dirty = this._rigidBody.node.hasChangedFlags; + if (dirty) { this.nodeTransformChanged(dirty); } + } + + syncPositionToPhysics (enableAnimated = false): void { + const b2body = this._body; + if (!b2body) return; + + const pos = this._rigidBody.node.worldPosition; + + //the belowing code seems useless? + const bodyType = this._rigidBody.type; + if (bodyType === ERigidBody2DType.Animated) { + tempVec2_2 = b2body.GetLinearVelocity(); + } else { + tempVec2_2 = b2body.GetPosition(); + } + + tempVec2_2.x = pos.x / PHYSICS_2D_PTM_RATIO; + tempVec2_2.y = pos.y / PHYSICS_2D_PTM_RATIO; + + if (bodyType === ERigidBody2DType.Animated && enableAnimated) { + this._animatedPos.set(tempVec2_2.x, tempVec2_2.y); + } else { + b2body.SetTransform(tempVec2_2, b2body.GetAngle()); + } + } + + syncRotationToPhysics (enableAnimated = false): void { + const b2body = this._body; + if (!b2body) return; + + const rot = this._rigidBody.node.worldRotation; + const euler = tempVec3; + Quat.toEulerInYXZOrder(euler, rot); + const rotation = toRadian(euler.z); + + const bodyType = this._rigidBody.type; + if (bodyType === ERigidBody2DType.Animated && enableAnimated) { + this._animatedAngle = rotation; + } else { + b2body.SetTransform(b2body.GetPosition(), rotation); + } + } + + resetVelocity (): void { + const b2body = this._body; + if (!b2body) return; + + tempVec2_1.x = 0; + tempVec2_1.y = 0; + + b2body.SetLinearVelocity(tempVec2_1); + b2body.SetAngularVelocity(0); + } + + setType (v: ERigidBody2DType): void { + this._body!.SetType(v as number); + } + setLinearDamping (v: number): void { + this._body!.SetLinearDamping(v); + } + setAngularDamping (v: number): void { + this._body!.SetAngularDamping(v); + } + setGravityScale (v: number): void { + this._body!.SetGravityScale(v); + } + setFixedRotation (v: boolean): void { + this._body!.SetFixedRotation(v); + } + setAllowSleep (v: boolean): void { + this._body!.SetSleepingAllowed(v); + } + isActive (): any { + return this._body!.IsEnabled(); + } + setActive (v: boolean): void { + this._body!.SetEnabled(v); + } + wakeUp (): void { + this._body!.SetAwake(true); + } + sleep (): void { + this._body!.SetAwake(false); + } + getMass (): any { + return this._body!.GetMass(); + } + setLinearVelocity (v: IVec2Like): void { + this._body!.SetLinearVelocity(v as B2.Vec2); + } + getLinearVelocity (out: Out): Out { + const velocity = this._body!.GetLinearVelocity(); + out.x = velocity.x; + out.y = velocity.y; + return out; + } + getLinearVelocityFromWorldPoint (worldPoint: IVec2Like, out: Out): Out { + out = out || new Vec2(); + tempVec2_1.x = worldPoint.x / PHYSICS_2D_PTM_RATIO; + tempVec2_1.y = worldPoint.y / PHYSICS_2D_PTM_RATIO; + const temp = this._body!.GetLinearVelocityFromWorldPoint(tempVec2_1); + out.x = temp.x * PHYSICS_2D_PTM_RATIO; + out.y = temp.y * PHYSICS_2D_PTM_RATIO; + return out; + } + setAngularVelocity (v: number): void { + this._body!.SetAngularVelocity(v); + } + getAngularVelocity (): number { + return toDegree(this._body!.GetAngularVelocity()); + } + + getLocalVector (worldVector: IVec2Like, out: Out): Out { + out = out || new Vec2(); + tempVec2_1.x = worldVector.x / PHYSICS_2D_PTM_RATIO; + tempVec2_1.y = worldVector.y / PHYSICS_2D_PTM_RATIO; + const temp = this._body!.GetLocalVector(tempVec2_1); + out.x = temp.x * PHYSICS_2D_PTM_RATIO; + out.y = temp.y * PHYSICS_2D_PTM_RATIO; + return out; + } + getWorldVector (localVector: IVec2Like, out: Out): Out { + tempVec2_1.x = localVector.x / PHYSICS_2D_PTM_RATIO; + tempVec2_1.y = localVector.y / PHYSICS_2D_PTM_RATIO; + const temp = this._body!.GetWorldVector(tempVec2_1); + out.x = temp.x * PHYSICS_2D_PTM_RATIO; + out.y = temp.y * PHYSICS_2D_PTM_RATIO; + return out; + } + + getLocalPoint (worldPoint: IVec2Like, out: Out): Out { + out = out || new Vec2(); + tempVec2_1.x = worldPoint.x / PHYSICS_2D_PTM_RATIO; + tempVec2_1.y = worldPoint.y / PHYSICS_2D_PTM_RATIO; + const temp = this._body!.GetLocalPoint(tempVec2_1); + out.x = temp.x * PHYSICS_2D_PTM_RATIO; + out.y = temp.y * PHYSICS_2D_PTM_RATIO; + return out; + } + + getWorldPoint (localPoint: IVec2Like, out: Out): Out { + out = out || new Vec2(); + tempVec2_1.x = localPoint.x / PHYSICS_2D_PTM_RATIO; + tempVec2_1.y = localPoint.y / PHYSICS_2D_PTM_RATIO; + const temp = this._body!.GetWorldPoint(tempVec2_1); + out.x = temp.x * PHYSICS_2D_PTM_RATIO; + out.y = temp.y * PHYSICS_2D_PTM_RATIO; + return out; + } + + getLocalCenter (out: Out): Out { + out = out || new Vec2(); + const pos = this._body!.GetLocalCenter(); + out.x = pos.x * PHYSICS_2D_PTM_RATIO; + out.y = pos.y * PHYSICS_2D_PTM_RATIO; + return out; + } + getWorldCenter (out: Out): Out { + out = out || new Vec2(); + const pos = this._body!.GetWorldCenter(); + out.x = pos.x * PHYSICS_2D_PTM_RATIO; + out.y = pos.y * PHYSICS_2D_PTM_RATIO; + return out; + } + + getInertia (): any { + return this._body!.GetInertia(); + } + + applyForce (force: IVec2Like, point: IVec2Like, wake: boolean): void { + if (this._body) { + tempVec2_1.x = point.x / PHYSICS_2D_PTM_RATIO; + tempVec2_1.y = point.y / PHYSICS_2D_PTM_RATIO; + this._body.ApplyForce(force as B2.Vec2, tempVec2_1, wake); + } + } + + applyForceToCenter (force: IVec2Like, wake: boolean): void { + if (this._body) { + this._body.ApplyForceToCenter(force as B2.Vec2, wake); + } + } + + applyTorque (torque: number, wake: boolean): void { + if (this._body) { + this._body.ApplyTorque(torque, wake); + } + } + + applyLinearImpulse (impulse: IVec2Like, point: IVec2Like, wake: boolean): void { + if (this._body) { + tempVec2_1.x = point.x / PHYSICS_2D_PTM_RATIO; + tempVec2_1.y = point.y / PHYSICS_2D_PTM_RATIO; + this._body.ApplyLinearImpulse(impulse as B2.Vec2, tempVec2_1, wake); + } + } + + applyLinearImpulseToCenter (impulse: IVec2Like, wake: boolean): void { + if (this._body) { + this._body.ApplyLinearImpulse(impulse as B2.Vec2, this._body.GetPosition(), wake); + } + } + + applyAngularImpulse (impulse: number, wake: boolean): void { + if (this._body) { + this._body.ApplyAngularImpulse(impulse, wake); + } + } +} diff --git a/cocos/physics-2d/box2d-wasm/shapes/box-shape-2d.ts b/cocos/physics-2d/box2d-wasm/shapes/box-shape-2d.ts new file mode 100644 index 00000000000..381632fb03a --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/shapes/box-shape-2d.ts @@ -0,0 +1,76 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { B2Shape2D } from './shape-2d'; +import { BoxCollider2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; +import { IBoxShape } from '../../spec/i-physics-shape'; +import { Vec2, Rect } from '../../../core'; + +const tempAabb = new Rect(); +const tempB2Vec2_1 = { x: 0, y: 0 }; + +export class B2BoxShape extends B2Shape2D implements IBoxShape { + _worldPoints: Vec2[] = [new Vec2(), new Vec2(), new Vec2(), new Vec2()]; + get worldPoints (): Readonly[] { + const aabb = tempAabb; + + const collider = this.collider as BoxCollider2D; + const size = collider.size; + const offset = collider.offset; + + aabb.x = offset.x - size.width / 2; + aabb.y = offset.y - size.height / 2; + aabb.width = size.width; + aabb.height = size.height; + + const wps = this._worldPoints; + const wp0 = wps[0]; const wp1 = wps[1]; + const wp2 = wps[2]; const wp3 = wps[3]; + + aabb.transformMat4ToPoints(collider.node.worldMatrix, wp0, wp1, wp2, wp3); + + return wps; + } + + _createShapes (scaleX: number, scaleY: number, relativePositionX: number, relativePositionY: number): B2.PolygonShape[] { + scaleX = Math.abs(scaleX); + scaleY = Math.abs(scaleY); + + const comp = this.collider as BoxCollider2D; + + const width = comp.size.width / 2 / PHYSICS_2D_PTM_RATIO * scaleX; + const height = comp.size.height / 2 / PHYSICS_2D_PTM_RATIO * scaleY; + const offsetX = (relativePositionX + comp.offset.x * scaleX) / PHYSICS_2D_PTM_RATIO; + const offsetY = (relativePositionY + comp.offset.y * scaleY) / PHYSICS_2D_PTM_RATIO; + + const shape = new B2.PolygonShape(); + tempB2Vec2_1.x = offsetX; + tempB2Vec2_1.y = offsetY; + shape.SetAsBoxWithCenterAndAngle(width, height, tempB2Vec2_1, 0); + + return [shape as unknown as B2.PolygonShape]; + } +} diff --git a/cocos/physics-2d/box2d-wasm/shapes/circle-shape-2d.ts b/cocos/physics-2d/box2d-wasm/shapes/circle-shape-2d.ts new file mode 100644 index 00000000000..254e2a1ece4 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/shapes/circle-shape-2d.ts @@ -0,0 +1,59 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { B2Shape2D } from './shape-2d'; +import { CircleCollider2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; +import { ICircleShape } from '../../spec/i-physics-shape'; +import { Vec2 } from '../../../core'; + +export class B2CircleShape extends B2Shape2D implements ICircleShape { + get worldRadius (): number { + return (this._shapes[0]).m_radius * PHYSICS_2D_PTM_RATIO; + } + + _worldPosition = new Vec2(); + get worldPosition (): Vec2 { + const p = (this._shapes[0] as B2.CircleShape).m_p; + return this._worldPosition.set(p.x * PHYSICS_2D_PTM_RATIO, p.y * PHYSICS_2D_PTM_RATIO); + } + + _createShapes (scaleX: number, scaleY: number, relativePositionX: number, relativePositionY: number): B2.CircleShape[] { + scaleX = Math.abs(scaleX); + scaleY = Math.abs(scaleY); + + const comp = this.collider as CircleCollider2D; + + const offsetX = (relativePositionX + comp.offset.x * scaleX) / PHYSICS_2D_PTM_RATIO; + const offsetY = (relativePositionY + comp.offset.y * scaleY) / PHYSICS_2D_PTM_RATIO; + + const shape = new B2.CircleShape(); + shape.m_radius = comp.radius / PHYSICS_2D_PTM_RATIO * scaleX; + shape.m_p.x = offsetX; + shape.m_p.y = offsetY; + + return [shape as unknown as B2.CircleShape]; + } +} diff --git a/cocos/physics-2d/box2d-wasm/shapes/polygon-shape-2d.ts b/cocos/physics-2d/box2d-wasm/shapes/polygon-shape-2d.ts new file mode 100644 index 00000000000..e192901f5ad --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/shapes/polygon-shape-2d.ts @@ -0,0 +1,115 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2 } from '../instantiated'; +import { B2Shape2D } from './shape-2d'; +import * as PolygonPartition from '../../framework/utils/polygon-partition'; +import { PolygonCollider2D } from '../../framework'; +import { PHYSICS_2D_PTM_RATIO } from '../../framework/physics-types'; +import { IPolygonShape } from '../../spec/i-physics-shape'; +import { Vec2, IVec2Like, warn } from '../../../core'; + +export class B2PolygonShape extends B2Shape2D implements IPolygonShape { + _worldPoints: Vec2[] = []; + get worldPoints (): Readonly[] { + const comp = this.collider as PolygonCollider2D; + const points = comp.points; + const worldPoints = this._worldPoints; + const m = comp.node.worldMatrix; + for (let i = 0; i < points.length; i++) { + if (!worldPoints[i]) { + worldPoints[i] = new Vec2(); + } + Vec2.transformMat4(worldPoints[i], points[i], m); + } + worldPoints.length = points.length; + + return this._worldPoints; + } + + _createShapes (scaleX: number, scaleY: number, relativePositionX: number, relativePositionY: number): B2.PolygonShape[] { + const shapes: B2.PolygonShape[] = []; + + const comp = this.collider as PolygonCollider2D; + const points = comp.points; + + // check if last point equal to first point + if (points.length > 0 && points[0].equals(points[points.length - 1])) { + points.length -= 1; + } + + const polys = PolygonPartition.ConvexPartition(points); + if (!polys) { + warn('[Physics2D] b2PolygonShape failed to decompose polygon into convex polygons, node name: ', comp.node.name); + return shapes; + } + + const offset = comp.offset; + + for (let i = 0; i < polys.length; i++) { + const poly = polys[i]; + + let shape: B2.PolygonShape | null = null; + const vertices = new B2.Vec2Vector(); + let firstVertice: B2.Vec2 | null = null; + + for (let j = 0, l = poly.length; j < l; j++) { + if (!shape) { + shape = new B2.PolygonShape(); + } + const p = poly[j]; + const x = (relativePositionX + (p.x + offset.x) * scaleX) / PHYSICS_2D_PTM_RATIO; + const y = (relativePositionY + (p.y + offset.y) * scaleY) / PHYSICS_2D_PTM_RATIO; + const v = { x, y }; + vertices.push_back(v); + + if (!firstVertice) { + firstVertice = v; + } + + if (vertices.size() === B2.maxPolygonVertices) { + shape!.Set(vertices, vertices.size() as number); + shapes.push(shape!); + + shape = null; + + if (j < l - 1) { + const temp = vertices.get(vertices.size() - 1); + vertices.resize(0, { x: 0, y: 0 });//clear + vertices.push_back(firstVertice); + vertices.push_back(temp); + } + } + } + + if (shape) { + shape.Set(vertices, vertices.size() as number); + shapes.push(shape); + } + vertices.delete(); + } + + return shapes; + } +} diff --git a/cocos/physics-2d/box2d-wasm/shapes/shape-2d.ts b/cocos/physics-2d/box2d-wasm/shapes/shape-2d.ts new file mode 100644 index 00000000000..5f102e03580 --- /dev/null +++ b/cocos/physics-2d/box2d-wasm/shapes/shape-2d.ts @@ -0,0 +1,228 @@ +/* + Copyright (c) 2022-2023 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 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. +*/ + +import { B2, getImplPtr, addImplPtrReference, addImplPtrReferenceWASM, removeImplPtrReference, + removeImplPtrReferenceWASM } from '../instantiated'; +import { IBaseShape } from '../../spec/i-physics-shape'; +import { Collider2D, PhysicsSystem2D, RigidBody2D, PHYSICS_2D_PTM_RATIO } from '../../../../exports/physics-2d-framework'; +import { Rect, Vec3 } from '../../../core'; +import { B2PhysicsWorld } from '../physics-world'; +import { PhysicsGroup } from '../../../physics/framework/physics-enum'; + +const tempFilter = { categoryBits: 0, maskBits: 0, groupIndex: 0 };// new B2.Filter(); +const lowerBound = { x: 0, y: 0 }; +const upperBound = { x: 0, y: 0 }; + +function getFilter (shape: B2Shape2D): B2.Filter { + const comp = shape.collider; + if (comp.body) { + tempFilter.categoryBits = (comp.group as PhysicsGroup) === PhysicsGroup.DEFAULT ? comp.body.group : comp.group; + } else { + tempFilter.categoryBits = comp.group; + } + tempFilter.maskBits = PhysicsSystem2D.instance.collisionMatrix[tempFilter.categoryBits]; + return tempFilter; +} + +export class B2Shape2D implements IBaseShape { + protected _shapes: B2.Shape[] = []; + protected _fixtures: B2.Fixture[] = []; + + protected _collider: Collider2D | null = null; + protected _body: B2.Body | null = null; + + private _inited = false; + + private _rect = new Rect(); + + get impl (): B2.Shape[] { + return this._shapes; + } + + get collider (): Collider2D { + return this._collider!; + } + + initialize (comp: Collider2D): void { + this._collider = comp; + } + + onLoad (): void { + //empty + } + + onEnable (): void { + PhysicsSystem2D.instance._callAfterStep(this, this._init); + } + + onDisable (): void { + PhysicsSystem2D.instance._callAfterStep(this, this._destroy); + } + + start (): void { + //empty + } + + onGroupChanged (): void { + const filter = getFilter(this); + this._fixtures.forEach((f): void => { + f.SetFilterData(filter); + }); + } + + apply (): void { + this._destroy(); + if (this.collider.enabledInHierarchy) { + this._init(); + } + } + + get worldAABB (): Readonly { + const MAX = 10e6; + + let minX = MAX; let minY = MAX; + let maxX = -MAX; let maxY = -MAX; + + const fixtures = this._fixtures; + for (let i = 0; i < fixtures.length; i++) { + const fixture = fixtures[i]; + + const count = fixture.GetShape().GetChildCount(); + for (let j = 0; j < count; j++) { + const aabb = fixture.GetAABB(j); + lowerBound.x = aabb.lowerBound.x; + lowerBound.y = aabb.lowerBound.y; + upperBound.x = aabb.upperBound.x; + upperBound.y = aabb.upperBound.y; + if (fixture.GetShape().m_type === B2.ShapeType.e_polygon) { //b2ShapeType.e_polygonShape + const skinWidth = fixture.GetShape().m_radius; + lowerBound.x += skinWidth; + lowerBound.y += skinWidth; + upperBound.x += skinWidth; + upperBound.y += skinWidth; + } + if (lowerBound.x < minX) minX = lowerBound.x; + if (lowerBound.y < minY) minY = lowerBound.y; + if (upperBound.x > maxX) maxX = upperBound.x; + if (upperBound.y > maxY) maxY = upperBound.y; + } + } + + minX *= PHYSICS_2D_PTM_RATIO; + minY *= PHYSICS_2D_PTM_RATIO; + maxX *= PHYSICS_2D_PTM_RATIO; + maxY *= PHYSICS_2D_PTM_RATIO; + + const r = this._rect; + r.x = minX; + r.y = minY; + r.width = maxX - minX; + r.height = maxY - minY; + + return r; + } + + getFixtureIndex (fixture: B2.Fixture): number { + return this._fixtures.indexOf(fixture); + } + + //relativePositionX/Y : relative Position from shape to rigid body + _createShapes (scaleX: number, scaleY: number, relativePositionX: number, relativePositionY: number): B2.Shape[] { + return []; + } + + _init (): void { + if (this._inited) return; + + const comp = this.collider; + const scale = comp.node.worldScale; + // relative Position from shape to rigid body + let relativePosition = Vec3.ZERO; + const body = comp.getComponent(RigidBody2D); + + //if rigid body is not attached to the same node of collider, this b2.shape is attached + // to the groundRigidBody(pos zero, rot zero) + if (body && body.impl && body.impl.impl) { + this._body = body.impl.impl as B2.Body; + } else { + this._body = (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).groundBodyImpl; + relativePosition = comp.node.worldPosition; + } + + const shapes = scale.x === 0 && scale.y === 0 ? [] : this._createShapes(scale.x, scale.y, relativePosition.x, relativePosition.y); + + const filter = getFilter(this); + + for (let i = 0; i < shapes.length; i++) { + const shape = shapes[i]; + + const fixDef = new B2.FixtureDef(); + fixDef.density = comp.density; + fixDef.isSensor = comp.sensor; + fixDef.friction = comp.friction; + fixDef.restitution = comp.restitution; + fixDef.SetShape(shape); + fixDef.filter = filter; + const fixture = this._body.CreateFixture(fixDef as B2.FixtureDef); + //fixture.m_userData = this; + addImplPtrReference(this, getImplPtr(fixture)); + addImplPtrReferenceWASM(fixture, getImplPtr(fixture)); + + if (body?.enabledContactListener) { + (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).registerContactFixture(fixture); + } + + this._shapes.push(shape); + this._fixtures.push(fixture); + } + + this._inited = true; + } + + _destroy (): void { + if (!this._inited) return; + + const fixtures = this._fixtures; + const body = this._body; + + for (let i = fixtures.length - 1; i >= 0; i--) { + const fixture = fixtures[i]; + //fixture.m_userData = null; + removeImplPtrReference(getImplPtr(fixture)); + removeImplPtrReferenceWASM(getImplPtr(fixture)); + + (PhysicsSystem2D.instance.physicsWorld as B2PhysicsWorld).unregisterContactFixture(fixture); + + if (body) { + body.DestroyFixture(fixture); + } + } + + this._body = null; + + this._fixtures.length = 0; + this._shapes.length = 0; + this._inited = false; + } +} diff --git a/cocos/physics-2d/box2d/physics-world.ts b/cocos/physics-2d/box2d/physics-world.ts index 5e6acc38b09..95dcf76cda0 100644 --- a/cocos/physics-2d/box2d/physics-world.ts +++ b/cocos/physics-2d/box2d/physics-world.ts @@ -23,13 +23,13 @@ */ import b2 from '@cocos/box2d'; -import { EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; +import { EDITOR_NOT_IN_PREVIEW, TEST } from 'internal:constants'; import { IPhysicsWorld } from '../spec/i-physics-world'; import { IVec2Like, Vec3, Quat, toRadian, Vec2, toDegree, Rect, CCObject, js } from '../../core'; import { PHYSICS_2D_PTM_RATIO, ERaycast2DType, ERigidBody2DType } from '../framework/physics-types'; -import { Canvas } from '../../2d/framework'; -import { Graphics } from '../../2d/components'; +// import { Canvas } from '../../2d/framework'; +// import { Graphics } from '../../2d/components'; import { b2RigidBody2D } from './rigid-body'; import { PhysicsContactListener } from './platform/physics-contact-listener'; @@ -88,7 +88,7 @@ export class b2PhysicsWorld implements IPhysicsWorld { this._raycastQueryCallback = new PhysicsRayCastCallback(); } - _debugGraphics: Graphics | null = null; + _debugGraphics: any = null; _b2DebugDrawer: b2.Draw | null = null; _debugDrawFlags = 0; @@ -118,7 +118,7 @@ export class b2PhysicsWorld implements IPhysicsWorld { } canvas = new Node('Canvas'); - canvas.addComponent(Canvas); + canvas.addComponent('cc.Canvas'); canvas.parent = scene; } @@ -129,9 +129,10 @@ export class b2PhysicsWorld implements IPhysicsWorld { node.worldPosition = Vec3.ZERO; node.layer = Layers.Enum.UI_2D; - this._debugGraphics = node.addComponent(Graphics); + this._debugGraphics = node.addComponent('cc.Graphics'); this._debugGraphics.lineWidth = 3; + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument const debugDraw = new PhysicsDebugDraw(this._debugGraphics); this._b2DebugDrawer = debugDraw; this._world.SetDebugDraw(debugDraw); @@ -177,7 +178,7 @@ export class b2PhysicsWorld implements IPhysicsWorld { callback.init(type, mask); this._world.RayCast(callback, tempVec2_1, tempVec2_2); - const fixtures = callback.getFixtures(); + const fixtures = callback.getFixtures() as b2.Fixture[]; if (fixtures.length > 0) { const points = callback.getPoints(); const normals = callback.getNormals(); @@ -299,10 +300,10 @@ export class b2PhysicsWorld implements IPhysicsWorld { // read private property const compPrivate = comp as any; - const linearVelocity = compPrivate._linearVelocity; + const linearVelocity = compPrivate._linearVelocity as Vec2; bodyDef.linearVelocity.Set(linearVelocity.x, linearVelocity.y); - bodyDef.angularVelocity = toRadian(compPrivate._angularVelocity); + bodyDef.angularVelocity = toRadian(compPrivate._angularVelocity as number); const b2Body = this._world.CreateBody(bodyDef); b2Body.m_userData = body; @@ -382,6 +383,7 @@ export class b2PhysicsWorld implements IPhysicsWorld { } drawDebug (): void { + if (TEST) return; this._checkDebugDrawValid(); if (!this._debugGraphics) { diff --git a/cocos/physics-2d/builtin/builtin-world.ts b/cocos/physics-2d/builtin/builtin-world.ts index 331fa9d65d3..504e375eb57 100644 --- a/cocos/physics-2d/builtin/builtin-world.ts +++ b/cocos/physics-2d/builtin/builtin-world.ts @@ -22,11 +22,11 @@ THE SOFTWARE. */ -import { EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; +import { EDITOR_NOT_IN_PREVIEW, TEST } from 'internal:constants'; import { IPhysicsWorld } from '../spec/i-physics-world'; -import { Graphics } from '../../2d'; +// import { Graphics } from '../../2d'; import { CCObject, Vec3, Color, IVec2Like, Vec2, Rect, js } from '../../core'; -import { Canvas } from '../../2d/framework'; +// import { Canvas } from '../../2d/framework'; import { BuiltinShape2D } from './shapes/shape-2d'; import { BuiltinBoxShape } from './shapes/box-shape-2d'; import { BuiltinCircleShape } from './shapes/circle-shape-2d'; @@ -43,7 +43,7 @@ const testIntersectResults: Collider2D[] = []; export class BuiltinPhysicsWorld implements IPhysicsWorld { private _contacts: BuiltinContact[] = []; private _shapes: BuiltinShape2D[] = []; - private _debugGraphics: Graphics | null = null; + private _debugGraphics: any = null; private _debugDrawFlags = 0; get debugDrawFlags (): number { @@ -141,13 +141,15 @@ export class BuiltinPhysicsWorld implements IPhysicsWorld { } drawDebug (): void { + if (TEST) return; + if (!this._debugDrawFlags) { return; } this._checkDebugDrawValid(); - const debugDrawer = this._debugGraphics!; + const debugDrawer = this._debugGraphics; if (!debugDrawer) { return; } @@ -212,7 +214,7 @@ export class BuiltinPhysicsWorld implements IPhysicsWorld { return; } canvas = new Node('Canvas'); - canvas.addComponent(Canvas); + canvas.addComponent('cc.Canvas'); canvas.parent = scene; } @@ -222,7 +224,7 @@ export class BuiltinPhysicsWorld implements IPhysicsWorld { node.parent = canvas; node.worldPosition = Vec3.ZERO; - this._debugGraphics = node.addComponent(Graphics); + this._debugGraphics = node.addComponent('cc.Graphics'); this._debugGraphics.lineWidth = 2; } @@ -260,10 +262,18 @@ export class BuiltinPhysicsWorld implements IPhysicsWorld { impl (): any { return null; } - setGravity (): void { } - setAllowSleep (): void { } - syncPhysicsToScene (): void { } - syncSceneToPhysics (): void { } + setGravity (): void { + //empty + } + setAllowSleep (): void { + //empty + } + syncPhysicsToScene (): void { + //empty + } + syncSceneToPhysics (): void { + //empty + } raycast (p1: IVec2Like, p2: IVec2Like, type: ERaycast2DType): RaycastResult2D[] { return []; } diff --git a/cocos/physics-2d/framework/index.ts b/cocos/physics-2d/framework/index.ts index df5b2ecce26..5ad79a2566a 100644 --- a/cocos/physics-2d/framework/index.ts +++ b/cocos/physics-2d/framework/index.ts @@ -60,6 +60,8 @@ export const Physics2DUtils = { PolygonPartition, }; +export { selector }; + cclegacy.internal.physics2d = { selector, }; diff --git a/cocos/physics-2d/framework/physics-selector.ts b/cocos/physics-2d/framework/physics-selector.ts index 39545e108a5..958ae1da47b 100644 --- a/cocos/physics-2d/framework/physics-selector.ts +++ b/cocos/physics-2d/framework/physics-selector.ts @@ -27,12 +27,13 @@ import { EDITOR, DEBUG, TEST, EDITOR_NOT_IN_PREVIEW } from 'internal:constants'; import { IRigidBody2D } from '../spec/i-rigid-body'; import { IBoxShape, ICircleShape, IPolygonShape, IBaseShape } from '../spec/i-physics-shape'; import { IPhysicsWorld } from '../spec/i-physics-world'; -import { errorID } from '../../core'; +import { errorID, log } from '../../core'; import { ECollider2DType, EJoint2DType } from './physics-types'; import { IJoint2D, IDistanceJoint, ISpringJoint, IFixedJoint, IMouseJoint, IRelativeJoint, ISliderJoint, IWheelJoint, IHingeJoint } from '../spec/i-physics-joint'; -export type IPhysicsEngineId = 'builtin' | 'box2d' | string; +// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents +export type IPhysicsEngineId = 'builtin' | 'box2d' | 'box2d-wasm'| string; interface IPhysicsWrapperObject { PhysicsWorld: any, @@ -109,7 +110,7 @@ export interface IPhysicsSelector { } function register (id: IPhysicsEngineId, wrapper: IPhysicsWrapperObject): void { - if (!EDITOR && !TEST) console.info(`[PHYSICS2D]: register ${id}.`); + if (!EDITOR && !TEST) log(`[PHYSICS2D]: register ${id}.`); selector.backend[id] = wrapper; if (!selector.physicsWorld || selector.id === id) { const mutableSelector = selector as Mutable; @@ -123,12 +124,12 @@ function switchTo (id: IPhysicsEngineId): void { const mutableSelector = selector as Mutable; if (selector.physicsWorld && id !== selector.id && selector.backend[id] != null) { //selector.physicsWorld.destroy();//todo - if (!TEST) console.info(`[PHYSICS2D]: switch from ${selector.id} to ${id}.`); + if (!TEST) log(`[PHYSICS2D]: switch from ${selector.id} to ${id}.`); mutableSelector.id = id; mutableSelector.wrapper = selector.backend[id]; mutableSelector.physicsWorld = createPhysicsWorld(); } else { - if (!EDITOR && !TEST) console.info(`[PHYSICS2D]: using ${mutableSelector.id}.`); + if (!EDITOR && !TEST) log(`[PHYSICS2D]: using ${mutableSelector.id}.`); mutableSelector.physicsWorld = createPhysicsWorld(); } } diff --git a/cocos/physics-2d/framework/physics-system.ts b/cocos/physics-2d/framework/physics-system.ts index 5b9491db8df..5f0a1de17de 100644 --- a/cocos/physics-2d/framework/physics-system.ts +++ b/cocos/physics-2d/framework/physics-system.ts @@ -177,6 +177,10 @@ export class PhysicsSystem2D extends Eventify(System) { return selector.id === 'box2d'; } + static get PHYSICS_BOX2D_WASM (): boolean { + return selector.id === 'box2d-wasm'; + } + /** * @en * Gets the predefined physics groups. @@ -374,10 +378,9 @@ export class PhysicsSystem2D extends Eventify(System) { testAABB (rect: Rect): readonly Collider2D[] { return this.physicsWorld.testAABB(rect); } + static constructAndRegister (): void { + director.registerSystem(PhysicsSystem2D.ID, PhysicsSystem2D.instance, System.Priority.LOW); + } } -function initPhysicsSystem (): void { - director.registerSystem(PhysicsSystem2D.ID, PhysicsSystem2D.instance, System.Priority.LOW); -} - -director.once(Director.EVENT_INIT, (): void => { initPhysicsSystem(); }); +director.once(Director.EVENT_INIT, (): void => { PhysicsSystem2D.constructAndRegister(); }); diff --git a/editor/engine-features/schema.json b/editor/engine-features/schema.json index ecdcc5fe494..b6934c7e5dc 100644 --- a/editor/engine-features/schema.json +++ b/editor/engine-features/schema.json @@ -106,6 +106,9 @@ "physics-2d-builtin": { "$ref": "#/definitions/Item" }, + "physics-2d-box2d-wasm": { + "$ref": "#/definitions/Item" + }, "physics-ammo": { "$ref": "#/definitions/Item" }, @@ -253,6 +256,9 @@ "physics-2d-builtin": { "$ref": "#/definitions/BaseItem" }, + "physics-2d-box2d-wasm": { + "$ref": "#/definitions/BaseItem" + }, "physics-ammo": { "$ref": "#/definitions/BaseItem" }, diff --git a/editor/engine-features/types.ts b/editor/engine-features/types.ts index 2ff6a5f7cd6..9c069d75e6f 100644 --- a/editor/engine-features/types.ts +++ b/editor/engine-features/types.ts @@ -22,6 +22,7 @@ export type EngineFeature = | 'physics-2d' | 'physics-2d-box2d' | 'physics-2d-builtin' + | 'physics-2d-box2d-wasm' | 'intersection-2d' | 'audio' | 'video' diff --git a/exports/physics-2d-box2d-wasm.ts b/exports/physics-2d-box2d-wasm.ts new file mode 100644 index 00000000000..c21d0973123 --- /dev/null +++ b/exports/physics-2d-box2d-wasm.ts @@ -0,0 +1,26 @@ +/* + Copyright (c) 2020 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 '../cocos/physics-2d/box2d-wasm/instantiate'; diff --git a/exports/wait-for-box2d-instantiation.ts b/exports/wait-for-box2d-instantiation.ts new file mode 100644 index 00000000000..dd23861d66b --- /dev/null +++ b/exports/wait-for-box2d-instantiation.ts @@ -0,0 +1,27 @@ +/* + Copyright (c) 2020 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. + */ + +// eslint-disable-next-line no-restricted-exports +export { waitForBox2dWasmInstantiation as default } from '../cocos/physics-2d/box2d-wasm/instantiated'; diff --git a/native/external-config.json b/native/external-config.json index b16d14480ec..72909dbc542 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-10" + "checkout": "v3.8.1-11" } } diff --git a/scripts/build-engine/.vscode/launch.json b/scripts/build-engine/.vscode/launch.json index 127a470180d..c6891179c58 100644 --- a/scripts/build-engine/.vscode/launch.json +++ b/scripts/build-engine/.vscode/launch.json @@ -42,6 +42,7 @@ "physics-2d-framework", "physics-2d-box2d", "physics-2d-builtin", + "physics-2d-box2d-wasm", "intersection-2d", "primitive", "profiler", diff --git a/scripts/build-engine/tests/stats-query/cc.config.json b/scripts/build-engine/tests/stats-query/cc.config.json index 02b5291577d..3a15eb63e6b 100644 --- a/scripts/build-engine/tests/stats-query/cc.config.json +++ b/scripts/build-engine/tests/stats-query/cc.config.json @@ -21,6 +21,7 @@ "physics-2d-framework": { "modules": [ "physics-2d-framework" ] }, "physics-2d-box2d": { "modules": [ "physics-2d-box2d", "physics-2d-framework" ] }, "physics-2d-builtin": { "modules": [ "physics-2d-builtin", "physics-2d-framework" ] }, + "physics-2d-box2d-wasm": { "modules": [ "physics-2d-box2d-wasm", "physics-2d-framework" ] }, "intersection-2d": { "modules": [ "intersection-2d" ] }, "primitive": { "modules": [ "primitive" ] }, "profiler": { "modules": [ "profiler" ] }, diff --git a/tests/init.ts b/tests/init.ts index 6f321dca9f2..4e43708972d 100644 --- a/tests/init.ts +++ b/tests/init.ts @@ -80,6 +80,7 @@ jest.mock( 'external:emscripten/webgpu/glslang.wasm', 'external:emscripten/physx/physx.release.wasm.wasm', 'external:emscripten/spine/spine.wasm', + 'external:emscripten/box2d/box2d.release.wasm.wasm', ].forEach(moduleId => { jest.mock(moduleId, () => ({ @@ -97,6 +98,7 @@ jest.mock( 'external:emscripten/webgpu/glslang.js', 'external:emscripten/physx/physx.release.wasm.js', 'external:emscripten/spine/spine.js', + 'external:emscripten/box2d/box2d.release.wasm.js', ].forEach(moduleId => { jest.mock(moduleId, () => ({ @@ -126,6 +128,12 @@ jest.mock( { virtual: true }, ); +jest.mock( + 'external:emscripten/box2d/box2d.release.asm.js', + () => jest.requireActual('../native/external/emscripten/box2d/box2d.release.asm.js'), + { virtual: true }, +); + jest.mock('../cocos/core/platform/debug', () => { const result = { __esModule: true, // Use it when dealing with esModules diff --git a/tests/physics2d/collider.ts b/tests/physics2d/collider.ts new file mode 100644 index 00000000000..dae5a929535 --- /dev/null +++ b/tests/physics2d/collider.ts @@ -0,0 +1,43 @@ +import { EPSILON, Quat, Vec2, Vec3 } from "../../cocos/core"; +import { director } from "../../cocos/game"; +import { Node } from "../../cocos/scene-graph"; +import * as physics2d from "../../exports/physics-2d-framework"; + +/** + * This function is used to test the api of the RigidBody + */ +export default function (parent: Node, _steps = 0) { + //skip builtin for now + if (physics2d.selector.id === 'builtin') + return; + + // basic api + { + const nodeCollider = new Node('Collider2D'); + parent.addChild(nodeCollider); + const initPos = new Vec3(0, 10, 0); + nodeCollider.worldPosition = initPos; + const body = nodeCollider.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + const collider = nodeCollider.addComponent(physics2d.BoxCollider2D) as physics2d.Collider2D; + + expect(collider.body).toBe(body); + + collider.density = 100; + expect(collider.density).toBe(100); + collider.apply(); + expect(body.getMass()).toBe(0.09765625); + + collider.friction = 1; + expect(collider.friction).toBe(1); + + collider.restitution = 1; + expect(collider.restitution).toBe(1); + + collider.sensor = true; + expect(collider.sensor).toBe(true); + + parent.destroyAllChildren(); + parent.removeAllChildren(); + } + +} \ No newline at end of file diff --git a/tests/physics2d/events.ts b/tests/physics2d/events.ts new file mode 100644 index 00000000000..fa59e35cda6 --- /dev/null +++ b/tests/physics2d/events.ts @@ -0,0 +1,49 @@ +import { EPSILON, Quat, Vec2, Vec3 } from "../../cocos/core"; +import { director } from "../../cocos/game"; +import { Node } from "../../cocos/scene-graph"; +import * as physics2d from "../../exports/physics-2d-framework"; + +/** + * This function is used to test the api of the RigidBody + */ +export default function (parent: Node, _steps = 0) { + //skip builtin for now + if (physics2d.selector.id === 'builtin') + return; + + // basic api + { + const nodeStaticCollider = new Node('StaticCollider2D'); + parent.addChild(nodeStaticCollider); + const initPos = new Vec3(0, 0, 0); + nodeStaticCollider.worldPosition = initPos; + const staticBody = nodeStaticCollider.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + const staticCollider = nodeStaticCollider.addComponent(physics2d.BoxCollider2D) as physics2d.Collider2D; + staticBody.type = physics2d.ERigidBody2DType.Static; + //staticBody.enabledContactListener = true; + + const nodeDynamicCollider = new Node('DynamicCollider2D'); + parent.addChild(nodeDynamicCollider); + nodeDynamicCollider.worldPosition = new Vec3(0, 2, 0); + const dynamicBody = nodeDynamicCollider.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + const dynamicCollider = nodeDynamicCollider.addComponent(physics2d.BoxCollider2D) as physics2d.Collider2D; + dynamicBody.enabledContactListener = true; + dynamicBody.type = physics2d.ERigidBody2DType.Dynamic; + + function onBeginContact (selfCollider, otherCollider, contact: physics2d.IPhysics2DContact) { + expect(contact.colliderA).toBe(dynamicCollider); + expect(contact.colliderB).toBe(staticCollider); + } + + dynamicCollider.on(physics2d.Contact2DType.BEGIN_CONTACT, onBeginContact); + + const dt = physics2d.PhysicsSystem2D.instance.fixedTimeStep; + for (let i = 0; i < 3000; i++) { + director.tick(dt); + } + + parent.destroyAllChildren(); + parent.removeAllChildren(); + } + +} \ No newline at end of file diff --git a/tests/physics2d/physics2d.test.ts b/tests/physics2d/physics2d.test.ts index 75d5329573d..db993f0cd54 100644 --- a/tests/physics2d/physics2d.test.ts +++ b/tests/physics2d/physics2d.test.ts @@ -1,6 +1,56 @@ +import { director, game, Game } from "../../cocos/game"; import Utils from "./utilis"; +import * as physics2d from "../../exports/physics-2d-framework"; +import { Node, Scene } from "../../cocos/scene-graph"; + +import waitForBox2dWasmInstantiation from "../../exports/wait-for-box2d-instantiation"; +waitForBox2dWasmInstantiation(); +import "../../exports/physics-2d-box2d-wasm"; +import "../../exports/physics-2d-box2d"; +import "../../exports/physics-2d-builtin"; + +import RigidBodyTest from "./rigid-body"; +import ColliderTest from "./collider"; +import SceneQueryTest from "./scene-query"; +import EventTest from "./events"; + +game.emit(Game.EVENT_PRE_SUBSYSTEM_INIT); +physics2d.PhysicsSystem2D.constructAndRegister(); test(`physics2d test | utils`, done => { Utils(); done(); }); + +for (const id in physics2d.selector.backend) { + test(`physics2d test | ${id}`, done => { + // init test scene (which will also immediately destroy the previous test scene) + const scene = new Scene('test-' + id); + director.runSceneImmediate(scene); + + // switch to backend after the previous scene is immediately destroyed + physics2d.selector.switchTo(id); + expect(physics2d.selector.id).toBe(id); + + const temp0 = new Node(); + scene.addChild(temp0); + + //test rigid body + RigidBodyTest(temp0); + + //test collider + ColliderTest(temp0); + + //test scene query + SceneQueryTest(temp0); + + //test events + EventTest(temp0); + + // destroy test scene + temp0.destroy(); + scene.destroy(); + // all works done + done(); + }) +} \ No newline at end of file diff --git a/tests/physics2d/rigid-body.ts b/tests/physics2d/rigid-body.ts new file mode 100644 index 00000000000..2fc4603d1d1 --- /dev/null +++ b/tests/physics2d/rigid-body.ts @@ -0,0 +1,142 @@ +import { EPSILON, Quat, Vec2, Vec3 } from "../../cocos/core"; +import { director } from "../../cocos/game"; +import { Node } from "../../cocos/scene-graph"; +import * as physics2d from "../../exports/physics-2d-framework"; + +/** + * This function is used to test the api of the RigidBody + */ +export default function (parent: Node, _steps = 0) { + //skip builtin for now + if (physics2d.selector.id === 'builtin') + return; + + // basic api + { + const nodeRigidBody = new Node('RigidBody'); + parent.addChild(nodeRigidBody); + const initPos = new Vec3(0, 10, 0); + nodeRigidBody.worldPosition = initPos; + const body = nodeRigidBody.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + + //test getLinearVelocityFromWorldPoint + { + const v2_0 = new Vec2(1, 0); + const velocity = new Vec2(); + body.getLinearVelocityFromWorldPoint(v2_0, velocity); + expect(Vec2.equals(velocity, Vec2.ZERO)).toBe(true); + } + //test getLocalVector + { + const v2_0 = new Vec2(1, 0); + const v2_1 = new Vec2(); + body.getLocalVector(v2_0, v2_1); + expect(Vec2.equals(v2_0, v2_1)).toBe(true); + } + //test getWorldVector + { + const v2_0 = new Vec2(1, 0); + const v2_1 = new Vec2(); + body.getWorldVector(v2_0, v2_1); + expect(Vec2.equals(v2_0, v2_1)).toBe(true); + } + //test getLocalPoint + { + const v2_0 = new Vec2(1, 0); + const v2_1 = new Vec2(); + body.getLocalPoint(v2_0, v2_1); + let expectLocalPoint = new Vec2(1, -10); + expect(Vec2.equals(expectLocalPoint, v2_1)).toBe(true); + } + //test getWorldPoint + { + const v2_0 = new Vec2(1, 0); + const v2_1 = new Vec2(); + body.getWorldPoint(v2_0, v2_1); + let expectWorldPoint = new Vec2(1, 10); + expect(Vec2.equals(expectWorldPoint, v2_1)).toBe(true); + } + + parent.destroyAllChildren(); + parent.removeAllChildren(); + } + + // applyForceToCenter + { + const nodeRigidBody = new Node('RigidBody2D'); + parent.addChild(nodeRigidBody); + const initPos = new Vec3(0, 0, 0); + nodeRigidBody.worldPosition = initPos; + const body = nodeRigidBody.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + + body.applyForceToCenter(new Vec2(1, 0), true); + body.gravityScale = 0; + + const dt = physics2d.PhysicsSystem2D.instance.fixedTimeStep; + for(let i = 0; i < 10; i++) + director.tick(dt); + + expect(nodeRigidBody.worldPosition.x > initPos.x).toBe(true); + expect(Math.abs(nodeRigidBody.worldPosition.y - initPos.y) < EPSILON).toBe(true); + expect(Quat.equals(nodeRigidBody.worldRotation, Quat.IDENTITY)).toBe(true); + expect(Math.abs(body.linearVelocity.y) < EPSILON).toBe(true); + expect(Math.abs(body.linearVelocity.x) > EPSILON).toBe(true); + expect(Math.abs(body.angularVelocity) < EPSILON).toBe(true); + + parent.destroyAllChildren(); + parent.removeAllChildren(); + } + + // applyTorque + if(0)//todo + { + const nodeRigidBody = new Node('RigidBody'); + parent.addChild(nodeRigidBody); + const initPos = new Vec3(0, 0, 0); + nodeRigidBody.worldPosition = initPos; + const body = nodeRigidBody.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + nodeRigidBody.addComponent(physics2d.BoxCollider2D); + + body.applyTorque(10, true); + body.gravityScale = 0; + + const dt = physics2d.PhysicsSystem2D.instance.fixedTimeStep; + for(let i = 0; i < 10; i++) + director.tick(dt); + + let eulerAngle = new Vec3(); + nodeRigidBody.worldRotation.getEulerAngles(eulerAngle); + expect(nodeRigidBody.worldPosition.y === initPos.y).toBe(true); + expect(Math.abs(eulerAngle.x) < EPSILON).toBe(true); + expect(Math.abs(eulerAngle.y) < EPSILON).toBe(true); + expect(Math.abs(eulerAngle.z) > EPSILON).toBe(true); + + parent.destroyAllChildren(); + parent.removeAllChildren(); + } + + //sleep and wakeup + { + const nodeRigidBody = new Node('RigidBody'); + parent.addChild(nodeRigidBody); + const initPos = new Vec3(0, 0, 0); + nodeRigidBody.worldPosition = initPos; + const body = nodeRigidBody.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + + + body.allowSleep = true; + body.sleep(); + expect(body.isAwake()).toBe(false); + body.wakeUp(); + expect(body.isAwake()).toBe(true); + + // todo + // body.allowSleep = false; + // body.sleep(); + // expect(body.isAwake()).toBe(true); + + parent.destroyAllChildren(); + parent.removeAllChildren(); + } + +} \ No newline at end of file diff --git a/tests/physics2d/scene-query.ts b/tests/physics2d/scene-query.ts new file mode 100644 index 00000000000..585832e2ae4 --- /dev/null +++ b/tests/physics2d/scene-query.ts @@ -0,0 +1,96 @@ +import { EPSILON, Quat, Rect, Vec2, Vec3 } from "../../cocos/core"; +import { director } from "../../cocos/game"; +import { Node } from "../../cocos/scene-graph"; +import * as physics2d from "../../exports/physics-2d-framework"; + +/** + * This function is used to test the api of the scene query + */ +export default function (parent: Node, _steps = 0) { + //skip builtin for now + if (physics2d.selector.id === 'builtin') + return; + + const nodeCollider = new Node('Collider2D'); + parent.addChild(nodeCollider); + const initPos = new Vec3(10, 0, 0); + nodeCollider.worldPosition = initPos; + const body = nodeCollider.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + const collider = nodeCollider.addComponent(physics2d.BoxCollider2D) as physics2d.Collider2D; + collider.group = 2; + + // add another collider + const nodeCollider2 = new Node('Collider2D2'); + parent.addChild(nodeCollider2); + const initPos2 = new Vec3(20, 0, 0); + nodeCollider2.worldPosition = initPos2; + const body2 = nodeCollider2.addComponent(physics2d.RigidBody2D) as physics2d.RigidBody2D; + const collider2 = nodeCollider2.addComponent(physics2d.BoxCollider2D) as physics2d.Collider2D; + collider2.group = physics2d.PhysicsGroup.DEFAULT; + + //test raycast cloest + { + const p0 = new Vec2(0, 0); + const p1 = new Vec2(20, 0); + let result = physics2d.PhysicsSystem2D.instance.raycast(p0, p1); + expect(result.length).toBe(1); + expect(result[0].collider.uuid).toBe(collider.uuid); + expect(Vec2.equals(result[0].point, new Vec2(9.5, 0))).toBe(true); + expect(Vec2.equals(result[0].normal, new Vec2(-1, 0))).toBe(true); + expect(Math.abs(result[0].fraction - 0.475)< 0.0001).toBe(true); + } + + //test raycast all + { + const p0 = new Vec2(0, 0); + const p1 = new Vec2(20, 0); + const type = physics2d.ERaycast2DType.All; + let result = physics2d.PhysicsSystem2D.instance.raycast(p0, p1, type); + expect(result.length).toBe(2); + + expect(result[1].collider.uuid).toBe(collider.uuid); + expect(Vec2.equals(result[1].point, new Vec2(9.5, 0))).toBe(true); + expect(Vec2.equals(result[1].normal, new Vec2(-1, 0))).toBe(true); + expect(Math.abs(result[1].fraction - 0.475)< 0.0001).toBe(true); + + expect(result[0].collider.uuid).toBe(collider2.uuid); + expect(Vec2.equals(result[0].point, new Vec2(19.5, 0))).toBe(true); + expect(Vec2.equals(result[0].normal, new Vec2(-1, 0))).toBe(true); + expect(Math.abs(result[0].fraction - 0.975)< 0.0001).toBe(true); + + } + + //test raycast all with group mask + { + const p0 = new Vec2(0, 0); + const p1 = new Vec2(20, 0); + const type = physics2d.ERaycast2DType.All; + const mask = physics2d.PhysicsGroup.DEFAULT; + let result = physics2d.PhysicsSystem2D.instance.raycast(p0, p1, type, mask); + expect(result.length).toBe(1); + expect(result[0].collider.uuid).toBe(collider2.uuid); + expect(Vec2.equals(result[0].point, new Vec2(19.5, 0))).toBe(true); + expect(Vec2.equals(result[0].normal, new Vec2(-1, 0))).toBe(true); + expect(Math.abs(result[0].fraction - 0.975)< 0.0001).toBe(true); + } + + //test testPoint + { + let result = physics2d.PhysicsSystem2D.instance.testPoint(new Vec2(10, 0)); + expect(result.length).toBe(1); + expect(result[0].uuid).toBe(collider.uuid); + } + + //test testAABB + { + let rect = new Rect(0, 0, 30, 30); + let result = physics2d.PhysicsSystem2D.instance.testAABB(rect); + expect(result.length).toBe(2); + expect(result[0].uuid).toBe(collider2.uuid); + expect(result[1].uuid).toBe(collider.uuid); + } + + + parent.destroyAllChildren(); + parent.removeAllChildren(); +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index cb1ed02d828..be0012eabd6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,6 +36,7 @@ "./native/external/emscripten/physx/physx", "./native/external/emscripten/webgpu/webgpu", "./native/external/emscripten/spine/spine", + "./native/external/emscripten/box2d/box2d", // pal "./@types/pal/system-info", From 7c760c3056f33bfc5b4cdc982f94d0220f7c7aea Mon Sep 17 00:00:00 2001 From: zxx43 Date: Fri, 18 Aug 2023 23:26:36 +0800 Subject: [PATCH 150/184] 3.8.1 optimize particle pvdata type (#15928) * optimize pvdata type * fix eslint * change name of _attrs to _particleVertexData * add missed type * convert type --- cocos/particle/models/particle-batch-model.ts | 152 ++++++++---------- .../renderer/particle-system-renderer-cpu.ts | 96 ++++++----- 2 files changed, 125 insertions(+), 123 deletions(-) diff --git a/cocos/particle/models/particle-batch-model.ts b/cocos/particle/models/particle-batch-model.ts index a302acdeddf..ec93e74857e 100644 --- a/cocos/particle/models/particle-batch-model.ts +++ b/cocos/particle/models/particle-batch-model.ts @@ -173,21 +173,15 @@ export default class ParticleBatchModel extends scene.Model { )); const vBuffer: ArrayBuffer = new ArrayBuffer(this._vertAttribSize * this._bufferSize * this._vertCount); if (this._mesh && this._capacity > 0) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison - let vOffset = (this._vertAttrs![this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD)] as any).offset; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this._mesh.copyAttribute(0, AttributeName.ATTR_TEX_COORD, vBuffer, this._vertAttribSize, vOffset); // copy mesh uv to ATTR_TEX_COORD - // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison - let vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD3); + let vOffset = (this._vertAttrs![this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD as string)] as any).offset; + this._mesh.copyAttribute(0, AttributeName.ATTR_TEX_COORD, vBuffer, this._vertAttribSize, vOffset as number); // copy mesh uv to ATTR_TEX_COORD + let vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD3 as string); vOffset = (this._vertAttrs![vIdx++] as any).offset; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this._mesh.copyAttribute(0, AttributeName.ATTR_POSITION, vBuffer, this._vertAttribSize, vOffset); // copy mesh position to ATTR_TEX_COORD3 + this._mesh.copyAttribute(0, AttributeName.ATTR_POSITION, vBuffer, this._vertAttribSize, vOffset as number); // copy mesh position to ATTR_TEX_COORD3 vOffset = (this._vertAttrs![vIdx++] as any).offset; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this._mesh.copyAttribute(0, AttributeName.ATTR_NORMAL, vBuffer, this._vertAttribSize, vOffset); // copy mesh normal to ATTR_NORMAL + this._mesh.copyAttribute(0, AttributeName.ATTR_NORMAL, vBuffer, this._vertAttribSize, vOffset as number); // copy mesh normal to ATTR_NORMAL vOffset = (this._vertAttrs![vIdx++] as any).offset; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - if (!this._mesh.copyAttribute(0, AttributeName.ATTR_COLOR, vBuffer, this._vertAttribSize, vOffset)) { // copy mesh color to ATTR_COLOR1 + if (!this._mesh.copyAttribute(0, AttributeName.ATTR_COLOR, vBuffer, this._vertAttribSize, vOffset as number)) { // copy mesh color to ATTR_COLOR1 const vb = new Uint32Array(vBuffer); for (let iVertex = 0; iVertex < this._vertCount; ++iVertex) { vb[iVertex * this._vertAttrsFloatCount + vOffset / 4] = Color.WHITE._val; @@ -274,22 +268,16 @@ export default class ParticleBatchModel extends scene.Model { const vBuffer: ArrayBuffer = new ArrayBuffer(this._vertAttribSizeStatic * this._vertCount); if (this._mesh) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison - let vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD); // find ATTR_TEX_COORD index + let vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD as string); // find ATTR_TEX_COORD index let vOffset = (this._vertAttrs![vIdx] as any).offset; // find ATTR_TEX_COORD offset - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this._mesh.copyAttribute(0, AttributeName.ATTR_TEX_COORD, vBuffer, this._vertAttribSizeStatic, vOffset); // copy mesh uv to ATTR_TEX_COORD - // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison - vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD3); // find ATTR_TEX_COORD3 index + this._mesh.copyAttribute(0, AttributeName.ATTR_TEX_COORD, vBuffer, this._vertAttribSizeStatic, vOffset as number); // copy mesh uv to ATTR_TEX_COORD + vIdx = this._vertAttrs!.findIndex((val): boolean => val.name === AttributeName.ATTR_TEX_COORD3 as string); // find ATTR_TEX_COORD3 index vOffset = (this._vertAttrs![vIdx++] as any).offset; // find ATTR_TEX_COORD3 offset - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this._mesh.copyAttribute(0, AttributeName.ATTR_POSITION, vBuffer, this._vertAttribSizeStatic, vOffset); // copy mesh position to ATTR_TEX_COORD3 + this._mesh.copyAttribute(0, AttributeName.ATTR_POSITION, vBuffer, this._vertAttribSizeStatic, vOffset as number); // copy mesh position to ATTR_TEX_COORD3 vOffset = (this._vertAttrs![vIdx++] as any).offset; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - this._mesh.copyAttribute(0, AttributeName.ATTR_NORMAL, vBuffer, this._vertAttribSizeStatic, vOffset); // copy mesh normal to ATTR_NORMAL + this._mesh.copyAttribute(0, AttributeName.ATTR_NORMAL, vBuffer, this._vertAttribSizeStatic, vOffset as number); // copy mesh normal to ATTR_NORMAL vOffset = (this._vertAttrs![vIdx++] as any).offset; - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - if (!this._mesh.copyAttribute(0, AttributeName.ATTR_COLOR, vBuffer, this._vertAttribSizeStatic, vOffset)) { // copy mesh color to ATTR_COLOR1 + if (!this._mesh.copyAttribute(0, AttributeName.ATTR_COLOR, vBuffer, this._vertAttribSizeStatic, vOffset as number)) { // copy mesh color to ATTR_COLOR1 const vb = new Uint32Array(vBuffer); for (let iVertex = 0; iVertex < this._vertCount; ++iVertex) { vb[iVertex * this._vertStaticAttrsFloatCount + vOffset / 4] = Color.WHITE._val; @@ -345,41 +333,41 @@ export default class ParticleBatchModel extends scene.Model { if (!this._useInstance) { if (!this._mesh) { let offset: number = index * this._vertAttrsFloatCount; - this._vdataF32![offset++] = pvdata[0].x; // position - this._vdataF32![offset++] = pvdata[0].y; - this._vdataF32![offset++] = pvdata[0].z; - this._vdataF32![offset++] = pvdata[1].x; // uv - this._vdataF32![offset++] = pvdata[1].y; - this._vdataF32![offset++] = pvdata[1].z; // frame idx - this._vdataF32![offset++] = pvdata[2].x; // size - this._vdataF32![offset++] = pvdata[2].y; - this._vdataF32![offset++] = pvdata[2].z; - this._vdataF32![offset++] = pvdata[3].x; // rotation - this._vdataF32![offset++] = pvdata[3].y; - this._vdataF32![offset++] = pvdata[3].z; - this._vdataUint32![offset++] = pvdata[4]; // color - if (pvdata[5]) { - this._vdataF32![offset++] = pvdata[5].x; // velocity - this._vdataF32![offset++] = pvdata[5].y; - this._vdataF32![offset++] = pvdata[5].z; + this._vdataF32![offset++] = pvdata.position.x; // position + this._vdataF32![offset++] = pvdata.position.y; + this._vdataF32![offset++] = pvdata.position.z; + this._vdataF32![offset++] = pvdata.texcoord.x; // uv + this._vdataF32![offset++] = pvdata.texcoord.y; + this._vdataF32![offset++] = pvdata.texcoord.z; // frame idx + this._vdataF32![offset++] = pvdata.size.x; // size + this._vdataF32![offset++] = pvdata.size.y; + this._vdataF32![offset++] = pvdata.size.z; + this._vdataF32![offset++] = pvdata.rotation.x; // rotation + this._vdataF32![offset++] = pvdata.rotation.y; + this._vdataF32![offset++] = pvdata.rotation.z; + this._vdataUint32![offset++] = pvdata.color; // color + if (pvdata.velocity) { + this._vdataF32![offset++] = pvdata.velocity.x; // velocity + this._vdataF32![offset++] = pvdata.velocity.y; + this._vdataF32![offset++] = pvdata.velocity.z; } } else { for (let i = 0; i < this._vertCount; i++) { let offset: number = (index * this._vertCount + i) * this._vertAttrsFloatCount; - this._vdataF32![offset++] = pvdata[0].x; // position - this._vdataF32![offset++] = pvdata[0].y; - this._vdataF32![offset++] = pvdata[0].z; + this._vdataF32![offset++] = pvdata.position.x; // position + this._vdataF32![offset++] = pvdata.position.y; + this._vdataF32![offset++] = pvdata.position.z; offset += 2; // this._vdataF32![offset++] = index; - // this._vdataF32![offset++] = pvdata[1].y; - this._vdataF32![offset++] = pvdata[1].z; // frame idx - this._vdataF32![offset++] = pvdata[2].x; // size - this._vdataF32![offset++] = pvdata[2].y; - this._vdataF32![offset++] = pvdata[2].z; - this._vdataF32![offset++] = pvdata[3].x; // rotation - this._vdataF32![offset++] = pvdata[3].y; - this._vdataF32![offset++] = pvdata[3].z; - this._vdataUint32![offset++] = pvdata[4]; // color + // this._vdataF32![offset++] = pvdata.texcoord.y; + this._vdataF32![offset++] = pvdata.texcoord.z; // frame idx + this._vdataF32![offset++] = pvdata.size.x; // size + this._vdataF32![offset++] = pvdata.size.y; + this._vdataF32![offset++] = pvdata.size.z; + this._vdataF32![offset++] = pvdata.rotation.x; // rotation + this._vdataF32![offset++] = pvdata.rotation.y; + this._vdataF32![offset++] = pvdata.rotation.z; + this._vdataUint32![offset++] = pvdata.color; // color } } } else { @@ -390,40 +378,40 @@ export default class ParticleBatchModel extends scene.Model { private addParticleVertexDataIns (index: number, pvdata: PVData): void { let offset: number = index * this._vertAttrsFloatCount; if (!this._mesh) { - this._vdataF32![offset++] = pvdata[0].x; // position - this._vdataF32![offset++] = pvdata[0].y; - this._vdataF32![offset++] = pvdata[0].z; - this._vdataF32![offset++] = pvdata[1].z; // frame idx - - this._vdataF32![offset++] = pvdata[2].x; // size - this._vdataF32![offset++] = pvdata[2].y; - this._vdataF32![offset++] = pvdata[2].z; - - this._vdataF32![offset++] = pvdata[3].x; // rotation - this._vdataF32![offset++] = pvdata[3].y; - this._vdataF32![offset++] = pvdata[3].z; - - this._vdataUint32![offset++] = pvdata[4]; // color - if (pvdata[5]) { - this._vdataF32![offset++] = pvdata[5].x; // velocity - this._vdataF32![offset++] = pvdata[5].y; - this._vdataF32![offset++] = pvdata[5].z; + this._vdataF32![offset++] = pvdata.position.x; // position + this._vdataF32![offset++] = pvdata.position.y; + this._vdataF32![offset++] = pvdata.position.z; + this._vdataF32![offset++] = pvdata.texcoord.z; // frame idx + + this._vdataF32![offset++] = pvdata.size.x; // size + this._vdataF32![offset++] = pvdata.size.y; + this._vdataF32![offset++] = pvdata.size.z; + + this._vdataF32![offset++] = pvdata.rotation.x; // rotation + this._vdataF32![offset++] = pvdata.rotation.y; + this._vdataF32![offset++] = pvdata.rotation.z; + + this._vdataUint32![offset++] = pvdata.color; // color + if (pvdata.velocity) { + this._vdataF32![offset++] = pvdata.velocity.x; // velocity + this._vdataF32![offset++] = pvdata.velocity.y; + this._vdataF32![offset++] = pvdata.velocity.z; } } else { - this._vdataF32![offset++] = pvdata[0].x; // position - this._vdataF32![offset++] = pvdata[0].y; - this._vdataF32![offset++] = pvdata[0].z; - this._vdataF32![offset++] = pvdata[1].z; // frame idx + this._vdataF32![offset++] = pvdata.position.x; // position + this._vdataF32![offset++] = pvdata.position.y; + this._vdataF32![offset++] = pvdata.position.z; + this._vdataF32![offset++] = pvdata.texcoord.z; // frame idx - this._vdataF32![offset++] = pvdata[2].x; // size - this._vdataF32![offset++] = pvdata[2].y; - this._vdataF32![offset++] = pvdata[2].z; + this._vdataF32![offset++] = pvdata.size.x; // size + this._vdataF32![offset++] = pvdata.size.y; + this._vdataF32![offset++] = pvdata.size.z; - this._vdataF32![offset++] = pvdata[3].x; // rotation - this._vdataF32![offset++] = pvdata[3].y; - this._vdataF32![offset++] = pvdata[3].z; + this._vdataF32![offset++] = pvdata.rotation.x; // rotation + this._vdataF32![offset++] = pvdata.rotation.y; + this._vdataF32![offset++] = pvdata.rotation.z; - this._vdataUint32![offset++] = pvdata[4]; // color + this._vdataUint32![offset++] = pvdata.color; // color } } diff --git a/cocos/particle/renderer/particle-system-renderer-cpu.ts b/cocos/particle/renderer/particle-system-renderer-cpu.ts index 524d9ba9805..0f91aae63a5 100644 --- a/cocos/particle/renderer/particle-system-renderer-cpu.ts +++ b/cocos/particle/renderer/particle-system-renderer-cpu.ts @@ -138,9 +138,23 @@ const _matInsInfo: IMaterialInstanceInfo = { subModelIdx: 0, }; -// TODO: we should not use this type, should use a uniform array type instead. -// Tracking issue: https://github.com/cocos/cocos-engine/issues/15553 -export type PVData = [Vec3, Vec3, Vec3, Vec3, number, Vec3 | null, null]; +export class PVData { + public position: Vec3; + public texcoord: Vec3; + public size: Vec3; + public rotation: Vec3; + public color: number; + public velocity: Vec3 | null; + + constructor () { + this.position = new Vec3(); + this.texcoord = new Vec3(); + this.size = new Vec3(); + this.rotation = new Vec3(); + this.color = 0; + this.velocity = null; + } +} export default class ParticleSystemRendererCPU extends ParticleSystemRendererBase { private _defines: MacroRecord; @@ -149,7 +163,7 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas private _tmp_velLenScale: Vec4; private _defaultMat: Material | null = null; private _node_scale: Vec3; - private _attrs: PVData; + private _particleVertexData: PVData; private _particles: RecyclePool | null = null; private _defaultTrailMat: Material | null = null; private _updateList: Map = new Map(); @@ -165,6 +179,7 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas private _gravity: Vec4 = new Vec4(); constructor (info: any) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument super(info); this._model = null; @@ -172,7 +187,7 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas this._frameTile_velLenScale = new Vec4(1, 1, 0, 0); this._tmp_velLenScale = this._frameTile_velLenScale.clone(); this._node_scale = new Vec3(); - this._attrs = new Array(7) as PVData; + this._particleVertexData = new PVData(); this._defines = { CC_USE_WORLD_SPACE: true, CC_USE_BILLBOARD: true, @@ -233,6 +248,7 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas return this._defaultTrailMat; } + // eslint-disable-next-line @typescript-eslint/no-empty-function public setNewParticle (p: Particle): void { } @@ -258,6 +274,7 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas for (let i = 0, len = PARTICLE_MODULE_ORDER.length; i < len; i++) { const p = this._animateList[PARTICLE_MODULE_ORDER[i]]; if (p) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument this._runAnimateList.push(p); } } @@ -279,7 +296,7 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas // reorder this._runAnimateList.length = 0; for (let i = 0, len = PARTICLE_MODULE_ORDER.length; i < len; i++) { - const p = this._animateList[PARTICLE_MODULE_ORDER[i]]; + const p: IParticleModule = this._animateList[PARTICLE_MODULE_ORDER[i]]; if (p) { this._runAnimateList.push(p); } @@ -518,29 +535,28 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas private _fillMeshData (p: Particle, idx: number, fi: number): void { const i = idx / 4; - this._attrs[0] = p.position; + Vec3.copy(this._particleVertexData.position, p.position); _tempAttribUV.z = fi; - this._attrs[1] = _tempAttribUV; - this._attrs[2] = p.size; - this._attrs[3] = p.rotation; - this._attrs[4] = p.color._val; - this._model!.addParticleVertexData(i, this._attrs); + Vec3.copy(this._particleVertexData.texcoord, _tempAttribUV); + Vec3.copy(this._particleVertexData.size, p.size); + Vec3.copy(this._particleVertexData.rotation, p.rotation); + this._particleVertexData.color = p.color._val; + this._model!.addParticleVertexData(i, this._particleVertexData); } private _fillStrecthedData (p: Particle, idx: number, fi: number): void { if (!this._useInstance) { for (let j = 0; j < 4; ++j) { // four verts per particle. - this._attrs[0] = p.position; + Vec3.copy(this._particleVertexData.position, p.position); _tempAttribUV.x = _uvs[2 * j]; _tempAttribUV.y = _uvs[2 * j + 1]; _tempAttribUV.z = fi; - this._attrs[1] = _tempAttribUV; - this._attrs[2] = p.size; - this._attrs[3] = p.rotation; - this._attrs[4] = p.color._val; - this._attrs[5] = p.ultimateVelocity; - this._attrs[6] = null; - this._model!.addParticleVertexData(idx++, this._attrs); + Vec3.copy(this._particleVertexData.texcoord, _tempAttribUV); + Vec3.copy(this._particleVertexData.size, p.size); + Vec3.copy(this._particleVertexData.rotation, p.rotation); + this._particleVertexData.color = p.color._val; + this._particleVertexData.velocity = p.ultimateVelocity; + this._model!.addParticleVertexData(idx++, this._particleVertexData); } } else { this._fillStrecthedDataIns(p, idx, fi); @@ -549,29 +565,28 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas private _fillStrecthedDataIns (p: Particle, idx: number, fi: number): void { const i = idx / 4; - this._attrs[0] = p.position; + Vec3.copy(this._particleVertexData.position, p.position); _tempAttribUV.z = fi; - this._attrs[1] = _tempAttribUV; - this._attrs[2] = p.size; - this._attrs[3] = p.rotation; - this._attrs[4] = p.color._val; - this._attrs[5] = p.ultimateVelocity; - this._model!.addParticleVertexData(i, this._attrs); + Vec3.copy(this._particleVertexData.texcoord, _tempAttribUV); + Vec3.copy(this._particleVertexData.size, p.size); + Vec3.copy(this._particleVertexData.rotation, p.rotation); + this._particleVertexData.color = p.color._val; + this._particleVertexData.velocity = p.ultimateVelocity; + this._model!.addParticleVertexData(i, this._particleVertexData); } private _fillNormalData (p: Particle, idx: number, fi: number): void { if (!this._useInstance) { for (let j = 0; j < 4; ++j) { // four verts per particle. - this._attrs[0] = p.position; + Vec3.copy(this._particleVertexData.position, p.position); _tempAttribUV.x = _uvs[2 * j]; _tempAttribUV.y = _uvs[2 * j + 1]; _tempAttribUV.z = fi; - this._attrs[1] = _tempAttribUV; - this._attrs[2] = p.size; - this._attrs[3] = p.rotation; - this._attrs[4] = p.color._val; - this._attrs[5] = null; - this._model!.addParticleVertexData(idx++, this._attrs); + Vec3.copy(this._particleVertexData.texcoord, _tempAttribUV); + Vec3.copy(this._particleVertexData.size, p.size); + Vec3.copy(this._particleVertexData.rotation, p.rotation); + this._particleVertexData.color = p.color._val; + this._model!.addParticleVertexData(idx++, this._particleVertexData); } } else { this._fillNormalDataIns(p, idx, fi); @@ -580,14 +595,13 @@ export default class ParticleSystemRendererCPU extends ParticleSystemRendererBas private _fillNormalDataIns (p: Particle, idx: number, fi: number): void { const i = idx / 4; - this._attrs[0] = p.position; + Vec3.copy(this._particleVertexData.position, p.position); _tempAttribUV.z = fi; - this._attrs[1] = _tempAttribUV; - this._attrs[2] = p.size; - this._attrs[3] = p.rotation; - this._attrs[4] = p.color._val; - this._attrs[5] = null; - this._model!.addParticleVertexData(i, this._attrs); + Vec3.copy(this._particleVertexData.texcoord, _tempAttribUV); + Vec3.copy(this._particleVertexData.size, p.size); + Vec3.copy(this._particleVertexData.rotation, p.rotation); + this._particleVertexData.color = p.color._val; + this._model!.addParticleVertexData(i, this._particleVertexData); } public updateVertexAttrib (): void { From c19d63d921424ac8f5101eb5349b9422cb9722ab Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Fri, 18 Aug 2023 23:39:50 +0800 Subject: [PATCH 151/184] Disallow using image bitmap by default (#16035) * Disallow using image bitmap by default * fix lint --- cocos/asset/asset-manager/asset-manager.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cocos/asset/asset-manager/asset-manager.ts b/cocos/asset/asset-manager/asset-manager.ts index 56455b0986a..e82d6fe7dcb 100644 --- a/cocos/asset/asset-manager/asset-manager.ts +++ b/cocos/asset/asset-manager/asset-manager.ts @@ -201,7 +201,7 @@ export class AssetManager { * 是否优先使用 image bitmap 来加载图片,启用之后,图片加载速度会更快, 但内存占用会变高。 * */ - public allowImageBitmap = !EDITOR && !sys.isMobile; + public allowImageBitmap = false; /** * @en @@ -429,7 +429,7 @@ export class AssetManager { this._projectBundles = settings.querySettings(Settings.Category.ASSETS, 'projectBundles') || []; const assetsOverride = settings.querySettings(Settings.Category.ASSETS, 'assetsOverrides') || {}; for (const key in assetsOverride) { - this.assetsOverrideMap.set(key, assetsOverride[key]); + this.assetsOverrideMap.set(key, assetsOverride[key] as string); } } @@ -632,9 +632,9 @@ export class AssetManager { this.loadAny({ url }, opts, null, (err, data): void => { if (err) { error(err.message, err.stack); - if (onComp) { onComp(err, data); } + if (onComp) { onComp(err, data as T); } } else { - factory.create(url, data, opts.ext || path.extname(url), opts, (p1, p2): void => { + factory.create(url, data, (opts.ext as string) || path.extname(url), opts, (p1, p2): void => { if (onComp) { onComp(p1, p2 as T); } }); } @@ -693,7 +693,7 @@ export class AssetManager { this.loadAny({ url: nameOrUrl }, opts, null, (err, data): void => { if (err) { error(err.message, err.stack); - if (onComp) { onComp(err, data); } + if (onComp) { onComp(err, data as Bundle); } } else { factory.create(nameOrUrl, data, 'bundle', opts, (p1, p2): void => { if (onComp) { onComp(p1, p2 as Bundle); } @@ -791,7 +791,7 @@ export class AssetManager { input: [item], onProgress: onProg, options: opts, - onComplete: asyncify((err, data: T): void => { + onComplete: asyncify((err: Error | null, data: T): void => { if (!err) { if (!opts.assetId) { data._uuid = ''; From bde3cd4cc3d8020c1b6142ba67759a449da2ef00 Mon Sep 17 00:00:00 2001 From: Yiwen <15225434259xue@gmail.com> Date: Mon, 21 Aug 2023 10:15:24 +0800 Subject: [PATCH 152/184] Add adv mesh functionalities. (#16009) * stage * update * update * fix physics & ray cast problem * fix default value, clean unused code, fix lint errors * clean code * update meta file * update external, license * fix tidy, circular dep * fix type cast * rm unit test * fix unit test * update comment --- EngineErrorMap.md | 12 + cocos/3d/assets/mesh.ts | 156 ++++++- cocos/3d/misc/create-mesh.ts | 30 +- cocos/3d/misc/mesh-codec.ts | 81 ++++ cocos/asset/assets/rendering-sub-mesh.ts | 148 +++++-- cocos/core/math/utils.ts | 66 +++ cocos/gfx/base/define.ts | 6 +- .../cannon/shapes/cannon-trimesh-shape.ts | 12 +- .../components/colliders/mesh-collider.ts | 2 - .../physx/shapes/physx-trimesh-shape.ts | 13 +- cocos/render-scene/scene/model.ts | 6 +- .../data-structures/vs-input.chunk | 2 +- editor/i18n/en/assets.js | 125 +++--- editor/i18n/zh/assets.js | 6 +- editor/inspector/assets/fbx/index.js | 2 +- editor/inspector/assets/fbx/model.js | 389 +++++++++--------- licenses/LICENSE_meshoptimizer.md | 21 + native/cocos/3d/assets/Mesh.cpp | 34 +- native/cocos/3d/assets/Mesh.h | 6 + native/cocos/3d/misc/CreateMesh.cpp | 68 +++ native/cocos/3d/misc/CreateMesh.h | 7 + native/cocos/core/assets/RenderingSubMesh.cpp | 148 +++++-- native/cocos/math/Utils.cpp | 57 +++ native/cocos/math/Utils.h | 4 + native/external-config.json | 4 +- .../tests/unit-test/src/math_utils_test.cpp | 1 + platforms/native/engine/jsb-physics.js | 7 +- tests/init.ts | 14 + tsconfig.json | 1 + 29 files changed, 1037 insertions(+), 391 deletions(-) create mode 100644 cocos/3d/misc/mesh-codec.ts create mode 100644 licenses/LICENSE_meshoptimizer.md diff --git a/EngineErrorMap.md b/EngineErrorMap.md index bf943cfd907..2302385d19e 100644 --- a/EngineErrorMap.md +++ b/EngineErrorMap.md @@ -3343,6 +3343,18 @@ Can not update a static mesh. The primitiveIndex is out of range. +### 14202 + +meshopt asm decoder initialized + +### 14203 + +meshopt wasm decoder initialized + +### 14204 + +meshopt decoder error: %d + ### 14300 Can not keep world transform due to the zero scaling of parent node diff --git a/cocos/3d/assets/mesh.ts b/cocos/3d/assets/mesh.ts index 0ca33d88c63..d064d93ddb0 100644 --- a/cocos/3d/assets/mesh.ts +++ b/cocos/3d/assets/mesh.ts @@ -28,7 +28,7 @@ import { Asset } from '../../asset/assets/asset'; import { IDynamicGeometry } from '../../primitive/define'; import { BufferBlob } from '../misc/buffer-blob'; import { Skeleton } from './skeleton'; -import { geometry, cclegacy, sys, warnID, Mat4, Quat, Vec3, assertIsTrue, murmurhash2_32_gc } from '../../core'; +import { geometry, cclegacy, sys, warnID, Mat4, Quat, Vec3, assertIsTrue, murmurhash2_32_gc, errorID } from '../../core'; import { RenderingSubMesh } from '../../asset/assets'; import { Attribute, Device, Buffer, BufferInfo, AttributeName, BufferUsageBit, Feature, Format, @@ -36,6 +36,8 @@ import { } from '../../gfx'; import { Morph } from './morph'; import { MorphRendering, createMorphRendering } from './morph-rendering'; +import { MeshoptDecoder } from '../misc/mesh-codec'; +import zlib from '../../../external/compression/zlib.min'; function getIndexStrideCtor (stride: number): Uint8ArrayConstructor | Uint16ArrayConstructor | Uint32ArrayConstructor { switch (stride) { @@ -77,6 +79,13 @@ export declare namespace Mesh { attributes: Attribute[]; } + export interface IMeshCluster { + clusterView: IBufferView; + triangleView: IBufferView; + vertexView: IBufferView; + coneView?: IBufferView; + } + /** * @en Sub mesh contains a list of primitives with the same type (Point, Line or Triangle) * @zh 子网格。子网格由一系列相同类型的图元组成(例如点、线、面等)。 @@ -106,6 +115,11 @@ export declare namespace Mesh { * 如未定义或指向的映射表不存在,则默认 VB 内所有关节索引数据直接对应骨骼资源数据。 */ jointMapIndex?: number; + + /** + * @en The cluster data of the sub mesh + */ + cluster?: IMeshCluster; } /** @@ -197,6 +211,30 @@ export declare namespace Mesh { * @zh 动态网格特有数据 */ dynamic?: IDynamicStruct; + + /** + * @en Whether the mesh data is quantized to reduce memory usage + * @zh 此网格数据是否经过量化以减少内存占用。 + */ + quantized?: boolean; + + /** + * @en Whether the mesh data is encoded to reduce memory usage + * @zh + */ + encoded?: boolean; + + /** + * @en Whether the mesh data is compressed to reduce memory usage + * @zh 此网格数据是否经过压缩以减少内存占用。 + */ + compressed?: boolean; + + /** + * @en Whether the mesh contains cluster data + * @zh 此网格是否包含 cluster 数据。 + */ + cluster?: boolean; } /** @@ -362,9 +400,19 @@ export class Mesh extends Asset { if (this._initialized) { return; } - this._initialized = true; + let info = { struct: this.struct, data: this.data }; + if (info.struct.compressed) { // decompress mesh data + info = inflateMesh(info); + } + if (this.struct.encoded) { // decode mesh data + info = decodeMesh(info); + } + + this._struct = info.struct; + this._data = info.data; + if (this._struct.dynamic) { const device: Device = deviceManager.gfxDevice; const vertexBuffers: Buffer[] = []; @@ -436,7 +484,7 @@ export class Mesh extends Asset { } let indexBuffer: Buffer | null = null; - let ib: any = null; + let ib: Uint8Array | Uint16Array | Uint32Array | undefined; if (prim.indexView) { const idxView = prim.indexView; @@ -752,7 +800,8 @@ export class Mesh extends Asset { for (let i = 0; i < struct.vertexBundles.length; i++) { const vtxBdl = struct.vertexBundles[i]; for (let j = 0; j < vtxBdl.attributes.length; j++) { - if (vtxBdl.attributes[j].name === AttributeName.ATTR_POSITION || vtxBdl.attributes[j].name === AttributeName.ATTR_NORMAL) { + if (vtxBdl.attributes[j].name === (AttributeName.ATTR_POSITION as string) + || vtxBdl.attributes[j].name === (AttributeName.ATTR_NORMAL as string)) { const { format } = vtxBdl.attributes[j]; const inputView = new DataView( @@ -852,7 +901,8 @@ export class Mesh extends Asset { for (let v = 0; v < dstBundle.view.count; ++v) { dstAttrView = dstVBView.subarray(dstVBOffset, dstVBOffset + attrSize); vbView.set(dstAttrView, srcVBOffset); - if ((attr.name === AttributeName.ATTR_POSITION || attr.name === AttributeName.ATTR_NORMAL) && worldMatrix) { + if ((attr.name === (AttributeName.ATTR_POSITION as string) + || attr.name === (AttributeName.ATTR_NORMAL as string)) && worldMatrix) { const f32_temp = new Float32Array(vbView.buffer, srcVBOffset, 3); vec3_temp.set(f32_temp[0], f32_temp[1], f32_temp[2]); switch (attr.name) { @@ -1258,7 +1308,7 @@ export class Mesh extends Asset { const primitive = this._struct.primitives[primitiveIndex]; for (const vertexBundleIndex of primitive.vertexBundelIndices) { const vertexBundle = this._struct.vertexBundles[vertexBundleIndex]; - const iAttribute = vertexBundle.attributes.findIndex((a) => a.name === attributeName); + const iAttribute = vertexBundle.attributes.findIndex((a) => a.name === (attributeName as string)); if (iAttribute < 0) { continue; } @@ -1383,7 +1433,12 @@ function getReader (dataView: DataView, format: Format): ((offset: number) => nu break; } case FormatType.FLOAT: { - return (offset: number): number => dataView.getFloat32(offset, isLittleEndian); + switch (stride) { + case 2: return (offset: number) => dataView.getUint16(offset, isLittleEndian); + case 4: return (offset: number) => dataView.getFloat32(offset, isLittleEndian); + default: + } + break; } default: } @@ -1433,7 +1488,12 @@ function getWriter (dataView: DataView, format: Format): ((offset: number, value break; } case FormatType.FLOAT: { - return (offset: number, value: number): void => dataView.setFloat32(offset, value, isLittleEndian); + switch (stride) { + case 2: return (offset: number, value: number) => dataView.setUint16(offset, value, isLittleEndian); + case 4: return (offset: number, value: number) => dataView.setFloat32(offset, value, isLittleEndian); + default: + } + break; } default: } @@ -1441,4 +1501,84 @@ function getWriter (dataView: DataView, format: Format): ((offset: number, value return null; } +export function decodeMesh (mesh: Mesh.ICreateInfo): Mesh.ICreateInfo { + if (!mesh.struct.encoded) { + // the mesh is not encoded, so no need to decode + return mesh; + } + + // decode the mesh + if (!MeshoptDecoder.supported) { + return mesh; + } + + const res_checker = (res: number): void => { + if (res < 0) { + errorID(14204, res); + } + }; + + const struct = JSON.parse(JSON.stringify(mesh.struct)) as Mesh.IStruct; + + const bufferBlob = new BufferBlob(); + bufferBlob.setNextAlignment(0); + + for (const bundle of struct.vertexBundles) { + const view = bundle.view; + const bound = view.count * view.stride; + const buffer = new Uint8Array(bound); + const vertex = new Uint8Array(mesh.data.buffer, view.offset, view.length); + const res = MeshoptDecoder.decodeVertexBuffer(buffer, view.count, view.stride, vertex) as number; + res_checker(res); + + bufferBlob.setNextAlignment(view.stride); + const newView: Mesh.IBufferView = { + offset: bufferBlob.getLength(), + length: buffer.byteLength, + count: view.count, + stride: view.stride, + }; + bundle.view = newView; + bufferBlob.addBuffer(buffer); + } + + for (const primitive of struct.primitives) { + if (primitive.indexView === undefined) { + continue; + } + + const view = primitive.indexView; + const bound = view.count * view.stride; + const buffer = new Uint8Array(bound); + const index = new Uint8Array(mesh.data.buffer, view.offset, view.length); + const res = MeshoptDecoder.decodeIndexBuffer(buffer, view.count, view.stride, index) as number; + res_checker(res); + + bufferBlob.setNextAlignment(view.stride); + const newView: Mesh.IBufferView = { + offset: bufferBlob.getLength(), + length: buffer.byteLength, + count: view.count, + stride: view.stride, + }; + primitive.indexView = newView; + bufferBlob.addBuffer(buffer); + } + + const data = new Uint8Array(bufferBlob.getCombined()); + + return { + struct, + data, + }; +} + +export function inflateMesh (mesh: Mesh.ICreateInfo): Mesh.ICreateInfo { + const inflator = new zlib.Inflate(mesh.data); + const decompressed = inflator.decompress(); + mesh.data = decompressed; + mesh.struct.compressed = false; + return mesh; +} + // function get diff --git a/cocos/3d/misc/create-mesh.ts b/cocos/3d/misc/create-mesh.ts index dc1352344d8..176d6ee71ed 100644 --- a/cocos/3d/misc/create-mesh.ts +++ b/cocos/3d/misc/create-mesh.ts @@ -22,7 +22,7 @@ THE SOFTWARE. */ -import { Mesh } from '../assets/mesh'; +import { Mesh, decodeMesh, inflateMesh } from '../assets/mesh'; import { AttributeName, Format, FormatInfos, PrimitiveMode, Attribute } from '../../gfx'; import { Vec3 } from '../../core'; import { IGeometry, IDynamicGeometry, ICreateMeshOptions, ICreateDynamicMeshOptions } from '../../primitive/define'; @@ -56,7 +56,7 @@ export function createMesh (geometry: IGeometry, out?: Mesh, options?: ICreateMe attr = null; if (geometry.attributes) { for (const att of geometry.attributes) { - if (att.name === AttributeName.ATTR_POSITION) { + if (att.name === (AttributeName.ATTR_POSITION as string)) { attr = att; break; } @@ -78,7 +78,7 @@ export function createMesh (geometry: IGeometry, out?: Mesh, options?: ICreateMe attr = null; if (geometry.attributes) { for (const att of geometry.attributes) { - if (att.name === AttributeName.ATTR_NORMAL) { + if (att.name === (AttributeName.ATTR_NORMAL as string)) { attr = att; break; } @@ -100,7 +100,7 @@ export function createMesh (geometry: IGeometry, out?: Mesh, options?: ICreateMe attr = null; if (geometry.attributes) { for (const att of geometry.attributes) { - if (att.name === AttributeName.ATTR_TEX_COORD) { + if (att.name === (AttributeName.ATTR_TEX_COORD as string)) { attr = att; break; } @@ -122,7 +122,7 @@ export function createMesh (geometry: IGeometry, out?: Mesh, options?: ICreateMe attr = null; if (geometry.attributes) { for (const att of geometry.attributes) { - if (att.name === AttributeName.ATTR_TANGENT) { + if (att.name === (AttributeName.ATTR_TANGENT as string)) { attr = att; break; } @@ -144,7 +144,7 @@ export function createMesh (geometry: IGeometry, out?: Mesh, options?: ICreateMe attr = null; if (geometry.attributes) { for (const att of geometry.attributes) { - if (att.name === AttributeName.ATTR_COLOR) { + if (att.name === (AttributeName.ATTR_COLOR as string)) { attr = att; break; } @@ -434,6 +434,24 @@ export class MeshUtils { static createDynamicMesh (primitiveIndex: number, geometry: IDynamicGeometry, out?: Mesh, options?: ICreateDynamicMeshOptions): Mesh { return createDynamicMesh(primitiveIndex, geometry, out, options); } + + /** + * @en decode a mesh. + * + * @engineInternal + */ + static decodeMesh (mesh: Mesh.ICreateInfo): Mesh.ICreateInfo { + return decodeMesh(mesh); + } + + /** + * @en inflate a mesh. + * + * @engineInternal + */ + static inflateMesh (mesh: Mesh.ICreateInfo): Mesh.ICreateInfo { + return inflateMesh(mesh); + } } export declare namespace createMesh { diff --git a/cocos/3d/misc/mesh-codec.ts b/cocos/3d/misc/mesh-codec.ts new file mode 100644 index 00000000000..86094fce109 --- /dev/null +++ b/cocos/3d/misc/mesh-codec.ts @@ -0,0 +1,81 @@ +/* + Copyright (c) 2023 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 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. +*/ + +import meshopt_asm_factory from 'external:emscripten/meshopt/meshopt_decoder.asm.js'; +import meshopt_wasm_factory from 'external:emscripten/meshopt/meshopt_decoder.wasm.js'; + +import { WASM_SUPPORT_MODE } from 'internal:constants'; + +import { sys, logID } from '../../core'; + +import { game } from '../../game'; +import { WebAssemblySupportMode } from '../../misc/webassembly-support'; + +export const MeshoptDecoder = {} as any; + +function initDecoderASM (): Promise { + const Module = meshopt_asm_factory; + return Promise.all([Module.ready]).then(() => { + MeshoptDecoder.supported = true; + MeshoptDecoder.ready = Promise.resolve(); + MeshoptDecoder.decodeVertexBuffer = Module.decodeVertexBuffer; + MeshoptDecoder.decodeIndexBuffer = Module.decodeIndexBuffer; + MeshoptDecoder.decodeIndexSequence = Module.decodeIndexSequence; + MeshoptDecoder.decodeGltfBuffer = Module.decodeGltfBuffer; + MeshoptDecoder.useWorkers = Module.useWorkers; + MeshoptDecoder.decodeGltfBufferAsync = Module.decodeGltfBufferAsync; + logID(14202); + }); +} + +function initDecoderWASM (): Promise { + const Module = meshopt_wasm_factory; + return Promise.all([Module.ready]).then(() => { + MeshoptDecoder.supported = true; + MeshoptDecoder.ready = Promise.resolve(); + MeshoptDecoder.decodeVertexBuffer = Module.decodeVertexBuffer; + MeshoptDecoder.decodeIndexBuffer = Module.decodeIndexBuffer; + MeshoptDecoder.decodeIndexSequence = Module.decodeIndexSequence; + MeshoptDecoder.decodeGltfBuffer = Module.decodeGltfBuffer; + MeshoptDecoder.useWorkers = Module.useWorkers; + MeshoptDecoder.decodeGltfBufferAsync = Module.decodeGltfBufferAsync; + logID(14203); + }); +} + +export function InitDecoder (): Promise { + if (WASM_SUPPORT_MODE === (WebAssemblySupportMode.MAYBE_SUPPORT as number)) { + if (sys.hasFeature(sys.Feature.WASM)) { + return initDecoderWASM(); + } else { + return initDecoderASM(); + } + } else if (WASM_SUPPORT_MODE === (WebAssemblySupportMode.SUPPORT as number)) { + return initDecoderWASM(); + } else { + return initDecoderASM(); + } +} + +game.onPostInfrastructureInitDelegate.add(InitDecoder); diff --git a/cocos/asset/assets/rendering-sub-mesh.ts b/cocos/asset/assets/rendering-sub-mesh.ts index a648dc6a3ea..2ec5dd6a019 100644 --- a/cocos/asset/assets/rendering-sub-mesh.ts +++ b/cocos/asset/assets/rendering-sub-mesh.ts @@ -27,8 +27,9 @@ import { Attribute, Device, InputAssemblerInfo, Buffer, BufferInfo, AttributeName, BufferUsageBit, Format, FormatInfos, MemoryUsageBit, PrimitiveMode, DrawInfo, } from '../../gfx'; -import { Vec3, cclegacy } from '../../core'; +import { Vec3, approx, cclegacy, floatToHalf, halfToFloat, pseudoRandomRange } from '../../core'; import { Mesh } from '../../3d/assets/mesh'; +import { Root } from '../../root'; /** * @en Array views for index buffer @@ -123,6 +124,12 @@ export class RenderingSubMesh { private _drawInfo?: DrawInfo | null = null; + private static EMPTY_GEOMETRIC_INFO: IGeometricInfo = { + positions: new Float32Array(), + indices: new Uint8Array(), + boundingBox: { min: Vec3.ZERO, max: Vec3.ZERO }, + }; + /** * @en * sub mesh's constructor. @@ -135,8 +142,11 @@ export class RenderingSubMesh { * @param indirectBuffer @en indirect buffer. @zh 间接缓冲区。 */ constructor ( - vertexBuffers: Buffer[], attributes: Attribute[], primitiveMode: PrimitiveMode, - indexBuffer: Buffer | null = null, indirectBuffer: Buffer | null = null, + vertexBuffers: Buffer[], + attributes: Attribute[], + primitiveMode: PrimitiveMode, + indexBuffer: Buffer | null = null, + indirectBuffer: Buffer | null = null, isOwnerOfIndexBuffer = true, ) { this._attributes = attributes; @@ -187,40 +197,105 @@ export class RenderingSubMesh { return this._geometricInfo; } if (this.mesh === undefined) { - return { positions: new Float32Array(), indices: new Uint8Array(), boundingBox: { min: Vec3.ZERO, max: Vec3.ZERO } }; + return RenderingSubMesh.EMPTY_GEOMETRIC_INFO; } if (this.subMeshIdx === undefined) { - return { positions: new Float32Array(), indices: new Uint8Array(), boundingBox: { min: Vec3.ZERO, max: Vec3.ZERO } }; + return RenderingSubMesh.EMPTY_GEOMETRIC_INFO; } const { mesh } = this; const index = this.subMeshIdx; - const positions = mesh.readAttribute(index, AttributeName.ATTR_POSITION) as unknown as Float32Array; - const indices = mesh.readIndices(index) as Uint16Array; + const pAttri = this.attributes.find((element) => element.name === (AttributeName.ATTR_POSITION as string)); + + if (!pAttri) { + return RenderingSubMesh.EMPTY_GEOMETRIC_INFO; + } + + let positions: Float32Array | undefined; + switch (pAttri.format) { + case Format.RG32F: + case Format.RGB32F: + { + positions = mesh.readAttribute(index, AttributeName.ATTR_POSITION) as unknown as Float32Array; + if (!positions) { + return RenderingSubMesh.EMPTY_GEOMETRIC_INFO; + } + break; + } + case Format.RGBA32F: + { + const data = mesh.readAttribute(index, AttributeName.ATTR_POSITION) as unknown as Float32Array; + if (!data) { + return RenderingSubMesh.EMPTY_GEOMETRIC_INFO; + } + const count = data.length / 4; + positions = new Float32Array(count * 3); + for (let i = 0; i < count; ++i) { + const dstPtr = i * 3; + const srcPtr = i * 4; + positions[dstPtr] = data[srcPtr]; + positions[dstPtr + 1] = data[srcPtr + 1]; + positions[dstPtr + 2] = data[srcPtr + 2]; + } + break; + } + case Format.RG16F: + case Format.RGB16F: + { + const data = mesh.readAttribute(index, AttributeName.ATTR_POSITION) as unknown as Uint16Array; + if (!data) { + return RenderingSubMesh.EMPTY_GEOMETRIC_INFO; + } + positions = new Float32Array(data.length); + for (let i = 0; i < data.length; ++i) { + positions[i] = halfToFloat(data[i]); + } + break; + } + case Format.RGBA16F: + { + const data = mesh.readAttribute(index, AttributeName.ATTR_POSITION) as unknown as Uint16Array; + if (!data) { + return RenderingSubMesh.EMPTY_GEOMETRIC_INFO; + } + const count = data.length / 4; + positions = new Float32Array(count * 3); + for (let i = 0; i < count; ++i) { + const dstPtr = i * 3; + const srcPtr = i * 4; + positions[dstPtr] = halfToFloat(data[srcPtr]); + positions[dstPtr + 1] = halfToFloat(data[srcPtr + 1]); + positions[dstPtr + 2] = halfToFloat(data[srcPtr + 2]); + } + break; + } + default: + return RenderingSubMesh.EMPTY_GEOMETRIC_INFO; + } + + const indices = mesh.readIndices(index) || undefined; const max = new Vec3(); const min = new Vec3(); - const pAttri = this.attributes.find((element): boolean => element.name === AttributeName.ATTR_POSITION); - if (pAttri) { - const conut = FormatInfos[pAttri.format].count; + + const conut = FormatInfos[pAttri.format].count; + if (conut === 2) { + max.set(positions[0], positions[1], 0); + min.set(positions[0], positions[1], 0); + } else { + max.set(positions[0], positions[1], positions[2]); + min.set(positions[0], positions[1], positions[2]); + } + for (let i = 0; i < positions.length; i += conut) { if (conut === 2) { - max.set(positions[0], positions[1], 0); - min.set(positions[0], positions[1], 0); + max.x = positions[i] > max.x ? positions[i] : max.x; + max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y; + min.x = positions[i] < min.x ? positions[i] : min.x; + min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y; } else { - max.set(positions[0], positions[1], positions[2]); - min.set(positions[0], positions[1], positions[2]); - } - for (let i = 0; i < positions.length; i += conut) { - if (conut === 2) { - max.x = positions[i] > max.x ? positions[i] : max.x; - max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y; - min.x = positions[i] < min.x ? positions[i] : min.x; - min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y; - } else { - max.x = positions[i] > max.x ? positions[i] : max.x; - max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y; - max.z = positions[i + 2] > max.z ? positions[i + 2] : max.z; - min.x = positions[i] < min.x ? positions[i] : min.x; - min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y; - min.z = positions[i + 2] < min.z ? positions[i + 2] : min.z; - } + max.x = positions[i] > max.x ? positions[i] : max.x; + max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y; + max.z = positions[i + 2] > max.z ? positions[i + 2] : max.z; + min.x = positions[i] < min.x ? positions[i] : min.x; + min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y; + min.z = positions[i + 2] < min.z ? positions[i + 2] : min.z; } } this._geometricInfo = { positions, indices, boundingBox: { max, min } }; @@ -307,14 +382,14 @@ export class RenderingSubMesh { } let jointFormat: Format; let jointOffset: number; - const { device } = cclegacy.director.root; + const { device } = cclegacy.director.root as Root; for (let i = 0; i < prim.vertexBundelIndices.length; i++) { const bundle = struct.vertexBundles[prim.vertexBundelIndices[i]]; jointOffset = 0; jointFormat = Format.UNKNOWN; for (let j = 0; j < bundle.attributes.length; j++) { const attr = bundle.attributes[j]; - if (attr.name === AttributeName.ATTR_JOINTS) { + if (attr.name === (AttributeName.ATTR_JOINTS as string)) { jointFormat = attr.format; break; } @@ -324,8 +399,15 @@ export class RenderingSubMesh { const data = new Uint8Array(this.mesh.data.buffer, bundle.view.offset, bundle.view.length); const dataView = new DataView(data.slice().buffer); const idxMap = struct.jointMaps[prim.jointMapIndex]; - mapBuffer(dataView, (cur): number => idxMap.indexOf(cur), jointFormat, jointOffset, - bundle.view.length, bundle.view.stride, dataView); + mapBuffer( + dataView, + (cur): number => idxMap.indexOf(cur), + jointFormat, + jointOffset, + bundle.view.length, + bundle.view.stride, + dataView, + ); const buffer = device.createBuffer(new BufferInfo( BufferUsageBit.VERTEX | BufferUsageBit.TRANSFER_DST, MemoryUsageBit.DEVICE, diff --git a/cocos/core/math/utils.ts b/cocos/core/math/utils.ts index 3b653aba193..607f937ba70 100644 --- a/cocos/core/math/utils.ts +++ b/cocos/core/math/utils.ts @@ -299,3 +299,69 @@ export function enumerableProps (prototype: ValueType, attrs: string[]): void { Object.defineProperty(prototype, key, { enumerable: true }); }); } + +/** + * convert float to half (short) + */ + +const toHalf = (function () { + // https://stackoverflow.com/questions/32633585/how-do-you-convert-to-half-floats-in-javascript + const floatView = new Float32Array(1); + const int32View = new Int32Array(floatView.buffer); + + return function toHalf (fval: number): number { + floatView[0] = fval; + const fbits = int32View[0]; + const s = (fbits >> 16) & 0x8000; // sign + const em = fbits & 0x7fffffff; // exp and mantissa + + let h = (em - (112 << 23) + (1 << 12)) >> 13; + h = (em < (113 << 23)) ? 0 : h; // denormals-as-zero + + h = (em >= (143 << 23)) ? 0x7c00 : h; // overflow + + h = (em > (255 << 23)) ? 0x7e00 : h; // NaN + + int32View[0] = (s | h); // pack sign and half + + return int32View[0]; + }; +}()); + +const fromHalf = (function () { + const floatView = new Float32Array(1); + const int32View = new Int32Array(floatView.buffer); + + return function fromHalf (hval: number /* uint16 */): number { + const s = (hval >> 15) & 0x00000001; // sign + const em = hval & 0x00007fff; // exp and mantissa + + let h = (em << 13); // exponent/mantissa bits + let fbits = 0; + + if (h !== 0x7c00) { // // NaN/Inf + h += (112 << 23); // exp adjust + + if (em === 0) { // // Denormals-as-zero + h = (h & 0xfffff) >> 1; // // Mantissa shift + } else if (em === 0x7fff) { // // Inf/NaN? + h = 0x7fffffff; // // NaN + } + } else { + h = 0x7f800000; // // +/-Inf + } + + fbits = (s << 31) | h; // // Sign | Exponent | Mantissa + int32View[0] = fbits; + + return floatView[0]; + }; +}()); + +export function floatToHalf (val: number) { + return toHalf(val); +} + +export function halfToFloat (val: number) { + return fromHalf(val); +} diff --git a/cocos/gfx/base/define.ts b/cocos/gfx/base/define.ts index 6e614fb3630..235e0880c8e 100644 --- a/cocos/gfx/base/define.ts +++ b/cocos/gfx/base/define.ts @@ -2344,7 +2344,11 @@ export function getTypedArrayConstructor (info: FormatInfo): TypedArrayConstruct } } case FormatType.FLOAT: { - return Float32Array; + switch (stride) { + case 2: return Uint16Array; + case 4: return Float32Array; + default: return Float32Array; + } } default: } diff --git a/cocos/physics/cannon/shapes/cannon-trimesh-shape.ts b/cocos/physics/cannon/shapes/cannon-trimesh-shape.ts index 8804ff3cfa4..63d4f3bad6e 100644 --- a/cocos/physics/cannon/shapes/cannon-trimesh-shape.ts +++ b/cocos/physics/cannon/shapes/cannon-trimesh-shape.ts @@ -48,8 +48,16 @@ export class CannonTrimeshShape extends CannonShape implements ITrimeshShape { if (this._shape != null) { if (mesh && mesh.renderingSubMeshes.length > 0) { const vertices = mesh.renderingSubMeshes[0].geometricInfo.positions; - const indices = mesh.renderingSubMeshes[0].geometricInfo.indices as Uint16Array; - this.updateProperties(vertices, indices); + const indices = mesh.renderingSubMeshes[0].geometricInfo.indices; + if (indices instanceof Uint8Array) { + this.updateProperties(vertices, new Uint16Array(indices)); + } else if (indices instanceof Uint16Array) { + this.updateProperties(vertices, indices); + } else if (indices instanceof Uint32Array) { + this.updateProperties(vertices, new Uint16Array(indices)); + } else { + this.updateProperties(vertices, new Uint16Array()); + } } else { this.updateProperties(new Float32Array(), new Uint16Array()); } diff --git a/cocos/physics/framework/components/colliders/mesh-collider.ts b/cocos/physics/framework/components/colliders/mesh-collider.ts index e2b4dd912ba..608ad551b74 100644 --- a/cocos/physics/framework/components/colliders/mesh-collider.ts +++ b/cocos/physics/framework/components/colliders/mesh-collider.ts @@ -110,8 +110,6 @@ export class MeshCollider extends Collider { } } - /// PRIVATE PROPERTY /// - @serializable private _mesh: Mesh | null = null; diff --git a/cocos/physics/physx/shapes/physx-trimesh-shape.ts b/cocos/physics/physx/shapes/physx-trimesh-shape.ts index bdbd797b326..edb61e4450b 100644 --- a/cocos/physics/physx/shapes/physx-trimesh-shape.ts +++ b/cocos/physics/physx/shapes/physx-trimesh-shape.ts @@ -54,10 +54,17 @@ export class PhysXTrimeshShape extends PhysXShape implements ITrimeshShape { const meshScale = PhysXShape.MESH_SCALE; meshScale.setScale(Vec3.ONE); meshScale.setRotation(Quat.IDENTITY); - if (collider.convex) { + const posBuf = v.renderingSubMeshes[0].geometricInfo.positions; + let indBuf = v.renderingSubMeshes[0].geometricInfo.indices; + if (indBuf instanceof Uint16Array) { + indBuf = new Uint32Array(indBuf); + } + if (indBuf instanceof Uint8Array) { + indBuf = new Uint32Array(indBuf); + } + if (collider.convex || indBuf === undefined) { if (PX.MESH_CONVEX[v._uuid] == null) { const cooking = PhysXInstance.cooking; - const posBuf = v.readAttribute(0, AttributeName.ATTR_POSITION)! as unknown as Float32Array; PX.MESH_CONVEX[v._uuid] = createConvexMesh(posBuf, cooking, physics); } const convexMesh = PX.MESH_CONVEX[v._uuid]; @@ -65,8 +72,6 @@ export class PhysXTrimeshShape extends PhysXShape implements ITrimeshShape { } else { if (PX.MESH_STATIC[v._uuid] == null) { const cooking = PhysXInstance.cooking; - const posBuf = v.readAttribute(0, AttributeName.ATTR_POSITION)! as unknown as Float32Array; - const indBuf = v.readIndices(0)! as unknown as Uint32Array; // Uint16Array ? PX.MESH_STATIC[v._uuid] = createTriangleMesh(posBuf, indBuf, cooking, physics); } const trimesh = PX.MESH_STATIC[v._uuid]; diff --git a/cocos/render-scene/scene/model.ts b/cocos/render-scene/scene/model.ts index 360d856a821..1e455089938 100644 --- a/cocos/render-scene/scene/model.ts +++ b/cocos/render-scene/scene/model.ts @@ -36,7 +36,11 @@ import { IMacroPatch } from '../core/pass'; import { Mat4, Vec3, Vec4, geometry, cclegacy, EPSILON } from '../../core'; import { Attribute, DescriptorSet, Device, Buffer, BufferInfo, BufferUsageBit, MemoryUsageBit, Filter, Address, SamplerInfo, deviceManager, Texture } from '../../gfx'; -import { UBOLocal, UBOSH, UBOWorldBound, UNIFORM_LIGHTMAP_TEXTURE_BINDING, UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING, UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING, UNIFORM_REFLECTION_PROBE_DATA_MAP_BINDING, UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING } from '../../rendering/define'; +import { + UBOLocal, UBOSH, UBOWorldBound, UNIFORM_LIGHTMAP_TEXTURE_BINDING, UNIFORM_REFLECTION_PROBE_BLEND_CUBEMAP_BINDING, + UNIFORM_REFLECTION_PROBE_CUBEMAP_BINDING, UNIFORM_REFLECTION_PROBE_DATA_MAP_BINDING, + UNIFORM_REFLECTION_PROBE_TEXTURE_BINDING, +} from '../../rendering/define'; import { Root } from '../../root'; import { TextureCube } from '../../asset/assets'; import { ShadowType } from './shadows'; diff --git a/editor/assets/chunks/shading-entries/data-structures/vs-input.chunk b/editor/assets/chunks/shading-entries/data-structures/vs-input.chunk index 004fdd89ed9..d709284f991 100644 --- a/editor/assets/chunks/shading-entries/data-structures/vs-input.chunk +++ b/editor/assets/chunks/shading-entries/data-structures/vs-input.chunk @@ -55,4 +55,4 @@ layout(location = 2) in vec2 a_texCoord; #if __VERSION__ < 450 in float a_vertexId; #endif -#endif +#endif \ No newline at end of file diff --git a/editor/i18n/en/assets.js b/editor/i18n/en/assets.js index 7877f58ccdb..d2393bfd1bc 100644 --- a/editor/i18n/en/assets.js +++ b/editor/i18n/en/assets.js @@ -327,84 +327,65 @@ module.exports = { name: 'Add Vertex Color', title: 'Fill vertex color with white if the model file does not contain vertex color attribute.', }, - meshOptimizer: { - name: 'Mesh Optimizer', - title: 'Mesh Optimizer is used to simplify imported mesh.
Use it when you need to reduce model face count.
In some cases, face reduction could lead to various model defect.
Tweak properties and try again in those cases.', - simplification: { - name: 'Simplification', - title: 'Simplification', - si: { - name: 'Achieve The Ratio R', - title: 'Achieve The Ratio R', - }, - sa: { - name: 'Aggressively Simplify', - title: 'Aggressively Simplify', - }, + meshOptimize: { + name: 'Mesh Optimize', + title: 'Whether to optimize the mesh data.', + vertexCache: { + name: 'Vertex Cache', + title: 'Optimize the vertex buffer to improve vertex cache hit rate.
It is recommended to enable this option for models with high vertex count.', }, - scene: { - name: 'Scene', - title: 'Scene', - kn: { - name: 'Keep Nodes Transform', - title: 'Keep Nodes Transform', - }, - ke: { - name: 'Keep Extras Data', - title: 'Keep Extras Data', - }, + vertexFetch: { + name: 'Vertex Fetch', + title: 'Optimize the vertex buffer to improve vertex fetch efficiency.
It is recommended to enable this option for models with high vertex count.', }, - miscellaneous: { - name: 'Miscellaneous', - title: 'Miscellaneous', - noq: { - name: 'Disable Quantization', - title: 'Disable Quantization', - }, - v: { - name: 'Verbose Output', - title: 'Verbose Output', - }, + overdraw: { + name: 'Overdraw', + title: 'Optimize the vertex buffer to reduce overdraw.
It is recommended to enable this option for models with high vertex count.', }, - algorithm: { - name: 'Algorithm', - simplify: 'simplify', - gltfpack: 'gltfpack (deprecated)', + }, + meshSimplify: { + name: 'Mesh Simplify', + title: 'Whether to simplify the mesh data.', + targetRatio: { + name: 'Target Ratio', + title: 'The target ratio of the simplified mesh data.
It is recommended to set this value to 0.5.', }, - simplify:{ - targetRatio: { - name: 'Ratio', - title: 'The target face count ratio after face reduction.
0 means reduce to minimum, and 1 means no face reduction at all. ', - }, - preserveSurfaceCurvature: { - name: 'Surface Curvature', - title: 'Preserve Surface Curvature', - }, - preserveBorderEdges: { - name: 'Border Edges', - title: 'Preserve Border Edges', - }, - preserveUVSeamEdges: { - name: 'UV Seam Edges', - title: 'Preserve UV Seam Edges', - }, - preserveUVFoldoverEdges: { - name: 'UV Foldover Edges', - title: 'Preserve UV Foldover Edges', - }, - agressiveness: { - name: 'Agressiveness', - title: 'Face reduction algorithm aggressiveness.
The higher it sets, the more aggressive the face reduction algorithm tries to delete faces.
High aggressiveness setting is more likely to cause defects in result.', - }, - maxIterationCount: { - name: 'Max Iteration Count', - title: 'The max iteration counts that the algorithm tries to further reduce faces of a model.
High iteration count is more likely to reach face reduction target, yet it is more likely to take more time and has higher chance to cause mistakes.', - }, + autoErrorRate: { + name: 'Auto Error Rate', + title: 'Whether to automatically calculate the error rate of the simplified mesh data.', + }, + errorRate: { + name: 'Error Rate', + title: 'The max error rate of the simplified mesh data.
This value also alters the result size.
It is recommended to tune until you get a good result.', + }, + lockBoundary: { + name: 'Lock Boundary', + title: 'Whether to lock the boundary of the simplified mesh data.', + }, + }, + meshCluster: { + name: 'Mesh Cluster', + title: 'Whether to cluster the mesh data.', + generateBounding: { + name: 'Generate Bounding', + title: 'Whether to generate bounding sphere and normal cone for the clustered mesh data.', + }, + }, + meshCompress:{ + name: 'Mesh Compress', + title: 'Whether to compress the mesh data.', + encode: { + name: 'Encode', + title: 'Encode the mesh data to reduce data size.', + }, + compress: { + name: 'Compress', + title: 'Compress the mesh data to reduce data size.', }, - gltfpack: { - warn: 'The current asset uses the gltfpack mesh optimization algorithm, which has been deprecated. Please use the new simplify face reduction algorithm.', + quantize: { + name: 'Quantize', + title: 'Quantize the mesh data to reduce data size.', }, - warn: 'Warning: After optimization, the number and names of mesh resources will change, which will cause the loss of resources referenced by the components, please update them manually in time. (In addition, for prefabs pre-generated in the model resources, the resource synchronization mechanism will update them automatically)', }, animationBakeRate: { name: 'Animation Bake Rate', diff --git a/editor/i18n/zh/assets.js b/editor/i18n/zh/assets.js index 80f563243d2..edf9f8acf94 100644 --- a/editor/i18n/zh/assets.js +++ b/editor/i18n/zh/assets.js @@ -325,9 +325,9 @@ module.exports = { name: '填充顶点色', title: '如果模型没有顶点颜色属性,添加颜色属性,填充为白色。', }, - meshOptimizer: { - name: 'Mesh 优化', - title: 'Mesh 优化可以被用来简化导入的模型,可以在需要模型减面时使用。
在一些少数情况下减面后的模型可能会出现显示异常,如发生这种情况请尝试调整参数并重试。', + meshSimplify: { + name: 'Mesh 简化', + title: 'Mesh 简化可以被用来简化导入的模型,可以在需要模型减面时使用。
在一些少数情况下减面后的模型可能会出现显示异常,如发生这种情况请尝试调整参数并重试。', simplification: { name: 'Simplification', title: 'Simplification', diff --git a/editor/inspector/assets/fbx/index.js b/editor/inspector/assets/fbx/index.js index b143506cc0f..c1e2860ab3b 100644 --- a/editor/inspector/assets/fbx/index.js +++ b/editor/inspector/assets/fbx/index.js @@ -117,7 +117,7 @@ exports.listeners = { if (!value) { return; } // 只有被勾选的时候上报埋点 const trackMap = { - meshOptimizer: 'A100000', + meshSimplify: 'A100000', 'fbx.smartMaterialEnabled': 'A100001', disableMeshSplit: 'A100002', }; diff --git a/editor/inspector/assets/fbx/model.js b/editor/inspector/assets/fbx/model.js index 6fac16493b2..8c524043019 100644 --- a/editor/inspector/assets/fbx/model.js +++ b/editor/inspector/assets/fbx/model.js @@ -40,91 +40,83 @@ exports.template = /* html */` - -

- - + +
+ +
-
- - - +
+ + + -
-
-
- -
+ + +
+ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
+ + +
+ + +
+
- - + + - - + + - - + + - - + + +
+
+ +
+ + +
+
- - + + + +
+
+ +
+ + +
+
+ + + - - + + - - + +
+
@@ -254,25 +246,28 @@ exports.$ = { addVertexColorCheckbox: '.addVertexColor-checkbox', promoteSingleRootNodeCheckbox: '.promoteSingleRootNode-checkbox', generateLightmapUVNodeCheckbox: '.generateLightmapUVNode-checkbox', - meshOptimizerCheckbox: '.meshOptimizer-checkbox', - meshOptimizerAlgorithmSelect: '.meshOptimizer-algorithm-select', - // gltfpackOptions - meshOptimizerGltfpackOptions: '.gltfpack-options', - meshOptimizerSISlider: '.meshOptimizer-si-slider', - meshOptimizerSACheckbox: '.meshOptimizer-sa-checkbox', - meshOptimizerKNCheckbox: '.meshOptimizer-kn-checkbox', - meshOptimizerKECheckbox: '.meshOptimizer-ke-checkbox', - meshOptimizerNOQCheckbox: '.meshOptimizer-noq-checkbox', - meshOptimizerVCheckbox: '.meshOptimizer-v-checkbox', + + // meshOptimizeOptions + meshOptimizeCheckbox: '.meshOptimize-checkbox', + meshOptimizeVertexCacheCheckbox: '.meshOptimize-vertexCache-checkbox', + meshOptimizeVertexFetchCheckbox: '.meshOptimize-vertexFetch-checkbox', + meshOptimizeOverdrawCheckbox: '.meshOptimize-overdraw-checkbox', + // simplifyOptions - meshOptimizerSimplifyOptions: '.simplify-options', - meshOptimizerTargetRatioSlider: '.meshOptimizer-targetRatio-slider', - meshOptimizerPreserveSurfaceCurvatureCheckbox: '.meshOptimizer-preserveSurfaceCurvature-checkbox', - meshOptimizerPreserveBorderEdgesCheckbox: '.meshOptimizer-preserveBorderEdges-checkbox', - meshOptimizerPreserveUVSeamEdgesCheckbox: '.meshOptimizer-preserveUVSeamEdges-checkbox', - meshOptimizerPreserveUVFoldoverEdgesCheckbox: '.meshOptimizer-preserveUVFoldoverEdges-checkbox', - meshOptimizerAgressivenessSlider: '.meshOptimizer-agressiveness-slider', - meshOptimizerMaxIterationCountSlider: '.meshOptimizer-maxIterationCount-slider', + meshSimplifyCheckbox: '.meshSimplify-checkbox', + meshSimplifyTargetRatioSlider: '.meshSimplify-targetRatio-slider', + meshSimplifyAutoErrorRateCheckbox: '.meshSimplify-autoErrorRate-checkbox', + meshSimplifyErrorRateSlider: '.meshSimplify-errorRate-slider', + meshSimplifyLockBoundaryCheckbox: '.meshSimplify-lockBoundary-checkbox', + + meshClusterCheckbox: '.meshCluster-checkbox', + meshClusterGenerateBoundingCheckbox: '.meshCluster-generateBounding-checkbox', + + meshCompressCheckbox: '.meshCompress-checkbox', + meshCompressEncodeCheckbox: '.meshCompress-encode-checkbox', + meshCompressCompressCheckbox: '.meshCompress-compress-checkbox', + meshCompressQuantizeCheckbox: '.meshCompress-quantize-checkbox', + // lods lodsCheckbox: '.lods-checkbox', lodItems: '.lod-items', @@ -488,292 +483,278 @@ const Elements = { }, }, - meshOptimizer: { + // meshOptimize start + meshOptimize: { ready() { const panel = this; - panel.$.meshOptimizerCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.enable', 'boolean')); - panel.$.meshOptimizerCheckbox.addEventListener('confirm', () => { + panel.$.meshOptimizeCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimize.enable', 'boolean')); + panel.$.meshOptimizeCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshOptimizer, false, 'enable'); + panel.$.meshOptimizeCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshOptimize, false, 'enable'); - updateElementInvalid.call(panel, panel.$.meshOptimizerCheckbox, 'meshOptimizer.enable'); - updateElementReadonly.call(panel, panel.$.meshOptimizerCheckbox); + updateElementInvalid.call(panel, panel.$.meshOptimizeCheckbox, 'meshOptimize.enable'); + updateElementReadonly.call(panel, panel.$.meshOptimizeCheckbox); }, }, - meshOptimizerAlgorithm: { + meshOptimizeVertexCache: { ready() { const panel = this; - panel.$.meshOptimizerAlgorithmSelect.addEventListener('change', (event) => { - panel.setProp.call(panel, 'meshOptimizer.algorithm', 'string', event); - Elements.meshOptimizerAlgorithm.update.call(panel); - }); - panel.$.meshOptimizerAlgorithmSelect.addEventListener('confirm', () => { + panel.$.meshOptimizeVertexCacheCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimize.vertexCache', 'boolean')); + panel.$.meshOptimizeVertexCacheCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - let optionsHtml = ''; - const types = ['simplify', 'gltfpack']; - types.forEach((type) => { - optionsHtml += ``; - }); - panel.$.meshOptimizerAlgorithmSelect.innerHTML = optionsHtml; - - const defaultValue = 'simplify'; - panel.$.meshOptimizerAlgorithmSelect.value = getPropValue.call(panel, panel.meta.userData.meshOptimizer, defaultValue, 'algorithm'); + panel.$.meshOptimizeVertexCacheCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshOptimize, false, 'vertexCache'); - updateElementInvalid.call(panel, panel.$.meshOptimizerAlgorithmSelect, 'meshOptimizer.algorithm'); - updateElementReadonly.call(panel, panel.$.meshOptimizerAlgorithmSelect); - - if (panel.$.meshOptimizerAlgorithmSelect.value === defaultValue) { - panel.$.meshOptimizerGltfpackOptions.setAttribute('hidden', ''); - panel.$.meshOptimizerSimplifyOptions.removeAttribute('hidden'); - } else { - panel.$.meshOptimizerGltfpackOptions.removeAttribute('hidden'); - panel.$.meshOptimizerSimplifyOptions.setAttribute('hidden', ''); - } - - if (panel.$.meshOptimizerAlgorithmSelect.hasAttribute('invalid')) { - panel.$.meshOptimizerGltfpackOptions.setAttribute('hidden', ''); - panel.$.meshOptimizerSimplifyOptions.setAttribute('hidden', ''); - } + updateElementInvalid.call(panel, panel.$.meshOptimizeVertexCacheCheckbox, 'meshOptimize.vertexCache'); + updateElementReadonly.call(panel, panel.$.meshOptimizeVertexCacheCheckbox); }, }, - // gltfpackOptions start - si: { + meshOptimizeVertexFetch: { ready() { const panel = this; - panel.$.meshOptimizerSISlider.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.gltfpackOptions.si', 'number')); - panel.$.meshOptimizerSISlider.addEventListener('confirm', () => { + + panel.$.meshOptimizeVertexFetchCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimize.vertexFetch', 'boolean')); + panel.$.meshOptimizeVertexFetchCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerSISlider.value = getPropValue.call(panel, panel.meta.userData, 1, 'meshOptimizer.gltfpackOptions.si'); + panel.$.meshOptimizeVertexFetchCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshOptimize, false, 'vertexFetch'); - updateElementInvalid.call(panel, panel.$.meshOptimizerSISlider, 'meshOptimizer.gltfpackOptions.si'); - updateElementReadonly.call(panel, panel.$.meshOptimizerSISlider, true); + updateElementInvalid.call(panel, panel.$.meshOptimizeVertexFetchCheckbox, 'meshOptimize.vertexFetch'); + updateElementReadonly.call(panel, panel.$.meshOptimizeVertexFetchCheckbox); }, }, - sa: { + meshOptimizeOverdraw: { ready() { const panel = this; - panel.$.meshOptimizerSACheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.gltfpackOptions.sa', 'boolean')); - panel.$.meshOptimizerSACheckbox.addEventListener('confirm', () => { + + panel.$.meshOptimizeOverdrawCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimize.overdraw', 'boolean')); + panel.$.meshOptimizeOverdrawCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerSACheckbox.value = getPropValue.call(panel, panel.meta.userData, false, 'meshOptimizer.gltfpackOptions.sa'); + panel.$.meshOptimizeOverdrawCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshOptimize, false, 'overdraw'); - updateElementInvalid.call(panel, panel.$.meshOptimizerSACheckbox, 'meshOptimizer.gltfpackOptions.sa'); - updateElementReadonly.call(panel, panel.$.meshOptimizerSACheckbox, true); + updateElementInvalid.call(panel, panel.$.meshOptimizeOverdrawCheckbox, 'meshOptimize.overdraw'); + updateElementReadonly.call(panel, panel.$.meshOptimizeOverdrawCheckbox); }, }, - kn: { + // meshOptimize end + // meshSimplify start + meshSimplify: { ready() { const panel = this; - panel.$.meshOptimizerKNCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.gltfpackOptions.kn', 'boolean')); - panel.$.meshOptimizerKNCheckbox.addEventListener('confirm', () => { + + panel.$.meshSimplifyCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshSimplify.enable', 'boolean')); + panel.$.meshSimplifyCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerKNCheckbox.value = getPropValue.call(panel, panel.meta.userData, false, 'meshOptimizer.gltfpackOptions.kn'); + panel.$.meshSimplifyCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshSimplify, false, 'enable'); - updateElementInvalid.call(panel, panel.$.meshOptimizerKNCheckbox, 'meshOptimizer.gltfpackOptions.kn'); - updateElementReadonly.call(panel, panel.$.meshOptimizerKNCheckbox, true); + updateElementInvalid.call(panel, panel.$.meshSimplifyCheckbox, 'meshSimplify.enable'); + updateElementReadonly.call(panel, panel.$.meshSimplifyCheckbox); }, }, - ke: { + meshSimplifyTargetRatio: { ready() { const panel = this; - panel.$.meshOptimizerKECheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.gltfpackOptions.ke', 'boolean')); - panel.$.meshOptimizerKECheckbox.addEventListener('confirm', () => { + panel.$.meshSimplifyTargetRatioSlider.addEventListener('change', panel.setProp.bind(panel, 'meshSimplify.targetRatio', 'number')); + panel.$.meshSimplifyTargetRatioSlider.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerKECheckbox.value = getPropValue.call(panel, panel.meta.userData, false, 'meshOptimizer.gltfpackOptions.ke'); + panel.$.meshSimplifyTargetRatioSlider.value = getPropValue.call(panel, panel.meta.userData.meshSimplify, 1, 'targetRatio'); - updateElementInvalid.call(panel, panel.$.meshOptimizerKECheckbox, 'meshOptimizer.gltfpackOptions.ke'); - updateElementReadonly.call(panel, panel.$.meshOptimizerKECheckbox, true); + updateElementInvalid.call(panel, panel.$.meshSimplifyTargetRatioSlider, 'meshSimplify.targetRatio'); + updateElementReadonly.call(panel, panel.$.meshSimplifyTargetRatioSlider); }, }, - noq: { + meshSimplifyAutoErrorRateCheckbox: { ready() { const panel = this; - - panel.$.meshOptimizerNOQCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.gltfpackOptions.noq', 'boolean')); - panel.$.meshOptimizerNOQCheckbox.addEventListener('confirm', () => { + panel.$.meshSimplifyAutoErrorRateCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshSimplify.autoErrorRate', 'boolean')); + panel.$.meshSimplifyAutoErrorRateCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerNOQCheckbox.value = getPropValue.call(panel, panel.meta.userData, true, 'meshOptimizer.gltfpackOptions.noq'); + panel.$.meshSimplifyAutoErrorRateCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshSimplify, false, 'autoErrorRate'); - updateElementInvalid.call(panel, panel.$.meshOptimizerNOQCheckbox, 'meshOptimizer.gltfpackOptions.noq'); - updateElementReadonly.call(panel, panel.$.meshOptimizerNOQCheckbox, true); + updateElementInvalid.call(panel, panel.$.meshSimplifyAutoErrorRateCheckbox, 'meshSimplify.autoErrorRate'); + updateElementReadonly.call(panel, panel.$.meshSimplifyAutoErrorRateCheckbox); }, }, - v: { + meshSimplifyErrorRate: { ready() { const panel = this; - panel.$.meshOptimizerVCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.gltfpackOptions.v', 'boolean')); - panel.$.meshOptimizerVCheckbox.addEventListener('confirm', () => { + panel.$.meshSimplifyErrorRateSlider.addEventListener('change', panel.setProp.bind(panel, 'meshSimplify.errorRate', 'number')); + panel.$.meshSimplifyErrorRateSlider.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerVCheckbox.value = getPropValue.call(panel, panel.meta.userData, true, 'meshOptimizer.gltfpackOptions.v'); + panel.$.meshSimplifyErrorRateSlider.value = getPropValue.call(panel, panel.meta.userData.meshSimplify, 1, 'errorRate'); - updateElementInvalid.call(panel, panel.$.meshOptimizerVCheckbox, 'meshOptimizer.gltfpackOptions.v'); - updateElementReadonly.call(panel, panel.$.meshOptimizerVCheckbox, true); + updateElementInvalid.call(panel, panel.$.meshSimplifyErrorRateSlider, 'meshSimplify.errorRate'); + updateElementReadonly.call(panel, panel.$.meshSimplifyErrorRateSlider); }, }, - // gltfpackOptions end - // simplifyOptions start - targetRatio: { + meshSimplifyLockBoundaryCheckbox: { ready() { const panel = this; - panel.$.meshOptimizerTargetRatioSlider.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.simplifyOptions.targetRatio', 'number')); - panel.$.meshOptimizerTargetRatioSlider.addEventListener('confirm', () => { + panel.$.meshSimplifyLockBoundaryCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshSimplify.lockBoundary', 'boolean')); + panel.$.meshSimplifyLockBoundaryCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerTargetRatioSlider.value = getPropValue.call(panel, panel.meta.userData, 1, 'meshOptimizer.simplifyOptions.targetRatio'); + panel.$.meshSimplifyLockBoundaryCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshSimplify, false, 'lockBoundary'); - updateElementInvalid.call(panel, panel.$.meshOptimizerTargetRatioSlider, 'meshOptimizer.simplifyOptions.targetRatio'); - updateElementReadonly.call(panel, panel.$.meshOptimizerTargetRatioSlider); + updateElementInvalid.call(panel, panel.$.meshSimplifyLockBoundaryCheckbox, 'meshSimplify.lockBoundary'); + updateElementReadonly.call(panel, panel.$.meshSimplifyLockBoundaryCheckbox); }, }, - preserveSurfaceCurvature: { + meshClusterCheckbox: { ready() { const panel = this; - panel.$.meshOptimizerPreserveSurfaceCurvatureCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.simplifyOptions.preserveSurfaceCurvature', 'boolean')); - panel.$.meshOptimizerPreserveSurfaceCurvatureCheckbox.addEventListener('confirm', () => { + + panel.$.meshClusterCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshCluster.enable', 'boolean')); + panel.$.meshClusterCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerPreserveSurfaceCurvatureCheckbox.value = getPropValue.call(panel, panel.meta.userData, false, 'meshOptimizer.simplifyOptions.preserveSurfaceCurvature'); + panel.$.meshClusterCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshCluster, false, 'enable'); - updateElementInvalid.call(panel, panel.$.meshOptimizerPreserveSurfaceCurvatureCheckbox, 'meshOptimizer.simplifyOptions.preserveSurfaceCurvature'); - updateElementReadonly.call(panel, panel.$.meshOptimizerPreserveSurfaceCurvatureCheckbox); + updateElementInvalid.call(panel, panel.$.meshClusterCheckbox, 'meshCluster.enable'); + updateElementReadonly.call(panel, panel.$.meshClusterCheckbox); }, }, - preserveBorderEdges: { + meshClusterGenerateBoundingCheckbox: { ready() { const panel = this; - panel.$.meshOptimizerPreserveBorderEdgesCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.simplifyOptions.preserveBorderEdges', 'boolean')); - panel.$.meshOptimizerPreserveBorderEdgesCheckbox.addEventListener('confirm', () => { + + panel.$.meshClusterGenerateBoundingCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshCluster.generateBounding', 'boolean')); + panel.$.meshClusterGenerateBoundingCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerPreserveBorderEdgesCheckbox.value = getPropValue.call(panel, panel.meta.userData, false, 'meshOptimizer.simplifyOptions.preserveBorderEdges'); + panel.$.meshClusterGenerateBoundingCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshCluster, false, 'generateBounding'); - updateElementInvalid.call(panel, panel.$.meshOptimizerPreserveBorderEdgesCheckbox, 'meshOptimizer.simplifyOptions.preserveBorderEdges'); - updateElementReadonly.call(panel, panel.$.meshOptimizerPreserveBorderEdgesCheckbox); + updateElementInvalid.call(panel, panel.$.meshClusterGenerateBoundingCheckbox, 'meshCluster.generateBounding'); + updateElementReadonly.call(panel, panel.$.meshClusterGenerateBoundingCheckbox); }, }, - preserveUVSeamEdges: { + // meshSimplify end + // meshCompress start + meshCompress: { ready() { const panel = this; - panel.$.meshOptimizerPreserveUVSeamEdgesCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.simplifyOptions.preserveUVSeamEdges', 'boolean')); - panel.$.meshOptimizerPreserveUVSeamEdgesCheckbox.addEventListener('confirm', () => { + + panel.$.meshCompressCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshCompress.enable', 'boolean')); + panel.$.meshCompressCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerPreserveUVSeamEdgesCheckbox.value = getPropValue.call(panel, panel.meta.userData, false, 'meshOptimizer.simplifyOptions.preserveUVSeamEdges'); + panel.$.meshCompressCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshCompress, false, 'enable'); - updateElementInvalid.call(panel, panel.$.meshOptimizerPreserveUVSeamEdgesCheckbox, 'meshOptimizer.simplifyOptions.preserveUVSeamEdges'); - updateElementReadonly.call(panel, panel.$.meshOptimizerPreserveUVSeamEdgesCheckbox); + updateElementInvalid.call(panel, panel.$.meshCompressCheckbox, 'meshCompress.enable'); + updateElementReadonly.call(panel, panel.$.meshCompressCheckbox); }, }, - preserveUVFoldoverEdges: { + meshCompressEncode: { ready() { const panel = this; - panel.$.meshOptimizerPreserveUVFoldoverEdgesCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.simplifyOptions.preserveUVFoldoverEdges', 'boolean')); - panel.$.meshOptimizerPreserveUVFoldoverEdgesCheckbox.addEventListener('confirm', () => { + + panel.$.meshCompressEncodeCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshCompress.encode', 'boolean')); + panel.$.meshCompressEncodeCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerPreserveUVFoldoverEdgesCheckbox.value = getPropValue.call(panel, panel.meta.userData, false, 'meshOptimizer.simplifyOptions.preserveUVFoldoverEdges'); + panel.$.meshCompressEncodeCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshCompress, false, 'encode'); - updateElementInvalid.call(panel, panel.$.meshOptimizerPreserveUVFoldoverEdgesCheckbox, 'meshOptimizer.simplifyOptions.preserveUVFoldoverEdges'); - updateElementReadonly.call(panel, panel.$.meshOptimizerPreserveUVFoldoverEdgesCheckbox); + updateElementInvalid.call(panel, panel.$.meshCompressEncodeCheckbox, 'meshCompress.encode'); + updateElementReadonly.call(panel, panel.$.meshCompressEncodeCheckbox); }, }, - agressiveness: { + meshCompressCompress: { ready() { const panel = this; - panel.$.meshOptimizerAgressivenessSlider.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.simplifyOptions.agressiveness', 'number')); - panel.$.meshOptimizerAgressivenessSlider.addEventListener('confirm', () => { + + panel.$.meshCompressCompressCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshCompress.compress', 'boolean')); + panel.$.meshCompressCompressCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerAgressivenessSlider.value = getPropValue.call(panel, panel.meta.userData, 7, 'meshOptimizer.simplifyOptions.agressiveness'); + panel.$.meshCompressCompressCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshCompress, false, 'compress'); - updateElementInvalid.call(panel, panel.$.meshOptimizerAgressivenessSlider, 'meshOptimizer.simplifyOptions.agressiveness'); - updateElementReadonly.call(panel, panel.$.meshOptimizerAgressivenessSlider); + updateElementInvalid.call(panel, panel.$.meshCompressCompressCheckbox, 'meshCompress.compress'); + updateElementReadonly.call(panel, panel.$.meshCompressCompressCheckbox); }, }, - maxIterationCount: { + meshCompressQuantize: { ready() { const panel = this; - panel.$.meshOptimizerMaxIterationCountSlider.addEventListener('change', panel.setProp.bind(panel, 'meshOptimizer.simplifyOptions.maxIterationCount', 'number')); - panel.$.meshOptimizerMaxIterationCountSlider.addEventListener('confirm', () => { + + panel.$.meshCompressQuantizeCheckbox.addEventListener('change', panel.setProp.bind(panel, 'meshCompress.quantize', 'boolean')); + panel.$.meshCompressQuantizeCheckbox.addEventListener('confirm', () => { panel.dispatch('snapshot'); }); }, update() { const panel = this; - panel.$.meshOptimizerMaxIterationCountSlider.value = getPropValue.call(panel, panel.meta.userData, 100, 'meshOptimizer.simplifyOptions.maxIterationCount'); + panel.$.meshCompressQuantizeCheckbox.value = getPropValue.call(panel, panel.meta.userData.meshCompress, false, 'quantize'); - updateElementInvalid.call(panel, panel.$.meshOptimizerMaxIterationCountSlider, 'meshOptimizer.simplifyOptions.maxIterationCount'); - updateElementReadonly.call(panel, panel.$.meshOptimizerMaxIterationCountSlider); + updateElementInvalid.call(panel, panel.$.meshCompressQuantizeCheckbox, 'meshCompress.quantize'); + updateElementReadonly.call(panel, panel.$.meshCompressQuantizeCheckbox); }, }, - // simplifyOptions end + // meshCompress end // lods start lods: { ready() { @@ -1003,18 +984,18 @@ function getLodItemHTML(lodOptions, LODTriangleCounts, hasBuiltinLOD = false) {
LOD ${index}
-
+
Face count(%) + ${hasBuiltinLOD ? 'disabled' : ''}>
${LODTriangleCounts[index] || 0} Triangles
-
+
diff --git a/licenses/LICENSE_meshoptimizer.md b/licenses/LICENSE_meshoptimizer.md new file mode 100644 index 00000000000..962ed41ffbe --- /dev/null +++ b/licenses/LICENSE_meshoptimizer.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016-2023 Arseny Kapoulkine + +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. diff --git a/native/cocos/3d/assets/Mesh.cpp b/native/cocos/3d/assets/Mesh.cpp index e0b2034f89c..615a06b3aa9 100644 --- a/native/cocos/3d/assets/Mesh.cpp +++ b/native/cocos/3d/assets/Mesh.cpp @@ -26,6 +26,7 @@ #include "3d/assets/Morph.h" #include "3d/assets/Skeleton.h" #include "3d/misc/BufferBlob.h" +#include "3d/misc/CreateMesh.h" #include "base/std/hash/hash.h" #include "core/DataView.h" #include "core/assets/RenderingSubMesh.h" @@ -102,7 +103,13 @@ DataReaderCallback getReader(const DataView &dataView, gfx::Format format) { break; } case gfx::FormatType::FLOAT: { - return [&](uint32_t offset) -> TypedArrayElementType { return dataView.getFloat32(offset); }; + switch (stride) { + case 2: return [&](uint32_t offset) -> TypedArrayElementType { return dataView.getUint16(offset); }; + case 4: return [&](uint32_t offset) -> TypedArrayElementType { return dataView.getFloat32(offset); }; + default: + break; + } + break; } default: break; @@ -159,7 +166,13 @@ DataWritterCallback getWriter(DataView &dataView, gfx::Format format) { break; } case gfx::FormatType::FLOAT: { - return [&](uint32_t offset, const TypedArrayElementType &value) { dataView.setFloat32(offset, ccstd::get(value)); }; + switch (stride) { + case 2: return [&](uint32_t offset, const TypedArrayElementType &value) { dataView.setUint16(offset, ccstd::get(value)); }; + case 4: return [&](uint32_t offset, const TypedArrayElementType &value) { dataView.setFloat32(offset, ccstd::get(value)); }; + default: + break; + } + break; } default: break; @@ -293,6 +306,15 @@ void Mesh::initialize() { _initialized = true; + if (_struct.compressed) { + // decompress + MeshUtils::inflateMesh(_struct, _data); + } + if (_struct.encoded) { + // decode + MeshUtils::decodeMesh(_struct, _data); + } + if (_struct.dynamic.has_value()) { auto *device = gfx::Device::getInstance(); gfx::BufferList vertexBuffers; @@ -1301,7 +1323,13 @@ TypedArray Mesh::createTypedArrayWithGFXFormat(gfx::Format format, uint32_t coun break; } case gfx::FormatType::FLOAT: { - return Float32Array(count); + switch (stride) { + case 2: return Uint16Array(count); + case 4: return Float32Array(count); + default: + break; + } + break; } default: break; diff --git a/native/cocos/3d/assets/Mesh.h b/native/cocos/3d/assets/Mesh.h index 8f7c37fd529..0eac30df259 100644 --- a/native/cocos/3d/assets/Mesh.h +++ b/native/cocos/3d/assets/Mesh.h @@ -196,6 +196,12 @@ class Mesh : public Asset { * @zh 动态网格特有数据 */ ccstd::optional dynamic; + + ccstd::optional encoded; + + ccstd::optional compressed; + + ccstd::optional quantized; }; struct ICreateInfo { diff --git a/native/cocos/3d/misc/CreateMesh.cpp b/native/cocos/3d/misc/CreateMesh.cpp index fa3ee334b69..e479a23d33d 100644 --- a/native/cocos/3d/misc/CreateMesh.cpp +++ b/native/cocos/3d/misc/CreateMesh.cpp @@ -23,12 +23,14 @@ ****************************************************************************/ #include "3d/misc/CreateMesh.h" +#include #include #include "3d/misc/Buffer.h" #include "3d/misc/BufferBlob.h" #include "core/ArrayBuffer.h" #include "core/DataView.h" #include "core/assets/RenderingSubMesh.h" +#include "meshopt/meshoptimizer.h" #include "renderer/gfx-base/GFXDef-common.h" namespace cc { @@ -404,4 +406,70 @@ Mesh::ICreateInfo MeshUtils::createDynamicMeshInfo(const IDynamicGeometry &geome return createInfo; } +void MeshUtils::inflateMesh(const Mesh::IStruct &structInfo, Uint8Array &data) { + uLongf uncompressedSize = 0U; + for (const auto &prim : structInfo.primitives) { + uncompressedSize += prim.indexView->length; + } + for (const auto &vb : structInfo.vertexBundles) { + uncompressedSize += vb.view.length; + } + auto uncompressedData = Uint8Array(static_cast(uncompressedSize)); + auto res = uncompress(uncompressedData.buffer()->getData(), &uncompressedSize, data.buffer()->getData(), data.byteLength()); + data = uncompressedData; +} + +void MeshUtils::decodeMesh(Mesh::IStruct &structInfo, Uint8Array &data) { + BufferBlob bufferBlob; + + for (auto &bundle : structInfo.vertexBundles) { + auto &view = bundle.view; + auto bound = view.count * view.stride; + auto *buffer = ccnew ArrayBuffer(bound); + auto vertex = Uint8Array(data.buffer(), view.offset, view.length); + int res = meshopt_decodeVertexBuffer(buffer->getData(), view.count, view.stride, vertex.buffer()->getData() + vertex.byteOffset(), view.length); + if (res < 0) { + assert(false && "failed to decode vertex buffer"); + } + + bufferBlob.setNextAlignment(view.stride); + Mesh::IVertexBundle vertexBundle; + Mesh::IBufferView buffferView; + buffferView.offset = bufferBlob.getLength(); + buffferView.length = bound; + buffferView.count = view.count; + buffferView.stride = view.stride; + bufferBlob.addBuffer(buffer); + + bundle.view = buffferView; + } + + for (auto &primitive : structInfo.primitives) { + if (!primitive.indexView.has_value()) { + continue; + } + + auto view = *primitive.indexView; + auto bound = view.count * view.stride; + auto *buffer = ccnew ArrayBuffer(bound); + auto index = DataView(data.buffer(), view.offset, view.length); + int res = meshopt_decodeIndexBuffer(buffer->getData(), view.count, view.stride, index.buffer()->getData() + index.byteOffset(), view.length); + if (res < 0) { + assert(false && "failed to decode index buffer"); + } + + bufferBlob.setNextAlignment(view.stride); + Mesh::IBufferView buffferView; + buffferView.offset = bufferBlob.getLength(); + buffferView.length = bound; + buffferView.count = view.count; + buffferView.stride = view.stride; + bufferBlob.addBuffer(buffer); + + primitive.indexView = buffferView; + } + + data = Uint8Array(bufferBlob.getCombined()); +} + } // namespace cc diff --git a/native/cocos/3d/misc/CreateMesh.h b/native/cocos/3d/misc/CreateMesh.h index b87be8ad19f..84f1272168e 100644 --- a/native/cocos/3d/misc/CreateMesh.h +++ b/native/cocos/3d/misc/CreateMesh.h @@ -87,6 +87,13 @@ class MeshUtils { * @zh 创建一个动态网格ICreateInfo。 */ static Mesh::ICreateInfo createDynamicMeshInfo(const IDynamicGeometry &geometry, const ICreateDynamicMeshOptions &options = {}); + + /** + * + */ + static void inflateMesh(const Mesh::IStruct &structInfo, Uint8Array &data); + + static void decodeMesh(Mesh::IStruct &structInfo, Uint8Array &data); }; } // namespace cc diff --git a/native/cocos/core/assets/RenderingSubMesh.cpp b/native/cocos/core/assets/RenderingSubMesh.cpp index 363414194ca..de744d7d09a 100644 --- a/native/cocos/core/assets/RenderingSubMesh.cpp +++ b/native/cocos/core/assets/RenderingSubMesh.cpp @@ -28,6 +28,7 @@ #include "3d/misc/Buffer.h" #include "core/DataView.h" #include "core/TypedArray.h" +#include "math/Utils.h" #include "math/Vec3.h" #include "renderer/gfx-base/GFXBuffer.h" #include "renderer/gfx-base/GFXDevice.h" @@ -91,59 +92,118 @@ const IGeometricInfo &RenderingSubMesh::getGeometricInfo() { return EMPTY_GEOMETRIC_INFO; } - auto index = static_cast(_subMeshIdx.value()); + auto iter = std::find_if(_attributes.cbegin(), _attributes.cend(), [](const gfx::Attribute &element) -> bool { + return element.name == gfx::ATTR_NAME_POSITION; + }); + if (iter != _attributes.end()) { + return EMPTY_GEOMETRIC_INFO; + } + + const auto &attri = *iter; + const uint32_t count = gfx::GFX_FORMAT_INFOS[static_cast(attri.format)].count; + auto index = static_cast(_subMeshIdx.value()); const auto &positionsVar = _mesh->readAttribute(index, gfx::ATTR_NAME_POSITION); - const auto *pPositions = ccstd::get_if(&positionsVar); - if (pPositions != nullptr) { - const auto &positions = *pPositions; - const auto &indicesVar = _mesh->readIndices(index); - - Vec3 max; - Vec3 min; - - auto iter = std::find_if(_attributes.cbegin(), _attributes.cend(), [](const gfx::Attribute &element) -> bool { - return element.name == gfx::ATTR_NAME_POSITION; - }); - if (iter != _attributes.cend()) { - const auto &attri = *iter; - const uint32_t count = gfx::GFX_FORMAT_INFOS[static_cast(attri.format)].count; - if (count == 2) { - max.set(positions[0], positions[1], 0); - min.set(positions[0], positions[1], 0); - } else { - max.set(positions[0], positions[1], positions[2]); - min.set(positions[0], positions[1], positions[2]); - } - for (int i = 0; i < positions.length(); i += static_cast(count)) { - if (count == 2) { - max.x = positions[i] > max.x ? positions[i] : max.x; - max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y; - min.x = positions[i] < min.x ? positions[i] : min.x; - min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y; - } else { - max.x = positions[i] > max.x ? positions[i] : max.x; - max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y; - max.z = positions[i + 2] > max.z ? positions[i + 2] : max.z; - min.x = positions[i] < min.x ? positions[i] : min.x; - min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y; - min.z = positions[i + 2] < min.z ? positions[i + 2] : min.z; - } + Float32Array const *pPositions = nullptr; + switch (attri.format) { + case gfx::Format::RG32F: + case gfx::Format::RGB32F: { + pPositions = ccstd::get_if(&positionsVar); + if (pPositions == nullptr) { + return EMPTY_GEOMETRIC_INFO; + } + break; + } + case gfx::Format::RGBA32F: { + const auto *data = ccstd::get_if(&positionsVar); + if (data == nullptr) { + return EMPTY_GEOMETRIC_INFO; + } + const auto count = data->length() / 4; + auto *pos = ccnew Float32Array(count * 3); + for (uint32_t i = 0; i < count; i++) { + const auto dstPtr = i * 3; + const auto srcPtr = i * 4; + (*pos)[dstPtr] = (*data)[srcPtr]; + (*pos)[dstPtr + 1] = (*data)[srcPtr + 1]; + (*pos)[dstPtr + 2] = (*data)[srcPtr + 2]; + } + pPositions = pos; + break; + } + case gfx::Format::RG16F: + case gfx::Format::RGB16F: { + const auto *data = ccstd::get_if(&positionsVar); + if (data == nullptr) { + return EMPTY_GEOMETRIC_INFO; } + auto *pos = ccnew Float32Array(data->length()); + for (uint32_t i = 0; i < data->length(); ++i) { + (*pos)[i] = mathutils::halfToFloat((*data)[i]); + } + pPositions = pos; + break; + } + case gfx::Format::RGBA16F: { + const auto *data = ccstd::get_if(&positionsVar); + if (data == nullptr) { + return EMPTY_GEOMETRIC_INFO; + } + const auto count = data->length() / 4; + auto *pos = ccnew Float32Array(count * 3); + for (uint32_t i = 0; i < count; i++) { + const auto dstPtr = i * 3; + const auto srcPtr = i * 4; + (*pos)[dstPtr] = mathutils::halfToFloat((*data)[srcPtr]); + (*pos)[dstPtr + 1] = mathutils::halfToFloat((*data)[srcPtr + 1]); + (*pos)[dstPtr + 2] = mathutils::halfToFloat((*data)[srcPtr + 2]); + } + pPositions = pos; + break; + } + default: + return EMPTY_GEOMETRIC_INFO; + }; - IGeometricInfo info; - info.positions = positions; - info.indices = indicesVar; - info.boundingBox.max = max; - info.boundingBox.min = min; + const auto &positions = *pPositions; + const auto &indicesVar = _mesh->readIndices(index); - _geometricInfo = info; - return _geometricInfo.value(); + Vec3 max; + Vec3 min; + + if (count == 2) { + max.set(positions[0], positions[1], 0); + min.set(positions[0], positions[1], 0); + } else { + max.set(positions[0], positions[1], positions[2]); + min.set(positions[0], positions[1], positions[2]); + } + + for (int i = 0; i < positions.length(); i += static_cast(count)) { + if (count == 2) { + max.x = positions[i] > max.x ? positions[i] : max.x; + max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y; + min.x = positions[i] < min.x ? positions[i] : min.x; + min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y; + } else { + max.x = positions[i] > max.x ? positions[i] : max.x; + max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y; + max.z = positions[i + 2] > max.z ? positions[i + 2] : max.z; + min.x = positions[i] < min.x ? positions[i] : min.x; + min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y; + min.z = positions[i + 2] < min.z ? positions[i + 2] : min.z; } } - return EMPTY_GEOMETRIC_INFO; + IGeometricInfo info; + info.positions = positions; + info.indices = indicesVar; + info.boundingBox.max = max; + info.boundingBox.min = min; + + _geometricInfo = info; + return _geometricInfo.value(); } void RenderingSubMesh::genFlatBuffers() { diff --git a/native/cocos/math/Utils.cpp b/native/cocos/math/Utils.cpp index f15622a569b..5fdb01b56a3 100644 --- a/native/cocos/math/Utils.cpp +++ b/native/cocos/math/Utils.cpp @@ -50,6 +50,63 @@ float maxComponent(const Vec3 &v) { return std::max(std::max(v.x, v.y), v.z); } +uint16_t floatToHalf(float fval) { + union { + float f; + unsigned int ui; + } u = {fval}; + unsigned int ui = u.ui; + + int s = (ui >> 16) & 0x8000; // NOLINT + int em = ui & 0x7fffffff; // NOLINT + + /* bias exponent and round to nearest; 112 is relative exponent bias (127-15) */ + int h = (em - (112 << 23) + (1 << 12)) >> 13; + + /* underflow: flush to zero; 113 encodes exponent -14 */ + h = (em < (113 << 23)) ? 0 : h; + + /* overflow: infinity; 143 encodes exponent 16 */ + h = (em >= (143 << 23)) ? 0x7c00 : h; + + /* NaN; note that we convert all types of NaN to qNaN */ + h = (em > (255 << 23)) ? 0x7e00 : h; + + return static_cast(s | h); +} + +float halfToFloat(uint16_t hval) { + union { + float f; + unsigned int ui; + } u; + + int s = (hval >> 15) & 0x00000001; + int em = hval & 0x00007fff; + int m = 0; + + if (em > 0) { + /* normalized */ + if (em > 30 << 10) { + /* overflow: infinity */ + em = 255 << 23; + } else { + em = (em + (112 << 10)) << 13; + } + } else { + /* denormalized */ + if (em > 25 << 10) { + /* underflow: flush to zero */ + em = 0; + } else { + em = (em + (113 << 10)) >> 1; + } + } + + u.ui = ((uint16_t)(s << 31)) | em | m; // NOLINT + return u.f; +} + } // namespace mathutils } // namespace cc diff --git a/native/cocos/math/Utils.h b/native/cocos/math/Utils.h index 909fd30f6eb..0e33763be6b 100644 --- a/native/cocos/math/Utils.h +++ b/native/cocos/math/Utils.h @@ -284,5 +284,9 @@ auto absMax(F a, F b) { return std::fabs(a) > std::fabs(b) ? a : b; } +uint16_t floatToHalf(float fval); + +float halfToFloat(uint16_t hval); + } // namespace mathutils } // namespace cc diff --git a/native/external-config.json b/native/external-config.json index 72909dbc542..9b92430ee9a 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-11" + "checkout": "v3.8.1-12" } -} +} \ No newline at end of file diff --git a/native/tests/unit-test/src/math_utils_test.cpp b/native/tests/unit-test/src/math_utils_test.cpp index db5cff1ca40..7f08b4381ce 100644 --- a/native/tests/unit-test/src/math_utils_test.cpp +++ b/native/tests/unit-test/src/math_utils_test.cpp @@ -22,6 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include +#include #include #include "cocos/math/Math.h" #include "cocos/math/MathUtil.h" diff --git a/platforms/native/engine/jsb-physics.js b/platforms/native/engine/jsb-physics.js index 8b92d375ea9..89a488659c1 100644 --- a/platforms/native/engine/jsb-physics.js +++ b/platforms/native/engine/jsb-physics.js @@ -675,7 +675,7 @@ class PlaneShape extends Shape { function getConvexMesh (v) { if (!jsbPhy.CACHE.convex[v._uuid]) { - const posArr = cc.physics.utils.shrinkPositions(v.readAttribute(0, 'a_position')); + const posArr = cc.physics.utils.shrinkPositions(v.renderingSubMeshes[0].geometricInfo.positions); const world = cc.PhysicsSystem.instance.physicsWorld.impl; const convex = { positions: new Float32Array(posArr), positionLength: posArr.length / 3 }; jsbPhy.CACHE.convex[v._uuid] = world.createConvex(convex); @@ -685,9 +685,8 @@ function getConvexMesh (v) { function getTriangleMesh (v) { if (!jsbPhy.CACHE.trimesh[v._uuid]) { - const indArr = v.readIndices(0); - // const posArr = cc.physics.utils.shrinkPositions(v.readAttribute(0, 'a_position')); - const posArr = v.readAttribute(0, 'a_position'); + const posArr = v.renderingSubMeshes[0].geometricInfo.positions; + const indArr = v.renderingSubMeshes[0].geometricInfo.indices; const world = cc.PhysicsSystem.instance.physicsWorld.impl; const trimesh = { positions: new Float32Array(posArr), diff --git a/tests/init.ts b/tests/init.ts index 4e43708972d..cf8e31fe718 100644 --- a/tests/init.ts +++ b/tests/init.ts @@ -109,6 +109,14 @@ jest.mock( ); }); +jest.mock('external:emscripten/meshopt/meshopt_decoder.wasm.js', + () => ({ + __esModule: true, + default: function factory () { return Promise.resolve({}); }, + }), + { virtual: true, }, +); + jest.mock( 'external:emscripten/physx/physx.release.asm.js', () => jest.requireActual('../native/external/emscripten/physx/physx.release.asm.js'), @@ -122,6 +130,12 @@ jest.mock( { virtual: true }, ); +jest.mock( + 'external:emscripten/meshopt/meshopt_decoder.asm.js', + () => jest.requireActual('../native/external/emscripten/meshopt/meshopt_decoder.asm.js'), + { virtual: true }, +); + jest.mock( 'external:emscripten/spine/spine.asm.js', () => jest.requireActual('../native/external/emscripten/spine/spine.asm.js'), diff --git a/tsconfig.json b/tsconfig.json index be0012eabd6..a5c25c11c69 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,6 +36,7 @@ "./native/external/emscripten/physx/physx", "./native/external/emscripten/webgpu/webgpu", "./native/external/emscripten/spine/spine", + "./native/external/emscripten/meshopt/meshopt_decoder", "./native/external/emscripten/box2d/box2d", // pal From 63668b2a10db6b9db2803a92efcba9a35e5bd797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=9F=E6=88=98?= <40414978+PatriceJiang@users.noreply.github.com> Date: Mon, 21 Aug 2023 10:48:32 +0800 Subject: [PATCH 153/184] remember connected gamepad count (#16023) --- pal/input/web/gamepad-input.ts | 92 +++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 34 deletions(-) diff --git a/pal/input/web/gamepad-input.ts b/pal/input/web/gamepad-input.ts index 2b6f6561ccb..7d20b9df2b2 100644 --- a/pal/input/web/gamepad-input.ts +++ b/pal/input/web/gamepad-input.ts @@ -72,6 +72,8 @@ type WebGamepad = Gamepad; const XRLeftHandedness = 'left'; const XRRightHandedness = 'right'; +const devicesTmp: GamepadInputDevice[] = []; + enum Pose { HAND_LEFT = 1, HAND_RIGHT = 4, @@ -85,7 +87,7 @@ interface IPoseValue { } interface IPoseInfo { - readonly code: number; + readonly code: Pose; readonly position: DOMPointReadOnly; readonly orientation: DOMPointReadOnly; } @@ -184,7 +186,7 @@ export class GamepadInputDevice { [Pose.HAND_RIGHT]: { position: Vec3.ZERO, orientation: Quat.IDENTITY }, [Pose.AIM_LEFT]: { position: Vec3.ZERO, orientation: Quat.IDENTITY }, [Pose.AIM_RIGHT]: { position: Vec3.ZERO, orientation: Quat.IDENTITY }, - } + }; constructor (deviceId: number) { this._deviceId = deviceId; @@ -216,7 +218,7 @@ export class GamepadInputDevice { js.array.fastRemoveAt(GamepadInputDevice.all, removeIndex); } private static _getOrCreateInputDevice (id: number, connected: boolean): GamepadInputDevice { - let device = GamepadInputDevice.all.find((device) => device.deviceId === id); + let device = GamepadInputDevice.all.find((device) => device.deviceId === id); if (!device) { device = new GamepadInputDevice(id); GamepadInputDevice.all.push(device); @@ -225,29 +227,36 @@ export class GamepadInputDevice { return device; } - private static _ensureDirectorDefined (): Promise { - return new Promise((resolve) => { - GamepadInputDevice._intervalId = setInterval(() => { - if (legacyCC.director && legacyCC.Director) { - clearInterval(GamepadInputDevice._intervalId); - GamepadInputDevice._intervalId = -1; - resolve(); - } - }, 50); - }); + private static _ensureDirectorDefined (callback: () => void): void { + GamepadInputDevice._intervalId = setInterval(() => { + if (legacyCC.director && legacyCC.Director) { + clearInterval(GamepadInputDevice._intervalId); + GamepadInputDevice._intervalId = -1; + callback(); + } + }, 50); + } + + private static _totalGamepadCnt = 0; + private static _updateGamepadCnt (): void { + GamepadInputDevice._totalGamepadCnt = GamepadInputDevice._cachedWebGamepads.reduce((total, gamepad) => (gamepad ? total + 1 : total), 0); } private static _registerEvent (): void { - GamepadInputDevice._ensureDirectorDefined().then(() => { + GamepadInputDevice._ensureDirectorDefined(() => { + GamepadInputDevice._cachedWebGamepads = GamepadInputDevice._getWebGamePads(); + GamepadInputDevice._updateGamepadCnt(); legacyCC.director.on(legacyCC.Director.EVENT_BEGIN_FRAME, GamepadInputDevice._scanGamepads); - }).catch((e) => {}); + }); window.addEventListener('gamepadconnected', (e) => { GamepadInputDevice._cachedWebGamepads[e.gamepad.index] = e.gamepad; + GamepadInputDevice._updateGamepadCnt(); const device = GamepadInputDevice._getOrCreateInputDevice(e.gamepad.index, true); GamepadInputDevice._eventTarget.emit(InputEventType.GAMEPAD_CHANGE, new EventGamepad(InputEventType.GAMEPAD_CHANGE, device)); }); window.addEventListener('gamepaddisconnected', (e) => { GamepadInputDevice._cachedWebGamepads[e.gamepad.index] = null; + GamepadInputDevice._updateGamepadCnt(); const device = GamepadInputDevice._getOrCreateInputDevice(e.gamepad.index, false); GamepadInputDevice._removeInputDevice(e.gamepad.index); GamepadInputDevice._eventTarget.emit(InputEventType.GAMEPAD_CHANGE, new EventGamepad(InputEventType.GAMEPAD_CHANGE, device)); @@ -255,12 +264,15 @@ export class GamepadInputDevice { } private static _scanWebGamepads (devices: GamepadInputDevice[]): void { + const allDisconnected = GamepadInputDevice._totalGamepadCnt === 0; + if (allDisconnected) return; + const webGamepads = GamepadInputDevice._getWebGamePads(); if (!webGamepads) { return; } for (let i = 0; i < webGamepads.length; ++i) { - const webGamepad = webGamepads?.[i]; + const webGamepad = webGamepads[i]; if (!webGamepad) { continue; } @@ -302,12 +314,12 @@ export class GamepadInputDevice { } private static _scanGamepads (): void { - const devices: GamepadInputDevice[] = []; - GamepadInputDevice._scanWebGamepads(devices); - GamepadInputDevice._scanWebXRGamepads(devices); + devicesTmp.length = 0; + GamepadInputDevice._scanWebGamepads(devicesTmp); + GamepadInputDevice._scanWebXRGamepads(devicesTmp); // emit event - for (let i = 0; i < devices.length; ++i) { - const device = devices[i]; + for (let i = 0; i < devicesTmp.length; ++i) { + const device = devicesTmp[i]; GamepadInputDevice._eventTarget.emit(InputEventType.GAMEPAD_INPUT, new EventGamepad(InputEventType.GAMEPAD_INPUT, device)); } GamepadInputDevice._scanWebXRGamepadsPose(); @@ -320,8 +332,10 @@ export class GamepadInputDevice { GamepadInputDevice._cachedWebXRGamepadMap = null; if (GamepadInputDevice.xr && GamepadInputDevice.xr._connected) { GamepadInputDevice.xr._connected = false; - GamepadInputDevice._eventTarget.emit(InputEventType.GAMEPAD_CHANGE, - new EventGamepad(InputEventType.GAMEPAD_CHANGE, GamepadInputDevice.xr)); + GamepadInputDevice._eventTarget.emit( + InputEventType.GAMEPAD_CHANGE, + new EventGamepad(InputEventType.GAMEPAD_CHANGE, GamepadInputDevice.xr), + ); devices.push(GamepadInputDevice.xr); } return; @@ -337,20 +351,28 @@ export class GamepadInputDevice { if (!left && !right) { if (GamepadInputDevice.xr._connected) { GamepadInputDevice.xr._connected = false; - GamepadInputDevice._eventTarget.emit(InputEventType.GAMEPAD_CHANGE, - new EventGamepad(InputEventType.GAMEPAD_CHANGE, GamepadInputDevice.xr)); + GamepadInputDevice._eventTarget.emit( + InputEventType.GAMEPAD_CHANGE, + new EventGamepad(InputEventType.GAMEPAD_CHANGE, GamepadInputDevice.xr), + ); } } else if (!GamepadInputDevice.xr._connected) { GamepadInputDevice.xr._connected = true; - GamepadInputDevice._eventTarget.emit(InputEventType.GAMEPAD_CHANGE, - new EventGamepad(InputEventType.GAMEPAD_CHANGE, GamepadInputDevice.xr)); + GamepadInputDevice._eventTarget.emit( + InputEventType.GAMEPAD_CHANGE, + new EventGamepad(InputEventType.GAMEPAD_CHANGE, GamepadInputDevice.xr), + ); } - if (GamepadInputDevice.checkGamepadChanged(left, - GamepadInputDevice._cachedWebXRGamepadMap?.get(XRLeftHandedness))) { + if (GamepadInputDevice.checkGamepadChanged( + left, + GamepadInputDevice._cachedWebXRGamepadMap?.get(XRLeftHandedness), + )) { devices.push(GamepadInputDevice.xr); - } else if (GamepadInputDevice.checkGamepadChanged(right, - GamepadInputDevice._cachedWebXRGamepadMap?.get(XRRightHandedness))) { + } else if (GamepadInputDevice.checkGamepadChanged( + right, + GamepadInputDevice._cachedWebXRGamepadMap?.get(XRRightHandedness), + )) { devices.push(GamepadInputDevice.xr); } @@ -417,8 +439,10 @@ export class GamepadInputDevice { const info = infoList[i]; GamepadInputDevice.xr._updateWebPoseState(info); } - GamepadInputDevice._eventTarget.emit(InputEventType.HANDLE_POSE_INPUT, - new EventGamepad(InputEventType.HANDLE_POSE_INPUT, GamepadInputDevice.xr)); + GamepadInputDevice._eventTarget.emit( + InputEventType.HANDLE_POSE_INPUT, + new EventGamepad(InputEventType.HANDLE_POSE_INPUT, GamepadInputDevice.xr), + ); } private static _getWebXRGamepadMap (): (Map | undefined) { @@ -459,7 +483,7 @@ export class GamepadInputDevice { private _updateWebPoseState (info: IPoseInfo): void { if (info.code !== Pose.HAND_LEFT && info.code !== Pose.AIM_LEFT - && info.code !== Pose.HAND_RIGHT && info.code !== Pose.AIM_RIGHT) { + && info.code !== Pose.HAND_RIGHT && info.code !== Pose.AIM_RIGHT) { return; } From cfd5dc998b8040184ce7582bedfde02da42fdb91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=A3=AE=E6=96=8C?= Date: Mon, 21 Aug 2023 10:59:03 +0800 Subject: [PATCH 154/184] add message protocol manager for node editing (#15963) * add message protocol manager * optimize switch message protocol when editing node * add optimize * again --- .../components/batched-skinning-model.js | 10 +- .../components/light-probe-group-footer.js | 17 +-- .../inspector/components/lod-group/index.js | 18 +-- .../components/lod-group/lod-item.js | 3 +- .../components/lod-group/multi-lod-group.js | 3 +- .../components/particle-system-2d.js | 4 +- .../inspector/components/particle-system.js | 10 +- .../inspector/components/polygon-collider.js | 10 +- editor/inspector/components/terrain.js | 9 +- editor/inspector/contributions/node.js | 132 ++++++++++++------ editor/inspector/utils/prop.js | 26 ++++ 11 files changed, 157 insertions(+), 85 deletions(-) diff --git a/editor/inspector/components/batched-skinning-model.js b/editor/inspector/components/batched-skinning-model.js index 6067c7d1448..ef0ad382a07 100644 --- a/editor/inspector/components/batched-skinning-model.js +++ b/editor/inspector/components/batched-skinning-model.js @@ -1,5 +1,7 @@ const { template, $, update, close } = require('./base'); +const { getMessageProtocolScene } = require('../utils/prop'); + exports.template = template; exports.$ = $; exports.update = update; @@ -22,9 +24,9 @@ exports.ready = function() { $button.addEventListener('confirm', async () => { const uuids = this.dump.value.uuid.values || [this.dump.value.uuid.value]; - const undoID = await Editor.Message.request('scene', 'begin-recording', uuids); + const undoID = await Editor.Message.request(getMessageProtocolScene(this.$this), 'begin-recording', uuids); for (const uuid of uuids) { - await Editor.Message.request('scene', 'execute-component-method', { + await Editor.Message.request(getMessageProtocolScene(this.$this), 'execute-component-method', { uuid: uuid, name: 'cook', args: [], @@ -32,12 +34,12 @@ exports.ready = function() { } for (const uuid of uuids) { - await Editor.Message.request('scene', 'execute-component-method', { + await Editor.Message.request(getMessageProtocolScene(this.$this), 'execute-component-method', { uuid: uuid, name: 'combine', args: [], }); } - await Editor.Message.request('scene', 'end-recording', undoID); + await Editor.Message.request(getMessageProtocolScene(this.$this), 'end-recording', undoID); }); }; diff --git a/editor/inspector/components/light-probe-group-footer.js b/editor/inspector/components/light-probe-group-footer.js index 6ebcc7e25de..a7947207448 100644 --- a/editor/inspector/components/light-probe-group-footer.js +++ b/editor/inspector/components/light-probe-group-footer.js @@ -1,4 +1,5 @@ const { trackEventWithTimer } = require('../utils/metrics'); +const { getMessageProtocolScene } = require('../utils/prop'); exports.template = `
@@ -41,10 +42,10 @@ exports.update = async function(dump) { panel.dump = dump; } - const mode = await Editor.Message.request('scene', 'query-light-probe-edit-mode'); + const mode = await Editor.Message.request(getMessageProtocolScene(this.$this), 'query-light-probe-edit-mode'); panel.changeProbeMode(mode); - const boxMode = await Editor.Message.request('scene', 'query-light-probe-bounding-box-edit-mode'); + const boxMode = await Editor.Message.request(getMessageProtocolScene(this.$this), 'query-light-probe-bounding-box-edit-mode'); panel.changeProbeBoxMode(boxMode); }; @@ -61,14 +62,14 @@ exports.ready = function() { if (result.response === 0) { // 先关闭盒子模式 if (panel.sceneProbeBoxMode) { - await Editor.Message.request('scene', 'toggle-light-probe-bounding-box-edit-mode', !panel.sceneProbeBoxMode); + await Editor.Message.request(getMessageProtocolScene(this.$this), 'toggle-light-probe-bounding-box-edit-mode', !panel.sceneProbeBoxMode); } const uuidObject = panel.dump.value.uuid; const uuids = uuidObject.values ? uuidObject.values : [uuidObject.value]; - const undoID = await Editor.Message.request('scene', 'begin-recording', uuids); + const undoID = await Editor.Message.request(getMessageProtocolScene(this.$this), 'begin-recording', uuids); for (const uuid of uuids) { - Editor.Message.send('scene', 'execute-component-method', { + Editor.Message.send(getMessageProtocolScene(this.$this), 'execute-component-method', { uuid: uuid, name: 'generateLightProbes', args: [], @@ -77,12 +78,12 @@ exports.ready = function() { trackEventWithTimer('bakingSystem', 'A100006'); - await Editor.Message.request('scene', 'end-recording', undoID); + await Editor.Message.request(getMessageProtocolScene(this.$this), 'end-recording', undoID); } }); panel.$.edit.addEventListener('confirm', async () => { - await Editor.Message.request('scene', 'toggle-light-probe-edit-mode', !panel.sceneProbeMode); + await Editor.Message.request(getMessageProtocolScene(this.$this), 'toggle-light-probe-edit-mode', !panel.sceneProbeMode); trackEventWithTimer('bakingSystem', 'A100008'); }); @@ -90,7 +91,7 @@ exports.ready = function() { Editor.Message.addBroadcastListener('scene:light-probe-edit-mode-changed', panel.changeProbeModeBind); panel.$.box.addEventListener('confirm', async () => { - await Editor.Message.request('scene', 'toggle-light-probe-bounding-box-edit-mode', !panel.sceneProbeBoxMode); + await Editor.Message.request(getMessageProtocolScene(this.$this), 'toggle-light-probe-bounding-box-edit-mode', !panel.sceneProbeBoxMode); trackEventWithTimer('bakingSystem', 'A100007'); }); diff --git a/editor/inspector/components/lod-group/index.js b/editor/inspector/components/lod-group/index.js index 3fab395def8..ae9aea727aa 100644 --- a/editor/inspector/components/lod-group/index.js +++ b/editor/inspector/components/lod-group/index.js @@ -5,6 +5,7 @@ const { join } = require('path'); const lodItem = require('./lod-item'); const multiLodGroup = require('./multi-lod-group'); const { trackEventWithTimer } = require('../../utils/metrics'); +const { getMessageProtocolScene } = require('../../utils/prop'); module.paths.push(join(Editor.App.path, 'node_modules')); const Vue = require('vue/dist/vue.min.js'); @@ -236,7 +237,7 @@ exports.ready = function() { }, recalculateBounds() { const that = this; - Editor.Message.send('scene', 'execute-component-method', { + Editor.Message.send(getMessageProtocolScene(that.$el), 'execute-component-method', { uuid: that.dump.value.uuid.value, name: 'recalculateBounds', args: [], @@ -245,7 +246,7 @@ exports.ready = function() { }, resetObjectSize() { const that = this; - Editor.Message.send('scene', 'execute-component-method', { + Editor.Message.send(getMessageProtocolScene(that.$el), 'execute-component-method', { uuid: that.dump.value.uuid.value, name: 'resetObjectSize', args: [], @@ -264,21 +265,20 @@ exports.ready = function() { } const preValue = LODs[index].value.screenUsagePercentage.value; const nextValue = LODs[index + 1] ? LODs[index + 1].value.screenUsagePercentage.value : 0; - const undoID = await Editor.Message.request('scene', 'begin-recording', uuid); - await Editor.Message.request('scene', 'lod-insert', uuid, index + 1, (preValue + nextValue) / 2, null); - await Editor.Message.request('scene', 'end-recording', undoID); + const undoID = await Editor.Message.request(getMessageProtocolScene(that.$el), 'begin-recording', uuid); + await Editor.Message.request(getMessageProtocolScene(that.$el), 'lod-insert', uuid, index + 1, (preValue + nextValue) / 2, null); + await Editor.Message.request(getMessageProtocolScene(that.$el), 'end-recording', undoID); trackEventWithTimer('LOD', 'A100005'); } else if (operator === 'delete') { if (LODs.length === 1) { console.warn('At least one LOD, Can\'t delete any more'); return; } - const undoID = await Editor.Message.request('scene', 'begin-recording', uuid); - await Editor.Message.request('scene', 'lod-erase', uuid, index); - await Editor.Message.request('scene', 'end-recording', undoID); + const undoID = await Editor.Message.request(getMessageProtocolScene(that.$el), 'begin-recording', uuid); + await Editor.Message.request(getMessageProtocolScene(that.$el), 'lod-erase', uuid, index); + await Editor.Message.request(getMessageProtocolScene(that.$el), 'end-recording', undoID); trackEventWithTimer('LOD', 'A100006'); } - // Editor.Message.send('scene', 'snapshot'); }, }, }); diff --git a/editor/inspector/components/lod-group/lod-item.js b/editor/inspector/components/lod-group/lod-item.js index 999d7af91e4..d7e53836e55 100644 --- a/editor/inspector/components/lod-group/lod-item.js +++ b/editor/inspector/components/lod-group/lod-item.js @@ -1,6 +1,7 @@ 'use strict'; const { trackEventWithTimer } = require('../../utils/metrics'); +const { getMessageProtocolScene } = require('../../utils/prop'); exports.template = ` @@ -162,7 +163,7 @@ exports.methods = { }, async applyCameraSize() { const that = this; - let size = await Editor.Message.request('scene', 'lod-apply-current-camera-size', that.dump.value.uuid.value); + let size = await Editor.Message.request(getMessageProtocolScene(that.$el), 'lod-apply-current-camera-size', that.dump.value.uuid.value); if (that.$refs[that.screenUsagePercentageRef]) { const min = Editor.Utils.Math.divide(that.$refs[that.screenUsagePercentageRef].min, 100) || 0; let max = null; diff --git a/editor/inspector/components/lod-group/multi-lod-group.js b/editor/inspector/components/lod-group/multi-lod-group.js index 345574e2784..6976820fe6c 100644 --- a/editor/inspector/components/lod-group/multi-lod-group.js +++ b/editor/inspector/components/lod-group/multi-lod-group.js @@ -1,6 +1,7 @@ 'use strict'; const { trackEventWithTimer } = require('../../utils/metrics'); +const { getMessageProtocolScene } = require('../../utils/prop'); exports.template = `
@@ -114,7 +115,7 @@ exports.methods = { resetMultiObjectSize() { const that = this; that.dump.value.uuid.values.forEach((uuid) => { - Editor.Message.send('scene', 'execute-component-method', { + Editor.Message.send(getMessageProtocolScene(that.$el), 'execute-component-method', { uuid: uuid, name: 'resetObjectSize', args: [], diff --git a/editor/inspector/components/particle-system-2d.js b/editor/inspector/components/particle-system-2d.js index 45891d6e851..ce18062877c 100644 --- a/editor/inspector/components/particle-system-2d.js +++ b/editor/inspector/components/particle-system-2d.js @@ -1,4 +1,6 @@ const { template, $, update, close } = require('./base'); +const { getMessageProtocolScene } = require('../utils/prop'); + // 排列时,相邻元素的间隔间距 const MARGIN = '4px'; @@ -110,7 +112,7 @@ exports.ready = function() { $export.addEventListener('confirm', async (event) => { event.stopPropagation(); - let assetInfo = await Editor.Message.request('scene', 'export-particle-plist', this.dump.value.uuid.value); + let assetInfo = await Editor.Message.request(getMessageProtocolScene(this.$this), 'export-particle-plist', this.dump.value.uuid.value); if (assetInfo) { let values = [this.$this.dump.value]; if (this.$this.dump.values) { diff --git a/editor/inspector/components/particle-system.js b/editor/inspector/components/particle-system.js index 76a2cb3491f..b2a62d5d5cc 100644 --- a/editor/inspector/components/particle-system.js +++ b/editor/inspector/components/particle-system.js @@ -249,12 +249,12 @@ const uiElements = { const componentUUIDs = this.dump.value.uuid.values || [this.dump.value.uuid.value]; await Promise.all(componentUUIDs.map(uuid => { return new Promise((res) => { - Editor.Message.request('scene', 'execute-component-method', { + Editor.Message.request(propUtils.getMessageProtocolScene(this.$this), 'execute-component-method', { uuid, name: '_calculateBounding', args: [true], }).then(() => { - Editor.Message.request('scene', 'execute-component-method', { + Editor.Message.request(propUtils.getMessageProtocolScene(this.$this), 'execute-component-method', { uuid, name: 'gizmo.onNodeChanged', args: [], @@ -390,7 +390,7 @@ const uiElements = { this.$.showBounds.addEventListener('change', (event) => { const componentUUIDs = this.dump.value.uuid.values || [this.dump.value.uuid.value]; componentUUIDs.forEach(uuid => { - Editor.Message.send('scene', 'execute-component-method', { + Editor.Message.send(propUtils.getMessageProtocolScene(this.$this), 'execute-component-method', { uuid, name: 'gizmo.showBoundingBox', args: [event.target.value], @@ -407,7 +407,7 @@ const uiElements = { const componentUUIDs = this.dump.value.uuid.values || [this.dump.value.uuid.value]; const values = await Promise.all( componentUUIDs.map( - uuid => Editor.Message.request('scene', 'execute-component-method', { + uuid => Editor.Message.request(propUtils.getMessageProtocolScene(this.$this), 'execute-component-method', { uuid, name: 'gizmo.isShowBoundingBox', args: [], @@ -609,7 +609,7 @@ const uiElements = { if (!this.dump?.value?.uuid?.values && !this.dump?.value?.uuid?.value) { return; } let uuid = this.dump.value.uuid.values ? this.dump.value.uuid.values[0] : this.dump.value.uuid.value; if (!uuid) { return; } - let data = await Editor.Message.request('scene', 'execute-component-method', { + let data = await Editor.Message.request(propUtils.getMessageProtocolScene(this.$this), 'execute-component-method', { uuid, name: 'getNoisePreview', args: [100, 100], diff --git a/editor/inspector/components/polygon-collider.js b/editor/inspector/components/polygon-collider.js index e1811c7032c..6dae007c1fb 100644 --- a/editor/inspector/components/polygon-collider.js +++ b/editor/inspector/components/polygon-collider.js @@ -1,4 +1,5 @@ const { template, $, update, close } = require('./base'); +const { getMessageProtocolScene } = require('../utils/prop'); exports.template = template; exports.$ = $; @@ -21,20 +22,17 @@ exports.ready = function() { $button.addEventListener('change', (event) => { event.stopPropagation(); - // Editor.Message.send('scene', 'snapshot'); }); $button.addEventListener('confirm', async (event) => { event.stopPropagation(); const uuids = this.dump.value.uuid.values || [this.dump.value.uuid.value]; - const undoID = await Editor.Message.request('scene', 'begin-recording', uuids); + const undoID = await Editor.Message.request(getMessageProtocolScene(this.$this), 'begin-recording', uuids); for (const uuid of uuids) { - await Editor.Message.request('scene', 'regenerate-polygon-2d-points', uuid); + await Editor.Message.request(getMessageProtocolScene(this.$this), 'regenerate-polygon-2d-points', uuid); } - await Editor.Message.request('scene', 'end-recording', undoID); - - // Editor.Message.send('scene', 'snapshot'); + await Editor.Message.request(getMessageProtocolScene(this.$this), 'end-recording', undoID); }); }, }, diff --git a/editor/inspector/components/terrain.js b/editor/inspector/components/terrain.js index a4462d09b06..5b98f15a6a3 100644 --- a/editor/inspector/components/terrain.js +++ b/editor/inspector/components/terrain.js @@ -5,23 +5,22 @@ exports.$ = $; exports.update = update; exports.close = close; -const { setHidden } = require('../utils/prop'); +const { setHidden, getMessageProtocolScene } = require('../utils/prop'); exports.ready = function() { this.elements = { _asset: { ready(element) { element.addEventListener('change-dump', async (event) => { - // Editor.Message.send('scene', 'snapshot'); const uuid = this.dump.value.uuid.value; const dump = event.target.dump; - const undoID = await Editor.Message.request('scene', 'begin-recording', uuid); - Editor.Message.request('scene', 'execute-component-method', { + const undoID = await Editor.Message.request(getMessageProtocolScene(this.$this), 'begin-recording', uuid); + Editor.Message.request(getMessageProtocolScene(this.$this), 'execute-component-method', { uuid: this.dump.value.uuid.value, name: 'manager.addAssetToComp', args: [dump.value], }); - await Editor.Message.request('scene', 'end-recording', undoID); + await Editor.Message.request(getMessageProtocolScene(this.$this), 'end-recording', undoID); }); }, }, diff --git a/editor/inspector/contributions/node.js b/editor/inspector/contributions/node.js index cba64780a8c..7ddbbbec836 100644 --- a/editor/inspector/contributions/node.js +++ b/editor/inspector/contributions/node.js @@ -2,11 +2,17 @@ const fs = require('fs'); const path = require('path'); module.paths.push(path.join(Editor.App.path, 'node_modules')); +const Profile = require('@base/electron-profile'); const { throttle } = require('lodash'); const utils = require('./utils'); const { trackEventWithTimer } = require('../utils/metrics'); const { injectionStyle } = require('../utils/prop'); +// ipc messages protocol +const messageProtocol = { + scene: 'scene', +}; + const lockList = []; let lockPerform = false; let lastSnapShot = null; @@ -53,16 +59,16 @@ function snapshotLock(panel, lock, uuids, cancel = false) { // 不传options时,会自动记录到undo队列,不需要调用endRecording async function beginRecording(uuids, options) { if (!uuids) { return; } - const undoID = await Editor.Message.request('scene', 'begin-recording', uuids, options); + const undoID = await Editor.Message.request(messageProtocol.scene, 'begin-recording', uuids, options); return undoID; } async function endRecording(undoID, cancel) { if (!undoID) { return; } if (cancel) { - await Editor.Message.request('scene', 'cancel-recording', undoID); + await Editor.Message.request(messageProtocol.scene, 'cancel-recording', undoID); } else { - await Editor.Message.request('scene', 'end-recording', undoID); + await Editor.Message.request(messageProtocol.scene, 'end-recording', undoID); } } @@ -133,7 +139,7 @@ exports.listeners = { } if (setChildrenLayer) { - await Editor.Message.request('scene', 'set-node-and-children-layer', { + await Editor.Message.request(messageProtocol.scene, 'set-node-and-children-layer', { uuid, dump: { value, @@ -143,7 +149,7 @@ exports.listeners = { continue; } - await Editor.Message.request('scene', 'set-property', { + await Editor.Message.request(messageProtocol.scene, 'set-property', { uuid, path, dump: { @@ -167,7 +173,6 @@ exports.listeners = { clearTimeout(panel.previewTimeId); snapshotLock(panel, false); // In combination with change-dump, snapshot only generated once after ui-elements continuously changed. - // Editor.Message.send('scene', 'snapshot'); }, async 'create-dump'(event) { const panel = this; @@ -179,7 +184,6 @@ exports.listeners = { clearTimeout(panel.previewTimeId); - // Editor.Message.send('scene', 'snapshot'); const undoID = await beginRecording(panel.uuidList); const dump = target.dump; let cancel = false; @@ -190,13 +194,12 @@ exports.listeners = { dump.values[i] = dump.value; } - await Editor.Message.request('scene', 'update-property-from-null', { + await Editor.Message.request(messageProtocol.scene, 'update-property-from-null', { uuid, path: dump.path, }); } - // Editor.Message.send('scene', 'snapshot'); } catch (error) { cancel = true; console.error(error); @@ -222,7 +225,7 @@ exports.listeners = { dump.values[i] = dump.value; } - await Editor.Message.request('scene', 'reset-property', { + await Editor.Message.request(messageProtocol.scene, 'reset-property', { uuid, path: dump.path, }); @@ -277,7 +280,7 @@ exports.listeners = { // 预览新的值 value.uuid = assetUuid; - Editor.Message.send('scene', 'preview-set-property', { + Editor.Message.send(messageProtocol.scene, 'preview-set-property', { uuid, path, dump: { @@ -297,7 +300,7 @@ exports.listeners = { const uuid = panel.uuidList[i]; const { path } = dump; - Editor.Message.send('scene', 'cancel-preview-set-property', { + Editor.Message.send(messageProtocol.scene, 'cancel-preview-set-property', { uuid, path, }); @@ -527,6 +530,21 @@ const Elements = { Editor.Message.addBroadcastListener('project:setting-change', panel.__projectSettingChanged__); + panel.__throttleProfileChanged__ = throttle(async (protocol, file, key) => { + if (protocol === 'defaultPreferences' && file === 'packages/inspector.json' && key === 'message-protocol') { + await panel.__queryMessageProtocolScene__(); + + for (const prop in Elements) { + const element = Elements[prop]; + if (element.update) { + await element.update.call(panel); + } + } + } + }, 100, { leading: false, trailing: true }); + + Profile.on('change', panel.__throttleProfileChanged__); + // 识别拖入脚本资源 panel.$.container.addEventListener('dragover', (event) => { event.preventDefault(); @@ -587,7 +605,7 @@ const Elements = { try { dumps = await Promise.all( panel.uuidList.map((uuid) => { - return Editor.Message.request('scene', 'query-node', uuid); + return Editor.Message.request(messageProtocol.scene, 'query-node', uuid); }), ); } catch (err) { @@ -628,6 +646,10 @@ const Elements = { Editor.Message.removeBroadcastListener('scene:change-node', panel.__nodeChanged__); Editor.Message.removeBroadcastListener('scene:animation-time-change', panel.__animationTimeChange__); Editor.Message.removeBroadcastListener('project:setting-change', panel.__projectSettingChanged__); + + Profile.removeListener('change', panel.__throttleProfileChanged__); + panel.__throttleProfileChanged__.cancel(); + panel.__throttleProfileChanged__ = undefined; }, }, prefab: { @@ -656,7 +678,7 @@ const Elements = { break; } case 'unlink': { - await Editor.Message.request('scene', 'unlink-prefab', prefab.rootUuid, false); + await Editor.Message.request(messageProtocol.scene, 'unlink-prefab', prefab.rootUuid, false); break; } case 'local': { @@ -664,12 +686,12 @@ const Elements = { break; } case 'reset': { - await Editor.Message.request('scene', 'restore-prefab', prefab.rootUuid, prefab.uuid); + await Editor.Message.request(messageProtocol.scene, 'restore-prefab', prefab.rootUuid, prefab.uuid); break; } case 'save': { // apply-prefab是自定义的undo,在场景中实现了undo - await Editor.Message.request('scene', 'apply-prefab', prefab.rootUuid); + await Editor.Message.request(messageProtocol.scene, 'apply-prefab', prefab.rootUuid); break; } } @@ -967,13 +989,13 @@ const Elements = { // DIFFUSEMAP_WITH_REFLECTION 的枚举值为 2 if (envLightingType === 2) { - await Editor.Message.request('scene', 'execute-scene-script', { + await Editor.Message.request(messageProtocol.scene, 'execute-scene-script', { name: 'inspector', method: 'generateDiffuseMap', args: [envMapUuid], }); } else { - await Editor.Message.request('scene', 'execute-scene-script', { + await Editor.Message.request(messageProtocol.scene, 'execute-scene-script', { name: 'inspector', method: 'generateVector', args: [envMapUuid], @@ -981,13 +1003,13 @@ const Elements = { } }, async setEnvMapAndConvolutionMap(uuid) { - await Editor.Message.request('scene', 'execute-scene-script', { + await Editor.Message.request(messageProtocol.scene, 'execute-scene-script', { name: 'inspector', method: 'setSkyboxEnvMap', args: [uuid], }); if (uuid) { - await Editor.Message.request('scene', 'execute-scene-script', { + await Editor.Message.request(messageProtocol.scene, 'execute-scene-script', { name: 'inspector', method: 'setReflectionConvolutionMap', args: [uuid], @@ -1026,7 +1048,7 @@ const Elements = { panel.$.sceneSkyboxReflectionLoading.style.display = 'inline-flex'; panel.$.sceneSkyboxReflectionBake.style.display = 'none'; - await Editor.Message.request('scene', 'execute-scene-script', { + await Editor.Message.request(messageProtocol.scene, 'execute-scene-script', { name: 'inspector', method: 'bakeReflectionConvolution', args: [envMapData.value.uuid], @@ -1314,6 +1336,7 @@ const Elements = { $section.appendChild($panel); $section.__panels__.push($panel); $panel.dump = component; + $panel.messageProtocol = messageProtocol; $panel.update(component); }); @@ -1341,6 +1364,8 @@ const Elements = { panel.$.nodeSection.appendChild(array[index]); } array[index].setAttribute('src', file); + array[index].dump = panel.dump; + array[index].messageProtocol = messageProtocol; array[index].update(panel.dump); }); @@ -1408,11 +1433,11 @@ const Elements = { const uuidList = panel.uuidList; switch (type) { case 'save-o': { - Editor.Message.request('scene', 'apply-removed-component', uuidList[0], info.fileID); + Editor.Message.request(messageProtocol.scene, 'apply-removed-component', uuidList[0], info.fileID); break; } case 'reset': { - Editor.Message.request('scene', 'revert-removed-component', uuidList[0], info.fileID); + Editor.Message.request(messageProtocol.scene, 'revert-removed-component', uuidList[0], info.fileID); break; } } @@ -1498,7 +1523,7 @@ const Elements = { // 批量调用request意味着编辑操作在很多帧后才会完成,所以不能自动记录undo const undoID = await beginRecording(panel.uuidList); for (const uuid of panel.uuidList) { - await Editor.Message.request('scene', 'create-component', { + await Editor.Message.request(messageProtocol.scene, 'create-component', { uuid, component: detail.info.cid, }); @@ -1643,7 +1668,7 @@ exports.methods = { } } - Editor.Message.send('scene', cmd); + Editor.Message.send(messageProtocol.scene, cmd); }, /** @@ -1697,7 +1722,7 @@ exports.methods = { const values = dump.value.uuid.values || [dump.value.uuid.value]; const undoID = await beginRecording(values); for (const compUuid of values) { - await Editor.Message.request('scene', 'reset-component', { + await Editor.Message.request(messageProtocol.scene, 'reset-component', { uuid: compUuid, }); } @@ -1728,7 +1753,7 @@ exports.methods = { if (!uuids.length > 0) { return; } const undoID = await beginRecording(uuids); for (let i = 0; i < uuids.length; i++) { - await Editor.Message.request('scene', 'remove-array-element', { + await Editor.Message.request(messageProtocol.scene, 'remove-array-element', { uuid: uuids[i], path: '__comps__', index: indexes[i], @@ -1742,7 +1767,7 @@ exports.methods = { enabled: !isMultiple && index !== 0, async click() { const undoID = await beginRecording(uuid); - await Editor.Message.request('scene', 'move-array-element', { + await Editor.Message.request(messageProtocol.scene, 'move-array-element', { uuid, path: '__comps__', target: index, @@ -1756,7 +1781,7 @@ exports.methods = { enabled: !isMultiple && index !== total - 1, async click() { const undoID = await beginRecording(uuid); - await Editor.Message.request('scene', 'move-array-element', { + await Editor.Message.request(messageProtocol.scene, 'move-array-element', { uuid, path: '__comps__', target: index, @@ -1802,7 +1827,7 @@ exports.methods = { const index = indexes[i]; const nodeDump = nodeDumps.find(nodeDump => uuid === nodeDump.uuid.value); - await Editor.Message.request('scene', 'set-property', { + await Editor.Message.request(messageProtocol.scene, 'set-property', { uuid, path: nodeDump.__comps__[index].path, dump: clipboardComponentInfo.dump, @@ -1822,20 +1847,20 @@ exports.methods = { let index = 0; for (const dump of values) { const uuid = uuidList[index]; - await Editor.Message.request('scene', 'create-component', { + await Editor.Message.request(messageProtocol.scene, 'create-component', { uuid, component: clipboardComponentInfo.cid, }); // 检查是否创建成功,是的话,给赋值 - const nodeDump = await Editor.Message.request('scene', 'query-node', uuid); + const nodeDump = await Editor.Message.request(messageProtocol.scene, 'query-node', uuid); const length = nodeDump.__comps__ && nodeDump.__comps__.length; if (length) { const lastIndex = length - 1; const lastComp = nodeDump.__comps__[lastIndex]; if (lastComp?.cid === clipboardComponentInfo.cid) { - await Editor.Message.request('scene', 'set-property', { + await Editor.Message.request(messageProtocol.scene, 'set-property', { uuid, path: `__comps__.${lastIndex}`, dump: clipboardComponentInfo.dump, @@ -1876,7 +1901,7 @@ exports.methods = { async click() { const undoID = await beginRecording(uuidList); for (const uuid of uuidList) { - await Editor.Message.request('scene', 'reset-node', { + await Editor.Message.request(messageProtocol.scene, 'reset-node', { uuid, }); } @@ -1902,7 +1927,7 @@ exports.methods = { const undoID = await beginRecording(uuidList); for (const uuid of uuidList) { for (const attr of clipboardNodeInfo.attrs) { - await Editor.Message.request('scene', 'set-property', { + await Editor.Message.request(messageProtocol.scene, 'set-property', { uuid, path: attr, dump: clipboardNodeInfo.dump[attr], @@ -1917,7 +1942,7 @@ exports.methods = { label: Editor.I18n.t('ENGINE.menu.copy_node_world_transform'), enabled: !isMultiple, async click() { - const data = await Editor.Message.request('scene', 'execute-scene-script', { + const data = await Editor.Message.request(messageProtocol.scene, 'execute-scene-script', { name: 'inspector', method: 'queryNodeWorldTransform', args: [dump.uuid.value], @@ -1937,7 +1962,7 @@ exports.methods = { if (clipboardNodeWorldTransform.data) { const undoID = await beginRecording(uuidList); for (const uuid of uuidList) { - await Editor.Message.request('scene', 'execute-scene-script', { + await Editor.Message.request(messageProtocol.scene, 'execute-scene-script', { name: 'inspector', method: 'setNodeWorldTransform', args: [uuid, clipboardNodeWorldTransform.data], @@ -1954,20 +1979,20 @@ exports.methods = { async click() { const undoID = await beginRecording(uuidList); for (const uuid of uuidList) { - await Editor.Message.request('scene', 'create-component', { + await Editor.Message.request(messageProtocol.scene, 'create-component', { uuid, component: clipboardComponentInfo.cid, }); // 检查是否创建成功,是的话,给赋值 - const nodeDump = await Editor.Message.request('scene', 'query-node', uuid); + const nodeDump = await Editor.Message.request(messageProtocol.scene, 'query-node', uuid); const length = nodeDump.__comps__ && nodeDump.__comps__.length; if (length) { const lastIndex = length - 1; const lastComp = nodeDump.__comps__[lastIndex]; if (lastComp?.cid === clipboardComponentInfo.cid) { - await Editor.Message.request('scene', 'set-property', { + await Editor.Message.request(messageProtocol.scene, 'set-property', { uuid, path: `__comps__.${lastIndex}`, dump: clipboardComponentInfo.dump, @@ -1985,7 +2010,7 @@ exports.methods = { async click() { const undoID = await beginRecording(uuidList); for (const uuid of uuidList) { - await Editor.Message.request('scene', 'reset-property', { + await Editor.Message.request(messageProtocol.scene, 'reset-property', { uuid, path: 'position', }); @@ -1999,7 +2024,7 @@ exports.methods = { async click() { const undoID = await beginRecording(uuidList); for (const uuid of uuidList) { - await Editor.Message.request('scene', 'reset-property', { + await Editor.Message.request(messageProtocol.scene, 'reset-property', { uuid, path: 'rotation', }); @@ -2013,7 +2038,7 @@ exports.methods = { async click() { const undoID = await beginRecording(uuidList); for (const uuid of uuidList) { - await Editor.Message.request('scene', 'reset-property', { + await Editor.Message.request(messageProtocol.scene, 'reset-property', { uuid, path: 'scale', }); @@ -2027,7 +2052,7 @@ exports.methods = { async click() { const undoID = await beginRecording(uuidList); for (const uuid of uuidList) { - await Editor.Message.request('scene', 'reset-property', { + await Editor.Message.request(messageProtocol.scene, 'reset-property', { uuid, path: 'mobility', }); @@ -2052,7 +2077,7 @@ exports.methods = { const dumpData = materialUuids[assetUuid][dumpPath]; for (let i = 0; i < panel.uuidList.length; i++) { const nodeUuid = panel.uuidList[i]; - await Editor.Message.request('scene', 'set-property', { + await Editor.Message.request(messageProtocol.scene, 'set-property', { uuid: nodeUuid, path: dumpPath, dump: { @@ -2110,6 +2135,23 @@ exports.ready = async function ready() { // 为了避免把 ui-num-input, ui-color 的连续 change 进行 snapshot panel.snapshotLock = false; + // 节点的 ipc 协议,指向 scene 或 xr-scene 等进程 + panel.__queryMessageProtocolScene__ = async function() { + try { + if (!panel.messageProtocol) { + panel.messageProtocol = messageProtocol; + } + const config = await await Editor.Profile.getConfig('inspector', 'message-protocol'); + if (config) { + Object.assign(messageProtocol, config); + } + } catch (error) { + console.error(error); + messageProtocol.scene = 'scene'; + } + }; + await panel.__queryMessageProtocolScene__(); + for (const prop in Elements) { const element = Elements[prop]; if (element.ready) { diff --git a/editor/inspector/utils/prop.js b/editor/inspector/utils/prop.js index 6a7a0ad9692..ec76e9f7d52 100644 --- a/editor/inspector/utils/prop.js +++ b/editor/inspector/utils/prop.js @@ -184,6 +184,32 @@ exports.setHidden = function(data, element) { } }; +// In order to avoid a large number of operations in a short time, the function of returning the same operation result in a time period is added +let getMessageProtocolSceneResult = ''; +let getMessageProtocolSceneStartTime = Date.now(); +exports.getMessageProtocolScene = function(element) { + if (getMessageProtocolSceneResult && Date.now() - getMessageProtocolSceneStartTime < 1000) { + return getMessageProtocolSceneResult; + } + + getMessageProtocolSceneResult = ''; + getMessageProtocolSceneStartTime = Date.now(); + + while (element) { + element = element.parentElement || element.getRootNode().host; + if (element && element.messageProtocol) { + getMessageProtocolSceneResult = element.messageProtocol.scene; + break; + } + } + + if (!getMessageProtocolSceneResult) { + getMessageProtocolSceneResult = 'scene'; + } + + return getMessageProtocolSceneResult; +}; + exports.updatePropByDump = function(panel, dump) { panel.dump = dump; From 22c5bbc175d7d22c5b650edecf75bd8e642feb6f Mon Sep 17 00:00:00 2001 From: zxx43 Date: Mon, 21 Aug 2023 11:28:56 +0800 Subject: [PATCH 155/184] add a lot of missed functions for spine jsb (#16027) * add a lot of missed functions for spine jsb * change conversion type to number * check type is a number * change toNumber to toDouble --- .../cocos/bindings/manual/jsb_conversions.h | 30 +++++++++++ native/tools/swig-config/spine.i | 51 +++++++++++++++++-- 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/native/cocos/bindings/manual/jsb_conversions.h b/native/cocos/bindings/manual/jsb_conversions.h index 9170e2ce8f4..580dbfb4d44 100644 --- a/native/cocos/bindings/manual/jsb_conversions.h +++ b/native/cocos/bindings/manual/jsb_conversions.h @@ -1441,6 +1441,36 @@ bool sevalue_to_native(const se::Value &v, spine::Vector *ret, se::Object * return true; } + +template >> +bool sevalue_to_native(const se::Value &v, spine::Vector *ret, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming) + CC_ASSERT_NOT_NULL(ret); + CC_ASSERT(v.isObject()); + se::Object *obj = v.toObject(); + CC_ASSERT(obj->isArray()); + + bool ok = true; + uint32_t len = 0; + ok = obj->getArrayLength(&len); + if (!ok) { + ret->clear(); + return false; + } + + se::Value tmp; + for (uint32_t i = 0; i < len; ++i) { + ok = obj->getArrayElement(i, &tmp); + if (!ok || !tmp.isNumber()) { + ret->clear(); + return false; + } + + T nativeObj = static_cast(tmp.toDouble()); + ret->add(nativeObj); + } + + return true; +} #endif // CC_USE_SPINE /////////////////// shorter form diff --git a/native/tools/swig-config/spine.i b/native/tools/swig-config/spine.i index 9ffeb32ccbf..c8fa9127528 100644 --- a/native/tools/swig-config/spine.i +++ b/native/tools/swig-config/spine.i @@ -40,7 +40,6 @@ using namespace spine; // 1. 'Ignore Section' should be placed before attribute definition and %import/%include // 2. namespace is needed // -%ignore spine::MathUtil; %ignore cc::RefCounted; %ignore *::rtti; %ignore spine::SkeletonCache::SegmentData; @@ -48,6 +47,7 @@ using namespace spine; %ignore spine::SkeletonCache::FrameData; %ignore spine::SkeletonCache::AnimationData; %ignore spine::Skin::AttachmentMap::getEntries; +%ignore spine::AttachmentLoader::getRTTI; %ignore spine::Polygon::Polygon; %ignore spine::Polygon::_vertices; @@ -137,6 +137,13 @@ using namespace spine; %ignore spine::Bone::updateWorldTransform(float, float, float, float, float, float, float); %ignore spine::Skin::findAttachmentsForSlot; %ignore spine::SkeletonBinary::readSkeletonData(const unsigned char*, int); +%ignore spine::AttachmentLoader::newRegionAttachment(Skin&, const String&, const String&); +%ignore spine::AttachmentLoader::newMeshAttachment(Skin&, const String&, const String&); +%ignore spine::AttachmentLoader::newBoundingBoxAttachment(Skin&, const String&); +%ignore spine::AttachmentLoader::newPathAttachment(Skin&, const String&); +%ignore spine::AttachmentLoader::newPointAttachment(Skin&, const String&); +%ignore spine::AttachmentLoader::newClippingAttachment(Skin&, const String&); +%ignore spine::TextureLoader::load(AtlasPage&, const String&); // ----- Rename Section ------ // Brief: Classes, methods or attributes needs to be renamed @@ -205,6 +212,8 @@ using namespace spine; %rename(name) spine::Skin::AttachmentMap::Entry::_name; %rename(attachment) spine::Skin::AttachmentMap::Entry::_attachment; %rename(signum) spine::MathUtil::sign(float); +%rename(TextureAtlasPage) spine::AtlasPage; +%rename(TextureAtlasRegion) spine::AtlasRegion; // ----- Module Macro Section ------ // Brief: Generated code should be wrapped inside a macro @@ -407,7 +416,7 @@ using namespace spine; %attribute(spine::Skeleton, float, x, getX, setX); %attribute(spine::Skeleton, float, y, getY, setY); -%attribute(spine::SkeletonBinary, float, scale, setScale); +%attribute_writeonly(spine::SkeletonBinary, float, scale, setScale); %attribute(spine::SkeletonClipping, spine::Vector&, clippedVertices, getClippedVertices); %attribute(spine::SkeletonClipping, spine::Vector&, clippedTriangles, getClippedTriangles); @@ -594,6 +603,10 @@ using namespace spine; %include "editor-support/spine/SkeletonBounds.h" %include "editor-support/spine/SkeletonData.h" %include "editor-support/spine/SlotData.h" +%include "editor-support/spine/SkeletonBinary.h" +%include "editor-support/spine/AttachmentLoader.h" +%include "editor-support/spine/Atlas.h" +%include "editor-support/spine/TextureLoader.h" %include "editor-support/spine/TransformConstraint.h" %include "editor-support/spine/TransformConstraintData.h" @@ -750,11 +763,43 @@ using namespace spine; } %extend spine::SkeletonBinary { - SkeletonData *readSkeletonData(const std::vector& binary) { + spine::SkeletonData *readSkeletonData(const std::vector& binary) { std::vector input; for (int i = 0; i < binary.size(); ++i) { input.push_back(binary[i]); } return $self->readSkeletonData(input.data(), input.size()); } +} + +%extend spine::AttachmentLoader { + spine::RegionAttachment* newRegionAttachment(spine::Skin* skin, const spine::String& name, const spine::String& path) { + return $self->newRegionAttachment(*skin, name, path); + } + + spine::MeshAttachment* newMeshAttachment(spine::Skin* skin, const spine::String& name, const spine::String& path) { + return $self->newMeshAttachment(*skin, name, path); + } + + spine::BoundingBoxAttachment* newBoundingBoxAttachment(spine::Skin* skin, const spine::String& name) { + return $self->newBoundingBoxAttachment(*skin, name); + } + + spine::PathAttachment* newPathAttachment(spine::Skin* skin, const spine::String& name) { + return $self->newPathAttachment(*skin, name); + } + + spine::PointAttachment* newPointAttachment(spine::Skin* skin, const spine::String& name) { + return $self->newPointAttachment(*skin, name); + } + + spine::ClippingAttachment* newClippingAttachment(spine::Skin* skin, const spine::String& name) { + return $self->newClippingAttachment(*skin, name); + } +} + +%extend spine::TextureLoader { + void load(spine::AtlasPage* page, const spine::String& path) { + $self->load(*page, path); + } } \ No newline at end of file From ba93769911dbbd3b50e68c3bd093ea2d29c82658 Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Mon, 21 Aug 2023 12:01:27 +0800 Subject: [PATCH 156/184] fix mask change sprite size mode Bug (#16047) --- cocos/2d/components/mask.ts | 79 ++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/cocos/2d/components/mask.ts b/cocos/2d/components/mask.ts index afaf7dfb44a..a01247055d4 100644 --- a/cocos/2d/components/mask.ts +++ b/cocos/2d/components/mask.ts @@ -23,9 +23,10 @@ THE SOFTWARE. */ -import { ccclass, help, executionOrder, menu, tooltip, displayOrder, type, visible, serializable, range, slide, executeInEditMode } from 'cc.decorator'; +import { ccclass, help, executionOrder, menu, tooltip, displayOrder, + type, visible, serializable, range, slide, executeInEditMode } from 'cc.decorator'; import { JSB } from 'internal:constants'; -import { clamp, Color, Mat4, Vec2, Vec3, warnID, cclegacy, ccenum } from '../../core'; +import { clamp, Color, Mat4, Vec2, Vec3, warnID, cclegacy, ccenum, error } from '../../core'; import { Graphics } from './graphics'; import { TransformBit } from '../../scene-graph/node-enum'; import { Stage } from '../renderer/stencil-manager'; @@ -35,6 +36,7 @@ import { Sprite } from './sprite'; import { NodeEventType, Component } from '../../scene-graph'; import type { SpriteFrame } from '../assets'; import type { Material } from '../../asset/assets'; +import { MaterialInstance } from '../../render-scene'; const _worldMatrix = new Mat4(); const _vec2_temp = new Vec2(); @@ -45,8 +47,12 @@ function _calculateCircle (center: Vec3, radius: Vec3, segments: number): Vec3[] _circlePoints.length = 0; const anglePerStep = Math.PI * 2 / segments; for (let step = 0; step < segments; ++step) { - _circlePoints.push(new Vec3(radius.x * Math.cos(anglePerStep * step) + center.x, - radius.y * Math.sin(anglePerStep * step) + center.y, 0)); + _circlePoints.push(new Vec3( + radius.x * Math.cos(anglePerStep * step) + center.x, + radius.y * Math.sin(anglePerStep * step) + center.y, + + 0, + )); } return _circlePoints; @@ -224,7 +230,7 @@ export class Mask extends Component { if (this._sprite) { this._sprite.spriteFrame = value; } else { - console.error('please change type to sprite_stencil first'); + error('please change type to sprite_stencil first'); } } @@ -377,8 +383,6 @@ export class Mask extends Component { const node = this.node; sprite = this._sprite = node.addComponent(Sprite); } - sprite.color = Color.WHITE.clone(); - sprite.sizeMode = 0; } this._sprite!.stencilStage = this.inverted ? Stage.ENTER_LEVEL_INVERTED : Stage.ENTER_LEVEL; this._sprite!.updateMaterial(); @@ -463,7 +467,8 @@ export class Mask extends Component { // deprecated interface /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ get customMaterial (): Material | null { warnID(9007); @@ -479,7 +484,8 @@ export class Mask extends Component { } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ get color (): Color | null { warnID(9007); @@ -495,7 +501,8 @@ export class Mask extends Component { } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public markForUpdateRenderData (enable = true): void { warnID(9007); @@ -504,20 +511,23 @@ export class Mask extends Component { } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public requestRenderData (any): void { warnID(9007); } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public destroyRenderData (): void { warnID(9007); } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public updateRenderer (): void { warnID(9007); @@ -527,19 +537,22 @@ export class Mask extends Component { } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public fillBuffers (render: any): void { warnID(9007); } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public postUpdateAssembler (render: any): void { warnID(9007); } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public setNodeDirty (): void { warnID(9007); @@ -548,7 +561,8 @@ export class Mask extends Component { } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public setTextureDirty (): void { warnID(9007); @@ -557,7 +571,8 @@ export class Mask extends Component { } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ get sharedMaterial (): Material | null { warnID(9007); @@ -567,7 +582,8 @@ export class Mask extends Component { return null; } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ get sharedMaterials (): (Material | null)[] | null { warnID(9007); @@ -583,7 +599,8 @@ export class Mask extends Component { } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ get material (): any { warnID(9007); @@ -599,7 +616,8 @@ export class Mask extends Component { } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ get materials (): (any)[] { warnID(9007); @@ -615,7 +633,8 @@ export class Mask extends Component { } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public getMaterial (idx: number): any { warnID(9007); @@ -625,16 +644,18 @@ export class Mask extends Component { return null; } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ - public setMaterial (material: any, index: number): void { + public setMaterial (material: Material | MaterialInstance | null, index: number): void { warnID(9007); if (this.subComp) { this.subComp.setMaterial(material, index); } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public getMaterialInstance (idx: number): any { warnID(9007); @@ -644,16 +665,18 @@ export class Mask extends Component { return null; } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ - public setMaterialInstance (matInst: any, index: number): void { + public setMaterialInstance (matInst: Material | MaterialInstance | null, index: number): void { warnID(9007); if (this.subComp) { this.subComp.setMaterialInstance(matInst, index); } } /** - * @deprecated Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation + * @deprecated Since v3.6, Because mask changes the inheritance relationship, + * you can directly manipulate the rendering components under the same node to complete the operation */ public getRenderMaterial (index: number): any { warnID(9007); From 20dd273ea7ac3d1d41c1db80c4c6ca351dd48223 Mon Sep 17 00:00:00 2001 From: Canvas Date: Mon, 21 Aug 2023 13:34:44 +0800 Subject: [PATCH 157/184] fix spine wasm api. (#16004) * fix spine wasm api. * fix code format. * remove new api. * remove private function. * add setSlotsRange return type. * add setSlotsRange parameter type. * fix setUV. * Fix code description problem. * remove new api $ fix complete listeners. * fix bone setter. * fix code format. * fix code format. * fix code format. * fix bind api. * remove test code. * fix code format. * add api any ignore. * update external-config checkout to v3.8.1-14. --- cocos/spine/lib/spine-core.d.ts | 211 +-- cocos/spine/lib/spine-define.ts | 170 ++- cocos/spine/skeleton.ts | 96 +- .../editor-support/spine-wasm/CMakeLists.txt | 4 +- .../spine-wasm/spine-skeleton-instance.cpp | 2 +- .../spine-wasm/spine-type-export.cpp | 1198 ++++++++++------- native/external-config.json | 2 +- 7 files changed, 992 insertions(+), 691 deletions(-) diff --git a/cocos/spine/lib/spine-core.d.ts b/cocos/spine/lib/spine-core.d.ts index acce177ea13..49265a616e7 100644 --- a/cocos/spine/lib/spine-core.d.ts +++ b/cocos/spine/lib/spine-core.d.ts @@ -21,18 +21,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/* eslint @typescript-eslint/no-explicit-any: "off" */ declare namespace spine { class Animation { + constructor(name: string, timelines: Array, duration: number); + duration: number; name: string; timelines: Array; - timelineIds: Array; - duration: number; - constructor(name: string, timelines: Array, duration: number); - hasTimeline(id: number): boolean; apply(skeleton: Skeleton, lastTime: number, time: number, loop: boolean, events: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; - static binarySearch(values: ArrayLike, target: number, step?: number): number; - static linearSearch(values: ArrayLike, target: number, step: number): number; + hasTimeline(id: number): boolean; } interface Timeline { apply(skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; @@ -66,11 +64,10 @@ declare namespace spine { twoColor = 14 } abstract class CurveTimeline implements Timeline { - static LINEAR: number; - static STEPPED: number; - static BEZIER: number; - static BEZIER_SIZE: number; - private curves; + static readonly LINEAR: number; + static readonly STEPPED: number; + static readonly BEZIER: number; + static readonly BEZIER_SIZE: number; abstract getPropertyId(): number; constructor(frameCount: number); getFrameCount(): number; @@ -94,13 +91,7 @@ declare namespace spine { apply(skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; } class TranslateTimeline extends CurveTimeline { - static ENTRIES: number; - static PREV_TIME: number; - static PREV_X: number; - static PREV_Y: number; - static X: number; - static Y: number; - boneIndex: number; + static readonly ENTRIES: number; frames: ArrayLike; constructor(frameCount: number); getPropertyId(): number; @@ -119,43 +110,23 @@ declare namespace spine { } class ColorTimeline extends CurveTimeline { static ENTRIES: number; - static PREV_TIME: number; - static PREV_R: number; - static PREV_G: number; - static PREV_B: number; - static PREV_A: number; - static R: number; - static G: number; - static B: number; - static A: number; slotIndex: number; frames: ArrayLike; constructor(frameCount: number); getPropertyId(): number; + getSlotIndex(): number; + setSlotIndex(inValue: number): void; setFrame(frameIndex: number, time: number, r: number, g: number, b: number, a: number): void; apply(skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; } class TwoColorTimeline extends CurveTimeline { - static ENTRIES: number; - static PREV_TIME: number; - static PREV_R: number; - static PREV_G: number; - static PREV_B: number; - static PREV_A: number; - static PREV_R2: number; - static PREV_G2: number; - static PREV_B2: number; - static R: number; - static G: number; - static B: number; - static A: number; - static R2: number; - static G2: number; - static B2: number; + static readonly ENTRIES: number; slotIndex: number; frames: ArrayLike; constructor(frameCount: number); getPropertyId(): number; + getSlotIndex(): number; + setSlotIndex(inValue: number): void; setFrame(frameIndex: number, time: number, r: number, g: number, b: number, a: number, r2: number, g2: number, b2: number): void; apply(skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; } @@ -166,9 +137,11 @@ declare namespace spine { constructor(frameCount: number); getPropertyId(): number; getFrameCount(): number; + getSlotIndex(): number; + setSlotIndex(inValue: number): void; + getAttachmentNames(): Array; setFrame(frameIndex: number, time: number, attachmentName: string): void; apply(skeleton: Skeleton, lastTime: number, time: number, events: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; - setAttachment(skeleton: Skeleton, slot: Slot, attachmentName: string): void; } class DeformTimeline extends CurveTimeline { slotIndex: number; @@ -198,20 +171,8 @@ declare namespace spine { setFrame(frameIndex: number, time: number, drawOrder: Array): void; apply(skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; } - class IkConstraintTimeline extends CurveTimeline { - static ENTRIES: number; - static PREV_TIME: number; - static PREV_MIX: number; - static PREV_SOFTNESS: number; - static PREV_BEND_DIRECTION: number; - static PREV_COMPRESS: number; - static PREV_STRETCH: number; - static MIX: number; - static SOFTNESS: number; - static BEND_DIRECTION: number; - static COMPRESS: number; - static STRETCH: number; - ikConstraintIndex: number; + class IkConstraintTimeline extends Updatable { + static readonly ENTRIES: number; frames: ArrayLike; constructor(frameCount: number); getPropertyId(): number; @@ -220,29 +181,13 @@ declare namespace spine { } class TransformConstraintTimeline extends CurveTimeline { static ENTRIES: number; - static PREV_TIME: number; - static PREV_ROTATE: number; - static PREV_TRANSLATE: number; - static PREV_SCALE: number; - static PREV_SHEAR: number; - static ROTATE: number; - static TRANSLATE: number; - static SCALE: number; - static SHEAR: number; - transformConstraintIndex: number; - frames: ArrayLike; constructor(frameCount: number); getPropertyId(): number; setFrame(frameIndex: number, time: number, rotateMix: number, translateMix: number, scaleMix: number, shearMix: number): void; apply(skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; } class PathConstraintPositionTimeline extends CurveTimeline { - static ENTRIES: number; - static PREV_TIME: number; - static PREV_VALUE: number; - static VALUE: number; - pathConstraintIndex: number; - frames: ArrayLike; + static readonly ENTRIES: number; constructor(frameCount: number); getPropertyId(): number; setFrame(frameIndex: number, time: number, value: number): void; @@ -254,13 +199,7 @@ declare namespace spine { apply(skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; } class PathConstraintMixTimeline extends CurveTimeline { - static ENTRIES: number; - static PREV_TIME: number; - static PREV_ROTATE: number; - static PREV_TRANSLATE: number; - static ROTATE: number; - static TRANSLATE: number; - pathConstraintIndex: number; + static readonly ENTRIES: number; frames: ArrayLike; constructor(frameCount: number); getPropertyId(): number; @@ -268,36 +207,17 @@ declare namespace spine { apply(skeleton: Skeleton, lastTime: number, time: number, firedEvents: Array, alpha: number, blend: MixBlend, direction: MixDirection): void; } class AnimationState { - static emptyAnimation: Animation; - static SUBSEQUENT: number; - static FIRST: number; - static HOLD_SUBSEQUENT: number; - static HOLD_FIRST: number; - static HOLD_MIX: number; - static SETUP: number; - static CURRENT: number; data: AnimationStateData; tracks: TrackEntry[]; timeScale: number; - unkeyedState: number; - events: Event[]; - listeners: AnimationStateListener[]; - queue: EventQueue; - propertyIDs: IntSet; - animationsChanged: boolean; - trackEntryPool: Pool; constructor(data: AnimationStateData); update(delta: number): void; - updateMixingFrom(to: TrackEntry, delta: number): boolean; apply(skeleton: Skeleton): boolean; - applyMixingFrom(to: TrackEntry, skeleton: Skeleton, blend: MixBlend): number; applyAttachmentTimeline(timeline: AttachmentTimeline, skeleton: Skeleton, time: number, blend: MixBlend, attachments: boolean): void; setAttachment(skeleton: Skeleton, slot: Slot, attachmentName: string, attachments: boolean): void; applyRotateTimeline(timeline: Timeline, skeleton: Skeleton, time: number, alpha: number, blend: MixBlend, timelinesRotation: Array, i: number, firstFrame: boolean): void; - queueEvents(entry: TrackEntry, animationTime: number): void; clearTracks(): void; clearTrack(trackIndex: number): void; - setCurrent(index: number, current: TrackEntry, interrupt: boolean): void; setAnimation(trackIndex: number, animationName: string, loop: boolean): TrackEntry; setAnimationWith(trackIndex: number, animation: Animation, loop: boolean): TrackEntry; addAnimation(trackIndex: number, animationName: string, loop: boolean, delay: number): TrackEntry; @@ -305,16 +225,10 @@ declare namespace spine { setEmptyAnimation(trackIndex: number, mixDuration: number): TrackEntry; addEmptyAnimation(trackIndex: number, mixDuration: number, delay: number): TrackEntry; setEmptyAnimations(mixDuration: number): void; - expandToIndex(index: number): TrackEntry; trackEntry(trackIndex: number, animation: Animation, loop: boolean, last: TrackEntry): TrackEntry; - disposeNext(entry: TrackEntry): void; - _animationsChanged(): void; - computeHold(entry: TrackEntry): void; getCurrent(trackIndex: number): TrackEntry; - addListener(listener: AnimationStateListener): void; - removeListener(listener: AnimationStateListener): void; + setListener(listener: AnimationStateListener): void; clearListeners(): void; - clearListenerNotifications(): void; } class TrackEntry { animation: Animation; @@ -480,7 +394,6 @@ declare namespace spine { getWorldRotationY(): number; getWorldScaleX(): number; getWorldScaleY(): number; - updateAppliedTransform(): void; worldToLocal(world: Vector2): Vector2; localToWorld(local: Vector2): Vector2; worldToLocalRotation(worldRotation: number): number; @@ -501,7 +414,6 @@ declare namespace spine { shearY: number; transformMode: TransformMode; skinRequired: boolean; - color: Color; constructor(index: number, name: string, parent: BoneData); } enum TransformMode { @@ -588,10 +500,6 @@ declare namespace spine { isActive(): boolean; apply(): void; update(): void; - computeWorldPositions(path: PathAttachment, spacesCount: number, tangents: boolean, percentPosition: boolean, percentSpacing: boolean): number[]; - addBeforePosition(p: number, temp: Array, i: number, out: Array, o: number): void; - addAfterPosition(p: number, temp: Array, i: number, out: Array, o: number): void; - addCurvePosition(p: number, x1: number, y1: number, cx1: number, cy1: number, cx2: number, cy2: number, x2: number, y2: number, out: Array, o: number, tangents: boolean): void; } class PathConstraintData extends ConstraintData { bones: BoneData[]; @@ -657,13 +565,6 @@ declare namespace spine { y: number; constructor(data: SkeletonData); updateCache(): void; - sortIkConstraint(constraint: IkConstraint): void; - sortPathConstraint(constraint: PathConstraint): void; - sortTransformConstraint(constraint: TransformConstraint): void; - sortPathConstraintAttachment(skin: Skin, slotIndex: number, slotBone: Bone): void; - sortPathConstraintAttachmentWith(attachment: Attachment, slotBone: Bone): void; - sortBone(bone: Bone): void; - sortReset(bones: Array): void; updateWorldTransform(): void; setToSetupPose(): void; setBonesToSetupPose(): void; @@ -681,7 +582,7 @@ declare namespace spine { findIkConstraint(constraintName: string): IkConstraint; findTransformConstraint(constraintName: string): TransformConstraint; findPathConstraint(constraintName: string): PathConstraint; - getBounds(offset: Vector2, size: Vector2, temp?: Array): void; + //getBounds(offset: Vector2, size: Vector2, temp?: Array): void; update(delta: number): void; } class SkeletonBinary { @@ -719,15 +620,7 @@ declare namespace spine { setCurve(timeline: CurveTimeline, frameIndex: number, cx1: number, cy1: number, cx2: number, cy2: number): void; } class SkeletonBounds { - minX: number; - minY: number; - maxX: number; - maxY: number; - boundingBoxes: BoundingBoxAttachment[]; - polygons: ArrayLike[]; - private polygonPool; update(skeleton: Skeleton, updateAabb: boolean): void; - aabbCompute(): void; aabbContainsPoint(x: number, y: number): boolean; aabbIntersectsSegment(x1: number, y1: number, x2: number, y2: number): boolean; aabbIntersectsSkeleton(bounds: SkeletonBounds): boolean; @@ -745,6 +638,7 @@ declare namespace spine { private clipOutput; clippedVertices: number[]; clippedTriangles: number[]; + clippedUVs: number[]; private scratch; private clipAttachment; private clippingPolygons; @@ -753,8 +647,6 @@ declare namespace spine { clipEnd(): void; isClipping(): boolean; clipTriangles(vertices: ArrayLike, verticesLength: number, triangles: ArrayLike, trianglesLength: number, uvs: ArrayLike, light: Color, dark: Color, twoColor: boolean, strideFloat?: number, offsetV?: number, offsetI?: number): void; - clip(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, clippingArea: Array, output: Array): boolean; - static makeClockwise(polygon: ArrayLike): void; } class SkeletonData { name: string; @@ -820,12 +712,13 @@ declare namespace spine { setAttachment(slotIndex: number, name: string, attachment: Attachment): void; addSkin(skin: Skin): void; copySkin(skin: Skin): void; + findNamesForSlot(slotIndex: number, names: Array): void; + getBones(): Array; + getConstraints(): Array; getAttachment(slotIndex: number, name: string): Attachment; removeAttachment(slotIndex: number, name: string): void; getAttachments(): Array; getAttachmentsForSlot(slotIndex: number, attachments: Array): void; - clear(): void; - attachAll(skeleton: Skeleton, oldSkin: Skin): void; } class Slot { data: SlotData; @@ -933,16 +826,11 @@ declare namespace spine { translateMix: number; scaleMix: number; shearMix: number; - temp: Vector2; active: boolean; constructor(data: TransformConstraintData, skeleton: Skeleton); isActive(): boolean; apply(): void; update(): void; - applyAbsoluteWorld(): void; - applyRelativeWorld(): void; - applyAbsoluteLocal(): void; - applyRelativeLocal(): void; } class TransformConstraintData extends ConstraintData { bones: BoneData[]; @@ -1015,20 +903,28 @@ declare namespace spine { static rgb888ToColor(color: Color, value: number): void; } class MathUtils { - static PI: number; - static PI2: number; - static radiansToDegrees: number; - static radDeg: number; - static degreesToRadians: number; - static degRad: number; + static readonly PI: number; + static readonly PI2: number; + static readonly radiansToDegrees: number; + static readonly radDeg: number; + static readonly degreesToRadians: number; + static readonly degRad: number; + static abs(value: number): number; + static signum(value: number): number; static clamp(value: number, min: number, max: number): number; - static cosDeg(degrees: number): number; + static fmod(a: number, b: number): number; + static atan2(y: number, x: number): number; + static cos(radians: number): number; + static sin(radians: number): number; + static sqrt(value: number): number; + static acos(value: number): number; static sinDeg(degrees: number): number; - static signum(value: number): number; - static toInt(x: number): number; - static cbrt(x: number): number; + static cosDeg(degrees: number): number; + static isNan(value: number): number; + static random(): number; static randomTriangular(min: number, max: number): number; static randomTriangularWith(min: number, max: number, mode: number): number; + static pow(a: number, b: number): number; } abstract class Interpolation { protected abstract applyInternal(a: number): number; @@ -1103,7 +999,7 @@ declare namespace spine { } abstract class VertexEffect { begin(skeleton: Skeleton): void; - transform(position: Vector2, uv: Vector2, light: Color, dark: Color): void; + transform(x: number, y: number): void; end(): void; } // interface Math { @@ -1143,18 +1039,15 @@ declare namespace spine { Clipping = 6 } class BoundingBoxAttachment extends VertexAttachment { - color: Color; constructor(name: string); copy(): Attachment; } class ClippingAttachment extends VertexAttachment { endSlot: SlotData; - color: Color; constructor(name: string); copy(): Attachment; } class MeshAttachment extends VertexAttachment { - region: TextureRegion; path: string; regionUVs: ArrayLike; uvs: ArrayLike; @@ -1165,7 +1058,6 @@ declare namespace spine { hullLength: number; edges: Array; private parentMesh; - tempColor: Color; constructor(name: string); updateUVs(): void; getParentMesh(): MeshAttachment; @@ -1177,7 +1069,6 @@ declare namespace spine { lengths: Array; closed: boolean; constantSpeed: boolean; - color: Color; constructor(name: string); copy(): Attachment; } @@ -1185,7 +1076,6 @@ declare namespace spine { x: number; y: number; rotation: number; - color: Color; constructor(name: string); computeWorldPosition(bone: Bone, point: Vector2): Vector2; computeWorldRotation(bone: Bone): number; @@ -1248,7 +1138,6 @@ declare namespace spine { tempColor: Color; constructor(name: string); updateOffset(): void; - setRegion(region: TextureRegion): void; computeWorldVertices(bone: Bone, worldVertices: ArrayLike, offset: number, stride: number): void; copy(): Attachment; } @@ -1257,7 +1146,7 @@ declare namespace spine { jitterY: number; constructor(jitterX: number, jitterY: number); begin(skeleton: Skeleton): void; - transform(position: Vector2, uv: Vector2, light: Color, dark: Color): void; + transform(x: number, y: number): void; end(): void; } class SwirlEffect implements VertexEffect { @@ -1266,11 +1155,11 @@ declare namespace spine { centerY: number; radius: number; angle: number; - private worldX; - private worldY; + worldX; + worldY; constructor(radius: number, interpolation?: Interpolation); begin(skeleton: Skeleton): void; - transform(position: Vector2, uv: Vector2, light: Color, dark: Color): void; + transform(x: number, y: number): void; end(): void; } diff --git a/cocos/spine/lib/spine-define.ts b/cocos/spine/lib/spine-define.ts index 4ad387b7e28..447df050ff7 100644 --- a/cocos/spine/lib/spine-define.ts +++ b/cocos/spine/lib/spine-define.ts @@ -21,11 +21,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/* eslint @typescript-eslint/no-explicit-any: "off" */ import spine from './spine-core.js'; import { js } from '../../core'; -function overrideDefineArrayProp (prototype, getPropVector, name): void { +function overrideDefineArrayProp (prototype: any, getPropVector: any, name: string): void { Object.defineProperty(prototype, name, { get (): any[] { const array: any[] = []; @@ -41,7 +42,7 @@ function overrideDefineArrayProp (prototype, getPropVector, name): void { }); } -function overrideDefineArrayFunction (prototype, getPropVector, name): void { +function overrideDefineArrayFunction (prototype: any, getPropVector: any, name: string): void { Object.defineProperty(prototype, name, { value () { const array: any[] = []; @@ -151,60 +152,65 @@ function overrideProperty_BoneData (): void { proto: prototype, property: 'length', getter: prototype.getLength, + setter: prototype.setLength, }, { proto: prototype, property: 'x', getter: prototype.getX, + setter: prototype.setX, }, { proto: prototype, property: 'y', getter: prototype.getY, + setter: prototype.setY, }, { proto: prototype, property: 'rotation', getter: prototype.getRotation, + setter: prototype.setRotation, }, { proto: prototype, property: 'scaleX', getter: prototype.getScaleX, + setter: prototype.setScaleX, }, { proto: prototype, property: 'scaleY', getter: prototype.getScaleY, + setter: prototype.setScaleY, }, { proto: prototype, property: 'shearX', getter: prototype.getShearX, + setter: prototype.setShearX, }, { proto: prototype, property: 'shearY', getter: prototype.getShearY, + setter: prototype.setShearY, }, { proto: prototype, property: 'transformMode', getter: prototype.getTransformMode, + setter: prototype.setTransformMode, }, { proto: prototype, property: 'skinRequired', getter: prototype.getSkinRequired, + setter: prototype.setSkinRequired, }, - // { - // proto: spine.BoneData.prototype, - // property: 'color', - // getter: spine.BoneData.prototype.getProp_color, - // }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); } @@ -376,16 +382,19 @@ function overrideProperty_Event (): void { proto: prototype, property: 'intValue', getter: prototype.getIntValue, + setter: prototype.setIntValue, }, { proto: prototype, property: 'floatValue', getter: prototype.getFloatValue, + setter: prototype.setFloatValue, }, { proto: prototype, property: 'stringValue', getter: prototype.getStringValue, + setter: prototype.setStringValue, }, { proto: prototype, @@ -396,15 +405,17 @@ function overrideProperty_Event (): void { proto: prototype, property: 'volume', getter: prototype.getVolume, + setter: prototype.setVolume, }, { proto: prototype, property: 'balance', getter: prototype.getBalance, + setter: prototype.setBalance, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); } @@ -420,35 +431,78 @@ function overrideProperty_EventData (): void { proto: prototype, property: 'intValue', getter: prototype.getIntValue, + setter: prototype.setIntValue, }, { proto: prototype, property: 'floatValue', getter: prototype.getFloatValue, + setter: prototype.setFloatValue, }, { proto: prototype, property: 'stringValue', getter: prototype.getStringValue, + setter: prototype.setStringValue, }, { proto: prototype, property: 'audioPath', getter: prototype.getAudioPath, + setter: prototype.setAudioPath, }, { proto: prototype, property: 'volume', getter: prototype.getVolume, + setter: prototype.setVolume, }, { proto: prototype, property: 'balance', getter: prototype.getBalance, + setter: prototype.setBalance, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); + }); +} + +function overrideProperty_VertexAttachment (): void { + const prototype = spine.VertexAttachment.prototype as any; + const propertyPolyfills = [ + { + proto: prototype, + property: 'id', + getter: prototype.getId, + setter: prototype.setId, + }, + { + proto: prototype, + property: 'bones', + getter: prototype.getBones, + }, + { + proto: prototype, + property: 'vertices', + getter: prototype.getVertices, + }, + { + proto: prototype, + property: 'worldVerticesLength', + getter: prototype.getWorldVerticesLength, + setter: prototype.setWorldVerticesLength, + }, + { + proto: prototype, + property: 'deformAttachment', + getter: prototype.getDeformAttachment, + setter: prototype.setDeformAttachment, + }, + ]; + propertyPolyfills.forEach((prop): void => { + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); } @@ -473,10 +527,11 @@ function overrideProperty_ClippingAttachment (): void { proto: prototype, property: 'endSlot', getter: prototype.getEndSlot, + setter: prototype.setEndSlot, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); } @@ -487,6 +542,7 @@ function overrideProperty_MeshAttachment (): void { proto: prototype, property: 'path', getter: prototype.getPath, + setter: prototype.setPath, }, { proto: prototype, @@ -496,7 +552,7 @@ function overrideProperty_MeshAttachment (): void { { proto: prototype, property: 'uvs', - getter: prototype.getUvs, + getter: prototype.getUVs, }, { proto: prototype, @@ -512,16 +568,19 @@ function overrideProperty_MeshAttachment (): void { proto: prototype, property: 'width', getter: prototype.getWidth, + setter: prototype.setWidth, }, { proto: prototype, property: 'height', getter: prototype.getHeight, + setter: prototype.setHeight, }, { proto: prototype, property: 'hullLength', getter: prototype.getHullLength, + setter: prototype.setHullLength, }, { proto: prototype, @@ -530,7 +589,7 @@ function overrideProperty_MeshAttachment (): void { }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); } @@ -541,11 +600,13 @@ function overrideProperty_PathAttachment (): void { proto: prototype, property: 'closed', getter: prototype.getClosed, + setter: prototype.setClosed, }, { proto: prototype, property: 'constantSpeed', getter: prototype.getConstantSpeed, + setter: prototype.setConstantSpeed, }, ]; propertyPolyfills.forEach((prop): void => { @@ -561,20 +622,23 @@ function overrideProperty_PointAttachment (): void { proto: prototype, property: 'x', getter: prototype.getX, + setter: prototype.setX, }, { proto: prototype, property: 'y', getter: prototype.getY, + setter: prototype.setY, }, { proto: prototype, property: 'rotation', getter: prototype.getRotation, + setter: prototype.setRotation, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); } @@ -585,36 +649,43 @@ function overrideProperty_RegionAttachment (): void { proto: prototype, property: 'x', getter: prototype.getX, + setter: prototype.setX, }, { proto: prototype, property: 'y', getter: prototype.getY, + setter: prototype.setY, }, { proto: prototype, property: 'scaleX', getter: prototype.getScaleX, + setter: prototype.setScaleX, }, { proto: prototype, property: 'scaleY', getter: prototype.getScaleY, + setter: prototype.setScaleY, }, { proto: prototype, property: 'rotation', getter: prototype.getRotation, + setter: prototype.setRotation, }, { proto: prototype, property: 'width', getter: prototype.getWidth, + setter: prototype.setWidth, }, { proto: prototype, property: 'height', getter: prototype.getHeight, + setter: prototype.setHeight, }, { proto: prototype, @@ -625,17 +696,13 @@ function overrideProperty_RegionAttachment (): void { proto: prototype, property: 'path', getter: prototype.getPath, + setter: prototype.setPath, }, { proto: prototype, property: 'rendererObject', getter: prototype.getRendererObject, }, - // { - // proto: prototype, - // property: 'region', - // getter: prototype.getProp_region, - // }, { proto: prototype, property: 'offset', @@ -645,10 +712,11 @@ function overrideProperty_RegionAttachment (): void { proto: prototype, property: 'uvs', getter: prototype.getUVs, + setter: prototype.setUVs, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); } @@ -703,10 +771,11 @@ function overrideProperty_SlotData (): void { proto: prototype, property: 'blendMode', getter: prototype.getBlendMode, + setter: prototype.setBlendMode, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); } @@ -910,30 +979,35 @@ function overrideProperty_TransformConstraint (): void { proto: prototype, property: 'rotateMix', getter: prototype.getRotateMix, + setter: prototype.setRotateMix, }, { proto: prototype, property: 'translateMix', getter: prototype.getTranslateMix, + setter: prototype.setTranslateMix, }, { proto: prototype, property: 'scaleMix', getter: prototype.getScaleMix, + setter: prototype.setScaleMix, }, { proto: prototype, property: 'shearMix', getter: prototype.getShearMix, + setter: prototype.setShearMix, }, { proto: prototype, property: 'active', getter: prototype.getActive, + setter: prototype.setActive, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); overrideDefineArrayProp(prototype, prototype.getBones, 'bones'); } @@ -1092,6 +1166,24 @@ function overrideProperty_Bone (): void { propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); + + const worldToLocal = prototype.worldToLocal; + Object.defineProperty(prototype, 'worldToLocal', { + value (vec2: spine.Vector2) { + const vectors = worldToLocal.call(this, vec2.x, vec2.y); + vec2.x = vectors.get(0); + vec2.y = vectors.get(1); + }, + }); + + const localToWorld = prototype.localToWorld; + Object.defineProperty(prototype, 'localToWorld', { + value (vec2: spine.Vector2) { + const vectors = localToWorld.call(this, vec2.x, vec2.y); + vec2.x = vectors.get(0); + vec2.y = vectors.get(1); + }, + }); } function overrideProperty_Slot (): void { @@ -1155,6 +1247,17 @@ function overrideProperty_Skin (): void { } }, }); + const originFindNamesForSlot = prototype.findNamesForSlot; + Object.defineProperty(prototype, 'findNamesForSlot', { + value (slotIndex: number, names: Array) { + const vectors = originFindNamesForSlot.call(this, slotIndex); + const count = vectors.size(); + for (let i = 0; i < count; i++) { + const objPtr = vectors.get(i); + names.push(objPtr); + } + }, + }); } function overrideProperty_SkinEntry (): void { @@ -1191,8 +1294,8 @@ function overrideProperty_SkeletonClipping (): void { }, { proto: prototype, - property: 'UVs', - getter: prototype.getUVs, + property: 'clippedUVs', + getter: prototype.getClippedUVs, }, ]; propertyPolyfills.forEach((prop): void => { @@ -1212,55 +1315,65 @@ function overrideProperty_SkeletonData (): void { proto: prototype, property: 'defaultSkin', getter: prototype.getDefaultSkin, + setter: prototype.setDefaultSkin, }, { proto: prototype, property: 'x', getter: prototype.getX, + setter: prototype.setX, }, { proto: prototype, property: 'y', getter: prototype.getY, + setter: prototype.setY, }, { proto: prototype, property: 'width', getter: prototype.getWidth, + setter: prototype.setWidth, }, { proto: prototype, property: 'height', getter: prototype.getHeight, + setter: prototype.setHeight, }, { proto: prototype, property: 'version', getter: prototype.getVersion, + setter: prototype.setVersion, }, { proto: prototype, property: 'hash', getter: prototype.getHash, + setter: prototype.setHash, }, { proto: prototype, property: 'fps', getter: prototype.getFps, + setter: prototype.setFps, }, { proto: prototype, property: 'imagesPath', getter: prototype.getImagesPath, + setter: prototype.setImagesPath, }, { proto: prototype, property: 'audioPath', getter: prototype.getAudioPath, + setter: prototype.setAudioPath, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); overrideDefineArrayProp(prototype, prototype.getBones, 'bones'); @@ -1601,25 +1714,29 @@ function overrideProperty_Skeleton (): void { proto: prototype, property: 'scaleX', getter: prototype.getScaleX, + setter: prototype.setScaleX, }, { proto: prototype, property: 'scaleY', getter: prototype.getScaleY, + setter: prototype.setScaleY, }, { proto: prototype, property: 'x', getter: prototype.getX, + setter: prototype.setX, }, { proto: prototype, property: 'y', getter: prototype.getY, + setter: prototype.setY, }, ]; propertyPolyfills.forEach((prop): void => { - js.getset(prop.proto, prop.property, prop.getter); + js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); overrideDefineArrayProp(prototype, prototype.getBones, 'bones'); @@ -1698,6 +1815,7 @@ export function overrideSpineDefine (wasm): void { overrideProperty_PathAttachment(); overrideProperty_PointAttachment(); overrideProperty_RegionAttachment(); + overrideProperty_VertexAttachment(); overrideProperty_TextureAtlas(); overrideProperty_SlotData(); overrideProperty_IkConstraint(); diff --git a/cocos/spine/skeleton.ts b/cocos/spine/skeleton.ts index 08c61481ddd..90c375bb127 100644 --- a/cocos/spine/skeleton.ts +++ b/cocos/spine/skeleton.ts @@ -51,7 +51,7 @@ const CUSTOM_SLOT_TEXTURE_BEGIN = 10000; let _slotTextureID = CUSTOM_SLOT_TEXTURE_BEGIN; type TrackListener = (x: spine.TrackEntry) => void; -type TrackListener2 = (x: spine.TrackEntry, ev: spine.Event) => void; +type TrackListener2 = (x: spine.TrackEntry, ev: spine.Event | number) => void; /** * @en * Animation playback rate. @@ -290,6 +290,14 @@ export class Skeleton extends UIRenderer { * @engineInternal */ public _debugRenderer: Graphics | null = null; + /** + * @engineInternal + */ + public _startSlotIndex; + /** + * @engineInternal + */ + public _endSlotIndex; private _slotTextures: Map | null = null; @@ -298,7 +306,8 @@ export class Skeleton extends UIRenderer { this._useVertexOpacity = true; this._startEntry = { animation: { name: '' }, trackIndex: 0 } as spine.TrackEntry; this._endEntry = { animation: { name: '' }, trackIndex: 0 } as spine.TrackEntry; - + this._startSlotIndex = -1; + this._endSlotIndex = -1; if (!JSB) { this._instance = new spine.SkeletonInstance(); } @@ -626,8 +635,6 @@ export class Skeleton extends UIRenderer { this._updateDebugDraw(); } - // For Redo, Undo - // call markForUpdateRenderData to make sure renderData will be re-built. /** * @engineInternal */ @@ -750,6 +757,71 @@ export class Skeleton extends UIRenderer { this._flushAssembler(); } + /** + * @en Sets slots visible range. + * @zh 设置骨骼插槽可视范围。 + * @param {Number} startSlotIndex @en start slot index. @zh 开始插槽的索引。 + * @param {Number} endSlotIndex @en end slot index. @zh 结束插槽的索引。 + */ + public setSlotsRange (startSlotIndex: number, endSlotIndex: number): void { + if (this.isAnimationCached()) { + warn('Slots visible range can not be modified in cached mode.'); + } else { + this._startSlotIndex = startSlotIndex; + this._endSlotIndex = endSlotIndex; + } + } + + /** + * @en + * Returns the attachment for the slot and attachment name. + * The skeleton looks first in its skin, then in the skeleton data’s default skin.
+ * Returns a {{#crossLinkModule "sp.spine"}}sp.spine{{/crossLinkModule}}.Attachment object. + * @zh + * 通过 slot 和 attachment 的名称获取 attachment。Skeleton 优先查找它的皮肤,然后才是 Skeleton Data 中默认的皮肤。
+ * 返回一个 {{#crossLinkModule "sp.spine"}}sp.spine{{/crossLinkModule}}.Attachment 对象。 + * + * @method getAttachment + * @param {String} slotName @en slot name. @zh 插槽的名字。 + * @param {String} attachmentName @en attachment name. @en 附件的名称。 + * @return {sp.spine.Attachment} + */ + public getAttachment (slotName: string, attachmentName: string): spine.Attachment | null { + if (this._skeleton) { + return this._skeleton.getAttachmentByName(slotName, attachmentName); + } + return null; + } + + /** + * @en + * Sets the attachment for the slot and attachment name. + * The skeleton looks first in its skin, then in the skeleton data’s default skin. + * @zh + * 通过 slot 和 attachment 的名字来设置 attachment。 + * Skeleton 优先查找它的皮肤,然后才是 Skeleton Data 中默认的皮肤。 + * @method setAttachment + * @param {String} slotName @en slot name. @zh 插槽的名字。 + * @param {String} attachmentName @en attachment name. @en 附件的名称。 + */ + public setAttachment (slotName: string, attachmentName: string): void { + if (this._skeleton) { + this._skeleton.setAttachment(slotName, attachmentName); + } + this.invalidAnimationCache(); + } + + /** + * @en + * Get Texture Atlas used in attachments. + * @zh + * 获取附件图集。 + * @param regionAttachment @en An attachment type of RegionAttachment or BoundingBoxAttachment. @zh RegionAttachment 或 BoundingBoxAttachment 的附件。 + * @return @en TextureRegion contains texture and atlas text information. @zh TextureRegion包含纹理和图集文本信息。 + */ + public getTextureAtlas (regionAttachment: spine.RegionAttachment | spine.BoundingBoxAttachment): spine.TextureRegion { + return (regionAttachment as spine.RegionAttachment).region; + } /** * @en Set the current animation. Any queued animations are cleared.
* @zh 设置当前动画。队列中的任何的动画将被清除。
@@ -798,7 +870,6 @@ export class Skeleton extends UIRenderer { this.markForUpdateRenderData(); return trackEntry; } - /** * @en Adds an animation to be played delay seconds after the current or last queued animation.
* Returns a {{#crossLinkModule "sp.spine"}}sp.spine{{/crossLinkModule}}.TrackEntry object. @@ -1652,15 +1723,18 @@ export class Skeleton extends UIRenderer { /** * @en Sets the complete event listener for specified TrackEntry. * @zh 用来为指定的 TrackEntry 设置动画一次循环播放结束的事件监听。 - * @param entry + * @param entry @en AnimationState track. @zn 动画轨道属性。 * @param listener @en Listener for registering callback functions. @zh 监听器对象,可注册回调方法。 */ public setTrackCompleteListener (entry: spine.TrackEntry, listener: TrackListener2): void { - // TODO - // TrackEntryListeners.getListeners(entry).complete = function (trackEntry) { - // const loopCount = Math.floor(trackEntry.trackTime / trackEntry.animationEnd); - // listener(trackEntry, loopCount); - // }; + const onComplete = (trackEntry: spine.TrackEntry): void => { + const loopCount = Math.floor(trackEntry.trackTime / trackEntry.animationEnd); + const listenerID = TrackEntryListeners.addListener(listener); + listener(trackEntry, loopCount); + this._instance.setListener(listenerID, spine.EventType.event); + this._listener!.event = listener; + }; + TrackEntryListeners.getListeners(entry).complete = onComplete; } /** diff --git a/native/cocos/editor-support/spine-wasm/CMakeLists.txt b/native/cocos/editor-support/spine-wasm/CMakeLists.txt index d7884343b91..339864386b3 100644 --- a/native/cocos/editor-support/spine-wasm/CMakeLists.txt +++ b/native/cocos/editor-support/spine-wasm/CMakeLists.txt @@ -7,7 +7,7 @@ set(APP_NAME "spine" CACHE STRING "Project Name") project(${APP_NAME}_wasm) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -frtti -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=1") include_directories(../ ../../) @@ -17,7 +17,7 @@ file(GLOB COCOS_ADAPTER_SRC "./*.cpp") add_executable(${APP_NAME} ${SPINE_CORE_SRC} ${COCOS_ADAPTER_SRC} ) #add_executable(${APP_NAME} ${COCOS_ADAPTER_SRC}) -set(EMS_LINK_FLAGS "-O3 -s WASM=0 -s INITIAL_MEMORY=33554432 -s ALLOW_MEMORY_GROWTH=1 -s DYNAMIC_EXECUTION=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ +set(EMS_LINK_FLAGS "-O3 -s WASM=1 -s INITIAL_MEMORY=33554432 -s ALLOW_MEMORY_GROWTH=1 -s DYNAMIC_EXECUTION=0 -s ERROR_ON_UNDEFINED_SYMBOLS=0 \ -flto --no-entry --bind -s USE_ES6_IMPORT_META=0 -s EXPORT_ES6=1 -s MODULARIZE=1 -s EXPORT_NAME='spineWasm' \ -s ENVIRONMENT=web -s FILESYSTEM=0 -s NO_EXIT_RUNTIME=1 -s LLD_REPORT_UNDEFINED \ -s MIN_SAFARI_VERSION=110000 \ diff --git a/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp b/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp index f9f48916691..00d0d2af986 100644 --- a/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp +++ b/native/cocos/editor-support/spine-wasm/spine-skeleton-instance.cpp @@ -57,7 +57,7 @@ TrackEntry *SpineSkeletonInstance::setAnimation(float trackIndex, const std::str _skeleton->setToSetupPose(); return nullptr; } - auto *trackEntry = _animState->setAnimation(0, animation, loop); + auto *trackEntry = _animState->setAnimation(trackIndex, animation, loop); _animState->apply(*_skeleton); _skeleton->updateWorldTransform(); return trackEntry; diff --git a/native/cocos/editor-support/spine-wasm/spine-type-export.cpp b/native/cocos/editor-support/spine-wasm/spine-type-export.cpp index b5c22169054..f8d7bf54def 100644 --- a/native/cocos/editor-support/spine-wasm/spine-type-export.cpp +++ b/native/cocos/editor-support/spine-wasm/spine-type-export.cpp @@ -30,6 +30,16 @@ std::vector VECTOR_SP2STD(Vector &container) { return stdVector; } +template +std::vector> VECTOR_2_SP2STD(Vector> &container) { + int count = container.size(); + std::vector> stdVector(count); + for (int i = 0; i < count; i++) { + stdVector[i] = VECTOR_SP2STD(container[i]); + } + return stdVector; +} + template std::vector VECTOR_SP2STD2(Vector container) { int count = container.size(); @@ -40,10 +50,42 @@ std::vector VECTOR_SP2STD2(Vector container) { return stdVector; } +template +Vector VECTOR_STD2SP(std::vector &container) { + int count = container.size(); + Vector vecSP = Vector(); + vecSP.setSize(count, 0); + for (int i = 0; i < count; i++) { + vecSP[i] = container[i]; + } + return vecSP; +} + +template +Vector VECTOR_STD2SP_POINTER(std::vector &container) { + int count = container.size(); + Vector vecSP = Vector(); + vecSP.setSize(count, nullptr); + for (int i = 0; i < count; i++) { + vecSP[i] = container[i]; + } + return vecSP; +} + +template +void VECTOR_STD_COPY_SP(std::vector &stdVector, Vector &spVector) { + int count = stdVector.size(); + for (int i = 0; i < count; i++) { + stdVector[i] = spVector[i]; + } +} + } // namespace EMSCRIPTEN_BINDINGS(spine) { register_vector("VectorFloat"); + register_vector("VectorUnsignedShort"); + register_vector("VectorString"); register_vector("VectorBoneData"); register_vector("VectorBone"); register_vector("VectorSkinEntry"); @@ -149,36 +191,36 @@ EMSCRIPTEN_BINDINGS(spine) { .value("Clipping", AttachmentType_Clipping); ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // class_("Vector") - // .constructor<>() - // .constructor() - // .function("size", &Vector::size); - - // class_("Pool") - // .constructor<>(); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// class_("MathUtils") .class_property("PI", &MathUtil::Pi) .class_property("PI2", &MathUtil::Pi_2) - //.class_property("radiansToDegrees", &MathUtil::radiansToDegrees) .class_property("radDeg", &MathUtil::Rad_Deg) - //.class_property("degreesToRadians", &MathUtil::degreesToRadians) + .class_property("degreesToRadians", &MathUtil::Rad_Deg) + .class_property("degRad", &MathUtil::Deg_Rad) + .class_property("degreesToRadians", &MathUtil::Deg_Rad) + .class_function("abs", &MathUtil::abs) + .class_function("signum", &MathUtil::sign) .class_function("clamp", &MathUtil::clamp) - .class_function("cosDeg", &MathUtil::cosDeg) - .class_function("cosDeg", &MathUtil::cosDeg) + .class_function("fmod", &MathUtil::fmod) + .class_function("atan2", &MathUtil::atan2) + .class_function("cos", &MathUtil::cos) + .class_function("sin", &MathUtil::sin) + .class_function("sqrt", &MathUtil::sqrt) + .class_function("acos", &MathUtil::acos) .class_function("sinDeg", &MathUtil::sinDeg) - .class_function("signum", &MathUtil::sign); - //.class_function("toInt", &MathUtil::toInt) - //.class_function("cbrt", &MathUtil::randomTriangular) - //.class_function("randomTriangular", &MathUtil::randomTriangular) - //.class_function("randomTriangularWith", &MathUtil::randomTriangular); + .class_function("cosDeg", &MathUtil::cosDeg) + .class_function("isNan", &MathUtil::isNan) + .class_function("random", &MathUtil::random) + .class_function("randomTriangular", select_overload(&MathUtil::randomTriangular)) + .class_function("randomTriangularWith", select_overload(&MathUtil::randomTriangular)) + .class_function("pow", &MathUtil::pow); class_("Color") .constructor<>() .constructor() .function("set", static_cast(&Color::set)) - //.function("setFromColor", static_cast(&Color::set)) //no need .function("add", static_cast(&Color::add)) .function("clamp", &Color::clamp) .property("r", &Color::r) @@ -243,144 +285,199 @@ EMSCRIPTEN_BINDINGS(spine) { .function("setTranslateMix", &PathConstraintData::setTranslateMix); class_("SkeletonBounds") - //.function("getProp_minX", &SkeletonBounds::minX) - //.function("getProp_minY", &SkeletonBounds::minY) - //.function("getProp_maxX", &SkeletonBounds::maxX) - //.function("getProp_maxY", &SkeletonBounds::maxY) - //.function("getProp_boundingBoxes", &SkeletonBounds::boundingBoxes) - //.function("getProp_polygons", &SkeletonBounds::polygons) .function("update", &SkeletonBounds::update) - //.function("aabbCompute", &SkeletonBounds::aabbCompute) // private .function("aabbContainsPoint", &SkeletonBounds::aabbcontainsPoint) .function("aabbIntersectsSegment", &SkeletonBounds::aabbintersectsSegment) .function("aabbIntersectsSkeleton", &SkeletonBounds::aabbIntersectsSkeleton) - //.function("containsPoint", select_overload(&SkeletonBounds::containsPoint), allow_raw_pointers()) - //.function("containsPointPolygon", select_overload(&SkeletonBounds::containsPoint), allow_raw_pointers()) - //.function("intersectsSegment", select_overload(&SkeletonBounds::intersectsSegment)) - //.function("intersectsSegmentPolygon", select_overload(&SkeletonBounds::intersectsSegment), allow_raw_pointers()) + .function("containsPoint", optional_override([](SkeletonBounds &obj, float x, float y) { + return obj.containsPoint(x, y); }),allow_raw_pointers()) + .function("containsPointPolygon", optional_override([](SkeletonBounds &obj,Polygon* polygon, float x, float y) { + return obj.containsPoint(polygon, x, y); }),allow_raw_pointers()) + .function("intersectsSegment", optional_override([](SkeletonBounds &obj, float x1, float y1, float x2, float y2){ + return obj.intersectsSegment(x1, y1, x2, y2); }),allow_raw_pointers()) + .function("intersectsSegmentPolygon", optional_override([](SkeletonBounds &obj,Polygon* polygon, + float x1, float y1, float x2, float y2){ + return obj.intersectsSegment(polygon, x1, y1, x2, y2); }),allow_raw_pointers()) .function("getPolygon", &SkeletonBounds::getPolygon, allow_raw_pointers()) .function("getWidth", &SkeletonBounds::getWidth) .function("getHeight", &SkeletonBounds::getHeight); class_("Event") .constructor() - .function("getData", &Event::getData) + .function("getData", optional_override([](Event &obj) { + return &obj.getData(); }), allow_raw_pointers()) .function("getIntValue", &Event::getIntValue) + .function("setIntValue", &Event::setIntValue) .function("getFloatValue", &Event::getFloatValue) - .function("getStringValue", optional_override([](Event &obj) { return STRING_SP2STD(obj.getStringValue()); })) + .function("setFloatValue", &Event::setFloatValue) + .function("getStringValue", optional_override([](Event &obj) { + return STRING_SP2STD(obj.getStringValue()); })) + .function("setStringValue", optional_override([](Event &obj, const std::string &name) { + return obj.setStringValue(STRING_STD2SP(name)); }), allow_raw_pointers()) .function("getTime", &Event::getTime) .function("getVolume", &Event::getVolume) - .function("getBalance", &Event::getBalance); + .function("setVolume", &Event::setVolume) + .function("getBalance", &Event::getBalance) + .function("setBalance", &Event::setBalance); class_("EventData") .constructor() - .function("getName", optional_override([](EventData &obj) { return STRING_SP2STD(obj.getName()); })) + .function("getName", optional_override([](EventData &obj) { + return STRING_SP2STD(obj.getName()); })) .function("getIntValue", &EventData::getIntValue) + .function("setIntValue", &EventData::setIntValue) .function("getFloatValue", &EventData::getFloatValue) - .function("getStringValue", optional_override([](EventData &obj) { return STRING_SP2STD(obj.getStringValue()); })) - .function("getAudioPath", optional_override([](EventData &obj) { return STRING_SP2STD(obj.getAudioPath()); })) + .function("setFloatValue", &EventData::setFloatValue) + .function("getStringValue", optional_override([](EventData &obj) { + return STRING_SP2STD(obj.getStringValue()); })) + .function("setStringValue", optional_override([](EventData &obj, const std::string &name) { + return obj.setStringValue(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("getAudioPath", optional_override([](EventData &obj) { + return STRING_SP2STD(obj.getAudioPath()); })) + .function("setAudioPath", optional_override([](EventData &obj, const std::string &name) { + return obj.setAudioPath(STRING_STD2SP(name)); }), allow_raw_pointers()) .function("getVolume", &EventData::getVolume) - .function("getBalance", &EventData::getBalance); + .function("setVolume", &EventData::setVolume) + .function("getBalance", &EventData::getBalance) + .function("setBalance", &EventData::setBalance); class_("Attachment") - .function("getName", optional_override([](Attachment &obj) { return STRING_SP2STD(obj.getName()); })); + .function("getName", optional_override([](Attachment &obj) { + return STRING_SP2STD(obj.getName()); })); // pure_virtual and raw pointer class_>("VertexAttachment") - //.constructor() - .function("getProp_id", &VertexAttachment::getId) - .function("getProp_bones", &VertexAttachment::getBones) - .function("getProp_vertices", &VertexAttachment::getVertices) - .function("getProp_worldVerticesLength", &VertexAttachment::getWorldVerticesLength) - .function("getProp_deformAttachment", &VertexAttachment::getDeformAttachment, allow_raw_pointer()) - .function("getProp_name", &VertexAttachment::getName) - //.function("computeWorldVertices", &VertexAttachment::computeWorldVertices); - .function("copy", &VertexAttachment::copy, allow_raw_pointer()) - .function("copyTo", &VertexAttachment::copyTo, allow_raw_pointer()); + .function("id", &VertexAttachment::getId) + .function("getBones", optional_override([](VertexAttachment &obj) { + return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) + .function("getVertices", optional_override([](VertexAttachment &obj) { + return VECTOR_SP2STD(obj.getVertices()); }), allow_raw_pointers()) + .function("getWorldVerticesLength", &VertexAttachment::getWorldVerticesLength) + .function("setWorldVerticesLength", &VertexAttachment::setWorldVerticesLength) + .function("getDeformAttachment", &VertexAttachment::getDeformAttachment, allow_raw_pointer()) + .function("setDeformAttachment", &VertexAttachment::setDeformAttachment, allow_raw_pointer()) + .function("computeWorldVertices", optional_override([](VertexAttachment &obj, Slot &slot, size_t start, size_t count, std::vector worldVertices, size_t offset, size_t stride){ + auto spWorldVertices = VECTOR_STD2SP(worldVertices); + obj.computeWorldVertices(slot, start, count, spWorldVertices, offset, stride); + VECTOR_STD_COPY_SP(worldVertices, spWorldVertices); + })) + .function("copyTo", &VertexAttachment::copyTo, allow_raw_pointers()); class_>("BoundingBoxAttachment") .constructor() - .function("getName", optional_override([](BoundingBoxAttachment &obj) { return STRING_SP2STD(obj.getName()); })) + .function("getName", optional_override([](BoundingBoxAttachment &obj) { + return STRING_SP2STD(obj.getName()); })) .function("copy", &BoundingBoxAttachment::copy, allow_raw_pointers()); - //.function("getProp_color", &BoundingBoxAttachment::getColor) class_>("ClippingAttachment") .constructor() - .function("getEndSlot", &ClippingAttachment::getEndSlot, allow_raw_pointer()) - .function("copy", &ClippingAttachment::copy, allow_raw_pointer()); - //.function("getProp_color", &ClippingAttachment::getColor) + .function("getEndSlot", &ClippingAttachment::getEndSlot, allow_raw_pointers()) + .function("setEndSlot", &ClippingAttachment::setEndSlot, allow_raw_pointers()) + .function("copy", &ClippingAttachment::copy, allow_raw_pointers()); class_>("MeshAttachment") .constructor() - //.function("getProp_region", &MeshAttachment::getRegion) - .function("getPath", optional_override([](MeshAttachment &obj) { return STRING_SP2STD(obj.getPath()); })) - .function("getRegionUVs", &MeshAttachment::getRegionUVs) - .function("getUVs", &MeshAttachment::getUVs) - .function("getTriangles", &MeshAttachment::getTriangles) - .function("getColor", &MeshAttachment::getColor) + .function("getPath", optional_override([](MeshAttachment &obj) { + return STRING_SP2STD(obj.getPath()); })) + .function("setPath", &MeshAttachment::setPath) + .function("getRegionUVs", optional_override([](MeshAttachment &obj) { + return VECTOR_SP2STD(obj.getRegionUVs());})) + .function("getUVs", optional_override([](MeshAttachment &obj) { + return VECTOR_SP2STD(obj.getUVs());}), allow_raw_pointers()) + .function("getTriangles", optional_override([](MeshAttachment &obj) { + return VECTOR_SP2STD(obj.getTriangles());}), allow_raw_pointers()) + .function("getColor", optional_override([](MeshAttachment &obj) { + return &obj.getColor(); }), allow_raw_pointers()) .function("getWidth", &MeshAttachment::getWidth) + .function("setWidth", &MeshAttachment::setWidth) .function("getHeight", &MeshAttachment::getHeight) + .function("setHeight", &MeshAttachment::setHeight) .function("getHullLength", &MeshAttachment::getHullLength) - .function("getEdges", &MeshAttachment::getEdges) - //.function("getProp_tempColor", &MeshAttachment::getTempColor) // no tempColor + .function("setHullLength", &MeshAttachment::setHullLength) + .function("getEdges", optional_override([](MeshAttachment &obj) { + return VECTOR_SP2STD(obj.getEdges());})) .function("updateUVs", &MeshAttachment::updateUVs) - .function("getParentMesh", &MeshAttachment::getParentMesh, allow_raw_pointer()) - .function("setParentMesh", &MeshAttachment::setParentMesh, allow_raw_pointer()) - .function("copy", &MeshAttachment::copy, allow_raw_pointer()) - .function("newLinkedMesh", &MeshAttachment::newLinkedMesh, allow_raw_pointer()); + .function("getParentMesh", &MeshAttachment::getParentMesh, allow_raw_pointers()) + .function("setParentMesh", &MeshAttachment::setParentMesh, allow_raw_pointers()) + .function("copy", &MeshAttachment::copy, allow_raw_pointers()) + .function("newLinkedMesh", &MeshAttachment::newLinkedMesh, allow_raw_pointers()); class_>("PathAttachment") .constructor() - .function("getLengths", optional_override([](PathAttachment &obj) { return VECTOR_SP2STD(obj.getLengths()); })) + .function("getLengths", optional_override([](PathAttachment &obj) { + return VECTOR_SP2STD(obj.getLengths()); })) .function("getClosed", &PathAttachment::isClosed) + .function("setClosed", &PathAttachment::setClosed) .function("getConstantSpeed", &PathAttachment::isConstantSpeed) - //.function("getProp_color", &MeshAttachment::getColor) // no color + .function("setConstantSpeed", &PathAttachment::setConstantSpeed) .function("copy", &PathAttachment::copy, allow_raw_pointers()); class_>("PointAttachment") .constructor() .function("getX", &PointAttachment::getX) + .function("setX", &PointAttachment::setX) .function("getY", &PointAttachment::getY) + .function("setY", &PointAttachment::setY) .function("getRotation", &PointAttachment::getRotation) - //.function("computeWorldPosition", &PointAttachment::computeWorldPosition) //reference type + .function("setRotation", &PointAttachment::setRotation) + .function("computeWorldPosition", optional_override([](PointAttachment &obj, Bone &bone, float ox, float oy) { + obj.computeWorldPosition(bone, ox, oy);})) .function("computeWorldRotation", &PointAttachment::computeWorldRotation) - //.function("getProp_color", &PointAttachment::getColor) // no color - .function("copy", &PointAttachment::copy, allow_raw_pointer()); - - //class_("HasRendererObject") - // .constructor<>(); + .function("copy", &PointAttachment::copy, allow_raw_pointers()); class_>("RegionAttachment") .constructor() - // static U4: number; - // static V4: number; - // ....... .function("getX", &RegionAttachment::getX) + .function("setX", &RegionAttachment::setX) .function("getY", &RegionAttachment::getY) + .function("setY", &RegionAttachment::setY) .function("getScaleX", &RegionAttachment::getScaleX) + .function("setScaleX", &RegionAttachment::setScaleX) .function("getScaleY", &RegionAttachment::getScaleY) + .function("setScaleY", &RegionAttachment::setScaleY) .function("getRotation", &RegionAttachment::getRotation) + .function("setRotation", &RegionAttachment::setRotation) .function("getWidth", &RegionAttachment::getWidth) + .function("setWidth", &RegionAttachment::setWidth) .function("getHeight", &RegionAttachment::getHeight) - .function("getColor", &RegionAttachment::getColor) - .function("getPath", optional_override([](RegionAttachment &obj) { return STRING_SP2STD(obj.getPath()); })) - .function("getRendererObject", &RegionAttachment::getRendererObject, allow_raw_pointer()) - //.function("getProp_region", &PointAttachment::getRegion) + .function("setHeight", &RegionAttachment::setHeight) + .function("getColor", optional_override([](RegionAttachment &obj) { + return &obj.getColor(); }), allow_raw_pointers()) + .function("getPath", optional_override([](RegionAttachment &obj) { + return STRING_SP2STD(obj.getPath()); })) + .function("setPath", &RegionAttachment::setPath) + .function("getRendererObject", &RegionAttachment::getRendererObject, allow_raw_pointers()) .function("getOffset", &RegionAttachment::getOffset) - .function("getUVs", &RegionAttachment::getUVs) - //.function("getProp_tempColor", &PointAttachment::getTempColor) // have no tempColor + .function("setUVs", optional_override([](RegionAttachment &obj, std::vector &data) { + auto uvs = obj.getUVs(); + int count = data.size(); + float u = count > 1 ? data[0] : uvs[0]; + float v = count > 2 ? data[1] : uvs[1]; + float u2 = count > 3 ? data[2] : uvs[2]; + float v2 = count > 4 ? data[3] : uvs[3]; + bool rotate = count > 5 ? (data[4] != 0) : false; + obj.setUVs(u, v, u2, v2, rotate); + }), allow_raw_pointers()) + .function("getUVs", optional_override([](RegionAttachment &obj) { + return VECTOR_SP2STD(obj.getUVs());}), allow_raw_pointers()) .function("updateOffset", &RegionAttachment::updateOffset) - //.function("setRegion", &RegionAttachment::setRegion) // have no setRegion + .function("computeWorldVertices", optional_override([]( + RegionAttachment &obj, Bone &bone, std::vector worldVertices, + size_t offset, size_t stride){ + auto spWorldVertices = VECTOR_STD2SP(worldVertices); + obj.computeWorldVertices(bone, spWorldVertices, offset, stride); + VECTOR_STD_COPY_SP(worldVertices, spWorldVertices); + })) .function("copy", &RegionAttachment::copy, allow_raw_pointer()); - // class_("AttachmentLoader") - // .constructor<>() - // .function("newClippingAttachment", &AttachmentLoader::newClippingAttachment, pure_virtual(), allow_raw_pointer()) - // .function("newPointAttachment", &AttachmentLoader::newPointAttachment, pure_virtual(), allow_raw_pointer()) - // .function("newPathAttachment", &AttachmentLoader::newPathAttachment, pure_virtual(), allow_raw_pointer()) - // .function("newBoundingBoxAttachment", &AttachmentLoader::newBoundingBoxAttachment, pure_virtual(), allow_raw_pointer()) - // .function("newMeshAttachment", &AttachmentLoader::newMeshAttachment, pure_virtual(), allow_raw_pointer()) - // .function("newRegionAttachment", &AttachmentLoader::newRegionAttachment, pure_virtual(), allow_raw_pointer()); + class_("AttachmentLoader") + //.constructor<>() + .function("newClippingAttachment", &AttachmentLoader::newClippingAttachment, pure_virtual(), allow_raw_pointers()) + .function("newPointAttachment", &AttachmentLoader::newPointAttachment, pure_virtual(), allow_raw_pointers()) + .function("newPathAttachment", &AttachmentLoader::newPathAttachment, pure_virtual(), allow_raw_pointers()) + .function("newBoundingBoxAttachment", &AttachmentLoader::newBoundingBoxAttachment, pure_virtual(), allow_raw_pointers()) + .function("newMeshAttachment", &AttachmentLoader::newMeshAttachment, pure_virtual(), allow_raw_pointers()) + .function("newRegionAttachment", &AttachmentLoader::newRegionAttachment, pure_virtual(), allow_raw_pointers()); class_>("AtlasAttachmentLoader") .constructor() @@ -390,11 +487,11 @@ EMSCRIPTEN_BINDINGS(spine) { .function("newPathAttachment", &AtlasAttachmentLoader::newPathAttachment, allow_raw_pointer()) .function("newPointAttachment", &AtlasAttachmentLoader::newPointAttachment, allow_raw_pointer()) .function("newClippingAttachment", &AtlasAttachmentLoader::newClippingAttachment, allow_raw_pointer()); - //.function("getProp_atlas") class_("TextureAtlasPage") .constructor() - .function("getName", optional_override([](AtlasPage &obj) { return STRING_SP2STD((const String)obj.name); })) + .function("getName", optional_override([](AtlasPage &obj) { + return STRING_SP2STD((const String)obj.name); })) .property("minFilter", &AtlasPage::minFilter) .property("magFilter", &AtlasPage::magFilter) .property("uWrap", &AtlasPage::uWrap) @@ -405,20 +502,19 @@ EMSCRIPTEN_BINDINGS(spine) { class_("TextureAtlasRegion") //.property("page", &AtlasRegion::page) - .function("getName", optional_override([](AtlasRegion &obj) { return STRING_SP2STD((const String)obj.name); })) + .function("getName", optional_override([](AtlasRegion &obj) { + return STRING_SP2STD((const String)obj.name); })) .property("x", &AtlasRegion::x) .property("y", &AtlasRegion::y) .property("index", &AtlasRegion::index) .property("rotate", &AtlasRegion::rotate) .property("degrees", &AtlasRegion::degrees); - //.property("texture", &AtlasRegion::height) + //.property("texture", &AtlasRegion::height) class_("TextureAtlas") .constructor() - //.function("getProp_pages") - //.function("getProp_regions") - .function("findRegion", optional_override([](Atlas &obj, const std::string &name) { return obj.findRegion(STRING_STD2SP(name)); }), allow_raw_pointers()); - //.function("dispose"); + .function("findRegion", optional_override([](Atlas &obj, const std::string &name) { + return obj.findRegion(STRING_STD2SP(name)); }), allow_raw_pointers()); class_>("Pow") .constructor() @@ -436,31 +532,19 @@ EMSCRIPTEN_BINDINGS(spine) { // .property("x", &Vector2::x) // .property("y", &Vector2::y); - class_("BoneData") - .constructor() - .function("getIndex", &BoneData::getIndex) - .function("getName", optional_override([](BoneData &obj) { return STRING_SP2STD(obj.getName()); })) - .function("getParent", &BoneData::getParent, allow_raw_pointer()) - .function("getLength", &BoneData::getLength) - .function("getX", &BoneData::getX) - .function("getY", &BoneData::getY) - .function("getRotation", &BoneData::getRotation) - .function("getScaleX", &BoneData::getScaleX) - .function("getScaleY", &BoneData::getScaleY) - .function("getShearX", &BoneData::getShearX) - .function("getShearY", &BoneData::getShearY) - .function("getTransformMode", &BoneData::getTransformMode) - .function("getSkinRequired", &BoneData::isSkinRequired); - //.function("getProp_color", &BoneData::isSkinRequired) // have no color - class_("SlotData") .constructor() .function("getIndex", &SlotData::getIndex) - .function("getName", optional_override([](SlotData &obj) { return STRING_SP2STD(obj.getName()); })) - .function("getBoneData", &SlotData::getBoneData) - .function("getColor", &SlotData::getColor) - .function("getDarkColor", &SlotData::getDarkColor) - .function("getBlendMode", &SlotData::getBlendMode); + .function("getName", optional_override([](SlotData &obj) { + return STRING_SP2STD(obj.getName()); })) + .function("getBoneData", optional_override([](SlotData &obj) { + return &obj.getBoneData(); }), allow_raw_pointers()) + .function("getColor", optional_override([](SlotData &obj) { + return &obj.getColor();}), allow_raw_pointers()) + .function("getDarkColor", optional_override([](SlotData &obj) { + return &obj.getDarkColor();}), allow_raw_pointers()) + .function("getBlendMode", &SlotData::getBlendMode) + .function("setBlendMode", &SlotData::setBlendMode); class_("Updatable") .function("update", &Updatable::update, pure_virtual()) @@ -468,8 +552,10 @@ EMSCRIPTEN_BINDINGS(spine) { class_>("IkConstraint") .constructor() - .function("getData", &IkConstraint::getData) - .function("getBones", optional_override([](IkConstraint &obj) { return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) + .function("getData", optional_override([](IkConstraint &obj){ + return &obj.getData(); }), allow_raw_pointers()) + .function("getBones", optional_override([](IkConstraint &obj) { + return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) .function("getTarget", &IkConstraint::getTarget, allow_raw_pointer()) .function("setTarget", &IkConstraint::setTarget, allow_raw_pointer()) .function("getBendDirection", &IkConstraint::getBendDirection) @@ -487,19 +573,23 @@ EMSCRIPTEN_BINDINGS(spine) { .function("isActive", &IkConstraint::isActive) .function("apply", static_cast(&IkConstraint::apply)) .function("update", &IkConstraint::update) - //.function("apply1", static_cast(&IkConstraint::apply)) - //.function("apply2", static_cast(&IkConstraint::apply)) - ; + .class_function("apply1", optional_override([]( + IkConstraint &obj, Bone &bone, float targetX, float targetY, + bool compress, bool stretch, bool uniform, float alpha){ + obj.apply(bone, targetX, targetY, compress, stretch, uniform, alpha); + })) + .class_function("apply2", optional_override([]( + IkConstraint &obj, Bone &parent, Bone &child, float targetX, float targetY, + int bendDir, bool stretch, float softness, float alpha){ + obj.apply(parent, child, targetX, targetY, bendDir, stretch, softness, alpha); + })); class_>("PathConstraint") .constructor() - // private but no need, just wrap in js - // static const float EPSILON; - // static const int NONE; - // static const int BEFORE; - // static const int AFTER; - .function("getData", &PathConstraint::getData) - .function("getBones", optional_override([](PathConstraint &obj) { return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) + .function("getData", optional_override([](PathConstraint &obj) { + return &obj.getData(); }), allow_raw_pointers()) + .function("getBones", optional_override([](PathConstraint &obj) { + return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) .function("getTarget", &PathConstraint::getTarget, allow_raw_pointer()) .function("setTarget", &PathConstraint::setTarget, allow_raw_pointer()) .function("getPosition", &PathConstraint::getPosition) @@ -510,27 +600,17 @@ EMSCRIPTEN_BINDINGS(spine) { .function("setRotateMix", &PathConstraint::setRotateMix) .function("getTranslateMix", &PathConstraint::getTranslateMix) .function("getTranslateMix", &PathConstraint::setTranslateMix) - //.function("getProp_spaces", &PathConstraint::spaces) - //.function("getProp_positions", &PathConstraint::positions) - //.function("getProp_world", &PathConstraint::world) - //.function("getProp_curves", &PathConstraint::curves) - //.function("getProp_lengths", &PathConstraint::lengths) - //.function("getProp_segments", &PathConstraint::segments) .function("getActive", &PathConstraint::isActive) .function("isActive", &PathConstraint::isActive) .function("setActive", &PathConstraint::setActive) .function("apply", &PathConstraint::apply) - .function("update", &PathConstraint::update) - //.function("computeWorldPositions", &PathConstraint::computeWorldPositions) - //.function("addBeforePosition", &PathConstraint::addBeforePosition) - //.function("addAfterPosition", &PathConstraint::addAfterPosition) - //.function("addCurvePosition", &PathConstraint::addCurvePosition) // private - ; + .function("update", &PathConstraint::update); class_>("TransformConstraintData") .constructor() - .function("getBones", optional_override([](TransformConstraintData &obj) { return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) - .function("getTarget", &TransformConstraintData::getTarget, allow_raw_pointer()) + .function("getBones", optional_override([](TransformConstraintData &obj) { + return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) + .function("getTarget", &TransformConstraintData::getTarget, allow_raw_pointers()) .function("getRotateMix", &TransformConstraintData::getRotateMix) .function("getTranslateMix", &TransformConstraintData::getTranslateMix) .function("getScaleMix", &TransformConstraintData::getScaleMix) @@ -546,52 +626,79 @@ EMSCRIPTEN_BINDINGS(spine) { class_>("TransformConstraint") .constructor() - .function("getData", &TransformConstraint::getData) - .function("getBones", optional_override([](TransformConstraint &obj) { return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) - .function("getTarget", &TransformConstraint::getTarget, allow_raw_pointer()) + .function("getData", optional_override([](TransformConstraint &obj){ + return &obj.getData();}), allow_raw_pointers()) + .function("getBones", optional_override([](TransformConstraint &obj) { + return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) + .function("getTarget", &TransformConstraint::getTarget, allow_raw_pointers()) .function("getRotateMix", &TransformConstraint::getRotateMix) + .function("setRotateMix", &TransformConstraint::setRotateMix) .function("getTranslateMix", &TransformConstraint::getTranslateMix) + .function("setTranslateMix", &TransformConstraint::setTranslateMix) .function("getScaleMix", &TransformConstraint::getScaleMix) + .function("setScaleMix", &TransformConstraint::setScaleMix) .function("getShearMix", &TransformConstraint::getShearMix) - //.function("getProp_temp") // no + .function("setShearMix", &TransformConstraint::setShearMix) .function("getActive", &TransformConstraint::isActive) + .function("setActive", &TransformConstraint::setActive) .function("isActive", &TransformConstraint::isActive) .function("apply", &TransformConstraint::apply) .function("update", &TransformConstraint::update); - //.function("applyAbsoluteWorld", &TransformConstraint::applyAbsoluteWorld) - //.function("applyRelativeWorld", &TransformConstraint::applyRelativeWorld) - //.function("applyAbsoluteLocal", &TransformConstraint::applyAbsoluteLocal) - //.function("applyRelativeLocal", &TransformConstraint::applyRelativeLocal) class_>("Bone") .constructor() - .function("getData", &Bone::getData) - .function("getSkeleton", &Bone::getSkeleton) - .function("getParent", &Bone::getParent, allow_raw_pointers()) - //.function("getProp_children", &Bone::getChildren) + .function("getData", optional_override([](Bone &obj) { + return &obj.getData(); }), allow_raw_pointers()) + .function("getSkeleton", optional_override([](Bone &obj) { + return &obj.getSkeleton(); }), allow_raw_pointers()) + .function("getParent", optional_override([](Bone &obj) { + return obj.getParent(); }), allow_raw_pointers()) + .function("getChildren", optional_override([](Bone &obj) { + return VECTOR_SP2STD(obj.getChildren()); }), allow_raw_pointers()) .function("getX", &Bone::getX) + .function("setX", &Bone::setX) .function("getY", &Bone::getY) + .function("setY", &Bone::setY) .function("getRotation", &Bone::getRotation) + .function("setRotation", &Bone::setRotation) .function("getScaleX", &Bone::getScaleX) + .function("setScaleX", &Bone::setScaleX) .function("getScaleY", &Bone::getScaleY) + .function("setScaleY", &Bone::setScaleY) .function("getShearX", &Bone::getShearX) + .function("setShearX", &Bone::setShearX) .function("getShearY", &Bone::getShearY) + .function("setShearY", &Bone::setShearY) .function("getAX", &Bone::getAX) + .function("setAX", &Bone::setAX) .function("getAY", &Bone::getAY) + .function("setAY", &Bone::setAY) .function("getARotation", &Bone::getAppliedRotation) + .function("setARotation", &Bone::setAppliedRotation) .function("getAScaleX", &Bone::getAScaleX) + .function("setAScaleX", &Bone::setAScaleX) .function("getAScaleY", &Bone::getAScaleY) + .function("setAScaleY", &Bone::setAScaleY) .function("getAShearX", &Bone::getAShearX) + .function("setAShearX", &Bone::setAShearX) .function("getAShearY", &Bone::getAShearY) + .function("setAShearY", &Bone::setAShearY) .function("getAppliedValid", &Bone::isAppliedValid) + .function("setAppliedValid", &Bone::setAppliedValid) .function("getA", &Bone::getA) + .function("setA", &Bone::setA) .function("getB", &Bone::getB) + .function("setB", &Bone::setB) .function("getC", &Bone::getC) + .function("setC", &Bone::setC) .function("getD", &Bone::getD) - .function("getWorldY", &Bone::getWorldY) + .function("setD", &Bone::setD) .function("getWorldX", &Bone::getWorldX) - //.function("getProp_sorted", &Bone::getSorted) + .function("setWorldX", &Bone::setWorldX) + .function("getWorldY", &Bone::getWorldY) + .function("setWorldY", &Bone::setWorldY) .function("getActive", &Bone::isActive) + .function("setActive", &Bone::setActive) .function("isActive", &Bone::isActive) .function("update", &Bone::update) .function("updateWorldTransform", select_overload(&Bone::updateWorldTransform)) @@ -600,44 +707,65 @@ EMSCRIPTEN_BINDINGS(spine) { .function("getWorldRotationX", &Bone::getWorldRotationX) .function("getWorldRotationY", &Bone::getWorldRotationY) .function("getWorldScaleX", &Bone::getWorldScaleX) - .function("getWorldScaleY", &Bone::getWorldScaleY) - //.function("updateAppliedTransform", &Bone::updateAppliedTransform) - //.function("worldToLocal", &Bone::worldToLocal) - //.function("localToWorld", &Bone::localToWorld) + .function("getWorldScaleY", &Bone::getWorldScaleY) + .function("worldToLocal", optional_override([](Bone &obj, float a, float b) { + std::vector vec2(2); + obj.worldToLocal(a, b, vec2[0], vec2[1]); + return vec2; + }), + allow_raw_pointers() + ) + .function("localToWorld", optional_override([](Bone &obj, float a, float b) { + std::vector vec2(2); + obj.localToWorld(a, b, vec2[0], vec2[1]); + return vec2; + }), + allow_raw_pointers() + ) .function("worldToLocalRotation", &Bone::worldToLocalRotation) .function("localToWorldRotation", &Bone::localToWorldRotation) - .function("rotateWorld", &Bone::rotateWorld) - .function("setX", &Bone::setX) - .function("setY", &Bone::setY) - .function("setRotation", &Bone::setRotation) - .function("setScaleX", &Bone::setScaleX) - .function("setScaleY", &Bone::setScaleY) - .function("setShearX", &Bone::setShearX) - .function("setShearY", &Bone::setShearY) - .function("setAX", &Bone::setAX) - .function("setAY", &Bone::setAY) - .function("setARotation", &Bone::setAppliedRotation) - .function("setAScaleX", &Bone::setAScaleX) - .function("setAScaleY", &Bone::setAScaleY) - .function("setAShearX", &Bone::setAShearX) - .function("setAShearY", &Bone::setAShearY) - .function("setAppliedValid", &Bone::setAppliedValid) - .function("setA", &Bone::setA) - .function("setB", &Bone::setB) - .function("setC", &Bone::setC) - .function("setD", &Bone::setD) - .function("setWorldX", &Bone::setWorldX) - .function("setWorldY", &Bone::setWorldY) - .function("setActive", &Bone::setActive); + .function("rotateWorld", &Bone::rotateWorld); + + class_("BoneData") + .constructor() + .function("getIndex", &BoneData::getIndex) + .function("getName", optional_override([](BoneData &obj) { return STRING_SP2STD(obj.getName()); })) + .function("getParent", &BoneData::getParent, allow_raw_pointer()) + .function("getLength", &BoneData::getLength) + .function("setLength", &BoneData::setLength) + .function("getX", &BoneData::getX) + .function("setX", &BoneData::setX) + .function("getY", &BoneData::getY) + .function("setY", &BoneData::setY) + .function("getRotation", &BoneData::getRotation) + .function("setRotation", &BoneData::setRotation) + .function("getScaleX", &BoneData::getScaleX) + .function("setScaleX", &BoneData::setScaleX) + .function("getScaleY", &BoneData::getScaleY) + .function("setScaleY", &BoneData::setScaleY) + .function("getShearX", &BoneData::getShearX) + .function("setShearX", &BoneData::setShearX) + .function("getShearY", &BoneData::getShearY) + .function("setShearY", &BoneData::setShearY) + .function("getTransformMode", &BoneData::getTransformMode) + .function("setTransformMode", &BoneData::setTransformMode) + .function("getSkinRequired", &BoneData::isSkinRequired) + .function("setShinRequired", &BoneData::setSkinRequired); class_("Slot") .constructor() - .function("getData", &Slot::getData) - .function("getBone", &Slot::getBone) - .function("getColor", &Slot::getColor) - .function("getDarkColor", &Slot::getDarkColor) - .function("getDeform", &Slot::getDeform) - .function("getSkeleton", &Slot::getSkeleton) + .function("getData", optional_override([](Slot &obj) { + return &obj.getData(); }), allow_raw_pointers()) + .function("getBone", optional_override([](Slot &obj) { + return &obj.getBone(); }), allow_raw_pointers()) + .function("getColor", optional_override([](Slot &obj) { + return &obj.getColor(); }), allow_raw_pointers()) + .function("getDarkColor", optional_override([](Slot &obj) { + return &obj.getDarkColor(); }), allow_raw_pointers()) + .function("getDeform", optional_override([](Slot &obj) { + return VECTOR_SP2STD(obj.getDeform());}), allow_raw_pointers()) + .function("getSkeleton", optional_override([](Slot &obj) { + return &obj.getSkeleton(); }), allow_raw_pointers()) .function("getAttachment", &Slot::getAttachment, allow_raw_pointers()) .function("setAttachment", &Slot::setAttachment, allow_raw_pointers()) .function("setAttachmentTime", &Slot::setAttachmentTime) @@ -646,39 +774,52 @@ EMSCRIPTEN_BINDINGS(spine) { class_("Skin") .constructor() - .function("getName", optional_override([](Skin &obj) { return STRING_SP2STD(obj.getName()); })) - .function("getBones", optional_override([](Skin &obj) { return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) - .function("getConstraints", optional_override([](Skin &obj) { return VECTOR_SP2STD(obj.getConstraints()); }), allow_raw_pointers()) - .function("setAttachment", optional_override([](Skin &obj, size_t index, const std::string &name, Attachment *attachment) { return obj.setAttachment(index, STRING_STD2SP(name), attachment); }), allow_raw_pointers()) + .function("getName", optional_override([](Skin &obj) { + return STRING_SP2STD(obj.getName()); })) + .function("getBones", optional_override([](Skin &obj) { + return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) + .function("getConstraints", optional_override([](Skin &obj) { + return VECTOR_SP2STD(obj.getConstraints()); }), allow_raw_pointers()) + .function("setAttachment", optional_override([](Skin &obj, size_t index, + const std::string &name, Attachment *attachment) { + return obj.setAttachment(index, STRING_STD2SP(name), attachment); + }), allow_raw_pointers()) .function("addSkin", select_overload(&Skin::addSkin), allow_raw_pointers()) .function("copySkin", select_overload(&Skin::copySkin), allow_raw_pointers()) - .function("getAttachment", optional_override([](Skin &obj, size_t slotIndex, const std::string &name) { - return obj.getAttachment(slotIndex, STRING_STD2SP(name)); - }), - allow_raw_pointers()) + .function("findNamesForSlot", optional_override([](Skin &obj, size_t slotIndex) { + std::vector vetNames; + std::vector entriesVector; + auto entries = obj.getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == slotIndex) vetNames.push_back(STRING_SP2STD(entry._name)); + } + return vetNames; + }), allow_raw_pointers()) + .function("getAttachment", optional_override([](Skin &obj, size_t slotIndex, + const std::string &name) { + return obj.getAttachment(slotIndex, STRING_STD2SP(name)); + }), allow_raw_pointers()) .function("getAttachments", optional_override([](Skin &obj) { - std::vector entriesVector; - auto entries = obj.getAttachments(); - while (entries.hasNext()) { - entriesVector.push_back(&entries.next()); - } - return entriesVector; - }), - allow_raw_pointers()) - .function("removeAttachment", optional_override([](Skin &obj, size_t index, const std::string &name) { obj.removeAttachment(index, STRING_STD2SP(name)); })) + std::vector entriesVector; + auto entries = obj.getAttachments(); + while (entries.hasNext()) { + entriesVector.push_back(&entries.next()); + } + return entriesVector; + }),allow_raw_pointers()) + .function("removeAttachment", optional_override([](Skin &obj, size_t index, + const std::string &name) { + obj.removeAttachment(index, STRING_STD2SP(name)); })) .function("getAttachmentsForSlot", optional_override([](Skin &obj, size_t index) { - std::vector entriesVector; - auto entries = obj.getAttachments(); - while (entries.hasNext()) { - Skin::AttachmentMap::Entry &entry = entries.next(); - if (entry._slotIndex == index) entriesVector.push_back(&entry); - } - return entriesVector; - }), - allow_raw_pointers()) - //.function("clear", &Skin::clear); // have no clear - //.function("attachAll", &Skin::attachAll) - ; + std::vector entriesVector; + auto entries = obj.getAttachments(); + while (entries.hasNext()) { + Skin::AttachmentMap::Entry &entry = entries.next(); + if (entry._slotIndex == index) entriesVector.push_back(&entry); + } + return entriesVector; + }),allow_raw_pointers()); class_("SkinEntry") .constructor() @@ -690,200 +831,301 @@ EMSCRIPTEN_BINDINGS(spine) { .constructor<>() .function("getClippedVertices", &SkeletonClipping::getClippedVertices) .function("getClippedTriangles", &SkeletonClipping::getClippedTriangles) - .function("getUVs", &SkeletonClipping::getClippedUVs) + .function("getClippedUVs", &SkeletonClipping::getClippedUVs) .function("clipStart", &SkeletonClipping::clipStart, allow_raw_pointers()) .function("clipEndWithSlot", select_overload(&SkeletonClipping::clipEnd)) .function("clipEnd", select_overload(&SkeletonClipping::clipEnd)) .function("isClipping", &SkeletonClipping::isClipping); - //.function("clipTriangles", &SkeletonClipping::clipTriangles, allow_raw_pointers()); //paramters not match - //.function("clip", &SkeletonClipping::clip) - //.class_function("makeClockwise", &SkeletonClipping::makeClockwise) class_("SkeletonData") .constructor<>() - .function("getName", optional_override([](SkeletonData &obj) { return STRING_SP2STD(obj.getName()); })) - .function("getBones", optional_override([](SkeletonData &obj) { return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) - .function("getSlots", optional_override([](SkeletonData &obj) { return VECTOR_SP2STD(obj.getSlots()); }), allow_raw_pointers()) - .function("getSkins", optional_override([](SkeletonData &obj) { return VECTOR_SP2STD(obj.getSkins()); }), allow_raw_pointers()) - .function("getDefaultSkin", &SkeletonData::getDefaultSkin, allow_raw_pointer()) - .function("getEvents", optional_override([](SkeletonData &obj) { return VECTOR_SP2STD(obj.getEvents()); }), allow_raw_pointers()) - .function("getAnimations", optional_override([](SkeletonData &obj) { return VECTOR_SP2STD(obj.getAnimations()); }), allow_raw_pointers()) - .function("getIkConstraints", optional_override([](SkeletonData &obj) { return VECTOR_SP2STD(obj.getIkConstraints()); }), allow_raw_pointers()) - .function("getTransformConstraints", optional_override([](SkeletonData &obj) { return VECTOR_SP2STD(obj.getTransformConstraints()); }), allow_raw_pointers()) - .function("getPathConstraints", optional_override([](SkeletonData &obj) { return VECTOR_SP2STD(obj.getPathConstraints()); }), allow_raw_pointers()) + .function("getName", optional_override([](SkeletonData &obj) { + return STRING_SP2STD(obj.getName()); })) + .function("setName", &SkeletonData::setName) + .function("getBones", optional_override([](SkeletonData &obj) { + return VECTOR_SP2STD(obj.getBones()); }), allow_raw_pointers()) + .function("getSlots", optional_override([](SkeletonData &obj) { + return VECTOR_SP2STD(obj.getSlots()); }), allow_raw_pointers()) + .function("getSkins", optional_override([](SkeletonData &obj) { + return VECTOR_SP2STD(obj.getSkins()); }), allow_raw_pointers()) + .function("getDefaultSkin", &SkeletonData::getDefaultSkin, allow_raw_pointers()) + .function("setDefaultSkin", &SkeletonData::setDefaultSkin, allow_raw_pointers()) + .function("getEvents", optional_override([](SkeletonData &obj) { + return VECTOR_SP2STD(obj.getEvents()); }), allow_raw_pointers()) + .function("getAnimations", optional_override([](SkeletonData &obj) { + return VECTOR_SP2STD(obj.getAnimations()); }), allow_raw_pointers()) + .function("getIkConstraints", optional_override([](SkeletonData &obj) { + return VECTOR_SP2STD(obj.getIkConstraints()); }), allow_raw_pointers()) + .function("getTransformConstraints", optional_override([](SkeletonData &obj) { + return VECTOR_SP2STD(obj.getTransformConstraints()); }), allow_raw_pointers()) + .function("getPathConstraints", optional_override([](SkeletonData &obj) { + return VECTOR_SP2STD(obj.getPathConstraints()); }), allow_raw_pointers()) .function("getX", &SkeletonData::getX) + .function("setX", &SkeletonData::setX) .function("getY", &SkeletonData::getY) + .function("setY", &SkeletonData::setY) .function("getWidth", &SkeletonData::getWidth) + .function("setWidth", &SkeletonData::setWidth) .function("getHeight", &SkeletonData::getHeight) - .function("getVersion", optional_override([](SkeletonData &obj) { return STRING_SP2STD(obj.getVersion()); })) - .function("getHash", optional_override([](SkeletonData &obj) { return STRING_SP2STD(obj.getHash()); })) + .function("setHeight", &SkeletonData::setHeight) + .function("getVersion", optional_override([](SkeletonData &obj) { + return STRING_SP2STD(obj.getVersion()); })) + .function("setVersion", &SkeletonData::setVersion) + .function("getHash", optional_override([](SkeletonData &obj) { + return STRING_SP2STD(obj.getHash()); })) + .function("setHash", &SkeletonData::setHash) .function("getFps", &SkeletonData::getFps) - .function("getImagesPath", optional_override([](SkeletonData &obj) { return STRING_SP2STD(obj.getImagesPath()); })) - .function("getAudioPath", optional_override([](SkeletonData &obj) { return STRING_SP2STD(obj.getAudioPath()); })) - .function("findBone", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findBone(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findBoneIndex", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findBoneIndex(STRING_STD2SP(name)); })) - .function("findSlot", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findSlot(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findSlotIndex", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findSlotIndex(STRING_STD2SP(name)); })) - .function("findSkin", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findSkin(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findEvent", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findEvent(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findAnimation", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findAnimation(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findIkConstraint", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findIkConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findTransformConstraint", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findTransformConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findPathConstraint", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findPathConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findPathConstraintIndex", optional_override([](SkeletonData &obj, const std::string &name) { return obj.findPathConstraintIndex(STRING_STD2SP(name)); })); + .function("setFps", &SkeletonData::setFps) + .function("getImagesPath", optional_override([](SkeletonData &obj) { + return STRING_SP2STD(obj.getImagesPath()); })) + .function("setImagesPath", &SkeletonData::setImagesPath) + .function("getAudioPath", optional_override([](SkeletonData &obj) { + return STRING_SP2STD(obj.getAudioPath()); })) + .function("setAudioPath", &SkeletonData::setAudioPath) + .function("findBone", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findBone(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findBoneIndex", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findBoneIndex(STRING_STD2SP(name)); })) + .function("findSlot", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findSlot(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findSlotIndex", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findSlotIndex(STRING_STD2SP(name)); })) + .function("findSkin", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findSkin(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findEvent", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findEvent(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findAnimation", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findAnimation(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findIkConstraint", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findIkConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findTransformConstraint", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findTransformConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findPathConstraint", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findPathConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findPathConstraintIndex", optional_override([](SkeletonData &obj, const std::string &name) { + return obj.findPathConstraintIndex(STRING_STD2SP(name)); })); + + class_("Animation") + .constructor &, float>() + .function("apply", &Animation::apply, allow_raw_pointers()) + .function("getName", optional_override([](Animation &obj) { return STRING_SP2STD(obj.getName()); })) + .function("getTimelines", optional_override([](Animation &obj) { return VECTOR_SP2STD(obj.getTimelines()); })) + .function("hasTimeline", &Animation::hasTimeline) + .function("getDuration", &Animation::getDuration) + .function("setDuration", &Animation::setDuration); class_("Timeline") // to fix apply - .function("apply", &Timeline::apply, allow_raw_pointers()) + //.function("apply", &Timeline::apply, allow_raw_pointers()) + .function("apply", optional_override([](Timeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()) .function("getPropertyId", &Timeline::getPropertyId); class_>("CurveTimeline") - // static const float LINEAR; - // static const float STEPPED; - // static const float BEZIER; - // static const int BEZIER_SIZE; .function("getPropertyId", &CurveTimeline::getPropertyId, pure_virtual()) .function("getFrameCount", &CurveTimeline::getFrameCount) .function("setLinear", &CurveTimeline::setLinear) .function("setStepped", &CurveTimeline::setStepped) - .function("getCurveType", &CurveTimeline::getCurveType) .function("setCurve", &CurveTimeline::setCurve) - .function("getCurvePercent", &CurveTimeline::getCurvePercent); + .function("getCurvePercent", &CurveTimeline::getCurvePercent) + .function("getCurveType", &CurveTimeline::getCurveType); class_>("TranslateTimeline") .constructor() - // will wrap in js - // static const int ENTRIES - // static const int PREV_TIME; - // static const int PREV_X; - // static const int PREV_Y; - // static const int X; - // static const int Y; - //.function("getProp_boneIndex", &TranslateTimeline::getBoneIndex) - //.function("getProp_frames", &TranslateTimeline::getFrames) + .class_property("ENTRIES", &TranslateTimeline::ENTRIES) .function("getPropertyId", &TranslateTimeline::getPropertyId) .function("setFrame", &TranslateTimeline::setFrame) - .function("apply", &TranslateTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](TranslateTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("ScaleTimeline") .constructor() .function("getPropertyId", &ScaleTimeline::getPropertyId) - .function("apply", &ScaleTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](ScaleTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("ShearTimeline") .constructor() .function("getPropertyId", &ShearTimeline::getPropertyId) - .function("apply", &ShearTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](ShearTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("RotateTimeline") .constructor() - // will wrap in js - //static const int PREV_TIME = -2; - //static const int PREV_ROTATION = -1; - //static const int ROTATION = 1; + //.class_property("ENTRIES", &RotateTimeline::ENTRIES) not bind .function("getBoneIndex", &RotateTimeline::getBoneIndex) - .function("getFrames", optional_override([](RotateTimeline &obj) { return VECTOR_SP2STD(obj.getFrames()); })) + .function("setBoneIndex", &RotateTimeline::setBoneIndex) + .function("getFrames", optional_override([](RotateTimeline &obj) { + return VECTOR_SP2STD( obj.getFrames()); }), allow_raw_pointers()) .function("getPropertyId", &RotateTimeline::getPropertyId) .function("setFrame", &RotateTimeline::setFrame) - .function("apply", &RotateTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](RotateTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("ColorTimeline") .constructor() - // will wrap in js - // static const int PREV_TIME; - // static const int PREV_R; - // static const int PREV_G; - // static const int PREV_B; - // static const int PREV_A; - // static const int R; - // static const int G; - // static const int B; - // static const int A; + .class_property("ENTRIES", &ColorTimeline::ENTRIES) .function("getSlotIndex", &ColorTimeline::getSlotIndex) - .function("getFrames", optional_override([](ColorTimeline &obj) { return VECTOR_SP2STD(obj.getFrames()); })) + .function("setSlotIndex", &ColorTimeline::setSlotIndex) + .function("getFrames", optional_override([](ColorTimeline &obj) { return VECTOR_SP2STD(obj.getFrames()); }), allow_raw_pointers()) .function("getPropertyId", &ColorTimeline::getPropertyId) .function("setFrame", &ColorTimeline::setFrame) - .function("apply", &ColorTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](ColorTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("TwoColorTimeline") .constructor() - // static variables + .class_property("ENTRIES", &ColorTimeline::ENTRIES) .function("getSlotIndex", &TwoColorTimeline::getSlotIndex) - //.function("getProp_frames", &TwoColorTimeline::getFrames) + .function("setSlotIndex", &TwoColorTimeline::setSlotIndex) .function("getPropertyId", &TwoColorTimeline::getPropertyId) .function("setFrame", &TwoColorTimeline::setFrame) - .function("apply", &TwoColorTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](TwoColorTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("AttachmentTimeline") .constructor() .function("getSlotIndex", &AttachmentTimeline::getSlotIndex) - .function("getFrames", optional_override([](AttachmentTimeline &obj) { return VECTOR_SP2STD((Vector &)obj.getFrames()); })) - //.function("getProp_attachmentNames", &AttachmentTimeline::getAttachmentNames) + .function("setSlotIndex", &AttachmentTimeline::setSlotIndex) + .function("getFrames", optional_override([](AttachmentTimeline &obj) { + return VECTOR_SP2STD((Vector &)obj.getFrames()); }), allow_raw_pointers()) + .function("getAttachmentNames",optional_override([](AttachmentTimeline &obj) { + auto names = obj.getAttachmentNames(); + return VECTOR_SP2STD(names); }), allow_raw_pointers()) .function("getPropertyId", &AttachmentTimeline::getPropertyId) .function("getFrameCount", &AttachmentTimeline::getFrameCount) .function("setFrame", &AttachmentTimeline::setFrame) - .function("apply", &AttachmentTimeline::apply, allow_raw_pointers()); - //.function("setAttachment", &AttachmentTimeline::setAttachment) //have no setAttachment + .function("apply", optional_override([](AttachmentTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("DeformTimeline") .constructor() .function("getSlotIndex", &DeformTimeline::getSlotIndex) - .function("getAttachment", &DeformTimeline::getAttachment, allow_raw_pointer()) + .function("setSlotIndex", &DeformTimeline::setSlotIndex) + .function("getAttachment", &DeformTimeline::getAttachment, allow_raw_pointers()) + .function("setAttachment", &DeformTimeline::setAttachment, allow_raw_pointers()) .function("getFrames", optional_override([](DeformTimeline &obj) { return VECTOR_SP2STD((Vector &)obj.getFrames()); })) .function("getFrameVertices", &DeformTimeline::getVertices) .function("getPropertyId", &DeformTimeline::getPropertyId) .function("setFrame", &DeformTimeline::setFrame) - .function("apply", &DeformTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](DeformTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("EventTimeline") .constructor() - .function("getFrames", optional_override([](EventTimeline &obj) { return VECTOR_SP2STD2(obj.getFrames()); })) - .function("getEvents", optional_override([](EventTimeline &obj) { return VECTOR_SP2STD(obj.getEvents()); }), allow_raw_pointers()) + .function("getFrames", optional_override([](EventTimeline &obj) { + return VECTOR_SP2STD2(obj.getFrames()); })) + .function("getEvents", optional_override([](EventTimeline &obj) { + return VECTOR_SP2STD(obj.getEvents()); }), allow_raw_pointers()) .function("getPropertyId", &EventTimeline::getPropertyId) .function("getFrameCount", &EventTimeline::getFrameCount) .function("setFrame", &EventTimeline::setFrame, allow_raw_pointers()) - .function("apply", &EventTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](EventTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("DrawOrderTimeline") .constructor() - .function("getFrames", optional_override([](DrawOrderTimeline &obj) { return VECTOR_SP2STD(obj.getFrames()); })) - //.function("getProp_drawOrders", &EventTimeline::getDrawOrders) + .function("getFrames", optional_override([](DrawOrderTimeline &obj) { return VECTOR_SP2STD(obj.getFrames()); })) .function("getPropertyId", &DrawOrderTimeline::getPropertyId) .function("getFrameCount", &DrawOrderTimeline::getFrameCount) + .function("getDrawOrders", optional_override([](DrawOrderTimeline &obj){ + auto drawOrders = obj.getDrawOrders(); + return VECTOR_2_SP2STD(drawOrders); + }), allow_raw_pointers()) .function("setFrame", &DrawOrderTimeline::setFrame, allow_raw_pointers()) - .function("apply", &DrawOrderTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](DrawOrderTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("IkConstraintTimeline") .constructor() - // static variables - // .function("getProp_ikConstraintIndex", &EventTimeline::getFrames) // private - // .function("getProp_frames", &IkConstraintTimeline::getFrames) + .class_property("ENTRIES", &IkConstraintTimeline::ENTRIES) .function("getPropertyId", &IkConstraintTimeline::getPropertyId) .function("setFrame", &IkConstraintTimeline::setFrame) - .function("apply", &IkConstraintTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](IkConstraintTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("TransformConstraintTimeline") .constructor() - // static variables - // .function("getProp_ikConstraintIndex", &TransformConstraintTimeline::getFrames) // private - //.function("getProp_frames", &TransformConstraintTimeline::getFrames) + .class_property("ENTRIES", &TransformConstraintTimeline::ENTRIES) .function("getPropertyId", &TransformConstraintTimeline::getPropertyId) .function("setFrame", &TransformConstraintTimeline::setFrame) - .function("apply", &TransformConstraintTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](TransformConstraintTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("PathConstraintPositionTimeline") .constructor() - // static variables - // .function("getProp_ikConstraintIndex", &TransformConstraintTimeline::getFrames) // private - //.function("getProp_frames", &TransformConstraintTimeline::getFrames) + .class_property("ENTRIES", &TransformConstraintTimeline::ENTRIES) .function("getPropertyId", &PathConstraintPositionTimeline::getPropertyId) .function("setFrame", &PathConstraintPositionTimeline::setFrame) - .function("apply", &PathConstraintPositionTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](PathConstraintPositionTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_>("PathConstraintMixTimeline") .constructor() + .class_property("ENTRIES", &PathConstraintMixTimeline::ENTRIES) .function("getPropertyId", &PathConstraintMixTimeline::getPropertyId) - .function("apply", &PathConstraintMixTimeline::apply, allow_raw_pointers()); + .function("apply", optional_override([](PathConstraintMixTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), allow_raw_pointers()); class_("TrackEntry") .constructor<>() @@ -941,6 +1183,7 @@ EMSCRIPTEN_BINDINGS(spine) { class_("AnimationStateData") .constructor() .function("getDefaultMix", &AnimationStateData::getDefaultMix) + .function("setDefaultMix", &AnimationStateData::setDefaultMix) .function("getSkeletonData", &AnimationStateData::getSkeletonData, allow_raw_pointers()) .function("setMix", optional_override([](AnimationStateData &obj, const std::string& fromName, const std::string& toName, float duration) { return obj.setMix(STRING_STD2SP(fromName), STRING_STD2SP(toName), duration);})) @@ -948,82 +1191,54 @@ EMSCRIPTEN_BINDINGS(spine) { return obj.setMix(from, to, duration);}), allow_raw_pointers()) .function("getMix", &AnimationStateData::getMix, allow_raw_pointers()); - // .function("setMixWith", &Skeleton::setMixWith_Export) - //.function("getMix", &Skeleton::setMix_Export); - - class_("AnimationState") - .constructor() - // static variables - // .class_function("getProp_emptyAnimation",&AnimationState::getEmptyAnimation, allow_raw_pointers()) // private - .function("getData", &AnimationState::getData, allow_raw_pointers()) - .function("getTracks", optional_override([](AnimationState &obj) { return VECTOR_SP2STD(obj.getTracks()); }), allow_raw_pointers()) - .function("getTimeScale", &AnimationState::getTimeScale) - .function("setTimeScale", &AnimationState::setTimeScale) - //.function("getProp_unkeyedState") - //.function("getProp_events") - //.function("getProp_listeners") - //.function("getProp_queue") - //.function("getProp_queue") - //.function("getProp_propertyIDs", &AnimationState::getPropertyIDs) - //.function("getProp_animationsChanged", &AnimationState::getAnimationsChanged) - //.function("getProp_trackEntryPool", &AnimationState::getTrackEntryPool) - .function("update", &AnimationState::update) - //.function("updateMixingFrom", &AnimationState::updateMixingFrom, allow_raw_pointers()) //private - .function("apply", &AnimationState::apply) - // .function("applyMixingFrom", &AnimationState::applyMixingFrom, allow_raw_pointers()) //private - //.function("applyAttachmentTimeline", &AnimationState::applyAttachmentTimeline) // have no - //.function("setAttachment", &AnimationState::setAttachment) // have no - // .class_function("applyRotateTimeline", &AnimationState::applyRotateTimeline, allow_raw_pointers()) - // .function("queueEvents", &AnimationState::queueEvents, allow_raw_pointers()) - .function("clearTracks", &AnimationState::clearTracks) - .function("clearTrack", &AnimationState::clearTrack) - //.function("setCurrent", &AnimationState::setCurrent, allow_raw_pointers()) // private - .function("setAnimation", optional_override([](AnimationState &obj, uint32_t trackIndex, const std::string &animName, bool loop) { return obj.setAnimation(trackIndex, STRING_STD2SP(animName), loop); }), allow_raw_pointers()) - .function("setAnimationWith", optional_override([](AnimationState &obj, uint32_t trackIndex, Animation *animation, bool loop) { return obj.setAnimation(trackIndex, animation, loop); }), allow_raw_pointers()) - .function("addAnimation", optional_override([](AnimationState &obj, uint32_t trackIndex, const std::string &animName, bool loop, float delay) { return obj.addAnimation(trackIndex, STRING_STD2SP(animName), loop, delay); }), allow_raw_pointers()) - .function("addAnimationWith", optional_override([](AnimationState &obj, uint32_t trackIndex, Animation *animation, bool loop, float delay) { return obj.addAnimation(trackIndex, animation, loop, delay); }), allow_raw_pointers()) - .function("setEmptyAnimation", &AnimationState::setEmptyAnimation, allow_raw_pointers()) - .function("addEmptyAnimation", &AnimationState::addEmptyAnimation, allow_raw_pointers()) - .function("setEmptyAnimations", &AnimationState::setEmptyAnimations) - //.function("expandToIndex", &AnimationState::expandToIndex, allow_raw_pointers()) // private - //.function("trackEntry", &AnimationState::newTrackEntry, allow_raw_pointers()) // private - //.function("disposeNext", &AnimationState::disposeNext) // private - //.function("_animationsChanged", &AnimationState::animationsChanged) // private - //.function("computeHold", &AnimationState::computeHold, allow_raw_pointer()) // private - .function("getCurrent", &AnimationState::getCurrent, allow_raw_pointer()); + class_("AnimationState") + .constructor() + .function("getData", &AnimationState::getData, allow_raw_pointers()) + .function("getTracks", optional_override([](AnimationState &obj) { + return VECTOR_SP2STD(obj.getTracks()); }), allow_raw_pointers()) + .function("getTimeScale", &AnimationState::getTimeScale) + .function("setTimeScale", &AnimationState::setTimeScale) + .function("update", &AnimationState::update) + .function("apply", &AnimationState::apply) + .function("clearTracks", &AnimationState::clearTracks) + .function("clearTrack", &AnimationState::clearTrack) + .function("setAnimation", optional_override([](AnimationState &obj, uint32_t trackIndex, const std::string &animName, bool loop) { return obj.setAnimation(trackIndex, STRING_STD2SP(animName), loop); }), allow_raw_pointers()) + .function("setAnimationWith", optional_override([](AnimationState &obj, uint32_t trackIndex, Animation *animation, bool loop) { return obj.setAnimation(trackIndex, animation, loop); }), allow_raw_pointers()) + .function("addAnimation", optional_override([](AnimationState &obj, uint32_t trackIndex, const std::string &animName, bool loop, float delay) { return obj.addAnimation(trackIndex, STRING_STD2SP(animName), loop, delay); }), allow_raw_pointers()) + .function("addAnimationWith", optional_override([](AnimationState &obj, uint32_t trackIndex, Animation *animation, bool loop, float delay) { return obj.addAnimation(trackIndex, animation, loop, delay); }), allow_raw_pointers()) + .function("setEmptyAnimation", &AnimationState::setEmptyAnimation, allow_raw_pointers()) + .function("addEmptyAnimation", &AnimationState::addEmptyAnimation, allow_raw_pointers()) + .function("setEmptyAnimations", &AnimationState::setEmptyAnimations) + .function("getCurrent", &AnimationState::getCurrent, allow_raw_pointer()) + .function("setListener", optional_override([](AnimationState &obj, AnimationStateListener inValue) { + obj.setListener(inValue); }),allow_raw_pointers()) + .function("setListenerObject", optional_override([](AnimationState &obj, AnimationStateListenerObject *inValue) { + obj.setListener(inValue); }),allow_raw_pointers()) + .function("disableQueue", &AnimationState::disableQueue) + .function("enableQueue", &AnimationState::enableQueue); //.function("addListener", &AnimationState::addListener) //.function("removeListener", &AnimationState::removeListener) //.function("clearListeners", &AnimationState::clearListeners) // no have clearListeners - // .function("clearListenerNotifications", &AnimationState::clearListenerNotifications); // no have clearListenerNotifications - - class_("Animation") - .constructor &, float>() - .function("getName", optional_override([](Animation &obj) { return STRING_SP2STD(obj.getName()); })) - .function("getTimelines", optional_override([](Animation &obj) { return VECTOR_SP2STD(obj.getTimelines()); })) - //.function("getProp_timelineIds", &Animation::getTimelines) - .function("getDuration", &Animation::getDuration) - .function("setDuration", &Animation::setDuration) - .function("hasTimeline", &Animation::hasTimeline) - .function("apply", &Animation::apply, allow_raw_pointers()) - // .class_function("binarySearch", &Animation::binarySearch) - // .class_function("linearSearch", &Animation::linearSearch) - ; - - // private - // class_("EventQueue") - // .constructor& >() - // .function("start", &EventQueue::start, allow_raw_pointers()) - // .function("interrupt", &EventQueue::interrupt, allow_raw_pointers()) - // .function("end", &EventQueue::end, allow_raw_pointers()) - // .function("dispose", &EventQueue::dispose, allow_raw_pointers()) - // .function("complete", &EventQueue::complete, allow_raw_pointers()) - // .function("event", &EventQueue::event, allow_raw_pointers()) - // .function("drain", &EventQueue::drain) - // //.function("clear") - - // class_("AnimationStateListener") - - // class_("AnimationStateAdapter") + + //private + // class_("EventQueue") + // .constructor& >() + // .function("start", &EventQueue::start, allow_raw_pointers()) + // .function("interrupt", &EventQueue::interrupt, allow_raw_pointers()) + // .function("end", &EventQueue::end, allow_raw_pointers()) + // .function("dispose", &EventQueue::dispose, allow_raw_pointers()) + // .function("complete", &EventQueue::complete, allow_raw_pointers()) + // .function("event", &EventQueue::event, allow_raw_pointers()) + // .function("drain", &EventQueue::drain) + // .function("clear"); + + //class_("AnimationStateListener") + + //class_("AnimationStateListenerObject") + // .constructor<>() + // .function("callback", &AnimationStateListenerObject::callback, pure_virtual()); + + //class_("AnimationStateAdapter") class_("Skeleton") .constructor() @@ -1041,22 +1256,20 @@ EMSCRIPTEN_BINDINGS(spine) { .function("getPathConstraints", optional_override([](Skeleton &obj) { return VECTOR_SP2STD(obj.getPathConstraints()); }), allow_raw_pointers()) .function("getUpdateCacheList", &Skeleton::getUpdateCacheList, allow_raw_pointer()) - //.function("getProp_updateCacheReset", Skeleton::) .function("getSkin", &Skeleton::getSkin, allow_raw_pointer()) - .function("getColor", &Skeleton::getColor) + .function("getColor", optional_override([](Skeleton &obj){ + return &obj.getColor(); }), allow_raw_pointers()) .function("getTime", &Skeleton::getTime) + .function("setTime", &Skeleton::setTime) .function("getScaleX", &Skeleton::getScaleX) + .function("setScaleX", &Skeleton::setScaleX) .function("getScaleY", &Skeleton::getScaleY) + .function("setScaleY", &Skeleton::setScaleY) .function("getX", &Skeleton::getX) + .function("setX", &Skeleton::setX) .function("getY", &Skeleton::getY) + .function("setY", &Skeleton::setY) .function("updateCache", &Skeleton::updateCache) - //.function("sortIkConstraint") - //.function("sortPathConstraint") - //.function("sortTransformConstraint") - //.function("sortPathConstraintAttachment") - //.function("sortPathConstraintAttachmentWith") - // .function("sortBone", &Skeleton::sortBone, allow_raw_pointer()) - // .function("sortReset", &Skeleton::sortReset, allow_raw_pointer()) .function("updateWorldTransform", &Skeleton::updateWorldTransform) .function("setToSetupPose", &Skeleton::setToSetupPose) .function("setBonesToSetupPose", &Skeleton::setBonesToSetupPose) @@ -1080,97 +1293,104 @@ EMSCRIPTEN_BINDINGS(spine) { .function("setAttachment", optional_override([](Skeleton &obj, const std::string& slotName, const std::string& attachmentName) { return obj.setAttachment(STRING_STD2SP(slotName), STRING_STD2SP(attachmentName));})) .function("findIkConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findIkConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findTransformConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findTransformConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - .function("findPathConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findPathConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) - //.function("getBounds", &Skeleton::getBounds) - .function("update", &Skeleton::update); - - // incomplete - // class_("SkeletonBinary") - // .constructor() - // .function("setProp_scale", &SkeletonBinary::setScale); - //.function("getProp_scale", &SkeletonBinary::getScale) - //.function("readSkeletonData", &SkeletonBinary::readSkeletonData) - //.function("setCurve", &SkeletonBinary::setCurve); - // incomplete - - // class_("SkeletonJson") - // .constructor() - // .constructor(); - //.function("readSkeletonData", &SkeletonJson::readSkeletonData) - //.function("getProp_scale", &SkeletonJson::getScale) - - class_("VertexEffect") - .function("begin", &VertexEffect::begin, pure_virtual()) - //.function("transform", &VertexEffect::transform, pure_virtual()) - .function("end", &VertexEffect::end, pure_virtual()); - - class_>("JitterEffect") - .constructor() - .function("getJitterX", &JitterVertexEffect::getJitterX) - .function("setJitterX", &JitterVertexEffect::setJitterX) - .function("getJitterY", &JitterVertexEffect::getJitterY) - .function("setJitterY", &JitterVertexEffect::setJitterY) - .function("begin", &JitterVertexEffect::begin) - //.function("transform", &JitterVertexEffect::transform) - .function("end", &JitterVertexEffect::end); - - class_>("SwirlEffect") - .constructor() - .function("getCenterX", &SwirlVertexEffect::getCenterX) - .function("setCenterX", &SwirlVertexEffect::setCenterX) - .function("getCenterY", &SwirlVertexEffect::getCenterY) - .function("setCenterY", &SwirlVertexEffect::setCenterY) - .function("getRadius", &SwirlVertexEffect::getRadius) - .function("setRadius", &SwirlVertexEffect::setRadius) - .function("getAngle", &SwirlVertexEffect::getAngle) - .function("setAngle", &SwirlVertexEffect::setAngle) - .function("begin", &SwirlVertexEffect::begin) - //.function("transform", &SwirlVertexEffect::transform) - .function("end", &SwirlVertexEffect::end); - - class_("SlotMesh") - .property("vCount", &SlotMesh::vCount) - .property("iCount", &SlotMesh::iCount) - .property("blendMode", &SlotMesh::blendMode) - .property("textureID", &SlotMesh::textureID); - - register_vector("VectorSlotMesh"); - class_("SpineModel") - .property("vCount", &SpineModel::vCount) - .property("iCount", &SpineModel::iCount) - .property("vPtr", &SpineModel::vPtr) - .property("iPtr", &SpineModel::iPtr) - .function("getMeshes", &SpineModel::getMeshes); - - class_("SpineDebugShape") - .property("type", &SpineDebugShape::type) - .property("vOffset", &SpineDebugShape::vOffset) - .property("vCount", &SpineDebugShape::vCount) - .property("iOffset", &SpineDebugShape::iOffset) - .property("iCount", &SpineDebugShape::iCount); - - register_vector("VectorDebugShape"); - class_("SkeletonInstance") - .constructor<>() - .function("initSkeleton", &SpineSkeletonInstance::initSkeleton, allow_raw_pointers()) - .function("setAnimation", &SpineSkeletonInstance::setAnimation, allow_raw_pointers()) - .function("setSkin", &SpineSkeletonInstance::setSkin) - .function("updateAnimation", &SpineSkeletonInstance::updateAnimation) - .function("updateRenderData", &SpineSkeletonInstance::updateRenderData, allow_raw_pointer()) - .function("setPremultipliedAlpha", &SpineSkeletonInstance::setPremultipliedAlpha) - .function("setUseTint", &SpineSkeletonInstance::setUseTint) - .function("setColor", &SpineSkeletonInstance::setColor) - .function("setJitterEffect", &SpineSkeletonInstance::setJitterEffect, allow_raw_pointer()) - .function("setSwirlEffect", &SpineSkeletonInstance::setSwirlEffect, allow_raw_pointer()) - .function("clearEffect", &SpineSkeletonInstance::clearEffect) - .function("getAnimationState", &SpineSkeletonInstance::getAnimationState, allow_raw_pointer()) - .function("setMix", &SpineSkeletonInstance::setMix) - .function("setListener", &SpineSkeletonInstance::setListener) - .function("setDebugMode", &SpineSkeletonInstance::setDebugMode) - .function("getDebugShapes", &SpineSkeletonInstance::getDebugShapes) - .function("resizeSlotRegion", &SpineSkeletonInstance::resizeSlotRegion) - .function("setSlotTexture", &SpineSkeletonInstance::setSlotTexture); + .function("findTransformConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findTransformConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) + .function("findPathConstraint", optional_override([](Skeleton &obj, const std::string &name) { return obj.findPathConstraint(STRING_STD2SP(name)); }), allow_raw_pointers()) + //.function("getBounds", optional_override([](Skeleton &obj, &outX, ) {}), allow_raw_pointers()) + .function("update", &Skeleton::update); + + //incomplete + // class_("SkeletonBinary") + // .constructor() + // .constructor() + // .function("setScale", &SkeletonBinary::setScale) + // .function("getError", &SkeletonBinary::getError); + //.function("readSkeletonDataFile", optional_override([](SkeletonBinary &obj, const spine::String& path) { return obj.readSkeletonDataFile(path); })); + + // incomplete + //class_("SkeletonJson") + //.constructor() + //.constructor() + //.function("setScale", &SkeletonJson::setScale); + //.function("getError", &SkeletonJson::getError); + + class_("VertexEffect") + .function("begin", &VertexEffect::begin, pure_virtual()) + .function("transform", optional_override([](VertexEffect &obj, float x, float y) { + obj.transform(x, y); }), pure_virtual()) + .function("end", &VertexEffect::end, pure_virtual()); + + class_>("JitterEffect") + .constructor() + .function("getJitterX", &JitterVertexEffect::getJitterX) + .function("setJitterX", &JitterVertexEffect::setJitterX) + .function("getJitterY", &JitterVertexEffect::getJitterY) + .function("setJitterY", &JitterVertexEffect::setJitterY) + .function("begin", &JitterVertexEffect::begin) + .function("transform", optional_override([](VertexEffect &obj, float x, float y) { + obj.transform(x, y); }), pure_virtual()) + .function("end", &JitterVertexEffect::end); + + class_>("SwirlEffect") + .constructor() + .function("begin", &SwirlVertexEffect::begin) + .function("transform", optional_override([](VertexEffect &obj, float x, float y) { + obj.transform(x, y); }), pure_virtual()) + .function("end", &SwirlVertexEffect::end) + .function("getCenterX", &SwirlVertexEffect::getCenterX) + .function("setCenterX", &SwirlVertexEffect::setCenterX) + .function("getCenterY", &SwirlVertexEffect::getCenterY) + .function("setCenterY", &SwirlVertexEffect::setCenterY) + .function("getRadius", &SwirlVertexEffect::getRadius) + .function("setRadius", &SwirlVertexEffect::setRadius) + .function("getAngle", &SwirlVertexEffect::getAngle) + .function("setAngle", &SwirlVertexEffect::setAngle) + .function("getWorldX", &SwirlVertexEffect::getWorldX) + .function("setWorldX", &SwirlVertexEffect::setWorldX) + .function("getWorldY", &SwirlVertexEffect::getWorldY) + .function("setWorldY", &SwirlVertexEffect::setWorldY); + + class_("SlotMesh") + .property("vCount", &SlotMesh::vCount) + .property("iCount", &SlotMesh::iCount) + .property("blendMode", &SlotMesh::blendMode) + .property("textureID", &SlotMesh::textureID); + + register_vector("VectorSlotMesh"); + class_("SpineModel") + .property("vCount", &SpineModel::vCount) + .property("iCount", &SpineModel::iCount) + .property("vPtr", &SpineModel::vPtr) + .property("iPtr", &SpineModel::iPtr) + .function("getMeshes", &SpineModel::getMeshes); + + class_("SpineDebugShape") + .property("type", &SpineDebugShape::type) + .property("vOffset", &SpineDebugShape::vOffset) + .property("vCount", &SpineDebugShape::vCount) + .property("iOffset", &SpineDebugShape::iOffset) + .property("iCount", &SpineDebugShape::iCount); + + register_vector("VectorDebugShape"); + class_("SkeletonInstance") + .constructor<>() + .function("initSkeleton", &SpineSkeletonInstance::initSkeleton, allow_raw_pointers()) + .function("setAnimation", &SpineSkeletonInstance::setAnimation, allow_raw_pointers()) + .function("setSkin", &SpineSkeletonInstance::setSkin) + .function("updateAnimation", &SpineSkeletonInstance::updateAnimation) + .function("updateRenderData", &SpineSkeletonInstance::updateRenderData, allow_raw_pointer()) + .function("setPremultipliedAlpha", &SpineSkeletonInstance::setPremultipliedAlpha) + .function("setUseTint", &SpineSkeletonInstance::setUseTint) + .function("setColor", &SpineSkeletonInstance::setColor) + .function("setJitterEffect", &SpineSkeletonInstance::setJitterEffect, allow_raw_pointer()) + .function("setSwirlEffect", &SpineSkeletonInstance::setSwirlEffect, allow_raw_pointer()) + .function("clearEffect", &SpineSkeletonInstance::clearEffect) + .function("getAnimationState", &SpineSkeletonInstance::getAnimationState, allow_raw_pointer()) + .function("setMix", &SpineSkeletonInstance::setMix) + .function("setListener", &SpineSkeletonInstance::setListener) + .function("setDebugMode", &SpineSkeletonInstance::setDebugMode) + .function("getDebugShapes", &SpineSkeletonInstance::getDebugShapes) + .function("resizeSlotRegion", &SpineSkeletonInstance::resizeSlotRegion) + .function("setSlotTexture", &SpineSkeletonInstance::setSlotTexture); } EMSCRIPTEN_BINDINGS(cocos_spine) { diff --git a/native/external-config.json b/native/external-config.json index 9b92430ee9a..1ce55742884 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-12" + "checkout": "v3.8.1-14" } } \ No newline at end of file From 46592f013b3f7c3697fe4da33be5a153caef5a15 Mon Sep 17 00:00:00 2001 From: Cocos Robot <48829427+cocos-robot@users.noreply.github.com> Date: Mon, 21 Aug 2023 13:43:36 +0800 Subject: [PATCH 158/184] [ci skip][AUTO]: Automated code generating update: 0af68e43e95326958afc65ae5e6849ef8ac59c5d (#16023) (#16043) Co-authored-by: cocos-robot --- native/cocos/core/builtin/DebugInfos.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/native/cocos/core/builtin/DebugInfos.cpp b/native/cocos/core/builtin/DebugInfos.cpp index 8571eefcfa6..31ed13ab8ee 100644 --- a/native/cocos/core/builtin/DebugInfos.cpp +++ b/native/cocos/core/builtin/DebugInfos.cpp @@ -464,6 +464,9 @@ ccstd::unordered_map debugInfos = { { 14100, "Pool.destroy no longer take a function as parameter, Please specify destruct function in the construction of Pool instead" }, { 14200, "Can not update a static mesh." }, { 14201, "The primitiveIndex is out of range." }, +{ 14202, "meshopt asm decoder initialized" }, +{ 14203, "meshopt wasm decoder initialized" }, +{ 14204, "meshopt decoder error: %d" }, { 14300, "Can not keep world transform due to the zero scaling of parent node" }, { 14400, "Spline error: less than 2 knots." }, { 14401, "Spline error: less than 4 knots or not a multiple of 4.\n\n" }, From f55f423fe8695f51abffb82252d2b6d6d9ea5b7e Mon Sep 17 00:00:00 2001 From: ChiaNing Date: Mon, 21 Aug 2023 14:54:32 +0800 Subject: [PATCH 159/184] update meta (#16051) --- editor/assets/default_prefab/2d/Camera.prefab.meta | 2 +- editor/assets/default_prefab/2d/ui/Canvas.prefab.meta | 2 +- editor/assets/default_prefab/3d/Capsule.prefab.meta | 2 +- editor/assets/default_prefab/3d/Cone.prefab.meta | 2 +- editor/assets/default_prefab/3d/Cube.prefab.meta | 2 +- editor/assets/default_prefab/3d/Cylinder.prefab.meta | 2 +- editor/assets/default_prefab/3d/Plane.prefab.meta | 2 +- editor/assets/default_prefab/3d/Quad.prefab.meta | 2 +- editor/assets/default_prefab/3d/Sphere.prefab.meta | 2 +- editor/assets/default_prefab/3d/Torus.prefab.meta | 2 +- editor/assets/default_prefab/Camera.prefab | 2 +- editor/assets/default_prefab/Camera.prefab.meta | 2 +- editor/assets/default_prefab/Terrain.prefab.meta | 2 +- .../assets/default_prefab/effects/Particle System.prefab.meta | 2 +- .../assets/default_prefab/light/Directional Light.prefab.meta | 2 +- .../assets/default_prefab/light/Light Probe Group.prefab.meta | 2 +- editor/assets/default_prefab/light/Point Light.prefab | 2 +- editor/assets/default_prefab/light/Point Light.prefab.meta | 2 +- .../default_prefab/light/Ranged Directional Light.prefab | 2 +- .../default_prefab/light/Ranged Directional Light.prefab.meta | 2 +- .../assets/default_prefab/light/Reflection Probe.prefab.meta | 2 +- editor/assets/default_prefab/light/Sphere Light.prefab.meta | 2 +- editor/assets/default_prefab/light/Spot Light.prefab.meta | 2 +- editor/assets/default_prefab/ui/Button.prefab.meta | 2 +- editor/assets/default_prefab/ui/Canvas.prefab.meta | 2 +- editor/assets/default_prefab/ui/EditBox.prefab | 2 +- editor/assets/default_prefab/ui/EditBox.prefab.meta | 2 +- editor/assets/default_prefab/ui/Graphics.prefab.meta | 2 +- editor/assets/default_prefab/ui/Label.prefab.meta | 2 +- editor/assets/default_prefab/ui/Layout.prefab.meta | 2 +- editor/assets/default_prefab/ui/Mask.prefab.meta | 2 +- editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta | 2 +- editor/assets/default_prefab/ui/ProgressBar.prefab | 4 ++-- editor/assets/default_prefab/ui/ProgressBar.prefab.meta | 2 +- editor/assets/default_prefab/ui/RichText.prefab.meta | 2 +- editor/assets/default_prefab/ui/ScrollView.prefab.meta | 2 +- editor/assets/default_prefab/ui/Slider.prefab | 4 ++-- editor/assets/default_prefab/ui/Slider.prefab.meta | 2 +- editor/assets/default_prefab/ui/Sprite.prefab.meta | 2 +- editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta | 2 +- editor/assets/default_prefab/ui/SpriteSplash.prefab.meta | 2 +- editor/assets/default_prefab/ui/TiledMap.prefab.meta | 2 +- editor/assets/default_prefab/ui/Toggle.prefab.meta | 2 +- editor/assets/default_prefab/ui/ToggleContainer.prefab.meta | 2 +- editor/assets/default_prefab/ui/VideoPlayer.prefab.meta | 2 +- editor/assets/default_prefab/ui/WebView.prefab.meta | 2 +- editor/assets/default_prefab/ui/Widget.prefab.meta | 2 +- editor/assets/default_prefab/ui/pageView.prefab.meta | 2 +- editor/assets/tools/debug-view-runtime-control.prefab.meta | 2 +- 49 files changed, 51 insertions(+), 51 deletions(-) diff --git a/editor/assets/default_prefab/2d/Camera.prefab.meta b/editor/assets/default_prefab/2d/Camera.prefab.meta index 9140b81984e..2a9efe9d3ad 100644 --- a/editor/assets/default_prefab/2d/Camera.prefab.meta +++ b/editor/assets/default_prefab/2d/Camera.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "3487d118-0158-4983-93fe-c3822790e7c5", diff --git a/editor/assets/default_prefab/2d/ui/Canvas.prefab.meta b/editor/assets/default_prefab/2d/ui/Canvas.prefab.meta index 955de65ec05..7a02f8602a3 100644 --- a/editor/assets/default_prefab/2d/ui/Canvas.prefab.meta +++ b/editor/assets/default_prefab/2d/ui/Canvas.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "4c33600e-9ca9-483b-b734-946008261697", diff --git a/editor/assets/default_prefab/3d/Capsule.prefab.meta b/editor/assets/default_prefab/3d/Capsule.prefab.meta index a5a21cf019f..2cdc8360ae1 100644 --- a/editor/assets/default_prefab/3d/Capsule.prefab.meta +++ b/editor/assets/default_prefab/3d/Capsule.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "73ce1f7f-d1f4-4942-ad93-66ca3b3041ab", diff --git a/editor/assets/default_prefab/3d/Cone.prefab.meta b/editor/assets/default_prefab/3d/Cone.prefab.meta index 5b5113f9f0d..caef62b443a 100644 --- a/editor/assets/default_prefab/3d/Cone.prefab.meta +++ b/editor/assets/default_prefab/3d/Cone.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "6350d660-e888-4acf-a552-f3b719ae9110", diff --git a/editor/assets/default_prefab/3d/Cube.prefab.meta b/editor/assets/default_prefab/3d/Cube.prefab.meta index 12020ef451a..7a3b4277d85 100644 --- a/editor/assets/default_prefab/3d/Cube.prefab.meta +++ b/editor/assets/default_prefab/3d/Cube.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "30da77a1-f02d-4ede-aa56-403452ee7fde", diff --git a/editor/assets/default_prefab/3d/Cylinder.prefab.meta b/editor/assets/default_prefab/3d/Cylinder.prefab.meta index 6c5684fdca6..de6fd2091f3 100644 --- a/editor/assets/default_prefab/3d/Cylinder.prefab.meta +++ b/editor/assets/default_prefab/3d/Cylinder.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "ab3e16f9-671e-48a7-90b7-d0884d9cbb85", diff --git a/editor/assets/default_prefab/3d/Plane.prefab.meta b/editor/assets/default_prefab/3d/Plane.prefab.meta index d38151b7473..762d5e1c3cb 100644 --- a/editor/assets/default_prefab/3d/Plane.prefab.meta +++ b/editor/assets/default_prefab/3d/Plane.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "40563723-f8fc-4216-99ea-a81636435c10", diff --git a/editor/assets/default_prefab/3d/Quad.prefab.meta b/editor/assets/default_prefab/3d/Quad.prefab.meta index dc8e2b361b2..05f6a30a78f 100644 --- a/editor/assets/default_prefab/3d/Quad.prefab.meta +++ b/editor/assets/default_prefab/3d/Quad.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "34a07346-9f62-4a84-90ae-cb83f7a426c1", diff --git a/editor/assets/default_prefab/3d/Sphere.prefab.meta b/editor/assets/default_prefab/3d/Sphere.prefab.meta index ab4f2ec0c6f..379f0318d21 100644 --- a/editor/assets/default_prefab/3d/Sphere.prefab.meta +++ b/editor/assets/default_prefab/3d/Sphere.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "655c9519-1a37-472b-bae6-29fefac0b550", diff --git a/editor/assets/default_prefab/3d/Torus.prefab.meta b/editor/assets/default_prefab/3d/Torus.prefab.meta index eb825d2f575..1c916b0f66e 100644 --- a/editor/assets/default_prefab/3d/Torus.prefab.meta +++ b/editor/assets/default_prefab/3d/Torus.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "d47f5d5e-c931-4ff4-987b-cc818a728b82", diff --git a/editor/assets/default_prefab/Camera.prefab b/editor/assets/default_prefab/Camera.prefab index 8e18549598c..78c68520fcc 100644 --- a/editor/assets/default_prefab/Camera.prefab +++ b/editor/assets/default_prefab/Camera.prefab @@ -107,4 +107,4 @@ }, "fileId": "f8Nyw5r0hH9Zz+WrOqK1x/" } -] +] \ No newline at end of file diff --git a/editor/assets/default_prefab/Camera.prefab.meta b/editor/assets/default_prefab/Camera.prefab.meta index c59e4c5e4a4..647ff9aef3a 100644 --- a/editor/assets/default_prefab/Camera.prefab.meta +++ b/editor/assets/default_prefab/Camera.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "bb0a6472-cd67-4afb-a031-94fca8f4cc92", diff --git a/editor/assets/default_prefab/Terrain.prefab.meta b/editor/assets/default_prefab/Terrain.prefab.meta index 4cd34a340d4..66b2240a22e 100644 --- a/editor/assets/default_prefab/Terrain.prefab.meta +++ b/editor/assets/default_prefab/Terrain.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "90e8b0d4-12dc-412d-9156-ea1fdb18c15b", diff --git a/editor/assets/default_prefab/effects/Particle System.prefab.meta b/editor/assets/default_prefab/effects/Particle System.prefab.meta index 6623a93f2bb..fc311329e1c 100644 --- a/editor/assets/default_prefab/effects/Particle System.prefab.meta +++ b/editor/assets/default_prefab/effects/Particle System.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "f09a0597-10e6-49e5-8759-a148b5e85395", diff --git a/editor/assets/default_prefab/light/Directional Light.prefab.meta b/editor/assets/default_prefab/light/Directional Light.prefab.meta index 5294e53fb64..89d28c73bdc 100644 --- a/editor/assets/default_prefab/light/Directional Light.prefab.meta +++ b/editor/assets/default_prefab/light/Directional Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "a0e9756d-9128-4f49-8097-e041c8b733b8", diff --git a/editor/assets/default_prefab/light/Light Probe Group.prefab.meta b/editor/assets/default_prefab/light/Light Probe Group.prefab.meta index 91718973579..197281caacb 100644 --- a/editor/assets/default_prefab/light/Light Probe Group.prefab.meta +++ b/editor/assets/default_prefab/light/Light Probe Group.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.45", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "50dfda40-7c45-4868-a876-2fe2a4c782f4", diff --git a/editor/assets/default_prefab/light/Point Light.prefab b/editor/assets/default_prefab/light/Point Light.prefab index cb555e0070c..7f1cd6c7791 100644 --- a/editor/assets/default_prefab/light/Point Light.prefab +++ b/editor/assets/default_prefab/light/Point Light.prefab @@ -94,4 +94,4 @@ }, "fileId": "59eikBZx5K9aR06hUuVC37" } -] +] \ No newline at end of file diff --git a/editor/assets/default_prefab/light/Point Light.prefab.meta b/editor/assets/default_prefab/light/Point Light.prefab.meta index 54d9e7a4705..598d473c0e3 100644 --- a/editor/assets/default_prefab/light/Point Light.prefab.meta +++ b/editor/assets/default_prefab/light/Point Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "03029371-ee64-4f14-820a-d495ad7cdc29", diff --git a/editor/assets/default_prefab/light/Ranged Directional Light.prefab b/editor/assets/default_prefab/light/Ranged Directional Light.prefab index 73afa3b15ff..eaa64795ad6 100644 --- a/editor/assets/default_prefab/light/Ranged Directional Light.prefab +++ b/editor/assets/default_prefab/light/Ranged Directional Light.prefab @@ -92,4 +92,4 @@ }, "fileId": "aeyMch0nJBEbV/mk9CXYkW" } -] +] \ No newline at end of file diff --git a/editor/assets/default_prefab/light/Ranged Directional Light.prefab.meta b/editor/assets/default_prefab/light/Ranged Directional Light.prefab.meta index 9181f35f84d..69df4adf90d 100644 --- a/editor/assets/default_prefab/light/Ranged Directional Light.prefab.meta +++ b/editor/assets/default_prefab/light/Ranged Directional Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "df72d0f6-49d3-452a-b082-8b23d38b33af", diff --git a/editor/assets/default_prefab/light/Reflection Probe.prefab.meta b/editor/assets/default_prefab/light/Reflection Probe.prefab.meta index 872b7155bc6..0e0ab920114 100644 --- a/editor/assets/default_prefab/light/Reflection Probe.prefab.meta +++ b/editor/assets/default_prefab/light/Reflection Probe.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "d8b49b64-cfba-4cfa-be53-1e469547b28b", diff --git a/editor/assets/default_prefab/light/Sphere Light.prefab.meta b/editor/assets/default_prefab/light/Sphere Light.prefab.meta index f6235f6b6d1..1bebad0a135 100644 --- a/editor/assets/default_prefab/light/Sphere Light.prefab.meta +++ b/editor/assets/default_prefab/light/Sphere Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "4182ee46-ffa0-4de2-b66b-c93cc6c7e9b8", diff --git a/editor/assets/default_prefab/light/Spot Light.prefab.meta b/editor/assets/default_prefab/light/Spot Light.prefab.meta index 911d5933b42..d60bc004f17 100644 --- a/editor/assets/default_prefab/light/Spot Light.prefab.meta +++ b/editor/assets/default_prefab/light/Spot Light.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "7a49aa24-bd7a-40a8-b31a-b2a9da85abcd", diff --git a/editor/assets/default_prefab/ui/Button.prefab.meta b/editor/assets/default_prefab/ui/Button.prefab.meta index 6b0771367ba..22327fc1710 100644 --- a/editor/assets/default_prefab/ui/Button.prefab.meta +++ b/editor/assets/default_prefab/ui/Button.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "90bdd2a9-2838-4888-b66c-e94c8b7a5169", diff --git a/editor/assets/default_prefab/ui/Canvas.prefab.meta b/editor/assets/default_prefab/ui/Canvas.prefab.meta index 4384e4d0773..a398ec48963 100644 --- a/editor/assets/default_prefab/ui/Canvas.prefab.meta +++ b/editor/assets/default_prefab/ui/Canvas.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "f773db21-62b8-4540-956a-29bacf5ddbf5", diff --git a/editor/assets/default_prefab/ui/EditBox.prefab b/editor/assets/default_prefab/ui/EditBox.prefab index a7de7d3c8fb..300ba6dc4e3 100644 --- a/editor/assets/default_prefab/ui/EditBox.prefab +++ b/editor/assets/default_prefab/ui/EditBox.prefab @@ -379,7 +379,7 @@ }, "_type": 1, "_fillType": 0, - "_sizeMode": 1, + "_sizeMode": 0, "_fillCenter": { "__type__": "cc.Vec2", "x": 0, diff --git a/editor/assets/default_prefab/ui/EditBox.prefab.meta b/editor/assets/default_prefab/ui/EditBox.prefab.meta index f3ead2aa227..d72c1f6fb58 100644 --- a/editor/assets/default_prefab/ui/EditBox.prefab.meta +++ b/editor/assets/default_prefab/ui/EditBox.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "05e79121-8675-4551-9ad7-1b901a4025db", diff --git a/editor/assets/default_prefab/ui/Graphics.prefab.meta b/editor/assets/default_prefab/ui/Graphics.prefab.meta index 406c853a9f5..7c692252572 100644 --- a/editor/assets/default_prefab/ui/Graphics.prefab.meta +++ b/editor/assets/default_prefab/ui/Graphics.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "c96e159e-43ea-4a16-8279-05bc39119d1a", diff --git a/editor/assets/default_prefab/ui/Label.prefab.meta b/editor/assets/default_prefab/ui/Label.prefab.meta index 2c633805df3..6a5eacbd453 100644 --- a/editor/assets/default_prefab/ui/Label.prefab.meta +++ b/editor/assets/default_prefab/ui/Label.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "36008810-7ad3-47c0-8112-e30aee089e45", diff --git a/editor/assets/default_prefab/ui/Layout.prefab.meta b/editor/assets/default_prefab/ui/Layout.prefab.meta index ac6f83cd8ab..01428016c51 100644 --- a/editor/assets/default_prefab/ui/Layout.prefab.meta +++ b/editor/assets/default_prefab/ui/Layout.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "a9ef7dfc-ea8b-4cf8-918e-36da948c4de0", diff --git a/editor/assets/default_prefab/ui/Mask.prefab.meta b/editor/assets/default_prefab/ui/Mask.prefab.meta index 2b415c21c59..377ec5e6f5a 100644 --- a/editor/assets/default_prefab/ui/Mask.prefab.meta +++ b/editor/assets/default_prefab/ui/Mask.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "7fa63aed-f3e2-46a5-8a7c-c1a1adf6cea6", diff --git a/editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta b/editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta index 4876341a321..7072bfdef2b 100644 --- a/editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta +++ b/editor/assets/default_prefab/ui/ParticleSystem2D.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "f396261e-3e06-41ec-bdd6-9a8b6d99026f", diff --git a/editor/assets/default_prefab/ui/ProgressBar.prefab b/editor/assets/default_prefab/ui/ProgressBar.prefab index f87bd959eea..55faf5852a9 100644 --- a/editor/assets/default_prefab/ui/ProgressBar.prefab +++ b/editor/assets/default_prefab/ui/ProgressBar.prefab @@ -165,7 +165,7 @@ }, "_type": 1, "_fillType": 0, - "_sizeMode": 1, + "_sizeMode": 0, "_fillCenter": { "__type__": "cc.Vec2", "x": 0, @@ -245,7 +245,7 @@ }, "_type": 1, "_fillType": 0, - "_sizeMode": 1, + "_sizeMode": 0, "_fillCenter": { "__type__": "cc.Vec2", "x": 0, diff --git a/editor/assets/default_prefab/ui/ProgressBar.prefab.meta b/editor/assets/default_prefab/ui/ProgressBar.prefab.meta index 2f564bd5be8..e73a3746162 100644 --- a/editor/assets/default_prefab/ui/ProgressBar.prefab.meta +++ b/editor/assets/default_prefab/ui/ProgressBar.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "0d9353c4-6fb9-49bb-bc62-77f1750078c2", diff --git a/editor/assets/default_prefab/ui/RichText.prefab.meta b/editor/assets/default_prefab/ui/RichText.prefab.meta index 09136191923..262b90f4b93 100644 --- a/editor/assets/default_prefab/ui/RichText.prefab.meta +++ b/editor/assets/default_prefab/ui/RichText.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "fc6bfcfa-8086-4326-809b-0ba1226bac7d", diff --git a/editor/assets/default_prefab/ui/ScrollView.prefab.meta b/editor/assets/default_prefab/ui/ScrollView.prefab.meta index a54b724011e..98626d08d6f 100644 --- a/editor/assets/default_prefab/ui/ScrollView.prefab.meta +++ b/editor/assets/default_prefab/ui/ScrollView.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "c1baa707-78d6-4b89-8d5d-0b7fdf0c39bc", diff --git a/editor/assets/default_prefab/ui/Slider.prefab b/editor/assets/default_prefab/ui/Slider.prefab index c33106ae8e8..b404e1bb6b3 100644 --- a/editor/assets/default_prefab/ui/Slider.prefab +++ b/editor/assets/default_prefab/ui/Slider.prefab @@ -170,7 +170,7 @@ }, "_type": 0, "_fillType": 0, - "_sizeMode": 1, + "_sizeMode": 0, "_fillCenter": { "__type__": "cc.Vec2", "x": 0, @@ -311,7 +311,7 @@ }, "_type": 1, "_fillType": 0, - "_sizeMode": 1, + "_sizeMode": 0, "_fillCenter": { "__type__": "cc.Vec2", "x": 0, diff --git a/editor/assets/default_prefab/ui/Slider.prefab.meta b/editor/assets/default_prefab/ui/Slider.prefab.meta index e74b124a086..70669c12858 100644 --- a/editor/assets/default_prefab/ui/Slider.prefab.meta +++ b/editor/assets/default_prefab/ui/Slider.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "2bd7e5b6-cd8c-41a1-8136-ddb8efbf6326", diff --git a/editor/assets/default_prefab/ui/Sprite.prefab.meta b/editor/assets/default_prefab/ui/Sprite.prefab.meta index da1efd5e39a..26cd9988001 100644 --- a/editor/assets/default_prefab/ui/Sprite.prefab.meta +++ b/editor/assets/default_prefab/ui/Sprite.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "9db8cd0b-cbe4-42e7-96a9-a239620c0a9d", diff --git a/editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta b/editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta index 40cf1cc1d08..a257d54f0a8 100644 --- a/editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta +++ b/editor/assets/default_prefab/ui/SpriteRenderer.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "279ed042-5a65-4efe-9afb-2fc23c61e15a", diff --git a/editor/assets/default_prefab/ui/SpriteSplash.prefab.meta b/editor/assets/default_prefab/ui/SpriteSplash.prefab.meta index cbfcc852751..cb3d5a47078 100644 --- a/editor/assets/default_prefab/ui/SpriteSplash.prefab.meta +++ b/editor/assets/default_prefab/ui/SpriteSplash.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "e5f21aad-3a69-4011-ac62-b74352ac025e", diff --git a/editor/assets/default_prefab/ui/TiledMap.prefab.meta b/editor/assets/default_prefab/ui/TiledMap.prefab.meta index 4b1b2c4e25c..53301ade82b 100644 --- a/editor/assets/default_prefab/ui/TiledMap.prefab.meta +++ b/editor/assets/default_prefab/ui/TiledMap.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "3139fa4f-8c42-4ce6-98be-15e848d9734c", diff --git a/editor/assets/default_prefab/ui/Toggle.prefab.meta b/editor/assets/default_prefab/ui/Toggle.prefab.meta index bd92c9057e5..c05f65aa9f0 100644 --- a/editor/assets/default_prefab/ui/Toggle.prefab.meta +++ b/editor/assets/default_prefab/ui/Toggle.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "0e89afe7-56de-4f99-96a1-cba8a75bedd2", diff --git a/editor/assets/default_prefab/ui/ToggleContainer.prefab.meta b/editor/assets/default_prefab/ui/ToggleContainer.prefab.meta index 311dc9b3c86..e3affc6f159 100644 --- a/editor/assets/default_prefab/ui/ToggleContainer.prefab.meta +++ b/editor/assets/default_prefab/ui/ToggleContainer.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "2af73429-41d1-4346-9062-7798e42945dd", diff --git a/editor/assets/default_prefab/ui/VideoPlayer.prefab.meta b/editor/assets/default_prefab/ui/VideoPlayer.prefab.meta index 9f090bd41eb..24a28385ecc 100644 --- a/editor/assets/default_prefab/ui/VideoPlayer.prefab.meta +++ b/editor/assets/default_prefab/ui/VideoPlayer.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "7e089eaf-fa97-40d7-8a20-741a152585df", diff --git a/editor/assets/default_prefab/ui/WebView.prefab.meta b/editor/assets/default_prefab/ui/WebView.prefab.meta index a5df7884ecc..7ad242dfe02 100644 --- a/editor/assets/default_prefab/ui/WebView.prefab.meta +++ b/editor/assets/default_prefab/ui/WebView.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "9c541fa2-1dc8-4d8b-813a-aec89133f5b1", diff --git a/editor/assets/default_prefab/ui/Widget.prefab.meta b/editor/assets/default_prefab/ui/Widget.prefab.meta index bcf252290f4..e1ed816df8a 100644 --- a/editor/assets/default_prefab/ui/Widget.prefab.meta +++ b/editor/assets/default_prefab/ui/Widget.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "36ed4422-3542-4cc4-bf02-dc4bfc590836", diff --git a/editor/assets/default_prefab/ui/pageView.prefab.meta b/editor/assets/default_prefab/ui/pageView.prefab.meta index 95d4ec9593f..3c4e7e8d451 100644 --- a/editor/assets/default_prefab/ui/pageView.prefab.meta +++ b/editor/assets/default_prefab/ui/pageView.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "20a5d8cb-ccad-4543-a937-fccd98c9f3de", diff --git a/editor/assets/tools/debug-view-runtime-control.prefab.meta b/editor/assets/tools/debug-view-runtime-control.prefab.meta index 8ed35ee2c61..34527f2712b 100644 --- a/editor/assets/tools/debug-view-runtime-control.prefab.meta +++ b/editor/assets/tools/debug-view-runtime-control.prefab.meta @@ -1,5 +1,5 @@ { - "ver": "1.1.46", + "ver": "1.1.48", "importer": "prefab", "imported": true, "uuid": "7f4ddeab-efa9-4b76-bf6a-029520f68461", From 62a9da122ec4b757adc21f803c791752946e2541 Mon Sep 17 00:00:00 2001 From: qiuguohua Date: Mon, 21 Aug 2023 16:45:53 +0800 Subject: [PATCH 160/184] Use sdl2 on mac platform (#16030) * Use sdl2 on mac platform --- native/CMakeLists.txt | 2 +- native/cocos/engine/Engine.cpp | 2 +- native/cocos/platform/SDLHelper.cpp | 12 ++ native/cocos/platform/SDLHelper.h | 3 +- .../platform/linux/modules/SystemWindow.cpp | 2 +- native/cocos/platform/mac/AppDelegate.h | 5 - native/cocos/platform/mac/AppDelegate.mm | 69 -------- native/cocos/platform/mac/MacPlatform.h | 4 +- native/cocos/platform/mac/MacPlatform.mm | 113 ++++--------- native/cocos/platform/mac/View.mm | 159 ------------------ native/cocos/platform/mac/modules/Screen.mm | 8 +- .../cocos/platform/mac/modules/SystemWindow.h | 34 ++-- .../platform/mac/modules/SystemWindow.mm | 154 +++++++++-------- .../mac/modules/SystemWindowManager.h | 9 +- .../mac/modules/SystemWindowManager.mm | 67 +++++--- 15 files changed, 200 insertions(+), 443 deletions(-) diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 8e0e4296446..7125a5ff234 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -519,7 +519,7 @@ cocos_source_files( ) ############ main -if(NOT USE_SERVER_MODE AND (WINDOWS OR LINUX)) +if(NOT USE_SERVER_MODE AND (WINDOWS OR LINUX OR MACOSX)) cocos_source_files( cocos/platform/SDLHelper.h cocos/platform/SDLHelper.cpp diff --git a/native/cocos/engine/Engine.cpp b/native/cocos/engine/Engine.cpp index 86d7f48e69e..bae11828fdd 100644 --- a/native/cocos/engine/Engine.cpp +++ b/native/cocos/engine/Engine.cpp @@ -275,7 +275,7 @@ void Engine::tick() { // iOS/macOS use its own fps limitation algorithm. // Windows for Editor should not sleep,because Editor call tick function synchronously -#if (CC_PLATFORM == CC_PLATFORM_ANDROID || (CC_PLATFORM == CC_PLATFORM_WINDOWS && !CC_EDITOR) || CC_PLATFORM == CC_PLATFORM_OHOS || CC_PLATFORM == CC_PLATFORM_OPENHARMONY) || (defined(CC_SERVER_MODE) && (CC_PLATFORM == CC_PLATFORM_MAC_OSX)) +#if (CC_PLATFORM == CC_PLATFORM_ANDROID || (CC_PLATFORM == CC_PLATFORM_WINDOWS && !CC_EDITOR) || CC_PLATFORM == CC_PLATFORM_OHOS || CC_PLATFORM == CC_PLATFORM_OPENHARMONY || CC_PLATFORM == CC_PLATFORM_MACOS) if (dtNS < static_cast(_preferredNanosecondsPerFrame)) { CC_PROFILE(EngineSleep); std::this_thread::sleep_for( diff --git a/native/cocos/platform/SDLHelper.cpp b/native/cocos/platform/SDLHelper.cpp index 56e71618b8c..4c477471bf7 100644 --- a/native/cocos/platform/SDLHelper.cpp +++ b/native/cocos/platform/SDLHelper.cpp @@ -174,6 +174,8 @@ void SDLHelper::dispatchWindowEvent(uint32_t windowId, const SDL_WindowEvent &we events::WindowEvent::broadcast(ev); break; } +// On the mac platform this is done via setframesize int the view. +#if !(CC_PLATFORM == CC_PLATFORM_MACOS) case SDL_WINDOWEVENT_SIZE_CHANGED: { ev.type = WindowEvent::Type::SIZE_CHANGED; ev.width = wevent.data1; @@ -188,6 +190,7 @@ void SDLHelper::dispatchWindowEvent(uint32_t windowId, const SDL_WindowEvent &we events::WindowEvent::broadcast(ev); break; } +#endif case SDL_WINDOWEVENT_HIDDEN: { ev.type = WindowEvent::Type::HIDDEN; events::WindowEvent::broadcast(ev); @@ -371,9 +374,18 @@ uintptr_t SDLHelper::getWindowHandle(SDL_Window *window) { return reinterpret_cast(wmInfo.info.win.window); #elif (CC_PLATFORM == CC_PLATFORM_LINUX) return reinterpret_cast(wmInfo.info.x11.window); +#elif (CC_PLATFORM == CC_PLATFORM_MACOS) + return reinterpret_cast(wmInfo.info.cocoa.window); #endif CC_ABORT(); return 0; } +Vec2 SDLHelper::getWindowPosition(SDL_Window *window) { + int x = 0; + int y = 0; + SDL_GetWindowPosition(window, &x, &y); + return Vec2(x, y); +} + } // namespace cc diff --git a/native/cocos/platform/SDLHelper.h b/native/cocos/platform/SDLHelper.h index 2f368a00b95..4647f4d658b 100644 --- a/native/cocos/platform/SDLHelper.h +++ b/native/cocos/platform/SDLHelper.h @@ -25,6 +25,7 @@ #pragma once #include #include "engine/EngineEvents.h" +#include "math/Vec2.h" struct SDL_Window; union SDL_Event; @@ -52,7 +53,7 @@ class SDLHelper { static uintptr_t getDisplay(SDL_Window* window); #endif static void setCursorEnabled(bool value); - + static Vec2 getWindowPosition(SDL_Window *window); private: static void dispatchSDLEvent(uint32_t windowId, const SDL_Event& sdlEvent); static void dispatchWindowEvent(uint32_t windowId, const SDL_WindowEvent& wevent); diff --git a/native/cocos/platform/linux/modules/SystemWindow.cpp b/native/cocos/platform/linux/modules/SystemWindow.cpp index 7c3d280aa30..43ffcfdac60 100644 --- a/native/cocos/platform/linux/modules/SystemWindow.cpp +++ b/native/cocos/platform/linux/modules/SystemWindow.cpp @@ -80,7 +80,7 @@ void SystemWindow::closeWindow() { #ifndef CC_SERVER_MODE SDL_Event et; et.type = SDL_QUIT; - auto posted = SDL_PushEvent(&et); + SDL_PushEvent(&et); #endif } diff --git a/native/cocos/platform/mac/AppDelegate.h b/native/cocos/platform/mac/AppDelegate.h index 23ef37e266f..afe71490678 100644 --- a/native/cocos/platform/mac/AppDelegate.h +++ b/native/cocos/platform/mac/AppDelegate.h @@ -28,10 +28,5 @@ @interface AppDelegate : NSObject - (void)applicationDidFinishLaunching:(NSNotification*)aNotification; -- (void)windowWillMiniaturizeNotification; -- (void)windowDidDeminiaturizeNotification; -- (void)windowWillCloseNotification; -- (void)applicationWillTerminate:(NSNotification*)aNotification; - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication; -- (NSWindow*)getWindow; @end diff --git a/native/cocos/platform/mac/AppDelegate.mm b/native/cocos/platform/mac/AppDelegate.mm index 40b85baf1a8..91627d7dc00 100644 --- a/native/cocos/platform/mac/AppDelegate.mm +++ b/native/cocos/platform/mac/AppDelegate.mm @@ -32,76 +32,14 @@ of this software and associated engine source code (the "Software"), a limited, @interface AppDelegate () { NSWindow* _window; - // Game* _game; cc::MacPlatform* _platform; } @end @implementation AppDelegate -- (void)createLeftBottomWindow:(NSString*)title width:(int)w height:(int)h { - [self createWindow:title xPos:0 yPos:0 width:w height:h]; -} - -- (NSWindow*)createWindow:(NSString*)title xPos:(int)x yPos:(int)y width:(int)w height:(int)h { - //_window.title = title; - NSRect rect = NSMakeRect(x, y, w, h); - NSWindow* window = [[NSWindow alloc] initWithContentRect:rect - styleMask:NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable - backing:NSBackingStoreBuffered - defer:NO]; - if (!window) { - NSLog(@"Failed to allocated the window."); - return nullptr; - } - - ViewController* viewController = [[ViewController alloc] initWithSize:rect]; - window.contentViewController = viewController; - window.contentView = viewController.view; - [viewController release]; - viewController = nil; - - window.title = title; - [window.contentView setWantsBestResolutionOpenGLSurface:YES]; - [window makeKeyAndOrderFront:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowWillMiniaturizeNotification) - name:NSWindowWillMiniaturizeNotification - object:window]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowDidDeminiaturizeNotification) - name:NSWindowDidDeminiaturizeNotification - object:window]; - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowWillCloseNotification) - name:NSWindowWillCloseNotification - object:window]; - if (!_window) { - _window = window; - } - return window; -} - - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { _platform = dynamic_cast(cc::BasePlatform::getPlatform()); - CC_ASSERT_NOT_NULL(_platform); - _platform->loop(); -} - -- (void)windowWillMiniaturizeNotification { - _platform->onPause(); -} - -- (void)windowDidDeminiaturizeNotification { - _platform->onResume(); -} - -- (void)windowWillCloseNotification { - _platform->onClose(); -} - -- (NSWindow*)getWindow { - return _window; } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender @@ -109,13 +47,6 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sende return _platform->readyToExit() ? NSTerminateNow : NSTerminateLater; } -- (void)applicationWillTerminate:(NSNotification*)aNotification { - // delete _game; - //FIXME: will crash if relase it here. - // [_window release]; - _platform->onDestroy(); -} - - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication { return YES; } diff --git a/native/cocos/platform/mac/MacPlatform.h b/native/cocos/platform/mac/MacPlatform.h index 13485718cad..3b7da485c02 100644 --- a/native/cocos/platform/mac/MacPlatform.h +++ b/native/cocos/platform/mac/MacPlatform.h @@ -27,7 +27,7 @@ #include "platform/UniversalPlatform.h" namespace cc { - +class SystemWindowManager; class MacPlatform : public UniversalPlatform { public: MacPlatform() = default; @@ -58,8 +58,10 @@ class MacPlatform : public UniversalPlatform { void onPause() override; void onResume() override; void onClose() override; + void pollEvent() override; private: bool _readyToExit{false}; + std::shared_ptr _windowManager{nullptr}; }; } // namespace cc diff --git a/native/cocos/platform/mac/MacPlatform.mm b/native/cocos/platform/mac/MacPlatform.mm index 2266df306a8..722b358f2ed 100644 --- a/native/cocos/platform/mac/MacPlatform.mm +++ b/native/cocos/platform/mac/MacPlatform.mm @@ -32,7 +32,7 @@ of this software and associated engine source code (the "Software"), a limited, #include "modules/Network.h" #include "modules/System.h" #include "modules/Vibrator.h" - +#include "platform/SDLHelper.h" #if defined(CC_SERVER_MODE) #include "platform/empty/modules/Screen.h" #include "platform/empty/modules/SystemWindow.h" @@ -44,87 +44,26 @@ of this software and associated engine source code (the "Software"), a limited, #endif #import + #include "base/memory/Memory.h" extern int cocos_main(int argc, const char **argv); -@interface MyTimer : NSObject { - cc::MacPlatform *_platform; - NSTimer *_timer; -} -- (instancetype)initWithApp:(cc::MacPlatform *)platform fps:(int)fps; -- (void)start; -- (void)changeFPS; -- (void)pause; -- (void)resume; -@end - -@implementation MyTimer - -- (instancetype)initWithApp:(cc::MacPlatform *)platform fps:(int)fps { - if (self = [super init]) { - _platform = platform; - } - return self; -} -#if CC_EDITOR - - (void)start { } - - (void)changeFPS { } - - (void)pause { } - - (void)resume { } -#else -- (void)start { - int32_t fps = _platform->getFps(); - _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f / fps - target:self - selector:@selector(renderScene) - userInfo:nil - repeats:YES]; -} - -- (void)pause { - [_timer invalidate]; -} - -- (void)resume { - [self start]; -} - -- (void)changeFPS { - [self pause]; - [self resume]; -} - -- (void)renderScene { - _platform->runTask(); -} - -- (bool) isValid { - return [_timer valid]; -} -#endif -@end - -namespace { -MyTimer *_timer; -} - namespace cc { MacPlatform::~MacPlatform() { - [_timer release]; } int32_t MacPlatform::init() { - _timer = [[MyTimer alloc] initWithApp:this fps:60]; registerInterface(std::make_shared()); registerInterface(std::make_shared()); registerInterface(std::make_shared()); registerInterface(std::make_shared()); registerInterface(std::make_shared()); - registerInterface(std::make_shared()); + _windowManager = std::make_shared(); + registerInterface(_windowManager); registerInterface(std::make_shared()); - return 0; + return _windowManager->init(); } bool MacPlatform::readyToExit() { @@ -143,16 +82,12 @@ - (bool) isValid { runTask(); return 1; #else - [_timer start]; - NSArray *arguments = [[NSProcessInfo processInfo] arguments]; - int argc = static_cast(arguments.count); - std::vector argv; - argv.reserve(argc); - for (id arg in arguments) { - argv.emplace_back([arg UTF8String]); + while(!_readyToExit) { + pollEvent(); + runTask(); } - - return cocos_main(argc, argv.data()); + onDestroy(); + return 0; #endif } @@ -164,30 +99,38 @@ - (bool) isValid { } return 0; #else + NSArray *arguments = [[NSProcessInfo processInfo] arguments]; + argc = static_cast(arguments.count); + std::vector argVec; + argVec.reserve(argc); + for (id arg in arguments) { + argVec.emplace_back([arg UTF8String]); + } + id delegate = [[AppDelegate alloc] init]; - NSApplication.sharedApplication.delegate = delegate; - return NSApplicationMain(argc, argv); + [NSApp setDelegate:delegate]; + + if(cocos_main(argc, argVec.data()) != 0) { + return -1; + } + + return loop(); #endif } void MacPlatform::setFps(int32_t fps) { if(fps != getFps()) { UniversalPlatform::setFps(fps); - [_timer changeFPS]; } } void MacPlatform::onPause() { - [_timer pause]; - cc::WindowEvent ev; ev.type = cc::WindowEvent::Type::HIDDEN; cc::events::WindowEvent::broadcast(ev); } void MacPlatform::onResume() { - [_timer resume]; - cc::WindowEvent ev; ev.type = cc::WindowEvent::Type::SHOW; cc::events::WindowEvent::broadcast(ev); @@ -199,8 +142,12 @@ - (bool) isValid { cc::events::WindowEvent::broadcast(ev); } -cc::ISystemWindow *MacPlatform::createNativeWindow(uint32_t windowId, void *externalHandle) { +cc::ISystemWindow *MacPlatform::createNativeWindow(uint32_t windowId, void *externalHandle) { return ccnew SystemWindow(windowId, externalHandle); } +void MacPlatform::pollEvent() { + _windowManager->processEvent(); +} + } // namespace cc diff --git a/native/cocos/platform/mac/View.mm b/native/cocos/platform/mac/View.mm index 6fbb047f3aa..622a6097ae8 100644 --- a/native/cocos/platform/mac/View.mm +++ b/native/cocos/platform/mac/View.mm @@ -38,8 +38,6 @@ of this software and associated engine source code (the "Software"), a limited, @implementation View { cc::MouseEvent _mouseEvent; cc::KeyboardEvent _keyboardEvent; - NSRect _contentRect; - AppDelegate *_delegate; } - (CALayer *)makeBackingLayer { @@ -53,7 +51,6 @@ - (CALayer *)makeBackingLayer { - (instancetype)initWithFrame:(NSRect)frameRect { if (self = [super initWithFrame:frameRect]) { [self.window makeFirstResponder:self]; - _delegate = [[NSApplication sharedApplication] delegate]; int pixelRatio = [[NSScreen mainScreen] backingScaleFactor]; CGSize size = CGSizeMake(frameRect.size.width * pixelRatio, frameRect.size.height * pixelRatio); // Create CAMetalLayer @@ -74,11 +71,6 @@ - (instancetype)initWithFrame:(NSRect)frameRect { owner:self userInfo:nil] autorelease]; [self addTrackingArea:trackingArea]; - - NSWindow* window = self.window; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification - object:window]; - [self updateContentRect]; } return self; } @@ -94,7 +86,6 @@ - (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { ev.width = static_cast(size.width); ev.height = static_cast(size.height); cc::events::WindowEvent::broadcast(ev); - [self updateContentRect]; } - (void)displayLayer:(CALayer *)layer { @@ -118,7 +109,6 @@ - (void)setFrameSize:(NSSize)newSize { cc::events::WindowEvent::broadcast(ev); } - [self updateContentRect]; } - (void)viewDidChangeBackingProperties { @@ -142,24 +132,6 @@ - (void)viewDidChangeBackingProperties { ev.height = static_cast(height); cc::events::WindowEvent::broadcast(ev); } - [self updateContentRect]; -} - -- (void)keyDown:(NSEvent *)event { - _keyboardEvent.windowId = [self getWindowId]; - _keyboardEvent.key = translateKeycode(event.keyCode); - _keyboardEvent.action = [event isARepeat] ? cc::KeyboardEvent::Action::REPEAT - : cc::KeyboardEvent::Action::PRESS; - [self setModifierFlags:event]; - cc::events::Keyboard::broadcast(_keyboardEvent); -} - -- (void)keyUp:(NSEvent *)event { - _keyboardEvent.windowId = [self getWindowId]; - _keyboardEvent.key = translateKeycode(event.keyCode); - _keyboardEvent.action = cc::KeyboardEvent::Action::RELEASE; - [self setModifierFlags:event]; - cc::events::Keyboard::broadcast(_keyboardEvent); } - (void)flagsChanged:(NSEvent *)event { @@ -204,141 +176,10 @@ - (void)setModifierFlags:(NSEvent *)event { _keyboardEvent.metaKeyActive = false; } -- (void)mouseDown:(NSEvent *)event { - [self sendMouseEvent:0 - type:cc::MouseEvent::Type::DOWN - event:event]; -} - -- (void)mouseUp:(NSEvent *)event { - [self sendMouseEvent:0 - type:cc::MouseEvent::Type::UP - event:event]; -} - -- (void)mouseDragged:(NSEvent *)event { - [self mouseMoved:event]; -} - -- (void)mouseMoved:(NSEvent *)event { - [self sendMouseEvent:0 - type:cc::MouseEvent::Type::MOVE - event:event]; -} - -- (void)otherMouseDown:(NSEvent *)event { - [self sendMouseEvent:[self translateButtonNumber:event.buttonNumber] - type:cc::MouseEvent::Type::DOWN - event:event]; -} - -- (void)otherMouseUp:(NSEvent *)event { - [self sendMouseEvent:[self translateButtonNumber:event.buttonNumber] - type:cc::MouseEvent::Type::UP - event:event]; -} - -- (int)translateButtonNumber:(NSInteger)buttonNumber { - if (buttonNumber == 1) // left - return 0; - else if (buttonNumber == 2) // right - return 2; - else - return 1; -} - -- (void)scrollWheel:(NSEvent *)event { - double deltaX = [event scrollingDeltaX]; - double deltaY = [event scrollingDeltaY]; - - if ([event hasPreciseScrollingDeltas]) { - deltaX *= 0.1; - deltaY *= 0.1; - } - - if (fabs(deltaX) > 0.0 || fabs(deltaY) > 0.0) { - _mouseEvent.type = cc::MouseEvent::Type::WHEEL; - _mouseEvent.button = 0; - _mouseEvent.x = deltaX; - _mouseEvent.y = deltaY; - _mouseEvent.windowId = [self getWindowId]; - cc::events::Mouse::broadcast(_mouseEvent); - } -} - -- (void)rightMouseDown:(NSEvent *)event { - [self sendMouseEvent:2 - type:cc::MouseEvent::Type::DOWN - event:event]; -} - -- (void)rightMouseUp:(NSEvent *)event { - [self sendMouseEvent:2 - type:cc::MouseEvent::Type::UP - event:event]; -} - - (BOOL)acceptsFirstResponder { return YES; } -- (void)updateContentRect { - NSWindow* window = self.window; - _contentRect = [window contentRectForFrameRect:[window frame]]; -} - -- (void)windowDidMove:(NSNotification *)aNotification { - [self updateContentRect]; -} - -- (void)sendMouseEvent:(int)button type:(cc::MouseEvent::Type)type event:(NSEvent *)event { - _mouseEvent.windowId = [self getWindowId]; - _mouseEvent.type = type; - _mouseEvent.button = button; - _mouseEvent.xDelta = [event deltaX]; - _mouseEvent.yDelta = [event deltaY]; - - auto *windowMgr = CC_GET_PLATFORM_INTERFACE(cc::SystemWindowManager); - auto *window = static_cast( windowMgr->getWindowFromNSWindow([self window])); - const NSRect contentRect = [self frame]; - if(!window->isPointerLock()) { - const NSPoint pos = [event locationInWindow]; - _mouseEvent.x = pos.x; - _mouseEvent.y = contentRect.size.height - pos.y; - } else { - if(type == cc::MouseEvent::Type::MOVE) { - // Out of window only happens when mouse is moved. - _mouseEvent.x = _mouseEvent.x + [event deltaX]; - _mouseEvent.y = _mouseEvent.y + [event deltaY]; - float xMin = 0, xMax = 0; - float yMin = 0, yMax = 0; - xMax = contentRect.size.width; - yMax = contentRect.size.height; - --xMax; - --yMax; - if (_mouseEvent.x > xMax) { - _mouseEvent.x = xMax; - } else if (_mouseEvent.x < xMin) { - _mouseEvent.x = xMin; - } - - if (_mouseEvent.y > yMax) { - _mouseEvent.y = yMax; - } else if (_mouseEvent.y < yMin) { - _mouseEvent.y = yMin; - } - } - - auto mainDisplayId = CGMainDisplayID(); - - float windowX = _contentRect.origin.x; - float windowY = - CGDisplayPixelsHigh(mainDisplayId) - _contentRect.origin.y - _contentRect.size.height; - - window->setLastMousePos(windowX + _mouseEvent.x, windowY + _mouseEvent.y); - } - cc::events::Mouse::broadcast(_mouseEvent); -} - (int)getWindowId { auto *windowMgr = CC_GET_PLATFORM_INTERFACE(cc::SystemWindowManager); auto *window = windowMgr->getWindowFromNSWindow([self window]); diff --git a/native/cocos/platform/mac/modules/Screen.mm b/native/cocos/platform/mac/modules/Screen.mm index cad4ed26f44..e2049c8f135 100644 --- a/native/cocos/platform/mac/modules/Screen.mm +++ b/native/cocos/platform/mac/modules/Screen.mm @@ -31,7 +31,9 @@ of this software and associated engine source code (the "Software"), a limited, #include "base/Macros.h" #include "cocos/bindings/jswrapper/SeApi.h" - +#include "platform/interfaces/modules/ISystemWindowManager.h" +#include "platform/interfaces/modules/ISystemWindow.h" +#include "application/ApplicationManager.h" namespace cc { int Screen::getDPI() const { @@ -50,7 +52,9 @@ of this software and associated engine source code (the "Software"), a limited, global->getProperty("devicePixelRatio", &devicePixelRatioVal); return devicePixelRatioVal.isNumber() ? devicePixelRatioVal.toFloat() : 1.F; #else - return [[[[NSApplication sharedApplication] delegate] getWindow] backingScaleFactor]; + auto* window = CC_GET_MAIN_SYSTEM_WINDOW(); + NSWindow* nsWindow = reinterpret_cast(window->getWindowHandle()) ; + return [nsWindow backingScaleFactor]; #endif } diff --git a/native/cocos/platform/mac/modules/SystemWindow.h b/native/cocos/platform/mac/modules/SystemWindow.h index 5a58f9c685b..8678c3e09ef 100644 --- a/native/cocos/platform/mac/modules/SystemWindow.h +++ b/native/cocos/platform/mac/modules/SystemWindow.h @@ -24,23 +24,28 @@ #pragma once -#include #include +#include #include "platform/interfaces/modules/ISystemWindow.h" +struct SDL_Window; namespace cc { +class SDLHelper; +class CC_DLL SystemWindow : public ISystemWindow { + friend class SystemWindowManager; -class SystemWindow : public ISystemWindow { public: explicit SystemWindow(uint32_t windowId, void* externalHandle); ~SystemWindow() override; + bool createWindow(const char* title, + int w, int h, int flags) override; bool createWindow(const char* title, int x, int y, int w, int h, int flags) override; - bool createWindow(const char* title, - int w, int h, int flags) override; void closeWindow() override; + + virtual uint32_t getWindowId() const override { return _windowId; } uintptr_t getWindowHandle() const override; Size getViewSize() const override; @@ -48,27 +53,20 @@ class SystemWindow : public ISystemWindow { _width = w; _height = h; } - - uint32_t getWindowId() const override; - NSWindow* getNSWindow() const { return _window; } - /* @brief enable/disable(lock) the cursor, default is enabled */ void setCursorEnabled(bool value) override; - - bool isPointerLock() const; - void setLastMousePos(float x, float y); - + NSWindow* getNSWindow() const; private: - bool _pointerLock{false}; - float _lastMousePosX{0.0F}; - float _lastMousePosY{0.0F}; - int32_t _width{0}; - int32_t _height{0}; + SDL_Window* getSDLWindow() const { return _window; } + void initWindowProperty(SDL_Window* window, const char *title, int x, int y, int w, int h); + uint32_t _width{0}; + uint32_t _height{0}; uint32_t _windowId{0}; uintptr_t _windowHandle{0}; - NSWindow* _window{nullptr}; + SDL_Window* _window{nullptr}; }; + } // namespace cc diff --git a/native/cocos/platform/mac/modules/SystemWindow.mm b/native/cocos/platform/mac/modules/SystemWindow.mm index bb8d4760ac0..0b4bcc42863 100644 --- a/native/cocos/platform/mac/modules/SystemWindow.mm +++ b/native/cocos/platform/mac/modules/SystemWindow.mm @@ -1,18 +1,17 @@ /**************************************************************************** - Copyright (c) 2021-2022 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2021-2023 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. + 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 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 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, @@ -24,41 +23,74 @@ of this software and associated engine source code (the "Software"), a limited, ****************************************************************************/ #include "platform/mac/modules/SystemWindow.h" -#import -#include "platform/BasePlatform.h" -#include "platform/interfaces/modules/IScreen.h" - -#if CC_EDITOR +#include "platform/mac/ViewController.h" +#include "base/Log.h" +#include "base/Macros.h" + +// SDL headers +#include +#include "SDL2/SDL.h" +#include "SDL2/SDL_main.h" +#include "SDL2/SDL_syswm.h" +#include "engine/EngineEvents.h" +#include "platform/SDLHelper.h" +#import +#import +#import #import -#else -#include "platform/mac/AppDelegate.h" -#endif +#include "platform/interfaces/modules/IScreen.h" +#include "platform/BasePlatform.h" namespace cc { - SystemWindow::SystemWindow(uint32_t windowId, void *externalHandle) - : _windowId(windowId) { +: _windowId(windowId) { if (externalHandle) { _windowHandle = reinterpret_cast(externalHandle); } } -SystemWindow::~SystemWindow() = default; +SystemWindow::~SystemWindow() { + _windowHandle = 0; + _windowId = 0; +} + +void SystemWindow::initWindowProperty(SDL_Window* window, const char *title, int x, int y, int w, int h) { + CC_ASSERT(window != nullptr); + auto* nsWindow = reinterpret_cast(SDLHelper::getWindowHandle(window)); + NSRect rect = NSMakeRect(x, y, w, h); + ViewController* viewController = [[ViewController alloc] initWithSize:rect]; + nsWindow.contentViewController = viewController; + nsWindow.contentView = viewController.view; + NSString *astring = [NSString stringWithUTF8String:title]; + nsWindow.title = astring; + [nsWindow.contentView setWantsBestResolutionOpenGLSurface:YES]; + [nsWindow makeKeyAndOrderFront:nil]; + + [viewController release]; + viewController = nil; + _windowHandle = reinterpret_cast(nsWindow.contentView) ; + + auto dpr = [nsWindow backingScaleFactor]; + _width = w * dpr; + _height = h * dpr; +} + +NSWindow* SystemWindow::getNSWindow() const { + CC_ASSERT(_window != nullptr); + return reinterpret_cast(SDLHelper::getWindowHandle(_window)); +} bool SystemWindow::createWindow(const char *title, int w, int h, int flags) { #if CC_EDITOR - return createWindow(title, 0, 0, w, h, flags); + return createWindow(title, 0, 0, w, h, flags); #else - AppDelegate *delegate = [[NSApplication sharedApplication] delegate]; - NSString *aString = [NSString stringWithUTF8String:title]; - _window = [delegate createLeftBottomWindow:aString width:w height:h]; - NSView *view = [_window contentView]; - _windowHandle = reinterpret_cast(view); - - auto dpr = BasePlatform::getPlatform()->getInterface()->getDevicePixelRatio(); - _width = w * dpr; - _height = h * dpr; + _window = SDLHelper::createWindow(title, w, h, flags); + if (!_window) { + return false; + } + Vec2 pos = SDLHelper::getWindowPosition(_window); + initWindowProperty(_window, title, pos.x, pos.y, w, h); return true; #endif } @@ -76,67 +108,33 @@ of this software and associated engine source code (the "Software"), a limited, _windowHandle = reinterpret_cast(layer); return true; #else - AppDelegate *delegate = [[NSApplication sharedApplication] delegate]; - NSString *aString = [NSString stringWithUTF8String:title]; - _window = [delegate createWindow:aString xPos:x yPos:y width:w height:h]; - NSView *view = [_window contentView]; - _windowHandle = reinterpret_cast(view); - - auto dpr = BasePlatform::getPlatform()->getInterface()->getDevicePixelRatio(); - _width = w * dpr; - _height = h * dpr; + _window = SDLHelper::createWindow(title, x, y, w, h, flags); + if (!_window) { + return false; + } + initWindowProperty(_window, title, x, y, w, h); return true; #endif } void SystemWindow::closeWindow() { - //id window = [[[NSApplication sharedApplication] delegate] getWindow]; - if (_window) { - [_window close]; - _window = nullptr; - } -} - -void SystemWindow::setCursorEnabled(bool value) { - CGError result; - if(value) { - result = CGAssociateMouseAndMouseCursorPosition(YES); - [NSCursor unhide]; - if(_pointerLock) { - CGPoint point = - CGPointMake((float)_lastMousePosX, _lastMousePosY); - CGWarpMouseCursorPosition(point); - } - _pointerLock = false; - } else { - result = CGAssociateMouseAndMouseCursorPosition(NO); - [NSCursor hide]; - _pointerLock = true; - } - CC_ASSERT(result == kCGErrorSuccess); - events::PointerLock::broadcast(!value); +#ifndef CC_SERVER_MODE + SDL_Event et; + et.type = SDL_QUIT; + SDL_PushEvent(&et); +#endif } uintptr_t SystemWindow::getWindowHandle() const { - //NSView *view = [[[[NSApplication sharedApplication] delegate] getWindow] contentView]; return _windowHandle; } -SystemWindow::Size SystemWindow::getViewSize() const { - return Size{static_cast(_width), static_cast(_height)}; -} - -uint32_t SystemWindow::getWindowId() const { - return _windowId; -} - -bool SystemWindow::isPointerLock() const { - return _pointerLock; +void SystemWindow::setCursorEnabled(bool value) { + SDLHelper::setCursorEnabled(value); } -void SystemWindow::setLastMousePos(float x, float y) { - _lastMousePosX = x; - _lastMousePosY = y; +SystemWindow::Size SystemWindow::getViewSize() const { + return Size{static_cast(_width), static_cast(_height)}; } } // namespace cc diff --git a/native/cocos/platform/mac/modules/SystemWindowManager.h b/native/cocos/platform/mac/modules/SystemWindowManager.h index b2fefa440ff..699832e0c9d 100644 --- a/native/cocos/platform/mac/modules/SystemWindowManager.h +++ b/native/cocos/platform/mac/modules/SystemWindowManager.h @@ -23,7 +23,6 @@ ****************************************************************************/ #pragma once - #include #include "base/std/container/unordered_map.h" #include "platform/interfaces/modules/ISystemWindowManager.h" @@ -36,17 +35,17 @@ class ISystemWindow; class SystemWindowManager : public ISystemWindowManager { public: - explicit SystemWindowManager() = default; + SystemWindowManager() = default; - int init() override { return 0; } - void processEvent() override {} + int init() override; + void processEvent() override; ISystemWindow *createWindow(const ISystemWindowInfo &info) override; ISystemWindow *getWindow(uint32_t windowId) const override; const SystemWindowMap &getWindows() const override { return _windows; } + ISystemWindow *getWindowFromSDLWindow(SDL_Window *window) const; ISystemWindow *getWindowFromNSWindow(NSWindow *window) const; - private: uint32_t _nextWindowId{1}; // start from 1, 0 means an invalid ID SystemWindowMap _windows; diff --git a/native/cocos/platform/mac/modules/SystemWindowManager.mm b/native/cocos/platform/mac/modules/SystemWindowManager.mm index 61520c056f1..bcfe9f987b1 100644 --- a/native/cocos/platform/mac/modules/SystemWindowManager.mm +++ b/native/cocos/platform/mac/modules/SystemWindowManager.mm @@ -1,18 +1,17 @@ /**************************************************************************** - Copyright (c) 2021 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2021-2023 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. + 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 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 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, @@ -21,9 +20,10 @@ of this software and associated engine source code (the "Software"), a limited, 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 "SystemWindowManager.h" +#include "SDL2/SDL_events.h" #include "platform/BasePlatform.h" #include "platform/SDLHelper.h" #include "platform/interfaces/modules/ISystemWindowManager.h" @@ -31,19 +31,27 @@ of this software and associated engine source code (the "Software"), a limited, namespace cc { -ISystemWindow *SystemWindowManager::getWindow(uint32_t windowId) const { - if (windowId == 0) { - return nullptr; - } +int SystemWindowManager::init() { + return SDLHelper::init(); +} - auto iter = _windows.find(windowId); - if (iter != _windows.end()) { - return iter->second.get(); +void SystemWindowManager::processEvent() { + SDL_Event sdlEvent; + while (SDL_PollEvent(&sdlEvent) != 0) { + SDL_Window *sdlWindow = SDL_GetWindowFromID(sdlEvent.window.windowID); + // SDL_Event like SDL_QUIT does not associate a window + if (!sdlWindow) { + SDLHelper::dispatchSDLEvent(0, sdlEvent); + } else { + ISystemWindow *window = getWindowFromSDLWindow(sdlWindow); + CC_ASSERT(window); + uint32_t windowId = window->getWindowId(); + SDLHelper::dispatchSDLEvent(windowId, sdlEvent); + } } - return nullptr; } -ISystemWindow *SystemWindowManager::createWindow(const cc::ISystemWindowInfo &info) { +ISystemWindow *SystemWindowManager::createWindow(const ISystemWindowInfo &info) { ISystemWindow *window = BasePlatform::getPlatform()->createNativeWindow(_nextWindowId, info.externalHandle); if (window) { if (!info.externalHandle) { @@ -55,6 +63,27 @@ of this software and associated engine source code (the "Software"), a limited, return window; } +ISystemWindow *SystemWindowManager::getWindow(uint32_t windowId) const { + if (windowId == 0) + return nullptr; + + auto iter = _windows.find(windowId); + if (iter != _windows.end()) + return iter->second.get(); + return nullptr; +} + +cc::ISystemWindow *SystemWindowManager::getWindowFromSDLWindow(SDL_Window *window) const { + for (const auto &iter : _windows) { + SystemWindow *sysWindow = static_cast(iter.second.get()); + SDL_Window *sdlWindow = sysWindow->getSDLWindow(); + if (sdlWindow == window) { + return sysWindow; + } + } + return nullptr; +} + ISystemWindow *SystemWindowManager::getWindowFromNSWindow(NSWindow *window) const { for (const auto &iter : _windows) { SystemWindow *sysWindow = static_cast(iter.second.get()); From d78725eb3a5ca639ea3888e4f24fa462ccd91b79 Mon Sep 17 00:00:00 2001 From: fqamic Date: Mon, 21 Aug 2023 17:11:40 +0800 Subject: [PATCH 161/184] Adaptation of the xr platform 3.8.1 modification (#16056) * feat: xr sync android template for manifest * fix: for xr platform, compatible with historical packaging tool usage * improve: annotation optimization --- .../source/platforms/android.ts | 71 +++++++++++++++++++ .../template/app/AndroidManifest.xml | 4 +- .../template/instantapp/AndroidManifest.xml | 4 +- .../xr-meta/template/app/AndroidManifest.xml | 4 +- .../template/instantapp/AndroidManifest.xml | 4 +- .../template/app/AndroidManifest.xml | 4 +- .../template/instantapp/AndroidManifest.xml | 4 +- .../xr-pico/template/app/AndroidManifest.xml | 4 +- .../template/instantapp/AndroidManifest.xml | 4 +- .../xr-rokid/template/app/AndroidManifest.xml | 4 +- .../template/instantapp/AndroidManifest.xml | 4 +- .../template/app/AndroidManifest.xml | 4 +- .../template/instantapp/AndroidManifest.xml | 4 +- 13 files changed, 95 insertions(+), 24 deletions(-) diff --git a/scripts/native-pack-tool/source/platforms/android.ts b/scripts/native-pack-tool/source/platforms/android.ts index 6cb7d8f1260..03d3067a868 100644 --- a/scripts/native-pack-tool/source/platforms/android.ts +++ b/scripts/native-pack-tool/source/platforms/android.ts @@ -142,6 +142,46 @@ export class AndroidPackTool extends NativePackTool { return await this.copyToDist(); } + /** + * Deprecated, only be compatible with historical packaging tools + */ + protected async setOrientation() { + const cfg = this.params.platformParams.orientation; + const manifestPath = cchelper.join(this.paths.platformTemplateDirInPrj, 'app/AndroidManifest.xml'); + const instantManifestPath = cchelper.join(this.paths.platformTemplateDirInPrj, 'instantapp/AndroidManifest.xml'); + if (fs.existsSync(manifestPath) && fs.existsSync(instantManifestPath)) { + const pattern = /android:screenOrientation="[^"]*"/; + let replaceString = 'android:screenOrientation="unspecified"'; + + if (cfg.landscapeRight && cfg.landscapeLeft && (cfg.portrait || cfg.upsideDown)) { + replaceString = 'android:screenOrientation="fullSensor"'; + } else if ((cfg.landscapeRight || cfg.landscapeLeft) && (cfg.portrait || cfg.upsideDown)) { + replaceString = 'android:screenOrientation="unspecified"'; + } else if (cfg.landscapeRight && !cfg.landscapeLeft) { + replaceString = 'android:screenOrientation="landscape"'; + } else if (!cfg.landscapeRight && cfg.landscapeLeft) { + replaceString = 'android:screenOrientation="reverseLandscape"'; + } else if (cfg.landscapeRight && cfg.landscapeLeft) { + replaceString = 'android:screenOrientation="sensorLandscape"'; + } else if (cfg.portrait && !cfg.upsideDown) { + replaceString = 'android:screenOrientation="portrait"'; + } else if (!cfg.portrait && cfg.upsideDown) { + const oriValue = 'reversePortrait'; + replaceString = `android:screenOrientation="${oriValue}"`; + } else if (cfg.portrait && cfg.upsideDown) { + const oriValue = 'sensorPortrait'; + replaceString = `android:screenOrientation="${oriValue}"`; + } + + let content = await fs.readFile(manifestPath, 'utf8'); + content = content.replace(pattern, replaceString); + let instantContent = await fs.readFile(instantManifestPath, 'utf8'); + instantContent = instantContent.replace(pattern, replaceString); + await fs.writeFile(manifestPath, content); + await fs.writeFile(instantManifestPath, instantContent); + } + } + private mapOrientationValue() { const orientation = this.params.platformParams.orientation; let orientationValue = 'unspecified'; @@ -350,6 +390,37 @@ export class AndroidPackTool extends NativePackTool { } } + /** + * Deprecated, only be compatible with historical packaging tools + */ + protected async configAndroidInstant() { + if (!this.params.platformParams.androidInstant) { + console.log('android instant not configured'); + return; + } + const url = this.params.platformParams.remoteUrl; + if (!url) { + return; + } + const manifestPath = cchelper.join(this.paths.platformTemplateDirInPrj, 'instantapp/AndroidManifest.xml'); + if (!fs.existsSync(manifestPath)) { + throw new Error(`${manifestPath} not found`); + } + const urlInfo = URL.parse(url); + if (!urlInfo.host) { + throw new Error(`parse url ${url} fail`); + } + let manifest = fs.readFileSync(manifestPath, 'utf8'); + manifest = manifest.replace(//, (str) => { + let newStr = ''; + newStr += `\n ` + + `\n `; + return newStr; + }); + + fs.writeFileSync(manifestPath, manifest, 'utf8'); + } + private async generateAppNameValues() { const valuesPath = cchelper.join(this.paths.platformTemplateDirInPrj, 'res/values/strings.xml'); const matchCnt = fs.readFileSync(valuesPath, 'utf8').toString().split('\n').map(x => x.trim()).filter(x => /name=\"app_name\"/.test(x)).length; diff --git a/templates/xr-huaweivr/template/app/AndroidManifest.xml b/templates/xr-huaweivr/template/app/AndroidManifest.xml index 89419ae2d12..cc51f13aec8 100644 --- a/templates/xr-huaweivr/template/app/AndroidManifest.xml +++ b/templates/xr-huaweivr/template/app/AndroidManifest.xml @@ -20,7 +20,7 @@ diff --git a/templates/xr-huaweivr/template/instantapp/AndroidManifest.xml b/templates/xr-huaweivr/template/instantapp/AndroidManifest.xml index aa061c55845..a122933bebc 100644 --- a/templates/xr-huaweivr/template/instantapp/AndroidManifest.xml +++ b/templates/xr-huaweivr/template/instantapp/AndroidManifest.xml @@ -25,7 +25,7 @@ diff --git a/templates/xr-meta/template/app/AndroidManifest.xml b/templates/xr-meta/template/app/AndroidManifest.xml index 89419ae2d12..cc51f13aec8 100644 --- a/templates/xr-meta/template/app/AndroidManifest.xml +++ b/templates/xr-meta/template/app/AndroidManifest.xml @@ -20,7 +20,7 @@ diff --git a/templates/xr-meta/template/instantapp/AndroidManifest.xml b/templates/xr-meta/template/instantapp/AndroidManifest.xml index aa061c55845..a122933bebc 100644 --- a/templates/xr-meta/template/instantapp/AndroidManifest.xml +++ b/templates/xr-meta/template/instantapp/AndroidManifest.xml @@ -25,7 +25,7 @@ diff --git a/templates/xr-monado/template/app/AndroidManifest.xml b/templates/xr-monado/template/app/AndroidManifest.xml index 89419ae2d12..cc51f13aec8 100644 --- a/templates/xr-monado/template/app/AndroidManifest.xml +++ b/templates/xr-monado/template/app/AndroidManifest.xml @@ -20,7 +20,7 @@ diff --git a/templates/xr-monado/template/instantapp/AndroidManifest.xml b/templates/xr-monado/template/instantapp/AndroidManifest.xml index aa061c55845..a122933bebc 100644 --- a/templates/xr-monado/template/instantapp/AndroidManifest.xml +++ b/templates/xr-monado/template/instantapp/AndroidManifest.xml @@ -25,7 +25,7 @@ diff --git a/templates/xr-pico/template/app/AndroidManifest.xml b/templates/xr-pico/template/app/AndroidManifest.xml index 89419ae2d12..cc51f13aec8 100644 --- a/templates/xr-pico/template/app/AndroidManifest.xml +++ b/templates/xr-pico/template/app/AndroidManifest.xml @@ -20,7 +20,7 @@ diff --git a/templates/xr-pico/template/instantapp/AndroidManifest.xml b/templates/xr-pico/template/instantapp/AndroidManifest.xml index aa061c55845..a122933bebc 100644 --- a/templates/xr-pico/template/instantapp/AndroidManifest.xml +++ b/templates/xr-pico/template/instantapp/AndroidManifest.xml @@ -25,7 +25,7 @@ diff --git a/templates/xr-rokid/template/app/AndroidManifest.xml b/templates/xr-rokid/template/app/AndroidManifest.xml index 89419ae2d12..cc51f13aec8 100644 --- a/templates/xr-rokid/template/app/AndroidManifest.xml +++ b/templates/xr-rokid/template/app/AndroidManifest.xml @@ -20,7 +20,7 @@ diff --git a/templates/xr-rokid/template/instantapp/AndroidManifest.xml b/templates/xr-rokid/template/instantapp/AndroidManifest.xml index aa061c55845..a122933bebc 100644 --- a/templates/xr-rokid/template/instantapp/AndroidManifest.xml +++ b/templates/xr-rokid/template/instantapp/AndroidManifest.xml @@ -25,7 +25,7 @@ diff --git a/templates/xr-spaces/template/app/AndroidManifest.xml b/templates/xr-spaces/template/app/AndroidManifest.xml index c98db30bb8c..2be341646f8 100644 --- a/templates/xr-spaces/template/app/AndroidManifest.xml +++ b/templates/xr-spaces/template/app/AndroidManifest.xml @@ -22,7 +22,7 @@ diff --git a/templates/xr-spaces/template/instantapp/AndroidManifest.xml b/templates/xr-spaces/template/instantapp/AndroidManifest.xml index aa061c55845..a122933bebc 100644 --- a/templates/xr-spaces/template/instantapp/AndroidManifest.xml +++ b/templates/xr-spaces/template/instantapp/AndroidManifest.xml @@ -25,7 +25,7 @@ From 5f61d2a112928e158f0503b6781d665bb5b85aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=A3=AE=E6=96=8C?= Date: Mon, 21 Aug 2023 19:28:33 +0800 Subject: [PATCH 162/184] fix fbx and widget bug in inspector (#16057) * optimize widget layout * fix bug of resizing panel , fbx event point would not update position * change method name --- editor/inspector/assets/fbx/preview.js | 7 +++++-- editor/inspector/components/widget.js | 26 ++++++++++++++------------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/editor/inspector/assets/fbx/preview.js b/editor/inspector/assets/fbx/preview.js index ad9b5fa0967..a19ecff5a3e 100644 --- a/editor/inspector/assets/fbx/preview.js +++ b/editor/inspector/assets/fbx/preview.js @@ -28,7 +28,7 @@ exports.template = /* html */`
- +
@@ -310,7 +310,10 @@ const Elements = { const panel = this; function observer() { - panel.isPreviewDataDirty = true; + window.requestAnimationFrame(() => { + panel.isPreviewDataDirty = true; + panel.updateEventInfo(); + }); } panel.resizeObserver = new window.ResizeObserver(observer); diff --git a/editor/inspector/components/widget.js b/editor/inspector/components/widget.js index 8c7b0b371a0..a4b52964acd 100644 --- a/editor/inspector/components/widget.js +++ b/editor/inspector/components/widget.js @@ -945,6 +945,16 @@ exports.methods = { const lockDirection = LockFlags[direction]; return lockValue & lockDirection; }, + setLayout() { + const rect = this.$this.getBoundingClientRect(); + if (rect.width) { + if (rect.width > cssMediaWidth) { + this.layout = 'horizontal'; + } else { + this.layout = 'vertical'; + } + } + }, }; const uiElements = { baseProps: { @@ -1213,12 +1223,7 @@ exports.ready = function() { return; } - const rect = this.$this.getBoundingClientRect(); - if (rect.width > cssMediaWidth) { - this.layout = 'horizontal'; - } else { - this.layout = 'vertical'; - } + this.setLayout(); }); }); @@ -1235,12 +1240,9 @@ exports.update = function(dump) { this.dump = dump; this.dimensionHorizontal = this.getDimensionHorizontal(); this.dimensionVertical = this.getDimensionVertical(); - const rect = this.$this.getBoundingClientRect(); - if (rect.width > cssMediaWidth) { - this.layout = 'horizontal'; - } else { - this.layout = 'vertical'; - } + + this.setLayout(); + if (!this.vm) { this.vm = new Vue({ el: this.$.app, From 13d01a4d79629021959baab0317b830c883a2e54 Mon Sep 17 00:00:00 2001 From: Zeqiang Li Date: Tue, 22 Aug 2023 12:44:18 +0800 Subject: [PATCH 163/184] mtl depth resolve feature query update (#16061) --- native/cocos/renderer/gfx-metal/MTLDevice.mm | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/native/cocos/renderer/gfx-metal/MTLDevice.mm b/native/cocos/renderer/gfx-metal/MTLDevice.mm index 097d14dd0b1..25a5887fc87 100644 --- a/native/cocos/renderer/gfx-metal/MTLDevice.mm +++ b/native/cocos/renderer/gfx-metal/MTLDevice.mm @@ -139,7 +139,18 @@ of this software and associated engine source code (the "Software"), a limited, _features[toNumber(Feature::SUBPASS_DEPTH_STENCIL_INPUT)] = false; _features[toNumber(Feature::RASTERIZATION_ORDER_NOCOHERENT)] = true; - _features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] = [mtlDevice supportsFamily: MTLGPUFamilyApple3]; + if (@available(iOS 13.0, macOS 10.15, *)) { + // detph resolve requires MTLGPUFamilyApple3 while stencil resolve requires MTLGPUFamilyApple5 + _features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] = [mtlDevice supportsFamily:MTLGPUFamilyApple5]; + _features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] |= [mtlDevice supportsFamily:MTLGPUFamilyMac2]; + } else { +#if CC_PLATFOTM == CC_PLATFORM_IOS + id device = static_cast>(_mtlDevice); + _features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] = [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v4]; +#elif CC_PLATFOTM == CC_PLATFORM_MACOS + _features[toNumber(Feature::MULTI_SAMPLE_RESOLVE_DEPTH_STENCIL)] = false; +#endif + } QueueInfo queueInfo; queueInfo.type = QueueType::GRAPHICS; From f330132aa3e739fab9f8a8c4cf6a98f6c690cc24 Mon Sep 17 00:00:00 2001 From: Gin Date: Tue, 22 Aug 2023 13:57:03 +0800 Subject: [PATCH 164/184] improve: effects list sorting in material panel (#16060) * improve: effects list ordering in material panel * fixup: set collator option `numeric` to `true` * fixup: use `Object.value` & filter * fixup: filter predicate function --- editor/inspector/assets/material.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/editor/inspector/assets/material.js b/editor/inspector/assets/material.js index 739914da483..5ca424d74e8 100644 --- a/editor/inspector/assets/material.js +++ b/editor/inspector/assets/material.js @@ -180,14 +180,12 @@ exports.methods = { async updateEffect() { const effectMap = await Editor.Message.request('scene', 'query-all-effects'); + // see: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator + const collator = new Intl.Collator(undefined, { numeric: true }); - this.effects = Object.keys(effectMap).sort().reduce((arr, name) => { - const effect = effectMap[name]; - if (!effect.hideInEditor) { - arr.push(effect); - } - return arr; - }, []); + this.effects = Object.values(effectMap) + .filter((effect) => !effect.hideInEditor) + .sort((a, b) => collator.compare(a.name, b.name)); const effectOptionsHTML = renderGroupEffectOptions(this.effects); From baea594f93d035e2bfd9eafc02cf274fa5b9c1fe Mon Sep 17 00:00:00 2001 From: Santy-Wang Date: Tue, 22 Aug 2023 15:15:35 +0800 Subject: [PATCH 165/184] bump external tag (#16066) --- native/external-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/external-config.json b/native/external-config.json index 1ce55742884..e98b7dba9e9 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-14" + "checkout": "v3.8.1-15" } } \ No newline at end of file From 3febfab3101ae54ce789ab434b98fbcb35f4dae8 Mon Sep 17 00:00:00 2001 From: Yiwen <15225434259xue@gmail.com> Date: Tue, 22 Aug 2023 15:40:18 +0800 Subject: [PATCH 166/184] fix rendering submesh typo (#16063) * fix rendering submesh typo * fix typo * sync external tag --- native/cocos/core/assets/RenderingSubMesh.cpp | 2 +- native/cocos/math/Utils.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/native/cocos/core/assets/RenderingSubMesh.cpp b/native/cocos/core/assets/RenderingSubMesh.cpp index de744d7d09a..f8e09cb85e8 100644 --- a/native/cocos/core/assets/RenderingSubMesh.cpp +++ b/native/cocos/core/assets/RenderingSubMesh.cpp @@ -95,7 +95,7 @@ const IGeometricInfo &RenderingSubMesh::getGeometricInfo() { auto iter = std::find_if(_attributes.cbegin(), _attributes.cend(), [](const gfx::Attribute &element) -> bool { return element.name == gfx::ATTR_NAME_POSITION; }); - if (iter != _attributes.end()) { + if (iter == _attributes.end()) { return EMPTY_GEOMETRIC_INFO; } diff --git a/native/cocos/math/Utils.cpp b/native/cocos/math/Utils.cpp index 5fdb01b56a3..285a8178b8b 100644 --- a/native/cocos/math/Utils.cpp +++ b/native/cocos/math/Utils.cpp @@ -103,7 +103,7 @@ float halfToFloat(uint16_t hval) { } } - u.ui = ((uint16_t)(s << 31)) | em | m; // NOLINT + u.ui = ((s << 31)) | em | m; // NOLINT return u.f; } From 5b5c3cf977bf9fb00802be5d02979123d671d5aa Mon Sep 17 00:00:00 2001 From: troublemaker52025 Date: Wed, 23 Aug 2023 10:53:24 +0800 Subject: [PATCH 167/184] fix custom pipeline load float-output-process error (#16071) --- cocos/asset/assets/effect-asset.ts | 2 +- .../post-process/passes/float-output-process-pass.ts | 6 +++--- .../assets/effects/pipeline/float-output-process.effect | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos/asset/assets/effect-asset.ts b/cocos/asset/assets/effect-asset.ts index 5a51e03cc71..06d4fac7039 100644 --- a/cocos/asset/assets/effect-asset.ts +++ b/cocos/asset/assets/effect-asset.ts @@ -203,7 +203,7 @@ const legacyBuiltinEffectNames = [ 'geometry-renderer', 'debug-renderer', 'ssss-blur', - 'tone-mapping', + 'float-output-process', ]; /** diff --git a/cocos/rendering/post-process/passes/float-output-process-pass.ts b/cocos/rendering/post-process/passes/float-output-process-pass.ts index 4570061fe2e..29c554dfb45 100644 --- a/cocos/rendering/post-process/passes/float-output-process-pass.ts +++ b/cocos/rendering/post-process/passes/float-output-process-pass.ts @@ -33,9 +33,9 @@ import { SettingPass } from './setting-pass'; import { Root } from '../../../root'; export class FloatOutputProcessPass extends SettingPass { - name = 'FloatOutputProcessesPass'; - effectName = 'pipeline/float-output-processes'; - outputNames = ['FloatOutputProcesses']; + name = 'FloatOutputProcessPass'; + effectName = 'pipeline/float-output-process'; + outputNames = ['FloatOutputProcess']; enableInAllEditorCamera = true; enable = true; diff --git a/editor/assets/effects/pipeline/float-output-process.effect b/editor/assets/effects/pipeline/float-output-process.effect index 055d728a4e9..791a653a9bc 100644 --- a/editor/assets/effects/pipeline/float-output-process.effect +++ b/editor/assets/effects/pipeline/float-output-process.effect @@ -37,11 +37,11 @@ CCProgram tonemap-fs %{ layout(location = 0) out vec4 fragColor; vec3 HDR2LDR_PostProcess(vec3 color) { - vec3 tempColor = color.rgb; - #if CC_USE_HDR && CC_TONE_MAPPING_TYPE == HDR_TONE_MAPPING_ACES - tempColor.rgb = ACESToneMap(color.rgb); + #if CC_USE_HDR && CC_TONE_MAPPING_TYPE == TONE_MAPPING_ACES + return ACESToneMap(color.rgb); + #else + return color.rgb; #endif - return tempColor.rgb; } vec4 CCFragOutput_PostProcess(vec4 color) { From 563e9f780d824d6e6cd092e84e08ef9e735eec2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=A3=AE=E6=96=8C?= Date: Wed, 23 Aug 2023 11:08:57 +0800 Subject: [PATCH 168/184] fix change language would not update help doc link (#16067) --- editor/inspector/contributions/asset.js | 33 ++++++++-- editor/inspector/contributions/node.js | 81 ++++++++++++------------- 2 files changed, 66 insertions(+), 48 deletions(-) diff --git a/editor/inspector/contributions/asset.js b/editor/inspector/contributions/asset.js index 1482beec798..255b025959c 100644 --- a/editor/inspector/contributions/asset.js +++ b/editor/inspector/contributions/asset.js @@ -70,6 +70,9 @@ const Elements = { Editor.Message.addBroadcastListener('asset-db:asset-change', panel.__assetChanged__); + Elements.panel.i18nChangeBind = Elements.panel.i18nChange.bind(panel); + Editor.Message.addBroadcastListener('i18n:change', Elements.panel.i18nChangeBind); + panel.history = new History(); }, async update() { @@ -146,7 +149,7 @@ const Elements = { return JSON.stringify(meta); }); - panel.getHelpUrl(Editor.I18n.t(`ENGINE.help.assets.${panel.type}`)); + panel.setHelpUrl(panel.$.help, { help: panel.type }); }, close() { const panel = this; @@ -160,6 +163,12 @@ const Elements = { delete panel.history; }, + i18nChange() { + const panel = this; + + const $links = panel.$.container.querySelectorAll('ui-link'); + $links.forEach($link => panel.setHelpUrl($link)); + }, }, header: { ready() { @@ -572,16 +581,28 @@ exports.methods = { panel.$this.update(panel.uuidList, panel.renderMap); }, - getHelpUrl(url) { - const panel = this; + setHelpUrl($link, data) { + if (data) { + $link.helpData = data; + } else { + if (!$link.helpData) { + return; + } + data = $link.helpData; + } + + const url = this.getHelpUrl(data); if (url) { - panel.$.help.style.display = 'block'; - panel.$.help.value = url; + $link.style.display = 'block'; + $link.value = url; } else { - panel.$.help.style.display = 'none'; + $link.style.display = 'none'; } }, + getHelpUrl(data) { + return Editor.I18n.t(`ENGINE.help.assets.${data.help}`); + }, replaceContainerWithUISection(params) { const panel = this; const $containerDiv = panel.$.container; diff --git a/editor/inspector/contributions/node.js b/editor/inspector/contributions/node.js index 7ddbbbec836..efd9c8c9279 100644 --- a/editor/inspector/contributions/node.js +++ b/editor/inspector/contributions/node.js @@ -847,7 +847,7 @@ const Elements = { const panel = this; const $help = panel.$.sceneSkybox.querySelector('ui-link'); - $help.value = panel.getHelpUrl({ help: 'i18n:cc.Skybox' }); + panel.setHelpUrl($help, { help: 'i18n:cc.Skybox' }); $help.addEventListener('click', (event) => { event.stopPropagation(); event.preventDefault(); @@ -878,15 +878,18 @@ const Elements = { // 由于场景属性对象不是继承于 Component 所以没有修饰器,displayName, help 数据在这里配置 panel.dump._globals.ambient.displayName = 'Ambient'; - panel.dump._globals.ambient.help = panel.getHelpUrl({ help: 'i18n:cc.Ambient' }); + panel.dump._globals.ambient.editor = { help: 'i18n:cc.Ambient' }; + panel.dump._globals.ambient.help = panel.getHelpUrl(panel.dump._globals.ambient.editor); panel.$.sceneAmbient.render(panel.dump._globals.ambient); panel.dump._globals.fog.displayName = 'Fog'; - panel.dump._globals.fog.help = panel.getHelpUrl({ help: 'i18n:cc.Fog' }); + panel.dump._globals.fog.editor = { help: 'i18n:cc.Fog' }; + panel.dump._globals.fog.help = panel.getHelpUrl(panel.dump._globals.fog.editor); panel.$.sceneFog.render(panel.dump._globals.fog); panel.dump._globals.shadows.displayName = 'Shadows'; - panel.dump._globals.shadows.help = panel.getHelpUrl({ help: 'i18n:cc.Shadow' }); + panel.dump._globals.shadows.editor = { help: 'i18n:cc.Shadow' }; + panel.dump._globals.shadows.help = panel.getHelpUrl(panel.dump._globals.shadows.editor); panel.$.sceneShadows.render(panel.dump._globals.shadows); // skyBox 逻辑 start @@ -952,11 +955,13 @@ const Elements = { // skyBox 逻辑 end panel.dump._globals.octree.displayName = 'Octree Scene Culling'; - panel.dump._globals.octree.help = panel.getHelpUrl({ help: 'i18n:cc.OctreeCulling' }); + panel.dump._globals.octree.editor = { help: 'i18n:cc.OctreeCulling' }; + panel.dump._globals.octree.help = panel.getHelpUrl(panel.dump._globals.octree.editor); panel.$.sceneOctree.render(panel.dump._globals.octree); panel.dump._globals.skin.displayName = 'Skin'; - panel.dump._globals.skin.help = panel.getHelpUrl({ help: 'i18n:cc.Skin' }); + panel.dump._globals.skin.editor = { help: 'i18n:cc.Skin' }; + panel.dump._globals.skin.help = panel.getHelpUrl(panel.dump._globals.skin.editor); panel.$.sceneSkin.render(panel.dump._globals.skin); panel.dump._globals.postSettings.displayName = 'PostSettings'; @@ -1119,7 +1124,7 @@ const Elements = { panel.$skyboxProps = {}; - panel.$.nodeLink.value = Editor.I18n.t('ENGINE.help.cc.Node'); + panel.setHelpUrl(panel.$.nodeLink, { help: 'i18n:cc.Node' }); panel.$.nodeMenu.addEventListener('click', (event) => { event.stopPropagation(); @@ -1193,13 +1198,8 @@ const Elements = { $active.invalid = false; } - const url = panel.getHelpUrl(dump.editor); const $link = $section.querySelector('ui-link'); - if (url) { - $link.setAttribute('value', url); - } else { - $link.removeAttribute('value'); - } + panel.setHelpUrl($link, dump.editor); await Promise.all($section.__panels__.map(($panel) => { return $panel.update(dump); @@ -1271,13 +1271,10 @@ const Elements = { }); const $link = $section.querySelector('.link'); - const url = panel.getHelpUrl(component.editor); - if (url) { - $link.setAttribute('value', url); - $link.addEventListener('click', (event) => { - event.stopPropagation(); - }); - } + $link.addEventListener('click', (event) => { + event.stopPropagation(); + }); + panel.setHelpUrl($link, component.editor); const $menu = $section.querySelector('.menu'); $menu.addEventListener('click', (event) => { @@ -1387,25 +1384,8 @@ const Elements = { i18nChange() { const panel = this; - panel.$.nodeLink.value = Editor.I18n.t('ENGINE.help.cc.Node'); - - const sectionBody = panel.$.sectionBody; - for (let index = 0; index < sectionBody.__sections__.length; index++) { - const $section = sectionBody.__sections__[index]; - const $link = $section.querySelector('ui-link'); - - if (!$link) { - continue; - } - - const dump = $section.dump; - const url = panel.getHelpUrl(dump.editor); - if (url) { - $link.setAttribute('value', url); - } else { - $link.removeAttribute('value'); - } - } + const $links = panel.$.container.querySelectorAll('ui-link'); + $links.forEach($link => panel.setHelpUrl($link)); }, }, missingComponent: { @@ -1671,16 +1651,33 @@ exports.methods = { Editor.Message.send(messageProtocol.scene, cmd); }, + setHelpUrl($link, data) { + if (data) { + $link.helpData = data; + } else { + if (!$link.helpData) { + return; + } + data = $link.helpData; + } + + const url = this.getHelpUrl(data); + if (url) { + $link.setAttribute('value', url); + } else { + $link.removeAttribute('value'); + } + }, /** * 获取组件帮助菜单的 url * @param editor */ - getHelpUrl(editor) { - if (!editor || !editor.help) { + getHelpUrl(data) { + if (!data || !data.help) { return ''; } - const help = editor.help; + const help = data.help; /** * 约定的规则 From aff8320359a08175fc0af082ce2184d443131657 Mon Sep 17 00:00:00 2001 From: dogeFu <609075410@qq.com> Date: Wed, 23 Aug 2023 11:57:46 +0800 Subject: [PATCH 169/184] Fix : editor preview set fps no working (#16054) --- pal/pacer/pacer-web.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pal/pacer/pacer-web.ts b/pal/pacer/pacer-web.ts index f24212984a2..488c0eeab74 100644 --- a/pal/pacer/pacer-web.ts +++ b/pal/pacer/pacer-web.ts @@ -85,8 +85,9 @@ export class Pacer { start (): void { if (this._isPlaying) return; - + const recordStartTime = EDITOR || this._rAF === undefined || globalThis.__globalXR?.isWebXR; const updateCallback = (): void => { + if (recordStartTime) this._startTime = performance.now(); if (this._isPlaying) { this._stHandle = this._stTime(updateCallback); } From 0f5609b96b01a043f7c2fbad3fb9c2df5c8a480d Mon Sep 17 00:00:00 2001 From: SijieWang Date: Wed, 23 Aug 2023 11:57:57 +0800 Subject: [PATCH 170/184] [Optimize] clear-platform supports passing arguments. (#16073) --- native/utils/clear-platform.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/native/utils/clear-platform.js b/native/utils/clear-platform.js index 0cba7d8934e..42aa9ea1576 100644 --- a/native/utils/clear-platform.js +++ b/native/utils/clear-platform.js @@ -14,7 +14,7 @@ const child_process = require('child_process'); const fetch = require('node-fetch'); // usage: npm run clear-platform -let externalDir = path.join(__dirname, "../external"); +let externalDir = process.env.ENGINE_PATH ? path.join(process.env.ENGINE_PATH, "./native/external") : path.join(__dirname, "../external"); let failed = false; let macUsefulDirs = ['android', 'cmake', 'emscripten', 'ios', 'ios-m1-simulator', 'mac', 'ohos', 'sources', 'openharmony']; @@ -95,7 +95,7 @@ function cleanPlatform(platform) { } else { // others console.log(chalk.red(`Platform ${platform} is not supported, skip`)); } - // abnormal exit + // abnormal exit if (failed) { process.exit(-1); } @@ -185,7 +185,7 @@ async function minimizeBoost() { const BOOST_VERSION_DOTTED = BOOST_VERSION.join('.'); const BOOST_VERSION_UNDERSCORE = BOOST_VERSION.join('_'); const BOOST_ZIP_FILE = `boost_${BOOST_VERSION_UNDERSCORE}.tar.gz`; - const EXTERNAL_SOURCE_DIR = path.join(__dirname, '..', 'external', 'sources'); + const EXTERNAL_SOURCE_DIR = path.join(externalDir, 'sources'); const BOOST_DOWNLOAD = path.join(EXTERNAL_SOURCE_DIR, 'boost-download'); const BOOST_ORIG_PATH = path.join(EXTERNAL_SOURCE_DIR, 'boost'); const BOOST_DEST = path.join(EXTERNAL_SOURCE_DIR, 'boost-minimized'); @@ -195,7 +195,7 @@ async function minimizeBoost() { const BOOST_URL_LOCAL = `http://ftp.cocos.org/TestBuilds/Editor-3d/tools/boost_${BOOST_VERSION_UNDERSCORE}.tar.gz` const BCP_PATH = path.join(BOOST_DECOMPRESSED_PATH, 'dist', 'bin', execName('bcp')); - const ENGINE_ROOT = path.normalize(path.join(__dirname, '../../')); + const ENGINE_ROOT = path.normalize(path.join(externalDir, '../../')); let headersUsedByEngine = []; @@ -385,4 +385,4 @@ async function minimizeBoost() { await fnCollectBoostHeaders(); await fnRunBCP(); await fnCleanUp(); // skip this step when debugging -} \ No newline at end of file +} From a4990ce4e6751b330626442f36682e9d4e2344f2 Mon Sep 17 00:00:00 2001 From: Yiwen <15225434259xue@gmail.com> Date: Wed, 23 Aug 2023 11:59:56 +0800 Subject: [PATCH 171/184] Fix meshopt wechat (#16069) * fix wechat wasm problem, sync external tag * fix formatting * fix tidy, unit test --- cocos/3d/misc/mesh-codec.ts | 7 ++++++- native/external-config.json | 2 +- tests/init.ts | 7 +++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cocos/3d/misc/mesh-codec.ts b/cocos/3d/misc/mesh-codec.ts index 86094fce109..b6ed3862bc2 100644 --- a/cocos/3d/misc/mesh-codec.ts +++ b/cocos/3d/misc/mesh-codec.ts @@ -24,8 +24,10 @@ import meshopt_asm_factory from 'external:emscripten/meshopt/meshopt_decoder.asm.js'; import meshopt_wasm_factory from 'external:emscripten/meshopt/meshopt_decoder.wasm.js'; +import meshopt_wasm_url from 'external:emscripten/meshopt/meshopt_decoder.wasm.wasm'; import { WASM_SUPPORT_MODE } from 'internal:constants'; +import { instantiateWasm } from 'pal/wasm'; import { sys, logID } from '../../core'; @@ -51,7 +53,10 @@ function initDecoderASM (): Promise { function initDecoderWASM (): Promise { const Module = meshopt_wasm_factory; - return Promise.all([Module.ready]).then(() => { + function instantiate (importObject: WebAssembly.Imports): any { + return instantiateWasm(meshopt_wasm_url, importObject) as any; + } + return Promise.all([Module.ready(instantiate)]).then(() => { MeshoptDecoder.supported = true; MeshoptDecoder.ready = Promise.resolve(); MeshoptDecoder.decodeVertexBuffer = Module.decodeVertexBuffer; diff --git a/native/external-config.json b/native/external-config.json index e98b7dba9e9..788ca7be350 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-15" + "checkout": "v3.8.1-16" } } \ No newline at end of file diff --git a/tests/init.ts b/tests/init.ts index cf8e31fe718..1b826a307e0 100644 --- a/tests/init.ts +++ b/tests/init.ts @@ -91,6 +91,13 @@ jest.mock( ); }); +jest.mock('external:emscripten/meshopt/meshopt_decoder.wasm.wasm', + () => ({ + __esModule: true, + default: 'this should be a wasm url', + }), + { virtual: true, }, +); // Mock external wasm js module here [ From da507e4ba79467d981de3ea26d7bfabe04c88a5d Mon Sep 17 00:00:00 2001 From: Canvas Date: Wed, 23 Aug 2023 12:45:17 +0800 Subject: [PATCH 172/184] fix spine wasm api array bind (#16064) * fix some array type bindings. * change engine-native-external to v3.8.1-15. * revert v3.8.1-15 to v3.8.1-14. * fix code format. * fix code format. * fix getAttachmentNames api. * off no-unsafe-argument. * change engine-native-external checkout to v3.8.1-16. * optimize use vector set & fix edges prototype error. * add vector default value 0 annotation. --- cocos/spine/lib/spine-define.ts | 119 +++++++++--------- .../spine-wasm/spine-type-export.cpp | 51 ++++++-- 2 files changed, 101 insertions(+), 69 deletions(-) diff --git a/cocos/spine/lib/spine-define.ts b/cocos/spine/lib/spine-define.ts index 447df050ff7..28d53f939f2 100644 --- a/cocos/spine/lib/spine-define.ts +++ b/cocos/spine/lib/spine-define.ts @@ -22,6 +22,7 @@ THE SOFTWARE. */ /* eslint @typescript-eslint/no-explicit-any: "off" */ +/* eslint @typescript-eslint/no-unsafe-argument: "off" */ import spine from './spine-core.js'; import { js } from '../../core'; @@ -42,6 +43,53 @@ function overrideDefineArrayProp (prototype: any, getPropVector: any, name: stri }); } +function overrideDefineArrayArrayProp (prototype: any, getPropVector: any, name: string): void { + Object.defineProperty(prototype, name, { + get (): any[] { + const array: any[] = []; + const vectors = getPropVector.call(this); + const count = vectors.size(); + for (let i = 0; i < count; i++) { + const vectorI = vectors.get(i); + const countJ = vectorI.size(); + const arrayJ: any[] = []; + for (let j = 0; j < countJ; j++) { + arrayJ.push(vectorI.get(j)); + } + array.push(arrayJ); + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return array; + }, + }); +} + +function overrideDefineArrayPropGetSet (prototype: any, getPropVector: any, setPropVector: any, Type: any, name: string): void { + Object.defineProperty(prototype, name, { + get (): any[] { + const array: any[] = []; + const vectors = getPropVector.call(this); + const count = vectors.size(); + for (let i = 0; i < count; i++) { + const objPtr = vectors.get(i); + array.push(objPtr); + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return array; + }, + set (value: any[]) { + const vectors = new Type(); + const count = value.length; + // vector.resize(count, 0) default 0, because currently only the number type will use this function. + vectors.resize(count, 0); + for (let i = 0; i < count; i++) { + vectors.set(i, value[i]); + } + setPropVector.call(this, vectors); + }, + }); +} + function overrideDefineArrayFunction (prototype: any, getPropVector: any, name: string): void { Object.defineProperty(prototype, name, { value () { @@ -478,16 +526,6 @@ function overrideProperty_VertexAttachment (): void { getter: prototype.getId, setter: prototype.setId, }, - { - proto: prototype, - property: 'bones', - getter: prototype.getBones, - }, - { - proto: prototype, - property: 'vertices', - getter: prototype.getVertices, - }, { proto: prototype, property: 'worldVerticesLength', @@ -504,6 +542,8 @@ function overrideProperty_VertexAttachment (): void { propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); + overrideDefineArrayProp(prototype, prototype.getBones, 'bones'); + overrideDefineArrayProp(prototype, prototype.getVertices, 'vertices'); } function overrideProperty_BoundingBoxAttachment (): void { @@ -544,21 +584,6 @@ function overrideProperty_MeshAttachment (): void { getter: prototype.getPath, setter: prototype.setPath, }, - { - proto: prototype, - property: 'regionUVs', - getter: prototype.getRegionUVs, - }, - { - proto: prototype, - property: 'uvs', - getter: prototype.getUVs, - }, - { - proto: prototype, - property: 'triangles', - getter: prototype.getTriangles, - }, { proto: prototype, property: 'color', @@ -582,15 +607,14 @@ function overrideProperty_MeshAttachment (): void { getter: prototype.getHullLength, setter: prototype.setHullLength, }, - { - proto: prototype, - property: 'edges', - getter: prototype.getEdges, - }, ]; propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); + overrideDefineArrayProp(prototype, prototype.getRegionUVs, 'regionUVs'); + overrideDefineArrayProp(prototype, prototype.getUVs, 'uvs'); + overrideDefineArrayProp(prototype, prototype.getTriangles, 'triangles'); + overrideDefineArrayProp(prototype, prototype.getEdges, 'edges'); } function overrideProperty_PathAttachment (): void { @@ -708,16 +732,11 @@ function overrideProperty_RegionAttachment (): void { property: 'offset', getter: prototype.getOffset, }, - { - proto: prototype, - property: 'uvs', - getter: prototype.getUVs, - setter: prototype.setUVs, - }, ]; propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); + overrideDefineArrayPropGetSet(prototype, prototype.getUVs, prototype.setUVs, spine.wasmUtil.wasm.VectorFloat, 'uvs'); } function overrideProperty_TextureAtlas (): void { @@ -752,11 +771,6 @@ function overrideProperty_SlotData (): void { property: 'name', getter: prototype.getName, }, - { - proto: prototype, - property: 'boneData', - getter: prototype.getBoneData, - }, { proto: prototype, property: 'color', @@ -777,6 +791,8 @@ function overrideProperty_SlotData (): void { propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); + overrideDefineArrayProp(prototype, prototype.getBoneData, 'boneData'); + overrideDefineArrayProp(prototype, prototype.getDeform, 'deform'); } function overrideProperty_IkConstraint (): void { @@ -1166,7 +1182,7 @@ function overrideProperty_Bone (): void { propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); - + overrideDefineArrayProp(prototype, prototype.getChildren, 'children'); const worldToLocal = prototype.worldToLocal; Object.defineProperty(prototype, 'worldToLocal', { value (vec2: spine.Vector2) { @@ -1175,7 +1191,6 @@ function overrideProperty_Bone (): void { vec2.y = vectors.get(1); }, }); - const localToWorld = prototype.localToWorld; Object.defineProperty(prototype, 'localToWorld', { value (vec2: spine.Vector2) { @@ -1438,16 +1453,12 @@ function overrideProperty_AttachmentTimeline (): void { property: 'slotIndex', getter: prototype.getSlotIndex, }, - { - proto: prototype, - property: 'attachmentNames', - getter: prototype.getAttachmentNames, - }, ]; propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter); }); overrideDefineArrayProp(prototype, prototype.getFrames, 'frames'); + overrideDefineArrayProp(prototype, prototype.getAttachmentNames, 'attachmentNames'); } function overrideProperty_DeformTimeline (): void { @@ -1463,16 +1474,12 @@ function overrideProperty_DeformTimeline (): void { property: 'attachment', getter: prototype.getAttachment, }, - { - proto: prototype, - property: 'frameVertices', - getter: prototype.getFrameVertices, - }, ]; propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter); }); overrideDefineArrayProp(prototype, prototype.getFrames, 'frames'); + overrideDefineArrayArrayProp(prototype, prototype.getFrameVertices, 'frameVertices'); } function overrideProperty_EventTimeline (): void { @@ -1665,11 +1672,6 @@ function overrideProperty_Animation (): void { property: 'name', getter: prototype.getName, }, - // { - // proto: prototype, - // property: 'timelines', - // getter: prototype.getProp_timelines, - // }, { proto: prototype, property: 'duration', @@ -1680,6 +1682,7 @@ function overrideProperty_Animation (): void { propertyPolyfills.forEach((prop): void => { js.getset(prop.proto, prop.property, prop.getter, prop.setter); }); + overrideDefineArrayProp(prototype, prototype.getTimelines, 'timelines'); } function overrideProperty_Skeleton (): void { diff --git a/native/cocos/editor-support/spine-wasm/spine-type-export.cpp b/native/cocos/editor-support/spine-wasm/spine-type-export.cpp index f8d7bf54def..d612247558b 100644 --- a/native/cocos/editor-support/spine-wasm/spine-type-export.cpp +++ b/native/cocos/editor-support/spine-wasm/spine-type-export.cpp @@ -30,6 +30,15 @@ std::vector VECTOR_SP2STD(Vector &container) { return stdVector; } +const std::vector VECTOR_SP2STD_STRING(Vector &container) { + int count = container.size(); + std::vector stdVector(count); + for (int i = 0; i < count; i++) { + stdVector[i] = STRING_SP2STD(container[i]); + } + return stdVector; +} + template std::vector> VECTOR_2_SP2STD(Vector> &container) { int count = container.size(); @@ -84,6 +93,7 @@ void VECTOR_STD_COPY_SP(std::vector &stdVector, Vector &spVector) { EMSCRIPTEN_BINDINGS(spine) { register_vector("VectorFloat"); + register_vector>("VectorVectorFloat"); register_vector("VectorUnsignedShort"); register_vector("VectorString"); register_vector("VectorBoneData"); @@ -92,6 +102,7 @@ EMSCRIPTEN_BINDINGS(spine) { register_vector("VectorSlotData"); register_vector("VectorSlot"); register_vector("VectorAnimation"); + register_vector("VectorTimeline"); register_vector("VectorSkin"); register_vector("VectorEventData"); register_vector("VectorEvent"); @@ -907,25 +918,35 @@ EMSCRIPTEN_BINDINGS(spine) { class_("Animation") .constructor &, float>() - .function("apply", &Animation::apply, allow_raw_pointers()) + .function("apply", optional_override([](Animation &obj, Skeleton &skeleton, + float lastTime, float time, bool loop, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, loop, &pEvents, alpha, blend, direction); + })) .function("getName", optional_override([](Animation &obj) { return STRING_SP2STD(obj.getName()); })) - .function("getTimelines", optional_override([](Animation &obj) { return VECTOR_SP2STD(obj.getTimelines()); })) + .function("getTimelines", optional_override([](Animation &obj) { + return VECTOR_SP2STD(obj.getTimelines()); }), allow_raw_pointers()) .function("hasTimeline", &Animation::hasTimeline) .function("getDuration", &Animation::getDuration) .function("setDuration", &Animation::setDuration); class_("Timeline") - // to fix apply - //.function("apply", &Timeline::apply, allow_raw_pointers()) .function("apply", optional_override([](Timeline &obj, Skeleton &skeleton, float lastTime, float time, std::vector &stdPEvents, float alpha, MixBlend blend, MixDirection direction) { auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); - }), allow_raw_pointers()) - .function("getPropertyId", &Timeline::getPropertyId); + }), pure_virtual()) + .function("getPropertyId", &Timeline::getPropertyId, pure_virtual()); class_>("CurveTimeline") + .function("apply", optional_override([](CurveTimeline &obj, Skeleton &skeleton, + float lastTime, float time, std::vector &stdPEvents, float alpha, + MixBlend blend, MixDirection direction) { + auto pEvents = VECTOR_STD2SP_POINTER(stdPEvents); + obj.apply(skeleton, lastTime, time, &pEvents, alpha, blend, direction); + }), pure_virtual()) .function("getPropertyId", &CurveTimeline::getPropertyId, pure_virtual()) .function("getFrameCount", &CurveTimeline::getFrameCount) .function("setLinear", &CurveTimeline::setLinear) @@ -1018,11 +1039,14 @@ EMSCRIPTEN_BINDINGS(spine) { .function("getFrames", optional_override([](AttachmentTimeline &obj) { return VECTOR_SP2STD((Vector &)obj.getFrames()); }), allow_raw_pointers()) .function("getAttachmentNames",optional_override([](AttachmentTimeline &obj) { - auto names = obj.getAttachmentNames(); - return VECTOR_SP2STD(names); }), allow_raw_pointers()) + Vector attachmentNames = obj.getAttachmentNames(); + return VECTOR_SP2STD_STRING(attachmentNames); }), allow_raw_pointers()) .function("getPropertyId", &AttachmentTimeline::getPropertyId) .function("getFrameCount", &AttachmentTimeline::getFrameCount) - .function("setFrame", &AttachmentTimeline::setFrame) + .function("setFrame", optional_override([](AttachmentTimeline &obj, int frameIndex, float time, const std::string &attachmentName){ + const String attachmentNameSP = STRING_STD2SP(attachmentName); + obj.setFrame(frameIndex, time, attachmentNameSP); + }), allow_raw_pointers()) .function("apply", optional_override([](AttachmentTimeline &obj, Skeleton &skeleton, float lastTime, float time, std::vector &stdPEvents, float alpha, MixBlend blend, MixDirection direction) { @@ -1037,9 +1061,14 @@ EMSCRIPTEN_BINDINGS(spine) { .function("getAttachment", &DeformTimeline::getAttachment, allow_raw_pointers()) .function("setAttachment", &DeformTimeline::setAttachment, allow_raw_pointers()) .function("getFrames", optional_override([](DeformTimeline &obj) { return VECTOR_SP2STD((Vector &)obj.getFrames()); })) - .function("getFrameVertices", &DeformTimeline::getVertices) + .function("getFrameVertices", optional_override([](DeformTimeline &obj){ + return VECTOR_2_SP2STD(obj.getVertices()); + }), allow_raw_pointers()) .function("getPropertyId", &DeformTimeline::getPropertyId) - .function("setFrame", &DeformTimeline::setFrame) + .function("setFrame", optional_override([](DeformTimeline &obj, int frameIndex, float time, std::vector &vertices){ + Vector sp_vertices = VECTOR_STD2SP(vertices); + obj.setFrame(frameIndex, time, sp_vertices); + }), allow_raw_pointers()) .function("apply", optional_override([](DeformTimeline &obj, Skeleton &skeleton, float lastTime, float time, std::vector &stdPEvents, float alpha, MixBlend blend, MixDirection direction) { From e9ca89f73eef284786e4e1075e439bb7a2d0e05c Mon Sep 17 00:00:00 2001 From: Canvas Date: Wed, 23 Aug 2023 21:15:21 +0800 Subject: [PATCH 173/184] update external-config checkout to v3.8.1-17. (#16081) --- native/external-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/external-config.json b/native/external-config.json index 788ca7be350..ec906e37394 100644 --- a/native/external-config.json +++ b/native/external-config.json @@ -3,6 +3,6 @@ "type": "github", "owner": "cocos-creator", "name": "engine-native-external", - "checkout": "v3.8.1-16" + "checkout": "v3.8.1-17" } } \ No newline at end of file From e86f6d27fdcdb8f1ac17c0b91479d5be1ab0f3dd Mon Sep 17 00:00:00 2001 From: qiuguohua Date: Thu, 24 Aug 2023 10:47:45 +0800 Subject: [PATCH 174/184] Does not handle mismatched touchid (#16078) --- native/cocos/platform/openharmony/OpenHarmonyPlatform.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/native/cocos/platform/openharmony/OpenHarmonyPlatform.cpp b/native/cocos/platform/openharmony/OpenHarmonyPlatform.cpp index 7e47c1160d1..74211b5cc2b 100644 --- a/native/cocos/platform/openharmony/OpenHarmonyPlatform.cpp +++ b/native/cocos/platform/openharmony/OpenHarmonyPlatform.cpp @@ -93,7 +93,10 @@ void dispatchTouchEventCB(OH_NativeXComponent* component, void* window) { ev->type = cc::TouchEvent::Type::CANCELLED; } for (int i = 0; i < touchEvent.numPoints; ++i) { - ev->touches.emplace_back(touchEvent.touchPoints[i].x, touchEvent.touchPoints[i].y, touchEvent.touchPoints[i].id); + int32_t id = touchEvent.touchPoints[i].id; + if (touchEvent.id == id) { + ev->touches.emplace_back(touchEvent.touchPoints[i].x, touchEvent.touchPoints[i].y, id); + } } sendMsgToWorker(cc::MessageType::WM_XCOMPONENT_TOUCH_EVENT, reinterpret_cast(ev), window); } From dee666c994827581db01aaf93b1516c3f0da9356 Mon Sep 17 00:00:00 2001 From: fqamic Date: Thu, 24 Aug 2023 15:53:37 +0800 Subject: [PATCH 175/184] fix: xr platform crash with new material change (#16092) --- cocos/game/splash-screen.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/cocos/game/splash-screen.ts b/cocos/game/splash-screen.ts index 87ee4f71ff3..480f1c38953 100644 --- a/cocos/game/splash-screen.ts +++ b/cocos/game/splash-screen.ts @@ -496,11 +496,15 @@ export class SplashScreen { // keep scale to [-1, 1] only use offset this.projection.m00 = preTransforms[swapchain.surfaceTransform][0]; this.projection.m05 = preTransforms[swapchain.surfaceTransform][3] * device.capabilities.clipSpaceSignY; - this.bgMat.setProperty('u_projection', this.projection); - this.bgMat.passes[0].update(); - this.logoMat.setProperty('u_projection', this.projection); - this.logoMat.passes[0].update(); - if (this.watermarkMat) { + if (this.settings.background!.type === 'custom') { + this.bgMat.setProperty('u_projection', this.projection); + this.bgMat.passes[0].update(); + } + if (this.settings.logo!.type !== 'none') { + this.logoMat.setProperty('u_projection', this.projection); + this.logoMat.passes[0].update(); + } + if (this.settings.logo!.type === 'default' && this.watermarkMat) { this.watermarkMat.setProperty('u_projection', this.projection); this.watermarkMat.passes[0].update(); } From 16d720663a650623f5f9028a96117f1a17d78312 Mon Sep 17 00:00:00 2001 From: troublemaker52025 Date: Fri, 25 Aug 2023 10:46:10 +0800 Subject: [PATCH 176/184] Fix hot update for pipeline effects and Float-output-process flow (#16084) --- cocos/render-scene/scene/fog.ts | 7 ++- cocos/render-scene/scene/index.jsb.ts | 1 + cocos/rendering/custom/builtin-pipelines.ts | 2 + cocos/rendering/custom/custom-pipeline.ts | 59 ++++++++++++++----- cocos/rendering/custom/pipeline.ts | 2 + cocos/rendering/custom/web-pipeline.ts | 7 ++- cocos/rendering/debug-view.ts | 8 +++ .../post-process/passes/base-pass.ts | 2 + .../passes/float-output-process-pass.ts | 40 +++++++++++-- .../post-process/passes/forward-pass.ts | 5 +- .../post-process/passes/hbao-pass.ts | 11 ++++ .../post-process/post-process-builder.ts | 12 ++++ cocos/root.jsb.ts | 11 ++++ editor/assets/effects/advanced/sky.effect | 14 ++--- .../pipeline/float-output-process.effect | 26 +++++++- editor/assets/effects/pipeline/skybox.effect | 13 +++- 16 files changed, 184 insertions(+), 36 deletions(-) diff --git a/cocos/render-scene/scene/fog.ts b/cocos/render-scene/scene/fog.ts index ed303ebb3cb..36a6f504ac5 100644 --- a/cocos/render-scene/scene/fog.ts +++ b/cocos/render-scene/scene/fog.ts @@ -25,6 +25,7 @@ import { Enum, Color, Vec4, cclegacy } from '../../core'; import { FogInfo } from '../../scene-graph/scene-globals'; import { SRGBToLinear } from '../../rendering/pipeline-funcs'; +import { Root } from '../../root'; const _v4 = new Vec4(); @@ -71,7 +72,7 @@ export const FogType = Enum({ LAYERED: 3, }); -const FOG_TYPE_NONE = FogType.LAYERED + 1; +export const FOG_TYPE_NONE = FogType.LAYERED + 1; /** * @en The fog representation in the render scene. @@ -229,7 +230,7 @@ export class Fog { protected _fogRange = 1.2; protected _activated = false; - public initialize (fogInfo : FogInfo): void { + public initialize (fogInfo: FogInfo): void { this._activated = false; this.fogColor = fogInfo.fogColor; this._enabled = fogInfo.enabled; @@ -249,7 +250,7 @@ export class Fog { } protected _updatePipeline (): void { - const root = cclegacy.director.root; + const root = cclegacy.director.root as Root; const value = this.enabled ? this.type : FOG_TYPE_NONE; const accurateValue = this.accurate ? 1 : 0; const pipeline = root.pipeline; diff --git a/cocos/render-scene/scene/index.jsb.ts b/cocos/render-scene/scene/index.jsb.ts index 9cdfcdbacc9..ca62fa94c93 100644 --- a/cocos/render-scene/scene/index.jsb.ts +++ b/cocos/render-scene/scene/index.jsb.ts @@ -171,6 +171,7 @@ export const FogType = Enum({ */ LAYERED: 3, }); +export const FOG_TYPE_NONE = FogType.LAYERED + 1; export const FogInfo: typeof JsbFogInfo = jsb.FogInfo; export type FogInfo = JsbFogInfo; diff --git a/cocos/rendering/custom/builtin-pipelines.ts b/cocos/rendering/custom/builtin-pipelines.ts index eafed239dbb..1403ee8d602 100644 --- a/cocos/rendering/custom/builtin-pipelines.ts +++ b/cocos/rendering/custom/builtin-pipelines.ts @@ -121,6 +121,7 @@ export class DeferredPipelineBuilder implements PipelineBuilder { setupForwardRes(ppl, cameraInfo); return; } + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument if (!isUICamera(cameraInfo.camera)) { setupGBufferRes(ppl, cameraInfo); setupLightingRes(ppl, cameraInfo); @@ -134,6 +135,7 @@ export class DeferredPipelineBuilder implements PipelineBuilder { updateForwardRes(ppl, cameraInfo); return; } + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument if (!isUICamera(cameraInfo.camera)) { updateGBufferRes(ppl, cameraInfo); updateLightingRes(ppl, cameraInfo); diff --git a/cocos/rendering/custom/custom-pipeline.ts b/cocos/rendering/custom/custom-pipeline.ts index 993f71c6b50..e68fbbd0039 100644 --- a/cocos/rendering/custom/custom-pipeline.ts +++ b/cocos/rendering/custom/custom-pipeline.ts @@ -127,6 +127,7 @@ export class TestPipelineBuilder implements PipelineBuilder { constructor (pipelineSceneData: PipelineSceneData) { this._sceneInfo = new SceneInfo(pipelineSceneData); } + // interface public setup (cameras: Camera[], ppl: BasicPipeline): void { for (let i = 0; i < cameras.length; i++) { @@ -141,14 +142,21 @@ export class TestPipelineBuilder implements PipelineBuilder { ppl.update(camera); const info = this.prepareGameCamera(ppl, camera); this.prepareSceneInfo(camera.scene, camera.frustum, this._sceneInfo); - this.buildForward(ppl, camera, - info.id, info.width, info.height); + this.buildForward( + ppl, + camera, + info.id, + info.width, + info.height, + ); } } // implementation - private prepareSceneInfo (scene: Readonly, + private prepareSceneInfo ( + scene: Readonly, frustum: geometry.Frustum, - sceneInfo: SceneInfo): void { + sceneInfo: SceneInfo, + ): void { // clear scene info sceneInfo.reset(); // spot lights @@ -259,9 +267,14 @@ export class TestPipelineBuilder implements PipelineBuilder { ppl.updateDepthStencil(`SpotLightShadowDepth${id}2`, shadowSize.x, shadowSize.y); ppl.updateDepthStencil(`SpotLightShadowDepth${id}3`, shadowSize.x, shadowSize.y); } - private buildForwardTiled (ppl: BasicPipeline, - camera: Camera, id: number, width: number, height: number, - sceneInfo: SceneInfo): void { + private buildForwardTiled ( + ppl: BasicPipeline, + camera: Camera, + id: number, + width: number, + height: number, + sceneInfo: SceneInfo, + ): void { assert(this._tiled); assert(camera.scene !== null); // init @@ -288,8 +301,13 @@ export class TestPipelineBuilder implements PipelineBuilder { .addSceneOfCamera(camera, new LightInfo(), SceneFlags.BLEND); } } - private buildForward (ppl: BasicPipeline, - camera: Camera, id: number, width: number, height: number): void { + private buildForward ( + ppl: BasicPipeline, + camera: Camera, + id: number, + width: number, + height: number, + ): void { assert(camera.scene !== null); if (camera.scene === null) { return; @@ -325,8 +343,11 @@ export class TestPipelineBuilder implements PipelineBuilder { // queue.addSceneCulledByDirectionalLight(camera, // SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER, // light, 0); - queue.addSceneOfCamera(camera, new LightInfo(light, 0), - SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER); + queue.addSceneOfCamera( + camera, + new LightInfo(light, 0), + SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER, + ); } else { const csmLevel = ppl.pipelineSceneData.csmSupported ? light.csmLevel : 1; @@ -337,8 +358,11 @@ export class TestPipelineBuilder implements PipelineBuilder { // queue.addSceneCulledByDirectionalLight(camera, // SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER, // light, level); - queue.addSceneOfCamera(camera, new LightInfo(light, level), - SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER); + queue.addSceneOfCamera( + camera, + new LightInfo(light, level), + SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER, + ); } } } @@ -352,8 +376,13 @@ export class TestPipelineBuilder implements PipelineBuilder { vp.width = Math.max(1, vp.width); vp.height = Math.max(1, vp.height); } - private getMainLightViewport (light: DirectionalLight, w: number, h: number, level: number, - vp: Viewport): void { + private getMainLightViewport ( + light: DirectionalLight, + w: number, + h: number, + level: number, + vp: Viewport, + ): void { if (light.shadowFixedArea || light.csmLevel === CSMLevel.LEVEL_1) { vp.left = 0; vp.top = 0; diff --git a/cocos/rendering/custom/pipeline.ts b/cocos/rendering/custom/pipeline.ts index 9635183715e..87172d5f715 100644 --- a/cocos/rendering/custom/pipeline.ts +++ b/cocos/rendering/custom/pipeline.ts @@ -1423,6 +1423,8 @@ export interface PipelineBuilder { * @param pipeline @en Current render pipeline @zh 当前管线 */ setup (cameras: Camera[], pipeline: BasicPipeline): void; + + onGlobalPipelineStateChanged?(): void; } /** diff --git a/cocos/rendering/custom/web-pipeline.ts b/cocos/rendering/custom/web-pipeline.ts index 31be6f797d7..316e90a2431 100644 --- a/cocos/rendering/custom/web-pipeline.ts +++ b/cocos/rendering/custom/web-pipeline.ts @@ -1828,7 +1828,12 @@ export class WebPipeline implements BasicPipeline { this._macros[name] = value; } public onGlobalPipelineStateChanged (): void { - // do nothing + const builder = cclegacy.rendering.getCustomPipeline(macro.CUSTOM_PIPELINE_NAME); + if (builder) { + if (typeof builder.onGlobalPipelineStateChanged === 'function') { + builder.onGlobalPipelineStateChanged(); + } + } } beginSetup (): void { if (!this._renderGraph) this._renderGraph = new RenderGraph(); diff --git a/cocos/rendering/debug-view.ts b/cocos/rendering/debug-view.ts index 28d661ced23..ebf10db4629 100644 --- a/cocos/rendering/debug-view.ts +++ b/cocos/rendering/debug-view.ts @@ -161,6 +161,10 @@ export class DebugView { this._updatePipeline(); } + get debugViewType (): RenderingDebugViewType { + return this._getType(); + } + protected _singleMode = DebugViewSingleType.NONE; protected _compositeModeValue = 0; protected _lightingWithAlbedo = true; @@ -239,13 +243,16 @@ export class DebugView { private _enableCompositeMode (val: DebugViewCompositeType, enable: boolean): void { if (enable) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison this._compositeModeValue |= (1 << val); } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison this._compositeModeValue &= (~(1 << val)); } } private _enableAllCompositeMode (enable: boolean): void { + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison for (let i = 0; i < DebugViewCompositeType.MAX_BIT_COUNT; i++) { if (enable) { this._compositeModeValue |= (1 << i); @@ -261,6 +268,7 @@ export class DebugView { } else if (this._lightingWithAlbedo !== true || this._csmLayerColoration !== false) { return RenderingDebugViewType.COMPOSITE_AND_MISC; } else { + // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison for (let i = 0; i < DebugViewCompositeType.MAX_BIT_COUNT; i++) { if (!this.isCompositeModeEnabled(i)) { return RenderingDebugViewType.COMPOSITE_AND_MISC; diff --git a/cocos/rendering/post-process/passes/base-pass.ts b/cocos/rendering/post-process/passes/base-pass.ts index 3038bfaf661..54fecf11729 100644 --- a/cocos/rendering/post-process/passes/base-pass.ts +++ b/cocos/rendering/post-process/passes/base-pass.ts @@ -111,6 +111,8 @@ export abstract class BasePass { return this.enable; } + onGlobalPipelineStateChanged?(): void; + renderProfiler (camera): void { if (passContext.isFinalCamera && !EDITOR) { passContext.pass!.showStatistics = true; diff --git a/cocos/rendering/post-process/passes/float-output-process-pass.ts b/cocos/rendering/post-process/passes/float-output-process-pass.ts index 29c554dfb45..169d26d2afa 100644 --- a/cocos/rendering/post-process/passes/float-output-process-pass.ts +++ b/cocos/rendering/post-process/passes/float-output-process-pass.ts @@ -24,7 +24,7 @@ import { Vec4, cclegacy } from '../../../core'; import { ClearFlagBit, Format } from '../../../gfx'; -import { Camera } from '../../../render-scene/scene'; +import { Camera, FOG_TYPE_NONE } from '../../../render-scene/scene'; import { Pipeline } from '../../custom/pipeline'; import { getCameraUniqueID } from '../../custom/define'; import { passContext } from '../utils/pass-context'; @@ -44,23 +44,53 @@ export class FloatOutputProcessPass extends SettingPass { return ppl.getMacroBool('CC_USE_FLOAT_OUTPUT'); } + onGlobalPipelineStateChanged (): void { + passContext.material = this.material; + const passes = passContext.material.passes; + for (let i = 0; i < passes.length; i++) { + const pass = passes[i]; + pass.beginChangeStatesSilently(); + pass.tryCompile(); // force update shaders + pass.endChangeStatesSilently(); + } + } + needDepthInput (ppl: Pipeline): boolean { + return ppl.pipelineSceneData.fog.type !== FOG_TYPE_NONE; + } + public render (camera: Camera, ppl: Pipeline): void { const cameraID = getCameraUniqueID(camera); passContext.material = this.material; - const input = this.lastPass!.slotName(camera, 0); + let copyDS = ''; + let passIndx = 0; const inputDS = passContext.depthSlotName; + if (this.needDepthInput(ppl)) { + copyDS = 'floatOutputProcessCopyDS'; + // ==== Copy input DS === + const copyInputDSPassLayoutName = 'copy-pass'; + const copyInputDSPass = `floatOutputProcessCopyDS-pass${cameraID}`; + passContext.updatePassViewPort() + .addRenderPass(copyInputDSPassLayoutName, copyInputDSPass) + .setClearFlag(ClearFlagBit.COLOR) + .setClearColor(1.0, 0, 0, 0) + .setPassInput(inputDS, 'depthRaw') + .addRasterView(copyDS, Format.RGBA8) + .blitScreen(passIndx) + .version(); + } + + passIndx = 1; + const input = this.lastPass!.slotName(camera, 0); const output = this.slotName(camera, 0); const layoutName = 'tone-mapping'; const passName = `tone-mapping${cameraID}`; - const passIndx = 0; - passContext.clearFlag = ClearFlagBit.COLOR; Vec4.set(passContext.clearColor, camera.clearColor.x, camera.clearColor.y, camera.clearColor.z, camera.clearColor.w); passContext.updatePassViewPort() .addRenderPass(layoutName, passName) .setPassInput(input, 'u_texSampler') - .setPassInput(inputDS, 'DepthTex') + .setPassInput(copyDS, 'DepthTex') .addRasterView(output, Format.RGBA8) .blitScreen(passIndx) .version(); diff --git a/cocos/rendering/post-process/passes/forward-pass.ts b/cocos/rendering/post-process/passes/forward-pass.ts index e81630d80d2..fb73550de00 100644 --- a/cocos/rendering/post-process/passes/forward-pass.ts +++ b/cocos/rendering/post-process/passes/forward-pass.ts @@ -1,7 +1,7 @@ import { Vec4 } from '../../../core'; import { ClearFlagBit, Format } from '../../../gfx'; -import { Camera } from '../../../render-scene/scene'; +import { Camera, ShadowType } from '../../../render-scene/scene'; import { LightInfo, QueueHint, SceneFlags } from '../../custom/types'; import { getCameraUniqueID } from '../../custom/define'; import { Pipeline } from '../../custom/pipeline'; @@ -76,7 +76,8 @@ export class ForwardPass extends BasePass { SceneFlags.OPAQUE_OBJECT | SceneFlags.CUTOUT_OBJECT | SceneFlags.DEFAULT_LIGHTING | SceneFlags.GEOMETRY, ); - if (camera.scene?.mainLight) { + const shadowInfo = ppl.pipelineSceneData.shadows; + if (camera.scene?.mainLight && shadowInfo.enabled && shadowInfo.type === ShadowType.Planar) { pass.addQueue(QueueHint.RENDER_TRANSPARENT, 'planar-shadow') .addSceneOfCamera( camera, diff --git a/cocos/rendering/post-process/passes/hbao-pass.ts b/cocos/rendering/post-process/passes/hbao-pass.ts index aea741f6d32..f6f0e8a5893 100644 --- a/cocos/rendering/post-process/passes/hbao-pass.ts +++ b/cocos/rendering/post-process/passes/hbao-pass.ts @@ -194,6 +194,17 @@ export class HBAOPass extends SettingPass { return enable; } + onGlobalPipelineStateChanged (): void { + passContext.material = this.material; + const passes = passContext.material.passes; + for (let i = 0; i < passes.length; i++) { + const pass = passes[i]; + pass.beginChangeStatesSilently(); + pass.tryCompile(); // force update shaders + pass.endChangeStatesSilently(); + } + } + public getSceneScale (camera: Camera): number { let sceneScale = camera.nearClip; if (!this.averageObjectSize.has(camera.node.scene)) { diff --git a/cocos/rendering/post-process/post-process-builder.ts b/cocos/rendering/post-process/post-process-builder.ts index 5dd938caef3..c9174157a04 100644 --- a/cocos/rendering/post-process/post-process-builder.ts +++ b/cocos/rendering/post-process/post-process-builder.ts @@ -29,6 +29,18 @@ export class PostProcessBuilder implements PipelineBuilder { this.init(); } + onGlobalPipelineStateChanged (): void { + const passes = this.pipelines.get('forward'); + if (passes !== undefined) { + for (let i = 0; i < passes.length; i++) { + const pass = passes[i]; + if (typeof pass.onGlobalPipelineStateChanged === 'function') { + pass.onGlobalPipelineStateChanged(); + } + } + } + } + init (): void { const forward = new ForwardPass(); const forwardFinal = new ForwardFinalPass(); diff --git a/cocos/root.jsb.ts b/cocos/root.jsb.ts index f1e25ef5aa2..2e3ce09e2a4 100644 --- a/cocos/root.jsb.ts +++ b/cocos/root.jsb.ts @@ -224,6 +224,17 @@ rootProto._onDirectorPipelineChanged = function () { } } +const oldOnGlobalPipelineStateChanged = rootProto.onGlobalPipelineStateChanged; +rootProto.onGlobalPipelineStateChanged = function() { + oldOnGlobalPipelineStateChanged.call(this); + const builder = legacyCC.rendering.getCustomPipeline(macro.CUSTOM_PIPELINE_NAME); + if (builder) { + if (typeof builder.onGlobalPipelineStateChanged === 'function') { + builder.onGlobalPipelineStateChanged(); + } + } +} + const oldFrameMove = rootProto.frameMove; rootProto.frameMove = function (deltaTime: number) { oldFrameMove.call(this, deltaTime, legacyCC.director.getTotalFrames()); diff --git a/editor/assets/effects/advanced/sky.effect b/editor/assets/effects/advanced/sky.effect index c2f5232529f..ff98475005a 100644 --- a/editor/assets/effects/advanced/sky.effect +++ b/editor/assets/effects/advanced/sky.effect @@ -39,7 +39,7 @@ CCProgram surface-vertex %{ vec3 SurfacesVertexModifyWorldPos(in SurfacesStandardVertexIntermediate In) { // Apply uniform scaling for atmosphere effects - return In.worldPos * params.w; + return cc_cameraPos.xyz + In.worldPos * params.w; } }% @@ -62,13 +62,11 @@ CCProgram surface-fragment %{ vec4 SurfacesFragmentModifyBaseColorAndTransparency() { vec3 c = vec3(1.0); - #if CC_USE_IBL - vec3 normal = normalize(FSInput_worldNormal); - vec3 rotationDir = RotationVecFromAxisY(normal.xyz, cc_surfaceTransform.z, cc_surfaceTransform.w); - c = sampleEnvMap(environmentMap, rotationDir); - #if BLEND_ENV_MAP - c = mix(c, sampleEnvMap(blendEnvironmentMap, rotationDir), params.x); - #endif + vec3 normal = normalize(FSInput_worldNormal); + vec3 rotationDir = RotationVecFromAxisY(normal.xyz, cc_surfaceTransform.z, cc_surfaceTransform.w); + c = sampleEnvMap(environmentMap, rotationDir); + #if BLEND_ENV_MAP + c = mix(c, sampleEnvMap(blendEnvironmentMap, rotationDir), params.x); #endif return vec4(c * cc_ambientSky.w * params.y, 1.0); } diff --git a/editor/assets/effects/pipeline/float-output-process.effect b/editor/assets/effects/pipeline/float-output-process.effect index 791a653a9bc..de8f2d61d44 100644 --- a/editor/assets/effects/pipeline/float-output-process.effect +++ b/editor/assets/effects/pipeline/float-output-process.effect @@ -3,6 +3,11 @@ CCEffect %{ techniques: - passes: + - vert: tonemap-vs + frag: copy-fs + pass: copy-pass + depthTest: false + depthWrite: false - vert: tonemap-vs frag: tonemap-fs pass: tone-mapping @@ -17,6 +22,24 @@ CCProgram tonemap-vs %{ #include <./post-process/chunks/vs> }% +CCProgram copy-fs %{ + precision highp float; + #include + #include + + #pragma rate depthRaw pass + uniform sampler2D depthRaw; + + in vec2 v_uv; + + layout(location = 0) out vec4 fragColor; + + void main() { + float depth = texture(depthRaw, v_uv).r; + fragColor = packDepthToRGBA(depth); + } +}% + CCProgram tonemap-fs %{ precision highp float; #include @@ -26,6 +49,7 @@ CCProgram tonemap-fs %{ #include #include #include + #include in vec2 v_uv; @@ -49,7 +73,7 @@ CCProgram tonemap-fs %{ // fog related vec4 worldPos = vec4(0.0); #if CC_USE_FOG != CC_FOG_NONE - float depth = texture(DepthTex, v_uv).r; + float depth = unpackRGBAToDepth(texture(DepthTex, v_uv)); vec3 posHS = vec3(v_uv, depth) * 2.0 - vec3(1.0); CC_HANDLE_GET_CLIP_FLIP(posHS.xy); worldPos = GetWorldPosFromNDCPosRH(posHS, cc_matProj, cc_matViewProjInv); diff --git a/editor/assets/effects/pipeline/skybox.effect b/editor/assets/effects/pipeline/skybox.effect index 04c16fc0bf1..d9b90812ab1 100644 --- a/editor/assets/effects/pipeline/skybox.effect +++ b/editor/assets/effects/pipeline/skybox.effect @@ -62,6 +62,7 @@ CCProgram sky-fs %{ #include #include #include + #include #include #include @@ -75,7 +76,17 @@ CCProgram sky-fs %{ #else vec3 c = SRGBToLinear(fragTextureLod(environmentMap, rotationDir.xyz, 0.0).rgb); #endif - vec4 color = CCFragOutput(vec4(c * cc_ambientSky.w, 1.0)); + + vec4 color = vec4(c * cc_ambientSky.w, 1.0); + #if CC_USE_RGBE_OUTPUT + color = packRGBE(color.rgb); + #else + color.rgb = HDRToLDR(color.rgb); + color.rgb = LinearToSRGB(color.rgb); + #endif + + //todo: change to CCFragOutput when sky render queue has been fixed with custom pipeline + //return CCFragOutput(color); return color; } }% From 5071624db86b910bfdaee5cafeb9dcf8a4b6c7e4 Mon Sep 17 00:00:00 2001 From: jk20012001 Date: Fri, 25 Aug 2023 10:47:24 +0800 Subject: [PATCH 177/184] sheen lighting model (#16058) --- .../chunks/common/graph-expression/base.chunk | 42 ++++++++++++----- .../assets/chunks/common/lighting/brdf.chunk | 47 ++++++++++++++++++- .../lighting-flow/common-flow.chunk | 26 +++++----- .../model-functions/standard.chunk | 31 ++++++++++++ .../default-functions/standard-fs.chunk | 4 +- .../module-functions/standard-fs.chunk | 4 +- editor/assets/effects/advanced/fabric.effect | 28 ++++++----- 7 files changed, 140 insertions(+), 42 deletions(-) diff --git a/editor/assets/chunks/common/graph-expression/base.chunk b/editor/assets/chunks/common/graph-expression/base.chunk index c3ef49a59df..6b565e91c63 100644 --- a/editor/assets/chunks/common/graph-expression/base.chunk +++ b/editor/assets/chunks/common/graph-expression/base.chunk @@ -18,19 +18,6 @@ vec2 Rotator(vec2 uv, vec2 centerUV, float time, float speed) return vec2(dir.x, dir.z) + centerUV; } -// tangent space -> world space -// same as TransformVector -vec3 TransformNormalMap(vec3 vectorFromNormalMap) -{ - vec3 vectorTS = normalize(vectorFromNormalMap - vec3(0.5)); - vec3 normal = normalize(FSInput_worldNormal); - vec3 tangent = normalize(FSInput_worldTangent); - vec3 binormal = CalculateBinormal(normal, tangent, FSInput_mirrorNormal); - vec3 vecWS = vectorTS.x * tangent + vectorTS.y * binormal + vectorTS.z * normal; - return vecWS * vec3(1.0, 1.0, -1.0); // inverse Z for RH -} - - // return 0.0 when out of range // hardness: 0 - 1 float SphereMask(vec2 center, vec2 point, float radius, float hardness) @@ -45,3 +32,32 @@ float SphereMask(vec3 center, vec3 point, float radius, float hardness) float coef = pow(saturate(length / radius), 1.0 / (1.0 - saturate(sqrt(hardness)) + EPSILON)); return length > radius ? 0.0 : 1.0 - coef; } + + +// For Fragment Shader + +// tangent space -> world space +// same as TransformVector +vec3 TransformNormalMap(vec3 vectorFromNormalMap) +{ + vec3 vectorTS = normalize(vectorFromNormalMap - vec3(0.5)); + vec3 normal = normalize(FSInput_worldNormal); + vec3 tangent = normalize(FSInput_worldTangent); + vec3 binormal = CalculateBinormal(normal, tangent, FSInput_mirrorNormal); + vec3 vecWS = vectorTS.x * tangent + vectorTS.y * binormal + vectorTS.z * normal; + return vecWS * vec3(1.0, 1.0, -1.0); // inverse Z for RH +} + +// WorldPos -> UV +vec2 GetTriplanarMappingUV() +{ + vec3 Up = vec3(0.0, 1.0, 0.0); + vec3 U = cross(Up, FSInput_worldNormal.xyz); + if (length(U) < 0.01) + U = vec3(1.0, 0.0, 0.0); + else + U = normalize(U); + vec3 V = cross(U, FSInput_worldNormal.xyz); + V = normalize(V); + return fract(vec2(dot(FSInput_worldPos.xyz, U), dot(FSInput_worldPos.xyz, V))); +} diff --git a/editor/assets/chunks/common/lighting/brdf.chunk b/editor/assets/chunks/common/lighting/brdf.chunk index ef4fea792a1..79405c200ab 100644 --- a/editor/assets/chunks/common/lighting/brdf.chunk +++ b/editor/assets/chunks/common/lighting/brdf.chunk @@ -116,5 +116,50 @@ void IntegratedGFMultiplier (out vec3 integratedGF, out vec3 integratedF, vec3 s integratedGF = max(vec3(0.0), vec3(AB.x) + vec3(AB.y) / (specular + EPSILON_LOWP)); } -//Diffuse_Lambert +// isotropic sheen +float Sheen_HorizonFading(float NoL) +{ + const float horizonFade = 1.3; + float horiz = saturate( 1.0 + horizonFade * NoL); + return horiz * horiz; +} + +float Sheen(float NoHSat, float NoL, float NoV, float roughness) +{ + if (NoL <= 0.0 || NoV <= 0.0) + return 0.0; + float NoH2 = NoHSat*NoHSat; + float NoL2 = NoL*NoL; + float NoV2 = NoV*NoV; + roughness += EPSILON_LOWP; + float r2 = roughness*roughness; + + float t = 1.0 - NoH2 + NoH2/r2; + float Pi_D = 1.0 / (roughness * t * t); + + float Li = sqrt(1.0 - NoL2 + r2*NoL2) / NoL; + float Lo = sqrt(1.0 - NoV2 + r2*NoV2) / NoV; + float G = (1.0 - exp(-(Li + Lo))) / (Li + Lo); + + return Sheen_HorizonFading(NoL) * Pi_D * G / NoV; +} +// simplify estimation for env lighting convolution +float Sheen(float NoV, float roughness) +{ + NoV *= NoV; + float NoV2 = NoV*NoV; + roughness += EPSILON_LOWP; + float r2 = roughness*roughness; + + float t = 1.0 - NoV2 + NoV2/r2; + float Pi_D = 1.0 / (roughness * t * t); + + float Lo = sqrt(1.0 - NoV2 + r2*NoV2) / NoV; + float G = (1.0 - exp(-Lo)) / Lo; + + float sheen = Pi_D * G / NoV; + return pow(max(0.0, sheen), 0.5); +} + +// Diffuse_Lambert #define DiffuseCoefficient_EnergyConservation INV_PI diff --git a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk index 0324db26f35..14e26fb2c2b 100644 --- a/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk +++ b/editor/assets/chunks/lighting-models/lighting-flow/common-flow.chunk @@ -109,11 +109,11 @@ LightingIntermediateData lightingData2ndSpecular; CCSurfacesInitializeLightingIntermediateData(lightingData2ndSpecular, surfaceData2ndSpecular); CCSurfacesLightingCalculateIntermediateData_PerLight(lightingData2ndSpecular, surfaceData, lightDirWithLength); - CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, attenuatedLightColorAndIntensity, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); - CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF2ndSpecular, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, vec3(1.0)); - #if CC_SURFACES_LIGHTING_SHEEN - vec3 extraF = CCSurfaceLightingCalculateExtraFresnel(lightingData2ndSpecular); - lightingResult.directGF2ndSpecular *= extraF; + #if !CC_SURFACES_LIGHTING_SHEEN + CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, attenuatedLightColorAndIntensity, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); + CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF2ndSpecular, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, vec3(1.0)); + #else + CCSurfacesLightingCalculateDirectSheen(lightingResult.direct2ndSpecular, lightingResult.directGF2ndSpecular, lightingData2ndSpecular, attenuatedLightColorAndIntensity, surfaceData2ndSpecular.intensity2ndSpecular); #endif lightingResult.direct2ndSpecular *= multiplier; @@ -258,15 +258,15 @@ vec3 diff; CCSurfacesLightingInitializeColorWithLighting(diff, lightingResult.specularColorWithLighting2ndSpecular, surfaceData2ndSpecular, lightingData2ndSpecular); - CCSurfacesLightingCalculateEnvironment2ndSpecular(lightingResult.environment2ndSpecular, lightingData2ndSpecular, cc_ambientSky.w, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.environmentSpecular); - CCSurfaceLightingCalculateEnvironmentFresnel(lightingResult.environmentGF2ndSpecular, lightingResult.environmentSubLayerF, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular); + #if !CC_SURFACES_LIGHTING_SHEEN + CCSurfacesLightingCalculateEnvironment2ndSpecular(lightingResult.environment2ndSpecular, lightingData2ndSpecular, cc_ambientSky.w, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.environmentSpecular); + CCSurfaceLightingCalculateEnvironmentFresnel(lightingResult.environmentGF2ndSpecular, lightingResult.environmentSubLayerF, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular); - CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, cc_mainLitColor, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); - CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF2ndSpecular, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, lightingResult.environmentGF2ndSpecular); - #if CC_SURFACES_LIGHTING_SHEEN - vec3 extraF = CCSurfaceLightingCalculateExtraFresnel(lightingData2ndSpecular); - lightingResult.environmentGF2ndSpecular *= extraF; - lightingResult.directGF2ndSpecular *= extraF; + CCSurfacesLightingCalculateDirect2ndSpecular(lightingResult.direct2ndSpecular, lightingData2ndSpecular, cc_mainLitColor, surfaceData2ndSpecular.intensity2ndSpecular, lightingResult.directSpecular); + CCSurfaceLightingCalculateDirectFresnel(lightingResult.directGF2ndSpecular, lightingData2ndSpecular, lightingResult.specularColorWithLighting2ndSpecular, lightingResult.environmentGF2ndSpecular); + #else + CCSurfacesLightingCalculateDirectSheen(lightingResult.direct2ndSpecular, lightingResult.directGF2ndSpecular, lightingData2ndSpecular, cc_mainLitColor, surfaceData2ndSpecular.intensity2ndSpecular); + CCSurfacesLightingCalculateEnvironmentSheen(lightingResult.environment2ndSpecular, lightingResult.environmentGF2ndSpecular, lightingData2ndSpecular, cc_ambientSky.w, surfaceData2ndSpecular.intensity2ndSpecular); #endif #endif diff --git a/editor/assets/chunks/lighting-models/model-functions/standard.chunk b/editor/assets/chunks/lighting-models/model-functions/standard.chunk index a0a5054f127..3898c96d443 100644 --- a/editor/assets/chunks/lighting-models/model-functions/standard.chunk +++ b/editor/assets/chunks/lighting-models/model-functions/standard.chunk @@ -234,6 +234,37 @@ void CCSurfaceLightingCalculateEnvironmentFresnel(out vec3 integratedGF, vec3 in specularLighting = vec3(0.0); #endif } + + void CCSurfacesLightingCalculateDirectSheen(out vec3 specularLighting, out vec3 directGF, in LightingIntermediateData lightingData, in vec4 lightSourceColorAndIntensity, float intensitySpecular) + { + #if !CC_SURFACES_LIGHTING_DISABLE_SPECULAR + float sheen = Sheen(lightingData.NoHSat, lightingData.NoL, lightingData.NoV, lightingData.specularParam); + specularLighting = vec3(sheen) * intensitySpecular * lightSourceColorAndIntensity.xyz * lightSourceColorAndIntensity.w; + directGF = vec3(1.0); + #else + specularLighting = vec3(0.0); + #endif + } + + void CCSurfacesLightingCalculateEnvironmentSheen(out vec3 specularLighting, out vec3 environmentGF, in LightingIntermediateData lightingData, float lightIntensity, float intensitySpecular) + { + #if !CC_SURFACES_LIGHTING_DISABLE_SPECULAR + LightingIntermediateData lightingDataSheen = lightingData; + float roughness = lightingData.specularParam; + + // sample max distribute normal-vertical-direction reflection with fixed roughness + vec3 L = normalize(mix(lightingDataSheen.B, lightingDataSheen.N, 0.3)); + lightingDataSheen.specularParam = mix(0.5, 0.9, roughness); + lightingDataSheen.V = lightingDataSheen.N = L; + specularLighting = CalculateEnvironmentSpecular(lightingDataSheen, lightIntensity); + specularLighting *= intensitySpecular; + + // range limitation + environmentGF = vec3(Sheen(lightingData.NoV, roughness)); + #else + specularLighting = vec3(0.0); + #endif + } #endif #if CC_SURFACES_LIGHTING_TT diff --git a/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk b/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk index 038a9e75993..8229737b289 100644 --- a/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk +++ b/editor/assets/chunks/surfaces/default-functions/standard-fs.chunk @@ -220,8 +220,8 @@ vec3 SurfacesFragmentModifyClearCoatWorldNormal() vec4 SurfacesFragmentModifySheenParams() { //x: sheen roughness - //y: sheen ior - //z: sheen opacity + //y: sheen opacity + //z: unused //w: sheen intensity return vec4(0.7, 1.0, 1.0, 1.0); } diff --git a/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk b/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk index 86db9d4f507..d3deafc53c4 100644 --- a/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk +++ b/editor/assets/chunks/surfaces/module-functions/standard-fs.chunk @@ -91,14 +91,14 @@ void CCSurfacesFragmentGetMaterialData(inout SurfacesMaterialData surfaceData) // skip in shader graph, need extra code vec4 sheenParams = SurfacesFragmentModifySheenParams(); surfaceData.roughness2ndSpecular = saturate(sheenParams.x); - surfaceData.ior2ndSpecular = sheenParams.y; - surfaceData.intensity2ndSpecular = sheenParams.z * sheenParams.w; + surfaceData.intensity2ndSpecular = sheenParams.y * sheenParams.w; surfaceData.metallic2ndSpecular = 1.0; surfaceData.baseColor2ndSpecular = SurfacesFragmentModifySheenColor(); surfaceData.color2ndSpecular = vec3(1.0); // no extra coloration surfaceData.worldNormal2ndSpecular = surfaceData.worldNormal; surfaceData.worldTangent2ndSpecular = surfaceData.worldTangent; surfaceData.worldBinormal2ndSpecular = surfaceData.worldBinormal; + surfaceData.ior2ndSpecular = surfaceData.ior; //unused surfaceData.opacity2ndSpecular = 1.0; // unused #if CC_SURFACES_LIGHTING_ANISOTROPIC surfaceData.anisotropyShape2ndSpecular = surfaceData.anisotropyShape; diff --git a/editor/assets/effects/advanced/fabric.effect b/editor/assets/effects/advanced/fabric.effect index 4803793548b..c690c8ec884 100644 --- a/editor/assets/effects/advanced/fabric.effect +++ b/editor/assets/effects/advanced/fabric.effect @@ -27,9 +27,10 @@ CCEffect %{ anisotropyMap: { value: black, editor : { parent: IS_ANISOTROPY } } sheenColor: { value: [1.0, 1.0, 1.0, 1.0], linear: true, editor: { type: color } } sheenRoughness: { value: 1.0, target: emissiveScaleParam.x, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } - sheenIOR: { value: 1.0, target: emissiveScaleParam.y, editor: { slide: true, range: [1.0, 2.0], step: 0.001 } } - sheenOpacity: { value: 1.0, target: emissiveScaleParam.z, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } - sheenMap: { value: white, editor: { parent: USE_SHEEN_MAP, tooltips: 'r: sheen roughness g: sheen opacity' } } + sheenOpacity: { value: 1.0, target: emissiveScaleParam.y, editor: { slide: true, range: [0.0, 1.0], step: 0.001 } } + sheenIntensity: { value: 1.0, target: emissiveScaleParam.w, editor: { slide: true, range: [1.0, 3.0], step: 0.001 } } + sheenColorMap: { value: white, editor: { parent: USE_SHEEN_COLOR_MAP } } + sheenDataMap: { value: white, editor: { parent: USE_SHEEN_DATA_MAP, tooltips: 'r: sheen roughness g: sheen opacity' } } - &forward-add vert: standard-vs frag: standard-fs @@ -145,10 +146,8 @@ CCProgram macro-remapping %{ #define CC_SURFACES_USE_VERTEX_COLOR USE_VERTEX_COLOR #define CC_SURFACES_LIGHTING_SHEEN 1 - // depend on UI macros -#if IS_ANISOTROPY || USE_NORMAL_MAP + // sheen need tangent #define CC_SURFACES_USE_TANGENT_SPACE 1 -#endif // functionality for each effect #define CC_SURFACES_LIGHTING_ANISOTROPIC_ENVCONVOLUTION_COUNT 31 @@ -190,8 +189,11 @@ CCProgram surface-fragment %{ #if IS_ANISOTROPY && USE_ANISOTROPY_MAP uniform sampler2D anisotropyMap; #endif - #if USE_SHEEN_MAP - uniform sampler2D sheenMap; + #if USE_SHEEN_COLOR_MAP + uniform sampler2D sheenColorMap; + #endif + #if USE_SHEEN_DATA_MAP + uniform sampler2D sheenDataMap; #endif #pragma define OCCLUSION_CHANNEL r @@ -223,9 +225,9 @@ CCProgram surface-fragment %{ #define CC_SURFACES_FRAGMENT_MODIFY_SHEEN_PARAMS vec4 SurfacesFragmentModifySheenParams() { - vec4 param = vec4(emissiveScaleParam.x, emissiveScaleParam.y - 0.9, emissiveScaleParam.z, 1.0); - #if USE_SHEEN_MAP - param.xz *= texture(sheenMap, FSInput_texcoord).xy; + vec4 param = emissiveScaleParam; + #if USE_SHEEN_DATA_MAP + param.xy *= texture(sheenDataMap, FSInput_texcoord).xy; #endif return param; } @@ -233,7 +235,11 @@ CCProgram surface-fragment %{ #define CC_SURFACES_FRAGMENT_MODIFY_SHEEN_COLOR vec3 SurfacesFragmentModifySheenColor() { + #if USE_SHEEN_COLOR_MAP + return sheenColor.rgb * texture(sheenColorMap, FSInput_texcoord).rgb; + #else return sheenColor.rgb; + #endif } #include From 488c9579d694f62f435ff4ff69200e6ff32150f9 Mon Sep 17 00:00:00 2001 From: Leslie Leigh Date: Tue, 28 Mar 2023 19:43:15 +0800 Subject: [PATCH 178/184] Animation clip manipulation API lint: manip --- .../animation/animation-clip-manipulation.ts | 12 +++++++ .../exotic-animation/exotic-animation.ts | 30 +++++++++++++++++ editor/exports/exotic-animation.ts | 8 +++++ .../marionette/exotic-animation-operation.ts | 33 +++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 cocos/animation/animation-clip-manipulation.ts create mode 100644 editor/src/marionette/exotic-animation-operation.ts diff --git a/cocos/animation/animation-clip-manipulation.ts b/cocos/animation/animation-clip-manipulation.ts new file mode 100644 index 00000000000..1cac15794c0 --- /dev/null +++ b/cocos/animation/animation-clip-manipulation.ts @@ -0,0 +1,12 @@ +export enum TransformFlag { + POSITION = 0b111, + + ROTATION_X = 0b001_000, + ROTATION_Y = 0b010_000, + ROTATION_Z = 0b100_000, + ROTATION = ROTATION_X | ROTATION_Y | ROTATION_Z, + + SCALE = 0b111_000_000, + + ALL = POSITION | ROTATION | SCALE, +} diff --git a/cocos/animation/exotic-animation/exotic-animation.ts b/cocos/animation/exotic-animation/exotic-animation.ts index 96db72a57aa..37cc6b50e1e 100644 --- a/cocos/animation/exotic-animation/exotic-animation.ts +++ b/cocos/animation/exotic-animation/exotic-animation.ts @@ -30,6 +30,8 @@ import { TransformHandle } from '../core/animation-handle'; import { Pose } from '../core/pose'; import { CLASS_NAME_PREFIX_ANIM } from '../define'; import { Binder, RuntimeBinding, TrackBinding, TrackPath } from '../tracks/track'; +import { removeIf } from '../../core/utils/array'; +import { TransformFlag } from '../animation-clip-manipulation'; const SPLIT_METHOD_ENABLED = TEST || EDITOR; @@ -63,6 +65,18 @@ export class ExoticAnimation { return nodeAnimation; } + public removeNodeAnimation (path: string, flags: TransformFlag) { + const { _nodeAnimations: nodeAnimations } = this; + const index = nodeAnimations.findIndex((nodeAnimation) => nodeAnimation.path === path); + if (index >= 0) { + const nodeAnimation = nodeAnimations[index]; + nodeAnimation.remove(flags); + if (nodeAnimation.empty) { + this._nodeAnimations.splice(index, 0); + } + } + } + public collectAnimatedJoints (): string[] { return Array.from(new Set(this._nodeAnimations.map(({ path }) => path))); } @@ -96,6 +110,10 @@ class ExoticNodeAnimation { this._path = path; } + get empty () { + return !(this._position || this._rotation || this._scale); + } + public createPosition (times: FloatArray, values: FloatArray): void { this._position = new ExoticTrack(times, new ExoticVec3TrackValues(values)); } @@ -108,6 +126,18 @@ class ExoticNodeAnimation { this._scale = new ExoticTrack(times, new ExoticVec3TrackValues(values)); } + public remove (flags: TransformFlag): void { + if ((flags & TransformFlag.POSITION) === TransformFlag.POSITION) { + this._position = null; + } + if ((flags & TransformFlag.ROTATION) === TransformFlag.ROTATION) { + this._rotation = null; + } + if ((flags & TransformFlag.SCALE) === TransformFlag.SCALE) { + this._scale = null; + } + } + public createEvaluator (binder: Binder): ExoticNodeAnimationEvaluator { return new ExoticNodeAnimationEvaluator( this._path, diff --git a/editor/exports/exotic-animation.ts b/editor/exports/exotic-animation.ts index c808eaabff0..fc5a21f1876 100644 --- a/editor/exports/exotic-animation.ts +++ b/editor/exports/exotic-animation.ts @@ -15,3 +15,11 @@ export { additiveSettingsTag, AnimationClipAdditiveSettings, } from '../../cocos/animation/animation-clip'; + +export { + TransformFlag, +} from '../../cocos/animation/animation-clip-manipulation'; + +export { + removeNodeTransformAnimation, +} from '../src/marionette/exotic-animation-operation'; diff --git a/editor/src/marionette/exotic-animation-operation.ts b/editor/src/marionette/exotic-animation-operation.ts new file mode 100644 index 00000000000..d41ea3d60ef --- /dev/null +++ b/editor/src/marionette/exotic-animation-operation.ts @@ -0,0 +1,33 @@ +import { AnimationClip, exoticAnimationTag } from '../../../cocos/animation/animation-clip'; +import { TransformFlag } from '../../../cocos/animation/animation-clip-manipulation'; +import { Track, trackBindingTag } from '../../../cocos/animation/tracks/track'; + +export function removeNodeTransformAnimation(clip: AnimationClip, path: string, flags: TransformFlag) { + clip[exoticAnimationTag]?.removeNodeAnimation(path, flags); + + for (let iTrack = clip.tracksCount - 1; iTrack >= 0; --iTrack) { + const track = clip.getTrack(iTrack); + const trsPath = track[trackBindingTag].parseTrsPath(); + if (!trsPath || trsPath.node !== path) { + continue; + } + switch (trsPath.property) { + case 'position': + if ((flags & TransformFlag.POSITION) === TransformFlag.POSITION) { + clip.removeTrack(iTrack); + } + break; + case 'rotation': + case 'eulerAngles': + if ((flags & TransformFlag.ROTATION) === TransformFlag.ROTATION) { + clip.removeTrack(iTrack); + } + break; + case 'scale': + if ((flags & TransformFlag.SCALE) === TransformFlag.SCALE) { + clip.removeTrack(iTrack); + } + break; + } + } +} From fe5e2fd92246bc488a8f09e453e57192a22f4a07 Mon Sep 17 00:00:00 2001 From: shrinktofit Date: Mon, 14 Aug 2023 11:11:40 +0800 Subject: [PATCH 179/184] Pose graph 123 Bug introduce FF Fix clip overriding in animation graph Fix lint Fix lint --- .../marionette/animation-graph-context.ts | 12 ++ .../marionette/motion/animation-blend.ts | 2 + .../pose-graph/default-top-level-pose-node.ts | 29 +++++ .../marionette/pose-graph/pose-node.ts | 7 +- .../marionette/pose-graph/pose-nodes/all.ts | 2 + .../get-all-previous-layers-result.ts | 36 ++++++ .../marionette/pose-graph/pure-value-node.ts | 5 + .../pose-graph/pure-value-nodes/all.ts | 2 + .../pure-value-nodes/builtin/math/general.ts | 96 ++++++++++++++++ .../pure-value-nodes/builtin/math/prefix.ts | 1 + .../builtin/math/trigonometry.ts | 23 ++++ .../builtin/math/unary-numeric-base.ts | 26 +++++ .../pure-value-nodes/builtin/prefix.ts | 3 + .../state-machine/state-machine-eval.ts | 15 +-- editor/i18n/en/animation.js | 24 ++++ editor/i18n/zh/animation.js | 24 ++++ .../src/marionette/pose-graph-editor-api.ts | 3 + .../specialized-node-operation/index.ts | 24 ++++ .../operations/all.ts | 4 + .../operations/use-stashed-pose.ts | 60 ++++++++++ .../specialized-node-operation/registry.ts | 42 +++++++ .../__todo-state-weight-condition.test.ts | 106 ++++++++++++++++++ .../pose-nodes/utils/evaluation-mock.ts | 4 +- 23 files changed, 534 insertions(+), 16 deletions(-) create mode 100644 cocos/animation/marionette/pose-graph/pose-nodes/get-all-previous-layers-result.ts create mode 100644 cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/general.ts create mode 100644 cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/prefix.ts create mode 100644 cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/trigonometry.ts create mode 100644 cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/unary-numeric-base.ts create mode 100644 cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/prefix.ts create mode 100644 editor/src/marionette/specialized-node-operation/index.ts create mode 100644 editor/src/marionette/specialized-node-operation/operations/all.ts create mode 100644 editor/src/marionette/specialized-node-operation/operations/use-stashed-pose.ts create mode 100644 editor/src/marionette/specialized-node-operation/registry.ts create mode 100644 tests/animation/new-gen-anim/__todo-state-weight-condition.test.ts diff --git a/cocos/animation/marionette/animation-graph-context.ts b/cocos/animation/marionette/animation-graph-context.ts index ea090ca4bac..9d665bfcb55 100644 --- a/cocos/animation/marionette/animation-graph-context.ts +++ b/cocos/animation/marionette/animation-graph-context.ts @@ -16,6 +16,7 @@ import { PoseStashAllocator, RuntimeStashView } from './pose-graph/stash/runtime import { PoseHeapAllocator } from '../core/pose-heap-allocator'; import { RuntimeMotionSyncManager } from './pose-graph/motion-sync/runtime-motion-sync'; import { ReadonlyClipOverrideMap } from './clip-overriding'; +import { AllPreviousLayersResultManager } from './pose-graph/pose-node'; /** * This module contains stuffs related to animation graph's evaluation. @@ -186,17 +187,24 @@ export class AnimationGraphBindingContext { return this._motionSyncManager; } + public get allPreviousLayersResultManager (): AllPreviousLayersResultManager { + assertIsTrue(this._allPreviousLayersResultManager); + return this._allPreviousLayersResultManager; + } + /** * @internal */ public _setLayerWideContextProperties ( stashView: RuntimeStashView, motionSyncManager: RuntimeMotionSyncManager, + allPreviousLayersResultManager: AllPreviousLayersResultManager, ): void { assertIsTrue(!this._isLayerWideContextPropertiesSet); this._isLayerWideContextPropertiesSet = true; this._stashView = stashView; this._motionSyncManager = motionSyncManager; + this._allPreviousLayersResultManager = allPreviousLayersResultManager; } /** @@ -207,6 +215,7 @@ export class AnimationGraphBindingContext { this._isLayerWideContextPropertiesSet = false; this._stashView = undefined; this._motionSyncManager = undefined; + this._allPreviousLayersResultManager = undefined; } /** @@ -230,6 +239,8 @@ export class AnimationGraphBindingContext { private _isLayerWideContextPropertiesSet = false; private _stashView: RuntimeStashView | undefined; private _motionSyncManager: RuntimeMotionSyncManager | undefined; + private _allPreviousLayersResultManager: AllPreviousLayersResultManager | undefined; + private _clipOverrides: ReadonlyClipOverrideMap | undefined = undefined; private _resetTrigger (triggerName: string): void { @@ -1148,6 +1159,7 @@ export class DeferredPoseStashAllocator implements PoseStashAllocator { public allocatePose (): Pose { assertIsTrue(this._allocator); const pose = this._allocator.allocatePose(); + pose._poseTransformSpace = PoseTransformSpace.LOCAL; return pose; } diff --git a/cocos/animation/marionette/motion/animation-blend.ts b/cocos/animation/marionette/motion/animation-blend.ts index cfe62a039bf..f549b966589 100644 --- a/cocos/animation/marionette/motion/animation-blend.ts +++ b/cocos/animation/marionette/motion/animation-blend.ts @@ -167,6 +167,8 @@ export abstract class AnimationBlendEval implements MotionEval { if (finalPose) { return finalPose; } + + // TODO: cause wired behavior in additive layer. return context.pushDefaultedPose(); } diff --git a/cocos/animation/marionette/pose-graph/default-top-level-pose-node.ts b/cocos/animation/marionette/pose-graph/default-top-level-pose-node.ts index bf57c6b5f46..21d23cfbc6e 100644 --- a/cocos/animation/marionette/pose-graph/default-top-level-pose-node.ts +++ b/cocos/animation/marionette/pose-graph/default-top-level-pose-node.ts @@ -8,6 +8,7 @@ import { TopLevelStateMachineEvaluation } from '../state-machine/state-machine-e import { PoseNode } from './pose-node'; import { RuntimeMotionSyncManager } from './motion-sync/runtime-motion-sync'; import { PoseStashAllocator, RuntimeStashManager } from './stash/runtime-stash'; +import { AllPreviousLayersResultManager } from './pose-node'; export class DefaultTopLevelPoseNode extends PoseNode { constructor ( @@ -22,6 +23,7 @@ export class DefaultTopLevelPoseNode extends PoseNode { layer, bindingContext, poseStashAllocator, + this._allPreviousLayersResultManager, ); return record; @@ -86,10 +88,12 @@ export class DefaultTopLevelPoseNode extends PoseNode { } protected doEvaluate (context: AnimationGraphEvaluationContext): Pose { + const { _allPreviousLayersResultManager: allPreviousLayersResultManager } = this; const finalPose = context.pushDefaultedPose(); const { _layerRecords: layerRecords } = this; const nLayers = layerRecords.length; for (let iLayer = 0; iLayer < nLayers; ++iLayer) { + allPreviousLayersResultManager.set(finalPose); const layer = layerRecords[iLayer]; const layerPose = layer.stateMachineEvaluation.evaluate(context); const layerActualWeight = layer.weight * layer.stateMachineEvaluation.passthroughWeight; @@ -102,11 +106,14 @@ export class DefaultTopLevelPoseNode extends PoseNode { context.popPose(); layer.postEvaluate(); + + allPreviousLayersResultManager.delete(); } return finalPose; } private _layerRecords: LayerEvaluationRecord[]; + private _allPreviousLayersResultManager = new AllPreviousLayersResultManagerImpl(); } class LayerEvaluationRecord { @@ -114,6 +121,7 @@ class LayerEvaluationRecord { layer: Layer, bindingContext: AnimationGraphBindingContext, poseStashAllocator: PoseStashAllocator, + allPreviousLayersResultManager: AllPreviousLayersResultManager, ) { const stashManager = new RuntimeStashManager(poseStashAllocator); for (const [stashId, _] of layer.stashes()) { @@ -127,6 +135,7 @@ class LayerEvaluationRecord { bindingContext._setLayerWideContextProperties( stashManager, motionSyncManager, + allPreviousLayersResultManager, ); for (const [stashId, stash] of layer.stashes()) { @@ -190,3 +199,23 @@ class LayerEvaluationRecord { } export type { LayerEvaluationRecord }; + +export class AllPreviousLayersResultManagerImpl implements AllPreviousLayersResultManager { + public retrieve (context: AnimationGraphEvaluationContext): Pose { + const { _pose: pose } = this; + assertIsTrue(pose, `Can not retrieve previous layers pose. You're doing things in wrong order.`); + return context.pushDuplicatedPose(pose); + } + + public set (pose: Pose): void { + assertIsTrue(!this._pose); + this._pose = pose; + } + + public delete (): void { + assertIsTrue(this._pose); + this._pose = null; + } + + private _pose: Pose | null = null; +} diff --git a/cocos/animation/marionette/pose-graph/pose-node.ts b/cocos/animation/marionette/pose-graph/pose-node.ts index 4dd82a19c29..6c1acbee047 100644 --- a/cocos/animation/marionette/pose-graph/pose-node.ts +++ b/cocos/animation/marionette/pose-graph/pose-node.ts @@ -1,5 +1,5 @@ import { TEST } from 'internal:constants'; -import { assertIsTrue, ccenum } from '../../../core'; +import { assertIsTrue } from '../../../core'; import { ccclass } from '../../../core/data/decorators'; import { Pose, PoseTransformSpace } from '../../core/pose'; import { CLASS_NAME_PREFIX_ANIM } from '../../define'; @@ -12,6 +12,10 @@ import { import { PoseGraphNode } from './foundation/pose-graph-node'; import type { PoseNodeDependencyEvaluation } from './instantiation'; +export interface AllPreviousLayersResultManager { + retrieve(context: AnimationGraphEvaluationContext): Pose; +} + export enum PoseTransformSpaceRequirement { NO, @@ -19,7 +23,6 @@ export enum PoseTransformSpaceRequirement { COMPONENT, } -ccenum(PoseTransformSpaceRequirement); const POSE_NODE_EVALUATION_STACK_ORDER_DEBUG_ENABLED = !!TEST; diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/all.ts b/cocos/animation/marionette/pose-graph/pose-nodes/all.ts index 1232f49f552..e88af744b42 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/all.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/all.ts @@ -1,5 +1,7 @@ import './use-stashed-pose'; +import './get-all-previous-layers-result'; + import './state-machine'; import './play-motion'; diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/get-all-previous-layers-result.ts b/cocos/animation/marionette/pose-graph/pose-nodes/get-all-previous-layers-result.ts new file mode 100644 index 00000000000..d99984cfa73 --- /dev/null +++ b/cocos/animation/marionette/pose-graph/pose-nodes/get-all-previous-layers-result.ts @@ -0,0 +1,36 @@ +import { EDITOR } from 'internal:constants'; +import { assertIsTrue, warn } from '../../../../core'; +import { ccclass, editable, serializable } from '../../../../core/data/decorators'; +import { CLASS_NAME_PREFIX_ANIM } from '../../../define'; +import { poseGraphNodeAppearance, poseGraphNodeCategory } from '../decorator/node'; +import { PoseNode, AllPreviousLayersResultManager } from '../pose-node'; +import { POSE_GRAPH_NODE_MENU_PREFIX_POSE } from './menu-common'; +import { AnimationGraphBindingContext, AnimationGraphEvaluationContext, AnimationGraphSettleContext, AnimationGraphUpdateContext } from '../../animation-graph-context'; + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PoseNodeGetAllPreviousLayersResult`) +@poseGraphNodeCategory(POSE_GRAPH_NODE_MENU_PREFIX_POSE) +@poseGraphNodeAppearance({ + themeColor: '#CCCCCC', + inline: true, +}) +export class PoseNodeGetAllPreviousLayersResult extends PoseNode { + public bind (context: AnimationGraphBindingContext): void { + this._allPreviousLayersResultManager = context.allPreviousLayersResultManager; + } + + public settle (context: AnimationGraphSettleContext): void { + } + + public reenter (): void { + } + + protected doUpdate (context: AnimationGraphUpdateContext): void { + } + + protected doEvaluate (context: AnimationGraphEvaluationContext) { + assertIsTrue(this._allPreviousLayersResultManager); + return this._allPreviousLayersResultManager.retrieve(context); + } + + private _allPreviousLayersResultManager: AllPreviousLayersResultManager | undefined = undefined; +} diff --git a/cocos/animation/marionette/pose-graph/pure-value-node.ts b/cocos/animation/marionette/pose-graph/pure-value-node.ts index 6adc20e04fd..e3d7d4fe2b4 100644 --- a/cocos/animation/marionette/pose-graph/pure-value-node.ts +++ b/cocos/animation/marionette/pose-graph/pure-value-node.ts @@ -1,3 +1,5 @@ +import { DEBUG } from 'internal:constants'; +import { assertIsTrue } from '../../../core'; import { VarInstance } from '../variable'; import { PoseGraphNode } from './foundation/pose-graph-node'; import { PoseGraphType } from './foundation/type-system'; @@ -35,6 +37,9 @@ export abstract class PureValueNode extends PoseGraphNode { export abstract class SingleOutputPVNode extends PureValueNode { constructor (outputType: PoseGraphType) { + if (DEBUG) { + assertIsTrue(typeof outputType !== 'undefined'); + } super([outputType]); } diff --git a/cocos/animation/marionette/pose-graph/pure-value-nodes/all.ts b/cocos/animation/marionette/pose-graph/pure-value-nodes/all.ts index 00475ce86af..ad6eadb8163 100644 --- a/cocos/animation/marionette/pose-graph/pure-value-nodes/all.ts +++ b/cocos/animation/marionette/pose-graph/pure-value-nodes/all.ts @@ -1,3 +1,5 @@ import './get-variable'; +import './builtin/math/general'; +import './builtin/math/trigonometry'; export {}; diff --git a/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/general.ts b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/general.ts new file mode 100644 index 00000000000..4f3adcece6e --- /dev/null +++ b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/general.ts @@ -0,0 +1,96 @@ +import { clamp } from '../../../../../../core'; +import { ccclass, editable, serializable } from '../../../../../../core/data/decorators'; +import { poseGraphNodeAppearance, poseGraphNodeCategory } from '../../../decorator/node'; +import { PoseGraphType } from '../../../foundation/type-system'; +import { SingleOutputPVNode } from '../../../pure-value-node'; +import { input } from '../../../decorator/input'; +import { CLASS_NAME_PREFIX_ANIM } from '../../../../../define'; +import { POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH } from './prefix'; +import { PVNodeUnaryNumericBase } from './unary-numeric-base'; + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PVNodeAbs`) +@poseGraphNodeCategory(POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH) +@poseGraphNodeAppearance({ themeColor: '#B169C4' }) +export class PVNodeAbs extends PVNodeUnaryNumericBase { + protected evaluateValue (value: number) { + return Math.abs(value); + } +} + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PVNodeMin`) +@poseGraphNodeCategory(POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH) +@poseGraphNodeAppearance({ themeColor: '#B169C4' }) +export class PVNodeMin extends SingleOutputPVNode { + constructor () { + super(PoseGraphType.FLOAT); + } + + @serializable + @editable + @input({ type: PoseGraphType.FLOAT }) + public value0 = 0.0; + + @serializable + @editable + @input({ type: PoseGraphType.FLOAT }) + public value1 = 0.0; + + public selfEvaluateDefaultOutput () { + return Math.min(this.value0, this.value1); + } +} + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PVNodeMax`) +@poseGraphNodeCategory(POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH) +@poseGraphNodeAppearance({ themeColor: '#B169C4' }) +export class PVNodeMax extends SingleOutputPVNode { + constructor () { + super(PoseGraphType.FLOAT); + } + + @serializable + @editable + @input({ type: PoseGraphType.FLOAT }) + public value0 = 0.0; + + @serializable + @editable + @input({ type: PoseGraphType.FLOAT }) + public value1 = 0.0; + + public selfEvaluateDefaultOutput () { + return Math.max(this.value0, this.value1); + } +} + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PVNodeClamp`) +@poseGraphNodeCategory(POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH) +@poseGraphNodeAppearance({ themeColor: '#B169C4' }) +export class PVNodeClamp extends SingleOutputPVNode { + constructor () { + super(PoseGraphType.FLOAT); + } + + @serializable + @editable + @input({ type: PoseGraphType.FLOAT }) + public input = 0.0; + + @serializable + @editable + @input({ type: PoseGraphType.FLOAT }) + public min = 0.0; + + @serializable + @editable + @input({ type: PoseGraphType.FLOAT }) + public max = 0.0; + + public selfEvaluateDefaultOutput () { + return clamp( + this.input, + this.min, + this.max, + ); + } +} diff --git a/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/prefix.ts b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/prefix.ts new file mode 100644 index 00000000000..6fb33492c82 --- /dev/null +++ b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/prefix.ts @@ -0,0 +1 @@ +export const POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH = `i18n:ENGINE.animation_graph.pose_graph_node_sub_categories.math/`; diff --git a/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/trigonometry.ts b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/trigonometry.ts new file mode 100644 index 00000000000..cdd36ceff8c --- /dev/null +++ b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/trigonometry.ts @@ -0,0 +1,23 @@ +import { ccclass } from '../../../../../../core/data/decorators'; +import { poseGraphNodeAppearance, poseGraphNodeCategory } from '../../../decorator/node'; +import { CLASS_NAME_PREFIX_ANIM } from '../../../../../define'; +import { POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH } from './prefix'; +import { PVNodeUnaryNumericBase } from './unary-numeric-base'; + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PVNodeCosine`) +@poseGraphNodeCategory(POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH) +@poseGraphNodeAppearance({ themeColor: '#B169C4' }) +export class PVNodeCosine extends PVNodeUnaryNumericBase { + protected evaluateValue (value: number) { + return Math.cos(value); + } +} + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PVNodeSine`) +@poseGraphNodeCategory(POSE_GRAPH_NODE_MENU_PREFIX_PV_NODES_MATH) +@poseGraphNodeAppearance({ themeColor: '#B169C4' }) +export class PVNodeSine extends PVNodeUnaryNumericBase { + protected evaluateValue (value: number) { + return Math.sin(value); + } +} diff --git a/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/unary-numeric-base.ts b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/unary-numeric-base.ts new file mode 100644 index 00000000000..104cb29cfb2 --- /dev/null +++ b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/math/unary-numeric-base.ts @@ -0,0 +1,26 @@ +import { ccclass, editable, serializable } from '../../../../../../core/data/decorators'; +import { poseGraphNodeHide, poseGraphNodeAppearance } from '../../../decorator/node'; +import { PoseGraphType } from '../../../foundation/type-system'; +import { SingleOutputPVNode } from '../../../pure-value-node'; +import { input } from '../../../decorator/input'; +import { CLASS_NAME_PREFIX_ANIM } from '../../../../../define'; + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PVNodeUnaryNumericBase`) +@poseGraphNodeHide() +@poseGraphNodeAppearance({ themeColor: '#B169C4' }) +export abstract class PVNodeUnaryNumericBase extends SingleOutputPVNode { + constructor () { + super(PoseGraphType.FLOAT); + } + + @serializable + @editable + @input({ type: PoseGraphType.FLOAT }) + public operand = 0.0; + + public selfEvaluateDefaultOutput () { + return this.evaluateValue(this.operand); + } + + protected abstract evaluateValue(value: number): number; +} diff --git a/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/prefix.ts b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/prefix.ts new file mode 100644 index 00000000000..e7194c2330d --- /dev/null +++ b/cocos/animation/marionette/pose-graph/pure-value-nodes/builtin/prefix.ts @@ -0,0 +1,3 @@ +import { CLASS_NAME_PREFIX_ANIM } from '../../../../define'; + +export const CLASS_NAME_PREFIX_PV_NODES = CLASS_NAME_PREFIX_ANIM; diff --git a/cocos/animation/marionette/state-machine/state-machine-eval.ts b/cocos/animation/marionette/state-machine/state-machine-eval.ts index 9536abb54f4..0f228ffe9d3 100644 --- a/cocos/animation/marionette/state-machine/state-machine-eval.ts +++ b/cocos/animation/marionette/state-machine/state-machine-eval.ts @@ -21,9 +21,8 @@ import { TriggerResetter, } from '../animation-graph-context'; import { blendPoseInto, Pose } from '../../core/pose'; -import { PoseNode } from '../pose-graph/pose-node'; -import { instantiatePoseGraph, InstantiatedPoseGraph } from '../pose-graph/instantiation'; -import { ConditionEvaluationContext } from './condition/condition-base'; +import { InstantiatedPoseGraph, instantiatePoseGraph } from '../pose-graph/instantiation'; +import { ConditionBindingContext, ConditionEvaluationContext } from './condition/condition-base'; import { ReadonlyClipOverrideMap } from '../clip-overriding'; import { AnimationGraphEventBinding } from '../event/event-binding'; @@ -405,7 +404,6 @@ class TopLevelStateMachineEvaluation { relativeDestinationStart: false, exitCondition: 0.0, exitConditionEnabled: false, - activated: false, startEventBinding: undefined, endEventBinding: undefined, }; @@ -688,9 +686,6 @@ class TopLevelStateMachineEvaluation { const nTransitions = outgoingTransitions.length; for (let iTransition = 0; iTransition < nTransitions; ++iTransition) { const transition = outgoingTransitions[iTransition]; - if (transition.activated) { - continue; - } const { conditions } = transition; const nConditions = conditions.length; @@ -795,7 +790,6 @@ class TopLevelStateMachineEvaluation { /** * Update transitions, also update states within(includes the case of no transition). * @param deltaTime Time piece. - * @returns */ private _updateActivatedTransitions (deltaTime: number): void { const { @@ -1474,11 +1468,6 @@ interface TransitionEval { */ triggers: string[] | undefined; - /** - * Whether the transition is activated, if it has already been activated, it can not be activated(matched) again. - */ - activated: boolean; - startEventBinding: AnimationGraphEventBinding | undefined; endEventBinding: AnimationGraphEventBinding | undefined; } diff --git a/editor/i18n/en/animation.js b/editor/i18n/en/animation.js index 055ec951478..3c4b2b5ed31 100644 --- a/editor/i18n/en/animation.js +++ b/editor/i18n/en/animation.js @@ -8,6 +8,8 @@ module.exports = { pose_nodes_blend: 'Blend', pose_nodes_ik: 'Inverse Kinematic', pose_nodes_choose: 'Choose', + + math: 'Math', }, pose_graph_node_sub_menus: { play_or_sample_clip_motion: 'Animation Clip', @@ -339,11 +341,33 @@ module.exports = { }, }, }, + 'PoseNodeGetAllPreviousLayersResult': { + displayName: 'All Previous Layers Result', + }, 'PVNodeGetVariableBase': { displayName: 'Get Variable', title: 'Variable {variableName}', }, + + 'PVNodeMin': { + displayName: 'Min', + }, + 'PVNodeMax': { + displayName: 'Max', + }, + 'PVNodeAbs': { + displayName: 'Abs', + }, + 'PVNodeClamp': { + displayName: 'Clamp', + }, + 'PVNodeCosine': { + displayName: 'Cosine', + }, + 'PVNodeSine': { + displayName: 'Sine', + }, }, }, }, diff --git a/editor/i18n/zh/animation.js b/editor/i18n/zh/animation.js index a164ef8588a..63aa87fe022 100644 --- a/editor/i18n/zh/animation.js +++ b/editor/i18n/zh/animation.js @@ -8,6 +8,8 @@ module.exports = { pose_nodes_blend: '混合', pose_nodes_ik: '反向动力学', pose_nodes_choose: '选择', + + math: '数学', }, pose_graph_node_sub_menus: { play_or_sample_clip_motion: '动画剪辑', @@ -335,11 +337,33 @@ module.exports = { }, }, }, + 'PoseNodeGetAllPreviousLayersResult': { + displayName: '前序所有层级结果', + }, 'PVNodeGetVariableBase': { displayName: '获取变量', title: '变量 {variableName}', }, + + 'PVNodeMin': { + displayName: '取最小值', + }, + 'PVNodeMax': { + displayName: '取最小值', + }, + 'PVNodeAbs': { + displayName: '取绝对值', + }, + 'PVNodeClamp': { + displayName: '钳制', + }, + 'PVNodeCosine': { + displayName: '取余弦(cos)', + }, + 'PVNodeSine': { + displayName: '取正弦(sin)', + }, }, }, }, diff --git a/editor/src/marionette/pose-graph-editor-api.ts b/editor/src/marionette/pose-graph-editor-api.ts index cbd1cb20487..c0809fe2a30 100644 --- a/editor/src/marionette/pose-graph-editor-api.ts +++ b/editor/src/marionette/pose-graph-editor-api.ts @@ -336,4 +336,7 @@ export function* visitStashReferences(layer: Layer, stashId: string): Generator< } } +export { queryNodeSpecializedOperations, performNodeSpecializedOperation } from './specialized-node-operation'; +export type { NodeSpecializedOperation } from './specialized-node-operation'; + export * from './pose-graph/drag'; diff --git a/editor/src/marionette/specialized-node-operation/index.ts b/editor/src/marionette/specialized-node-operation/index.ts new file mode 100644 index 00000000000..a174185ae5a --- /dev/null +++ b/editor/src/marionette/specialized-node-operation/index.ts @@ -0,0 +1,24 @@ +import { poseGraphOp } from '../../../exports/new-gen-anim'; +import { getRegister, NodeSpecializedOperation, NodeSpecializedOperationContext } from './registry'; + +import './operations/all'; + +export type { NodeSpecializedOperation }; + +export function queryNodeSpecializedOperations(node: poseGraphOp.Node): NodeSpecializedOperation[] { + const register = getRegister(node); + if (!register) { + return []; + } else { + return register.query(node); + } +} + +export function performNodeSpecializedOperation(node: poseGraphOp.Node, operationId: string, context: NodeSpecializedOperationContext) { + const register = getRegister(node); + if (!register) { + return []; + } else { + return register.perform(node, operationId, context); + } +} diff --git a/editor/src/marionette/specialized-node-operation/operations/all.ts b/editor/src/marionette/specialized-node-operation/operations/all.ts new file mode 100644 index 00000000000..cf825fc5b9a --- /dev/null +++ b/editor/src/marionette/specialized-node-operation/operations/all.ts @@ -0,0 +1,4 @@ + +import './use-stashed-pose'; + +export {}; diff --git a/editor/src/marionette/specialized-node-operation/operations/use-stashed-pose.ts b/editor/src/marionette/specialized-node-operation/operations/use-stashed-pose.ts new file mode 100644 index 00000000000..0bfe5a322ba --- /dev/null +++ b/editor/src/marionette/specialized-node-operation/operations/use-stashed-pose.ts @@ -0,0 +1,60 @@ +import { assertIsTrue } from "../../../../../exports/base"; +import { copyPoseGraphNodes, pastePoseGraphNodes, poseGraphOp } from "../../../../exports/new-gen-anim"; +import { NodeSpecializedOperationContext, registerNodeSpecializedOperation } from "../registry"; +import { PoseNodeUseStashedPose } from '../../../../../cocos/animation/marionette/pose-graph/pose-nodes/use-stashed-pose'; +import { PoseNode } from "../../../../../cocos/animation/marionette/pose-graph/pose-node"; + +export {}; + +registerNodeSpecializedOperation(PoseNodeUseStashedPose, { + query(_node) { + return [{ + id: 'expand', + displayName: '展开暂存', + }]; + }, + perform(node, operationId, context) { + switch (operationId) { + case 'expand': + expandStash(node, context); + break; + } + }, +}); + +function expandStash(node: PoseNodeUseStashedPose, context: NodeSpecializedOperationContext) { + const stashId = node.stashName; + const stash = context.layer.getStash(stashId); + if (!stash) { + console.warn(`Stash ${stashId} does not exists.`); + return; + } + + const copyInfo = copyPoseGraphNodes(stash.graph, [...stash.graph.nodes()]); + + let outBinding: { + consumerNode: PoseNode, + inputKey: poseGraphOp.InputKey, + } | undefined; + for (const consumerNode of context.poseGraph.nodes()) { + const inputKeys = poseGraphOp.getInputKeys(consumerNode); + for (const inputKey of inputKeys) { + const binding = poseGraphOp.getInputBinding(context.poseGraph, consumerNode, inputKey); + if (binding && binding.producer === node) { + assertIsTrue(consumerNode instanceof PoseNode); + outBinding = { + consumerNode, + inputKey, + }; + break; + } + } + if (outBinding) { + break; + } + } + + pastePoseGraphNodes(context.poseGraph, copyInfo, { + outputNodeBindingRedirect: outBinding, + }); +} diff --git a/editor/src/marionette/specialized-node-operation/registry.ts b/editor/src/marionette/specialized-node-operation/registry.ts new file mode 100644 index 00000000000..e078d8af323 --- /dev/null +++ b/editor/src/marionette/specialized-node-operation/registry.ts @@ -0,0 +1,42 @@ +import { Constructor } from "../../../../exports/base"; +import { AnimationGraph, Layer, PoseGraph, poseGraphOp } from "../../../exports/new-gen-anim"; + +export interface NodeSpecializedOperation { + /** + * 操作 ID。 + */ + id: string; + + /** + * 操作显示名称。 + */ + displayName: string; +} + +export interface NodeSpecializedOperationContext { + animationGraph: AnimationGraph; + + layer: Layer; + + poseGraph: PoseGraph; +} + +export interface NodeSpecializedOperationRegister { + query(node: TNode): NodeSpecializedOperation[]; + + perform(node: TNode, operationId: string, context: NodeSpecializedOperationContext): void; +} + +const operationRegistry = new WeakMap, NodeSpecializedOperationRegister>(); + +export function registerNodeSpecializedOperation( + constructor: Constructor, + register: NodeSpecializedOperationRegister, +) { + operationRegistry.set(constructor, register); +} + +export function getRegister(node: poseGraphOp.Node) { + const register = operationRegistry.get(node.constructor as Constructor); + return register as NodeSpecializedOperationRegister; +} diff --git a/tests/animation/new-gen-anim/__todo-state-weight-condition.test.ts b/tests/animation/new-gen-anim/__todo-state-weight-condition.test.ts new file mode 100644 index 00000000000..e8c14bcfe8f --- /dev/null +++ b/tests/animation/new-gen-anim/__todo-state-weight-condition.test.ts @@ -0,0 +1,106 @@ +import { createAnimationGraph } from './utils/factory'; +import { LinearRealValueAnimationFixture } from './utils/fixtures'; +import { SingleRealValueObserver } from './utils/single-real-value-observer'; +import { AnimationGraphEvalMock } from './utils/eval-mock'; +import { lerp } from '../../../exports/base'; + +describe(`Used in interruption detection`, () => { + test(`Target state is transition destination`, () => { + const fixture = { + motion_a: new LinearRealValueAnimationFixture(1., 2., 3.), + motion_b: new LinearRealValueAnimationFixture(4., 5., 6.), + motion_c: new LinearRealValueAnimationFixture(7., 8., 9.), + observing_state_weight: 0.7, + }; + + const valueObserver = new SingleRealValueObserver(); + + const transitionDurationAToB = Math.min(fixture.motion_a.duration, fixture.motion_b.duration) * 0.5; + + const animationGraph = createAnimationGraph({ + layers: [{ + stateMachine: { + states: { + 'a': { type: 'motion', motion: fixture.motion_a.createMotion(valueObserver.getCreateMotionContext()) }, + 'b': { type: 'motion', motion: fixture.motion_b.createMotion(valueObserver.getCreateMotionContext()) }, + 'c': { type: 'motion', motion: fixture.motion_c.createMotion(valueObserver.getCreateMotionContext()) }, + }, + entryTransitions: [{ + to: 'a', + }], + transitions: [{ + from: 'a', to: 'b', + duration: transitionDurationAToB, + exitTimeEnabled: false, + conditions: [{ type: 'unary', operator: 'to-be-true', operand: { type: 'constant', value: true } }], + }, { + from: 'b', to: 'c', + duration: 1.0, + exitTimeEnabled: false, + conditions: [{ + type: 'binary', + operator: '>=', + lhsBinding: { type: 'state-weight' }, + rhs: fixture.observing_state_weight, + }], + }], + }, + }], + }); + + const evalMock = new AnimationGraphEvalMock(valueObserver.root, animationGraph); + + const thresholdTime = transitionDurationAToB * fixture.observing_state_weight; + + evalMock.goto(thresholdTime * 0.95); + expect(valueObserver.value).toBeCloseTo( + lerp( + fixture.motion_a.getExpected(evalMock.current), + fixture.motion_b.getExpected(evalMock.current), + evalMock.current / transitionDurationAToB, + ), + 5, + ); + + // TODO:!! this is not ideal! + evalMock.goto(thresholdTime * 1.01); + expect(valueObserver.value).toBeCloseTo( + lerp( + fixture.motion_a.getExpected(evalMock.current), + fixture.motion_b.getExpected(evalMock.current), + evalMock.current / transitionDurationAToB, + ), + 5, + ); + + evalMock.goto(thresholdTime * 1.05); + let cExpectedTime = evalMock.lastDeltaTime; + expect(valueObserver.value).toBeCloseTo( + lerp( + lerp( + fixture.motion_a.getExpected(evalMock.current), + fixture.motion_b.getExpected(evalMock.current), + evalMock.current / transitionDurationAToB, + ), + fixture.motion_c.getExpected(cExpectedTime), + cExpectedTime / 1.0, + ), + 5, + ); + + evalMock.goto(thresholdTime * 1.3); + cExpectedTime += evalMock.lastDeltaTime; + expect(valueObserver.value).toBeCloseTo( + lerp( + lerp( + fixture.motion_a.getExpected(evalMock.current), + fixture.motion_b.getExpected(evalMock.current), + evalMock.current / transitionDurationAToB, + ), + fixture.motion_c.getExpected(cExpectedTime), + cExpectedTime / 1.0, + ), + 5, + ); + }); +}); diff --git a/tests/animation/new-gen-anim/pose-graph/pose-nodes/utils/evaluation-mock.ts b/tests/animation/new-gen-anim/pose-graph/pose-nodes/utils/evaluation-mock.ts index dd3c4ca2404..8b53cd78887 100644 --- a/tests/animation/new-gen-anim/pose-graph/pose-nodes/utils/evaluation-mock.ts +++ b/tests/animation/new-gen-anim/pose-graph/pose-nodes/utils/evaluation-mock.ts @@ -13,7 +13,8 @@ import { AnimationGraphSettleContext, AnimationGraphUpdateContext, } from '../../../../../../cocos/animation/marionette/animation-graph-context'; -import { BindContext } from '../../../../../../cocos/animation/marionette/parametric';; +import { BindContext } from '../../../../../../cocos/animation/marionette/parametric'; +import { AllPreviousLayersResultManagerImpl } from '../../../../../../cocos/animation/marionette/pose-graph/default-top-level-pose-node'; import { PoseGraph } from '../../../../../../cocos/animation/marionette/pose-graph/pose-graph'; import { PoseNode, PoseTransformSpaceRequirement } from '../../../../../../cocos/animation/marionette/pose-graph/pose-node'; import { RuntimeStashManager } from '../../../../../../cocos/animation/marionette/pose-graph/stash/runtime-stash'; @@ -116,6 +117,7 @@ export class PoseNodeEvaluationMock { bindContext._setLayerWideContextProperties( stashManager, new RuntimeMotionSyncManager(), + new AllPreviousLayersResultManagerImpl(), ); this._resultObserver = resultFactory.create(origin, bindContext); From bbc2d6d23a2b339c57255116f43f9e8f57c70320 Mon Sep 17 00:00:00 2001 From: Leslie Leigh Date: Fri, 14 Jul 2023 14:31:50 +0800 Subject: [PATCH 180/184] PoseGraph: Add two bone ik edge tests Applylint tb xxxxx tt --- .../pose-nodes/ik/solve-two-bone-ik.ts | 68 +++-- .../pose-nodes/ik/two-bone-ik-solver.ts | 6 +- .../pose-nodes/ik/two-bone-ik-solver.test.ts | 240 +++++++++++++++++- tests/animation/new-gen-anim/utils/factory.ts | 10 +- 4 files changed, 303 insertions(+), 21 deletions(-) diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/ik/solve-two-bone-ik.ts b/cocos/animation/marionette/pose-graph/pose-nodes/ik/solve-two-bone-ik.ts index f0d1825b05f..082d69a0afe 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/ik/solve-two-bone-ik.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/ik/solve-two-bone-ik.ts @@ -4,6 +4,7 @@ import { Transform } from '../../../../core/transform'; import { debugTwoBoneIKDraw } from './two-bone-ik-debugger'; const SANITY_CHECK_ENABLED = DEBUG; +const ZERO_SEGMENT_LENGTH = 1e-5; class TwoBoneIKPositionSanityChecker { public reset (a: Readonly, b: Readonly, c: Readonly): void { @@ -48,19 +49,21 @@ class TwoBoneIKPositionSanityChecker { * @param target 末端关节要抵达的目标位置(世界空间)。 * @param hint 中间关节的提示位置(世界空间),用于决定中间关节的朝向。 */ -export const solveTwoBoneIK = ((): (root: Transform, middle: Transform, end: Transform, target: Vec3, middlePositionHint?: Vec3, debugKey?: unknown | undefined) => void => { +export const solveTwoBoneIK = (() => { const cacheQuat = new Quat(); const cacheHint = new Vec3(); const cacheBSolved = new Vec3(); const cacheCSolved = new Vec3(); - const calculateRotationBetweenRays = ((): (out: Quat, sourceOrigin: Readonly, sourceDestination: Readonly, targetOrigin: Readonly, targetDestination: Readonly) => Quat => { + const calculateRotationBetweenRays = (() => { const cacheVec3_1 = new Vec3(); const cacheVec3_2 = new Vec3(); return ( out: Quat, - sourceOrigin: Readonly, sourceDestination: Readonly, - targetOrigin: Readonly, targetDestination: Readonly, + sourceOrigin: Readonly, + sourceDestination: Readonly, + targetOrigin: Readonly, + targetDestination: Readonly, // eslint-disable-next-line arrow-body-style ): Quat => { return Quat.rotationTo( @@ -87,7 +90,7 @@ export const solveTwoBoneIK = ((): (root: Transform, middle: Transform, end: Tra const qC = end.rotation; if (DEBUG) { - if (typeof debugKey !== undefined) { + if (typeof debugKey !== 'undefined') { debugTwoBoneIKDraw(debugKey, pA, pB, pC); } } @@ -106,16 +109,20 @@ export const solveTwoBoneIK = ((): (root: Transform, middle: Transform, end: Tra const qA = calculateRotationBetweenRays( cacheQuat, - pA, pB, - pA, bSolved, + pA, + pB, + pA, + bSolved, ); Quat.multiply(qA, qA, root.rotation); root.rotation = qA; const qB = calculateRotationBetweenRays( cacheQuat, - pB, pC, - bSolved, cSolved, + pB, + pC, + bSolved, + cSolved, ); Quat.multiply(qB, qB, middle.rotation); middle.rotation = qB; @@ -125,7 +132,7 @@ export const solveTwoBoneIK = ((): (root: Transform, middle: Transform, end: Tra }; })(); -export const solveTwoBoneIKPositions = ((): (a: Readonly, b: Readonly, c: Readonly, target: Readonly, middleTarget: Readonly, bSolved: Vec3, cSolved: Vec3) => void => { +export const solveTwoBoneIKPositions = (() => { const cacheDirAT = new Vec3(); const cacheDirAB = new Vec3(); const cacheDirHeightLine = new Vec3(); @@ -133,6 +140,16 @@ export const solveTwoBoneIKPositions = ((): (a: Readonly, b: Readonly { + const cacheCross = new Vec3(); + const EPSILON = 1e-5; + const EPSILON_SQUARED = EPSILON ** 2; + return (a: Readonly, b: Readonly): boolean => { + const cross = Vec3.cross(cacheCross, a, b); + return Vec3.lengthSqr(cross) < EPSILON_SQUARED; + }; + })(); + return ( a: Readonly, b: Readonly, @@ -156,19 +173,39 @@ export const solveTwoBoneIKPositions = ((): (a: Readonly, b: Readonly= chainLength) { - // Target is too far + // If we can not form a triangle from the three sides AB, BC, AT, + // straighten the chain so that: + // - let AB point to T, + // - **THEN** let BC point to T. + // This exclusion also includes not only the following cases: + // - either of the sides is zero. + // - the target is too far to reach. + if (dAB + dBC <= dAT || dAB + dAT <= dBC || dBC + dAT <= dAB) { Vec3.scaleAndAdd(bSolved, a, dirAT, dAB); - Vec3.scaleAndAdd(cSolved, a, dirAT, chainLength); + Vec3.scaleAndAdd(cSolved, a, dirAT, dAB + (dAB < dAT ? dBC : -dBC)); sanityCheck?.(); return; } + const dirAB = Vec3.subtract(cacheDirAB, middleTarget, a); + const dirHeightLine = cacheDirHeightLine; + // Let height line to be the line AB's projection onto the plane having normal line AT, + // if AB and AT are not colinear. + // Otherwise, let it be an arbitrary vector perpend to the AT. + if (isAlmostColinear(dirAB, dirAT)) { + Vec3.generateOrthogonal(dirHeightLine, dirAT); + } else { + Vec3.projectOnPlane(dirHeightLine, dirAB, dirAT); + Vec3.normalize(dirHeightLine, dirHeightLine); + } + // Now we should have a solution with target reached. // And then solve the middle joint B as Ḃ. Vec3.copy(cSolved, target); // Calculate ∠BAC's cosine. + // Since we checked the triangle's validity, + // the cosine should be ideally in [-1, 1]. + // But still do clamp here to avoid rounding error. const cosḂAT = clamp( (dAB * dAB + dAT * dAT - dBC * dBC) / (2 * dAB * dAT), -1.0, @@ -176,9 +213,6 @@ export const solveTwoBoneIKPositions = ((): (a: Readonly, b: Readonly] | undefined { + PoseNodeTwoBoneIKSolver.prototype.getTitle = function getTitle ( + this: PoseNodeTwoBoneIKSolver, + ): ReturnType> { if (this.endEffectorBoneName) { return [`ENGINE.classes.${CLASS_NAME_PREFIX_ANIM}PoseNodeTwoBoneIKSolver.title`, { endEffectorBoneName: this.endEffectorBoneName, diff --git a/tests/animation/new-gen-anim/pose-graph/pose-nodes/ik/two-bone-ik-solver.test.ts b/tests/animation/new-gen-anim/pose-graph/pose-nodes/ik/two-bone-ik-solver.test.ts index 9dc65b371f6..ebf03d29b32 100644 --- a/tests/animation/new-gen-anim/pose-graph/pose-nodes/ik/two-bone-ik-solver.test.ts +++ b/tests/animation/new-gen-anim/pose-graph/pose-nodes/ik/two-bone-ik-solver.test.ts @@ -1,3 +1,11 @@ +import { poseGraphOp } from '../../../../../../cocos/animation/marionette/asset-creation'; +import { PoseNodeTwoBoneIKSolver, TargetSpecificationType } from '../../../../../../cocos/animation/marionette/pose-graph/pose-nodes/ik/two-bone-ik-solver'; +import { Vec3 } from '../../../../../../cocos/core'; +import { Node } from '../../../../../../exports/base'; +import { AnimationGraphEvalMock } from '../../../utils/eval-mock'; +import { createAnimationGraph } from '../../../utils/factory'; +import '../../../../../utils/matchers/value-type-asymmetric-matchers'; +import { getMagicSeed, PseudoRandomGenerator } from '../../../../../utils/random'; describe(`Error-formed`, () => { test.todo(`End effector not specified`); @@ -21,4 +29,234 @@ describe(`Error-formed`, () => { test.todo(`End effector target bone is specified and valid`); }); -}); \ No newline at end of file +}); + +describe(`A,B,T could not form a triangle`, () => { + describe(`Zero segment length`, () => { + test(`Both two segments has zero length(the bones are overlapped)`, () => { + const pA = new Vec3(1, 2, 3); + const pT = new Vec3(0.618, -3.14, 10.86); + const solved = doSolve( + pA, + pA, + pA, + pT, + undefined, + ); + expect(solved.middle.position).toBeCloseToVec3(pA); + expect(solved.endEffector.position).toBeCloseToVec3(pA); + }); + + describe(`Either the segment has zero length`, () => { + const pA = new Vec3(1, 2, 3); + const pC = new Vec3(0.618, -3.14, 10.86); + const tDirFromA = Object.freeze(Vec3.subtract(new Vec3(), new Vec3(7, 8, -9), pA).normalize()); + + test(`len(AB) is zero`, () => { + const solveAtChainLengthMultiplier = (multiplier: number) => { + const pT = Vec3.scaleAndAdd(new Vec3(), pA, tDirFromA, Vec3.distance(pA, pC) * multiplier); + const solved = doSolve(pA, pA, pC, pT, undefined); + expect(solved.middle.position).toBeCloseToVec3(pA); + expect(solved.endEffector.position).toBeCloseToVec3(Vec3.scaleAndAdd(new Vec3(), pA, tDirFromA, Vec3.distance(pA, pC))); + }; + + solveAtChainLengthMultiplier(1.2); + solveAtChainLengthMultiplier(0.7); + }); + + test(`len(BC) are overlapped`, () => { + const solveAtChainLengthMultiplier = (multiplier: number) => { + const pT = Vec3.scaleAndAdd(new Vec3(), pA, tDirFromA, Vec3.distance(pA, pC) * multiplier); + const solved = doSolve(pA, pC, pC, pT, undefined); + expect(solved.endEffector.position).toBeCloseToVec3(Vec3.scaleAndAdd(new Vec3(), pA, tDirFromA, Vec3.distance(pA, pC))); + expect(solved.middle.position).toBeCloseToVec3(solved.endEffector.position); + }; + + solveAtChainLengthMultiplier(1.2); + solveAtChainLengthMultiplier(0.7); + }); + }); + }); + + describe(`All sides are not zero, but could not form a triangle`, () => { + const g = new PseudoRandomGenerator(getMagicSeed()); + + const sl0 = g.positive(); + const sl1 = g.positive(); + const sl2 = sl0 + sl1 + g.positive(); + const vertexA = Object.freeze(new Vec3(g.finite(), g.finite(), g.finite())); + const dirAB = Object.freeze(Vec3.normalize(new Vec3(), new Vec3(g.normalized(), g.normalized(), g.normalized()))); + const dirBC = Object.freeze(Vec3.normalize(new Vec3(), new Vec3(g.normalized(), g.normalized(), g.normalized()))); + const dirAT = Object.freeze(Vec3.normalize(new Vec3(), new Vec3(g.normalized(), g.normalized(), g.normalized()))); + + test.each([ + // a b c + [`a+b { + const solve = (lenAB: number, lenAT: number) => { + const vertexB = Vec3.scaleAndAdd(new Vec3(), vertexA, dirAB, lenAB); + + const solved = doSolve( + vertexA, + vertexB, + Vec3.scaleAndAdd(new Vec3(), vertexB, dirBC, lenBC), + + Vec3.scaleAndAdd(new Vec3(), vertexA, dirAT, lenAT), + undefined, + ); + + expect(Vec3.normalize(new Vec3(), Vec3.subtract(new Vec3(), solved.middle.position, vertexA))).toBeCloseToVec3(dirAT); + const dirMiddleEndSolved = lenAB < lenAT ? 1 : -1; + expect(Vec3.normalize(new Vec3(), Vec3.subtract(new Vec3(), solved.endEffector.position, solved.middle.position))) + .toBeCloseToVec3(Vec3.multiplyScalar(new Vec3(), dirAT, dirMiddleEndSolved)); + }; + + solve(lenAB_, lenAT_); + solve(lenAT_, lenAB_); + }); + + test(`Bugfix`, () => { + const result = doSolve( + new Vec3(-0.09242249791874639, 0.7809744197151507, 0.0440291647921393), + new Vec3(-0.2202181390043632, 0.6506767191347834, 0.49891323892477991), + new Vec3(-0.10022652110916505, 0.7346849221083793, 0.12458274852241735), + new Vec3(-0.09780396078888308, 0.7339540517872343, 0.11183048623975389), + new Vec3(-0.2202181390043632, 0.6506767191347834, 0.4989132389247799), + ); + expect(result.endEffector.position).toBeCloseToVec3( + new Vec3(-0.09816044416293312, 0.7308392891636664, 0.11632183820444486)); + expect(result.middle.position).toBeCloseToVec3( + new Vec3(-0.12432196250955035, 0.5022538193953633, 0.4459321240655465)); + }) + }); + + describe(`AB is colinear with BT`, () => { + const coDir = Object.freeze(Vec3.normalize(new Vec3(), new Vec3(1, -1, 2))); + const pA = new Vec3(1, 2, 3); + const dAB = 0.4; + const dBC = 1.2; + const pB = Vec3.scaleAndAdd(new Vec3(), pA, coDir, dAB); + const pC = Vec3.scaleAndAdd(new Vec3(), pB, coDir, dBC); + const solveAtDistanceFromB = (distance: number) => doSolve( + pA, + pB, + pC, + Vec3.scaleAndAdd(new Vec3(), pB, coDir, distance), + undefined, + ); + describe(`Same direction`, () => { + test(`Longer than chain length`, () => { + const result = solveAtDistanceFromB(dBC * 1.2); + expect(result.endEffector.position).toBeCloseToVec3(pC); + }); + test(`Shorter than chain length`, () => { + const result = solveAtDistanceFromB(dBC * 0.7); + expect(result.endEffector.position).toBeCloseToVec3(pC); + }); + }); + test(`Opposite direction`, () => { + const coDir = Object.freeze(Vec3.normalize(new Vec3(), new Vec3(0.14195054214877403, 0.063693107343907707, -0.98782246970827026))); + const pA = new Vec3(9.0057184766238798, -2.5299869030302879, 95.299290089180317); + const dAB = 42.5720367; + const dBC = 40.1966896; + // const dAB = 0.4; + // const dBC = 1.2; + // const dAB = 42.5720367; + // const dBC = 1.2; + const result = doSolve( + pA, + Vec3.scaleAndAdd(new Vec3(), pA, coDir, dAB), + Vec3.scaleAndAdd(new Vec3(), pA, coDir, dAB + dBC), + // Vec3.scaleAndAdd(new Vec3(), pA, coDir, dAB + -0.3), + Vec3.scaleAndAdd(new Vec3(), pA, coDir, (dAB - dBC) * 0.5), + undefined, + ); + }); + }); +}); + +test.skip(`Edge case: target is almost Infinity from bones`, () => { + const result = doSolve( + new Vec3(-0.21317485899373015, 1.3981241276020546, -0.06900958751340587), + new Vec3(-0.25255526992058713, 1.122513395181039, -0.07067335755206586), + new Vec3(-0.30032509088559695, 0.8525761352143646, 0.000768669924157972), + new Vec3(-2.7378717978901504e+270, 8.311351261877791e+270, 2.751998222735035e+269), + undefined, + ); + // TODO: what do we expect? +}); + +function doSolve( + root: Readonly, + middle: Readonly, + endEffector: Readonly, + endEffectorTargetPosition: Readonly | undefined, + poleTargetPosition: Readonly | undefined, +): { + middle: { + position: Readonly; + }; + endEffector: { + position: Readonly; + }; +} { + const d_root_middle = Vec3.distance(root, middle); + const d_middle_endEffector = Vec3.distance(middle, endEffector); + + const animationGraph = createAnimationGraph({ + layers: [{ + stateMachine: { + entryTransitions: [{ to: 'p' }], + states: { 'p': { type: 'procedural', graph: (poseGraph) => { + const node = poseGraph.addNode(new PoseNodeTwoBoneIKSolver()); + node.endEffectorBoneName = 'EndEffector'; + if (!endEffectorTargetPosition) { + node.endEffectorTarget.type = TargetSpecificationType.NONE; + } else { + node.endEffectorTarget.type = TargetSpecificationType.VALUE; + Vec3.copy(node.endEffectorTarget.targetPosition, endEffectorTargetPosition); + } + if (!poleTargetPosition) { + node.poleTarget.type = TargetSpecificationType.NONE; + } else { + node.poleTarget.type = TargetSpecificationType.VALUE; + Vec3.copy(node.poleTarget.targetPosition, poleTargetPosition); + } + poseGraphOp.connectOutputNode(poseGraph, node); + } } }, + }, + }], + }); + + const origin = new Node(); + const rootNode = new Node(`Root`); + rootNode.parent = origin; + const middleNode = new Node(`Middle`); + middleNode.parent = rootNode; + const endEffectorNode = new Node(`EndEffector`); + endEffectorNode.parent = middleNode; + + rootNode.worldPosition = root; + middleNode.worldPosition = middle; + endEffectorNode.worldPosition = endEffector; + + const evalMock = new AnimationGraphEvalMock(origin, animationGraph); + evalMock.step(0.1); + + // Root position shall not change. + expect(rootNode.worldPosition).toStrictEqual(expect.objectContaining({ + x: root.x, + y: root.y, + z: root.z, + })); + // Chain segment lengths shall not change. + expect(Vec3.distance(rootNode.worldPosition, middleNode.worldPosition)).toBeCloseTo(d_root_middle, 5); + expect(Vec3.distance(middleNode.worldPosition, endEffectorNode.worldPosition)).toBeCloseTo(d_middle_endEffector, 5); + + return { + middle: { position: middleNode.worldPosition }, + endEffector: { position: endEffectorNode.worldPosition }, + }; +} diff --git a/tests/animation/new-gen-anim/utils/factory.ts b/tests/animation/new-gen-anim/utils/factory.ts index 1134c0e1d08..e79d04e5b0a 100644 --- a/tests/animation/new-gen-anim/utils/factory.ts +++ b/tests/animation/new-gen-anim/utils/factory.ts @@ -6,7 +6,7 @@ import { BinaryCondition, TriggerCondition, UnaryCondition } from "../../../../c import { MotionState } from "../../../../cocos/animation/marionette/state-machine/motion-state"; import { Bindable } from "../../../../cocos/animation/marionette/parametric"; import { TriggerResetMode, VariableType } from "../../../../cocos/animation/marionette/variable"; -import { assertIsTrue, Vec2 } from "../../../../exports/base"; +import { assertIsTrue, Quat, Vec2, Vec3 } from "../../../../exports/base"; import { TCVariableBinding } from "../../../../cocos/animation/marionette/state-machine/condition/binding/variable-binding"; import { TCAuxiliaryCurveBinding } from "../../../../cocos/animation/marionette/state-machine/condition/binding/auxiliary-curve-binding"; import { TCStateWeightBinding } from "../../../../cocos/animation/marionette/state-machine/condition/binding/state-weight-binding"; @@ -31,6 +31,8 @@ export function createAnimationGraph(params: AnimationGraphParams): AnimationGra } break; } + case 'vec3': animationGraph.addVariable(id, VariableType.VEC3_experimental, variableDeclarationParams.value); break; + case 'quat': animationGraph.addVariable(id, VariableType.QUAT_experimental, variableDeclarationParams.value); break; } } } @@ -299,6 +301,12 @@ export type VariableDeclarationParams = { } | { type: 'trigger', resetMode?: 'after-consumed' | 'next-frame-or-after-consumed'; +} | { + type: 'vec3'; + value?: Vec3; +} | { + type: 'quat'; + value?: Quat; }; interface LayerParams { From 520d00efdfcaebbf7f246e531ac590861cd72ab2 Mon Sep 17 00:00:00 2001 From: Leslie Leigh Date: Fri, 14 Jul 2023 15:14:36 +0800 Subject: [PATCH 181/184] Add pose node: PoseNodeLookAt lookat Look at Apply lint look Lint --- .../marionette/animation-graph-context.ts | 4 + .../marionette/pose-graph/pose-nodes/all.ts | 1 + .../pose-nodes/ik/look-at-debugging.ts | 111 +++++++ .../pose-graph/pose-nodes/ik/look-at.ts | 288 ++++++++++++++++++ editor/i18n/zh/animation.js | 46 +++ 5 files changed, 450 insertions(+) create mode 100644 cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at-debugging.ts create mode 100644 cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at.ts diff --git a/cocos/animation/marionette/animation-graph-context.ts b/cocos/animation/marionette/animation-graph-context.ts index 9d665bfcb55..a2710327243 100644 --- a/cocos/animation/marionette/animation-graph-context.ts +++ b/cocos/animation/marionette/animation-graph-context.ts @@ -787,6 +787,10 @@ class AnimationGraphEvaluationContext { return this._parentTable; } + get componentToWorldTransform () { + return this._getComponentToWorldTransform(); + } + public pushDefaultedPose (): Pose { const pose = this._poseAllocator.push(); pose.transforms.set(this[defaultTransformsTag]); diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/all.ts b/cocos/animation/marionette/pose-graph/pose-nodes/all.ts index e88af744b42..250505e1e13 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/all.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/all.ts @@ -20,5 +20,6 @@ import './copy-transform'; import './set-auxiliary-curve'; import './ik/two-bone-ik-solver'; +import './ik/look-at'; export {}; diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at-debugging.ts b/cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at-debugging.ts new file mode 100644 index 00000000000..360f0dd5e6e --- /dev/null +++ b/cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at-debugging.ts @@ -0,0 +1,111 @@ +import { Color, Vec3 } from '../../../../../core'; +import { AABB } from '../../../../../core/geometry'; +import { legacyCC } from '../../../../../core/global-exports'; +import type { Director } from '../../../../../game'; +import type { GeometryRenderer } from '../../../../../rendering/geometry-renderer'; +import { Transform } from '../../../../core/transform'; +import { AnimationGraphEvaluationContext } from '../../../animation-graph-context'; +import type { PoseNodeLookAt } from './look-at'; + +const getOrCreateGeometryRenderer = (): GeometryRenderer | undefined => { + const camera = (legacyCC.director as Director).getScene()?.renderScene?.cameras[0]; + if (!camera) { + return undefined; + } + camera.initGeometryRenderer(); + return camera.geometryRenderer ?? undefined; +}; + +const cacheWorldTransform = new Transform(); +const cacheTargetWorld = new Transform(); +const cacheRightAxis = new Vec3(); +const cacheAABB = new AABB(); +const cacheLineTo = new Vec3(); + +class LookAtDebugger { + public drawInputs ( + context: AnimationGraphEvaluationContext, + transform: Transform, + targetPosition: Readonly, + forwardAxis: Readonly, + upAxis: Readonly, + ): void { + const geometryRenderer = getOrCreateGeometryRenderer(); + if (!geometryRenderer) { + return; + } + const componentToWorld = context.componentToWorldTransform; + const worldTransform = Transform.multiply(cacheWorldTransform, componentToWorld, transform); + const targetWorld = Transform.setIdentity(cacheTargetWorld); + targetWorld.position = targetPosition; + Transform.multiply(targetWorld, componentToWorld, targetWorld); + + this._drawBonePosition(geometryRenderer, worldTransform.position); + this._drawBonePosition(geometryRenderer, targetWorld.position); + this._drawAxis(geometryRenderer, worldTransform.position, forwardAxis, 0.1, Color.BLUE); + this._drawAxis(geometryRenderer, worldTransform.position, upAxis, 0.1, Color.GREEN); + const rightAxis = Vec3.cross(cacheRightAxis, upAxis, forwardAxis); + Vec3.normalize(rightAxis, rightAxis); + this._drawAxis(geometryRenderer, worldTransform.position, rightAxis, 0.1, Color.RED); + geometryRenderer.addDashedLine( + worldTransform.position, + targetWorld.position, + Color.WHITE, + false, + ); + } + + // eslint-disable-next-line @typescript-eslint/no-empty-function + public drawResult (transform: Transform): void { + } + + private _drawBonePosition ( + geometryRenderer: GeometryRenderer, + position: Readonly, + ): void { + const halfExtent = 0.01; + geometryRenderer.addBoundingBox( + AABB.set( + cacheAABB, + position.x, + position.y, + position.z, + halfExtent, + halfExtent, + halfExtent, + ), + Color.WHITE, + true, + false, + ); + } + + private _drawAxis ( + geometryRenderer: GeometryRenderer, + position: Readonly, + dir: Readonly, + scale: number, + color: Color, + ): void { + Vec3.scaleAndAdd(cacheLineTo, position, dir, scale); + geometryRenderer.addLine( + position, + Vec3.scaleAndAdd(cacheLineTo, position, dir, scale), + color, + false, + ); + } +} + +// // eslint-disable-next-line @typescript-eslint/ban-types +// const debuggerMap = new WeakMap(); + +// export function createDebugger (poseNode: PoseNodeLookAt) { +// debuggerMap.set(poseNode, new LookAtDebugger()); +// } + +const globalDebugger = new LookAtDebugger(); + +export function getDebugger (_poseNode: PoseNodeLookAt): LookAtDebugger | undefined { + return globalDebugger; +} diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at.ts b/cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at.ts new file mode 100644 index 00000000000..f263c74ef4c --- /dev/null +++ b/cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at.ts @@ -0,0 +1,288 @@ +import { DEBUG, EDITOR } from 'internal:constants'; +import { ccclass, editable, serializable, type, visible } from '../../../../../core/data/decorators'; +import { CLASS_NAME_PREFIX_ANIM } from '../../../../define'; +import { PoseTransformSpaceRequirement } from '../../pose-node'; +import { approx, assertIsTrue, ccenum, Quat, Vec3 } from '../../../../../core'; +import { TransformHandle } from '../../../../core/animation-handle'; +import { input } from '../../decorator/input'; +import { poseGraphNodeCategory } from '../../decorator/node'; +import { Pose } from '../../../../core/pose'; +import { PoseNodeModifyPoseBase, TransformModificationQueue } from '../modify-pose-base'; +import { Transform } from '../../../../core/transform'; +import { AnimationGraphBindingContext, AnimationGraphEvaluationContext } from '../../../animation-graph-context'; +import { PoseGraphType } from '../../foundation/type-system'; +import { TransformSpace } from '../transform-space'; +import { POSE_GRAPH_NODE_MENU_PREFIX_IK } from './menu'; +import { getDebugger } from './look-at-debugging'; + +const cacheBoneTransform = new Transform(); +const cacheTargetPosition = new Vec3(); +const cacheTransform_evaluateTarget = new Transform(); +const cacheForwardAxisTransformed = new Vec3(); +const cacheRefUpAxisTransformed = new Vec3(); +const cacheLookAtRotation = new Quat(); + +export enum TargetSpecificationType { + /** + * Targets nothing. + */ + NONE, + + /** + * Targets the specified vector value. + */ + VALUE, + + /** + * Targets the specified bone. + */ + BONE, +} + +ccenum(TargetSpecificationType); + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PoseNodeLookAt.TargetSpecification`) +class TargetSpecification { + constructor (type?: TargetSpecificationType) { + if (typeof type !== 'undefined') { + this.type = type; + } + } + + @serializable + @editable + @type(TargetSpecificationType) + public type = TargetSpecificationType.VALUE; + + @serializable + @editable + @visible(function visible (this: TargetSpecification) { return this.type === TargetSpecificationType.VALUE; }) + public targetPosition = new Vec3(); + + @serializable + @editable + @type(TransformSpace) + @visible(function visible (this: TargetSpecification) { return this.type === TargetSpecificationType.VALUE; }) + public targetPositionSpace = TransformSpace.WORLD; + + @serializable + @editable + @visible(function visible (this: TargetSpecification) { return this.type === TargetSpecificationType.BONE; }) + public targetBone = ''; + + public bind (context: AnimationGraphBindingContext, sourceBoneHandle: TransformHandle): void { + this._sourceBoneHandle = sourceBoneHandle; + if (this.type === TargetSpecificationType.BONE && this.targetBone) { + this._targetBoneHandle = context.bindTransformByName(this.targetBone) ?? undefined; + } + } + + public evaluate (outTargetPosition: Vec3, pose: Pose, context: AnimationGraphEvaluationContext): Vec3 { + assertIsTrue(this._sourceBoneHandle); + if (this._targetBoneHandle) { + pose.transforms.getPosition(this._targetBoneHandle.index, outTargetPosition); + } else if (this.type === TargetSpecificationType.NONE) { + pose.transforms.getPosition(this._sourceBoneHandle.index, outTargetPosition); + } else { + const targetTransform = Transform.setIdentity(cacheTransform_evaluateTarget); + targetTransform.position = this.targetPosition; + context._convertTransformToPoseTransformSpace( + targetTransform, + this.targetPositionSpace, + pose, + this._sourceBoneHandle.index, + ); + Vec3.copy(outTargetPosition, targetTransform.position); + } + return outTargetPosition; + } + + private _sourceBoneHandle: TransformHandle | undefined = undefined; + private _targetBoneHandle: TransformHandle | undefined = undefined; +} + +@ccclass(`${CLASS_NAME_PREFIX_ANIM}PoseNodeLookAt`) +@poseGraphNodeCategory(POSE_GRAPH_NODE_MENU_PREFIX_IK) +export class PoseNodeLookAt extends PoseNodeModifyPoseBase { + @serializable + @editable + public debug = false; + + @serializable + @editable + public boneName = ''; + + @serializable + @editable + public readonly target = new TargetSpecification(TargetSpecificationType.VALUE); + + @serializable + @editable + public readonly forwardAxis = new Vec3(0, 0, 1); + + @serializable + @editable + public readonly referenceUpAxis = new Vec3(0, 1, 0); + + @input({ type: PoseGraphType.VEC3 }) + @visible(function visible (this: PoseNodeLookAt) { return this.target.type === TargetSpecificationType.VALUE; }) + get targetPosition (): Readonly { + return this.target.targetPosition; + } + + set targetPosition (value) { + Vec3.copy(this.target.targetPosition, value); + } + + public bind (context: AnimationGraphBindingContext): void { + super.bind(context); + if (!this.boneName) { + return; + } + const hBone = context.bindTransformByName(this.boneName); + if (!hBone) { + return; + } + this.target.bind(context, hBone); + this._workspace = new Workspace(hBone); + } + + protected getPoseTransformSpaceRequirement (): PoseTransformSpaceRequirement { + return PoseTransformSpaceRequirement.COMPONENT; + } + + protected modifyPose (context: AnimationGraphEvaluationContext, inputPose: Pose, modificationQueue: TransformModificationQueue): void { + const { + _workspace: workspace, + } = this; + + if (!workspace) { + return; + } + + const { + hBone: { index: boneIndex }, + } = workspace; + + // Fetch transforms. + const boneTransform = inputPose.transforms.getTransform(boneIndex, cacheBoneTransform); + + const targetPosition = this.target.evaluate(cacheTargetPosition, inputPose, context); + const forwardAxisTransformed = Vec3.transformQuat(cacheForwardAxisTransformed, this.forwardAxis, boneTransform.rotation); + const refUpAxisTransformed = Vec3.transformQuat(cacheRefUpAxisTransformed, this.referenceUpAxis, boneTransform.rotation); + + if (DEBUG && this.debug) { + getDebugger(this)?.drawInputs( + context, + boneTransform, + targetPosition, + forwardAxisTransformed, + refUpAxisTransformed, + ); + } + + // Solve. + const lookAtRotation = solveLookAt( + boneTransform.position, + forwardAxisTransformed, + refUpAxisTransformed, + targetPosition, + cacheLookAtRotation, + ); + Quat.multiply(lookAtRotation, lookAtRotation, boneTransform.rotation); + boneTransform.rotation = lookAtRotation; + + if (DEBUG && this.debug) { + getDebugger(this)?.drawResult(boneTransform); + } + + modificationQueue.push(boneIndex, boneTransform); + } + + private _workspace: Workspace | undefined = undefined; +} + +if (EDITOR) { + PoseNodeLookAt.prototype.getTitle = function getTitle (this: PoseNodeLookAt): ReturnType> { + if (this.boneName) { + return [`ENGINE.classes.${CLASS_NAME_PREFIX_ANIM}PoseNodeLookAt.title`, { + boneName: this.boneName, + }]; + } + return undefined; + }; +} + +class Workspace { + constructor ( + public hBone: TransformHandle, + ) { + } +} + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +const solveLookAt = (() => { + const cacheDesiredForward = new Vec3(); + const cacheInputUp = new Vec3(); + const cacheDesiredUp = new Vec3(); + const cacheSwingedUp = new Vec3(); + const cacheSwing = new Quat(); + const cacheTwist = new Quat(); + + function normalizeIfNotZero (v: Vec3, threshold = 1e-5): boolean { + const len = Vec3.len(v); + if (len < threshold) { + return false; + } else { + Vec3.multiplyScalar(v, v, 1.0 / len); + return true; + } + } + + // eslint-disable-next-line @typescript-eslint/explicit-function-return-type + const calculateRealUp = (() => { + const cacheRight = new Vec3(); + return (out: Vec3, forward: Readonly, referenceUp: Readonly): boolean => { + const right = Vec3.cross(cacheRight, referenceUp, forward); + if (!normalizeIfNotZero(right)) { + return false; + } else { + Vec3.cross(out, forward, right); + Vec3.normalize(out, out); + return true; + } + }; + })(); + + return ( + position: Readonly, + forward: Readonly, + referenceUp: Readonly, + targetPosition: Readonly, + out: Quat, + ): Quat => { + const desiredForward = Vec3.subtract(cacheDesiredForward, targetPosition, position); + if (!normalizeIfNotZero(desiredForward)) { + // Target is overlapped with us. + return Quat.identity(out); + } + + const swing = Quat.rotationTo(cacheSwing, forward, desiredForward); + + // If desired forward or input forward is colinear with reference up. + // We can not deduce either of the "true up vectors". + // So swing only. + const inputUp = cacheInputUp; + if (!calculateRealUp(inputUp, forward, referenceUp)) { + return Quat.copy(out, swing); + } + const desiredUp = cacheDesiredUp; + if (!calculateRealUp(desiredUp, desiredForward, referenceUp)) { + return Quat.copy(out, swing); + } + + const swingedUp = Vec3.transformQuat(cacheSwingedUp, inputUp, swing); + const twist = Quat.rotationTo(cacheTwist, swingedUp, desiredUp); + return Quat.multiply(out, twist, swing); + }; +})(); diff --git a/editor/i18n/zh/animation.js b/editor/i18n/zh/animation.js index 63aa87fe022..1c6b1a49f1c 100644 --- a/editor/i18n/zh/animation.js +++ b/editor/i18n/zh/animation.js @@ -337,6 +337,52 @@ module.exports = { }, }, }, + 'PoseNodeLookAt': { + displayName: '看向', + title: '{boneName} 看向目标', + properties: { + 'boneName': { + displayName: '骨骼', + tooltip: '进行追随的骨骼的名称。', + }, + 'target': { + displayName: '目标', + tooltip: '看向目标。', + }, + 'forwardAxis': { + displayName: '前向轴', + }, + 'referenceUpAxis': { + displayName: '参考向上轴', + }, + }, + inputs: { + __extends__: 'classes.cc.animation.PoseNodeModifyPoseBase.inputs', + 'targetPosition': { + displayName: '目标位置', + }, + }, + 'TargetSpecification': { + properties: { + 'type': { + displayName: '类型', + tooltip: '目标类型。', + }, + 'targetPosition': { + displayName: '目标位置', + tooltip: '目标位置。', + }, + 'targetPositionSpace': { + displayName: '目标位置空间', + tooltip: '目标位置的空间。', + }, + 'targetBone': { + displayName: '目标骨骼', + tooltip: '目标骨骼的名称。', + }, + }, + }, + }, 'PoseNodeGetAllPreviousLayersResult': { displayName: '前序所有层级结果', }, From bc479c126be7767d5e2c785c1b8b852e4719f367 Mon Sep 17 00:00:00 2001 From: Leslie Leigh Date: Fri, 14 Jul 2023 10:52:03 +0800 Subject: [PATCH 182/184] Apply lint --- .../marionette/pose-graph/pose-nodes/modify-pose-base.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cocos/animation/marionette/pose-graph/pose-nodes/modify-pose-base.ts b/cocos/animation/marionette/pose-graph/pose-nodes/modify-pose-base.ts index c2ff4ed7b70..ed1083663a5 100644 --- a/cocos/animation/marionette/pose-graph/pose-nodes/modify-pose-base.ts +++ b/cocos/animation/marionette/pose-graph/pose-nodes/modify-pose-base.ts @@ -5,7 +5,10 @@ import { PoseNode, PoseTransformSpaceRequirement } from '../pose-node'; import { input } from '../decorator/input'; import { poseGraphNodeHide } from '../decorator/node'; import { Pose, PoseTransformSpace } from '../../../core/pose'; -import { AnimationGraphBindingContext, AnimationGraphEvaluationContext, AnimationGraphSettleContext, AnimationGraphUpdateContext } from '../../animation-graph-context'; +import { + AnimationGraphBindingContext, AnimationGraphEvaluationContext, + AnimationGraphSettleContext, AnimationGraphUpdateContext, +} from '../../animation-graph-context'; import { PoseGraphType } from '../foundation/type-system'; import { assertIsTrue, CachedArray, Pool } from '../../../../core'; import { Transform } from '../../../core/transform'; From 997d17e249a0e842e62a9e94e0d909fab4b20012 Mon Sep 17 00:00:00 2001 From: shrinktofit Date: Fri, 30 Jun 2023 14:14:52 +0800 Subject: [PATCH 183/184] Pose graph gizmo ed --- editor/exports/new-gen-anim.ts | 2 + .../src/marionette/pose-graph/gizmo/common.ts | 72 +++++++++++++++++ .../src/marionette/pose-graph/gizmo/gizmo.ts | 81 +++++++++++++++++++ .../src/marionette/pose-graph/gizmo/index.ts | 8 ++ .../pose-graph/gizmo/pose-nodes/look-at.ts | 25 ++++++ 5 files changed, 188 insertions(+) create mode 100644 editor/src/marionette/pose-graph/gizmo/common.ts create mode 100644 editor/src/marionette/pose-graph/gizmo/gizmo.ts create mode 100644 editor/src/marionette/pose-graph/gizmo/index.ts create mode 100644 editor/src/marionette/pose-graph/gizmo/pose-nodes/look-at.ts diff --git a/editor/exports/new-gen-anim.ts b/editor/exports/new-gen-anim.ts index 277ea320e9f..c5e62f5db65 100644 --- a/editor/exports/new-gen-anim.ts +++ b/editor/exports/new-gen-anim.ts @@ -45,3 +45,5 @@ export { } from '../src/marionette/get-variable-value-attributes'; export * from '../src/marionette/pose-graph-editor-api'; + +export * from '../src/marionette/pose-graph/gizmo'; diff --git a/editor/src/marionette/pose-graph/gizmo/common.ts b/editor/src/marionette/pose-graph/gizmo/common.ts new file mode 100644 index 00000000000..654259b770d --- /dev/null +++ b/editor/src/marionette/pose-graph/gizmo/common.ts @@ -0,0 +1,72 @@ +import { PoseGraphNode } from "../../../../../cocos/animation/marionette/pose-graph/foundation/pose-graph-node"; +import { GeometryRenderer } from "../../../../../cocos/rendering/geometry-renderer"; +import { assertIsTrue, geometry, Node } from "../../../../../exports/base"; + +export interface PoseGraphNodeGizmoContext { + geometryRenderer: GeometryRenderer; + findNodeByName(name: string): Node | undefined; + getSkeletonBounds(): geometry.AABB; +} + +export class PoseGraphNodeGizmo { + constructor() { + + } + + public destroy() { + assertIsTrue(!this._target); + this.onDestroy(); + } + + public attach(target: TNode) { + assertIsTrue(!this._target); + this._target = target; + this.onTargetAttached(); + } + + public detach() { + assertIsTrue(this._target); + this.onTargetDetached(); + this._target = undefined; + } + + public draw(context: PoseGraphNodeGizmoContext) { + assertIsTrue(this._target); + this.onDraw(context); + } + + private _target: TNode | undefined = undefined; + + protected get target() { + assertIsTrue(this._target); + return this._target; + } + + protected onDestroy() { } + + protected onTargetAttached() { } + + protected onTargetDetached() { } + + protected onDraw(context: PoseGraphNodeGizmoContext) { } +} + +type PoseGraphNodeConstructor = new (...args: any[]) => PoseGraphNode; + +const poseGraphNodeGizmoRegistry = new WeakMap PoseGraphNodeGizmo>(); + +export function registerPoseGraphNodeGizmo( + nodeConstructor: PoseGraphNodeConstructor, + gizmoConstructor: new () => PoseGraphNodeGizmo, +) { + poseGraphNodeGizmoRegistry.set(nodeConstructor, gizmoConstructor); +} + +export function getPoseGraphNodeGizmoConstructor(node: PoseGraphNode) { + const nodeConstructor = node.constructor; + if (typeof nodeConstructor !== 'function') { + return; + } + const gizmoConstructor = poseGraphNodeGizmoRegistry.get(nodeConstructor as PoseGraphNodeConstructor); + return gizmoConstructor; +} diff --git a/editor/src/marionette/pose-graph/gizmo/gizmo.ts b/editor/src/marionette/pose-graph/gizmo/gizmo.ts new file mode 100644 index 00000000000..f5f4b2b1223 --- /dev/null +++ b/editor/src/marionette/pose-graph/gizmo/gizmo.ts @@ -0,0 +1,81 @@ +import { AnimationController } from "../../../../../cocos/animation/marionette/animation-controller"; +import { PoseGraphNode } from "../../../../../cocos/animation/marionette/pose-graph/foundation/pose-graph-node"; +import { GeometryRenderer } from "../../../../../cocos/rendering/geometry-renderer"; +import { assertIsTrue, geometry, Node } from "../../../../../exports/base"; +import { getPoseGraphNodeGizmoConstructor, PoseGraphNodeGizmo, PoseGraphNodeGizmoContext } from "./common"; + +class PoseGraphNodeGizmoContextImpl implements PoseGraphNodeGizmoContext { + get valid() { + return !!this._geometryRenderer; + } + + get geometryRenderer(): GeometryRenderer { + assertIsTrue(this._geometryRenderer); + return this._geometryRenderer; + } + + public findNodeByName(name: string): Node | undefined { + assertIsTrue(this._origin); + return undefined; + } + + public getSkeletonBounds(): geometry.AABB { + return new geometry.AABB(); + } + + private _origin: Node | undefined; + private _geometryRenderer: GeometryRenderer | undefined; +} + +export class PoseGraphSceneGizmo { + public attach(controller: AnimationController) { + assertIsTrue(!this._animationController); + this._animationController = controller; + } + + public detach() { + this._inactivateCurrent(); + } + + public update() { + this._activatedGizmo?.draw(this._context); + } + + public notifyNodeSelected(node: PoseGraphNode) { + this._inactivateCurrent(); + const nodeGizmo = this._selectNodeGizmo(node); + if (!nodeGizmo) { + return; + } + nodeGizmo.attach(node); + this._activatedGizmo = nodeGizmo; + } + + private _animationController: AnimationController; + private _context: PoseGraphNodeGizmoContextImpl = new PoseGraphNodeGizmoContextImpl(); + private _nodeGizmos: PoseGraphNodeGizmo[] = []; + private _activatedGizmo: PoseGraphNodeGizmo | undefined = undefined; + + private _inactivateCurrent() { + if (!this._activatedGizmo) { + return; + } + this._activatedGizmo.detach(); + this._activatedGizmo = undefined; + } + + private _selectNodeGizmo(node: PoseGraphNode): PoseGraphNodeGizmo | undefined { + const gizmoConstructor = getPoseGraphNodeGizmoConstructor(node); + if (!gizmoConstructor) { + return; + } + for (const instance of this._nodeGizmos) { + if (instance instanceof gizmoConstructor) { + return instance; + } + } + const gizmoInstance = new gizmoConstructor(); + this._nodeGizmos.push(gizmoInstance); + return gizmoInstance; + } +} diff --git a/editor/src/marionette/pose-graph/gizmo/index.ts b/editor/src/marionette/pose-graph/gizmo/index.ts new file mode 100644 index 00000000000..b2091a8b8e3 --- /dev/null +++ b/editor/src/marionette/pose-graph/gizmo/index.ts @@ -0,0 +1,8 @@ + +export { + PoseGraphSceneGizmo, +} from './gizmo'; + +import './pose-nodes/look-at'; + +export {}; diff --git a/editor/src/marionette/pose-graph/gizmo/pose-nodes/look-at.ts b/editor/src/marionette/pose-graph/gizmo/pose-nodes/look-at.ts new file mode 100644 index 00000000000..d097380d2b8 --- /dev/null +++ b/editor/src/marionette/pose-graph/gizmo/pose-nodes/look-at.ts @@ -0,0 +1,25 @@ + +import { PoseNodeLookAt } from '../../../../../../cocos/animation/marionette/pose-graph/pose-nodes/ik/look-at'; +import { AABB } from '../../../../../../cocos/core/geometry'; +import { Color, Mat4 } from '../../../../../../exports/base'; +import { PoseGraphNodeGizmo, PoseGraphNodeGizmoContext, registerPoseGraphNodeGizmo } from '../common'; + +class PoseNodeLookAtGizmo extends PoseGraphNodeGizmo { + protected onDraw(context: PoseGraphNodeGizmoContext) { + const boneNode = context.findNodeByName(this.target.boneName); + if (!boneNode) { + return; + } + context.geometryRenderer.addBoundingBox( + new AABB(boneNode.worldPosition.x, boneNode.worldPosition.y, boneNode.worldPosition.z), + Color.WHITE, + true, + undefined, + undefined, + true, + Mat4.fromQuat(new Mat4(), boneNode.worldRotation), + ); + } +} + +registerPoseGraphNodeGizmo(PoseNodeLookAt, PoseNodeLookAtGizmo); From 088cf4b729481d147c9faa553b6262caf3d054f2 Mon Sep 17 00:00:00 2001 From: shrinktofit Date: Mon, 14 Aug 2023 15:48:57 +0800 Subject: [PATCH 184/184] CCON pack --- cocos/asset/asset-manager/config.ts | 14 ++- cocos/asset/asset-manager/downloader.ts | 8 +- cocos/asset/asset-manager/pack-manager.ts | 11 +- cocos/serialization/compiled/typed-array.ts | 129 ++++++++++++++++++++ cocos/serialization/deserialize.ts | 114 ++++++++++++++++- editor/exports/serialization.ts | 8 ++ 6 files changed, 268 insertions(+), 16 deletions(-) create mode 100644 cocos/serialization/compiled/typed-array.ts diff --git a/cocos/asset/asset-manager/config.ts b/cocos/asset/asset-manager/config.ts index 1a4a0899332..88d32f0a44c 100644 --- a/cocos/asset/asset-manager/config.ts +++ b/cocos/asset/asset-manager/config.ts @@ -253,7 +253,7 @@ export default class Config { this._initUuid(options.uuids); this._initPath(options.paths); this._initScene(options.scenes); - this._initPackage(options.packs); + this._initPackage(options.packs, options.extensionMap); this._initVersion(options.versions); this._initRedirect(options.redirect); for (const ext in options.extensionMap) { @@ -382,12 +382,20 @@ export default class Config { } } - private _initPackage (packageList: Record): void { + private _initPackage (packageList: Record, extensionMap: IConfigOption['extensionMap']): void { if (!packageList) { return; } const assetInfos = this.assetInfos; for (const packUuid in packageList) { const uuids = packageList[packUuid]; - const pack = { uuid: packUuid, packedUuids: uuids, ext: '.json' }; + let mappedExtension = '.json'; + for (const ext in extensionMap) { + const mappedUUIDs = extensionMap[ext]; + if (mappedUUIDs.includes(packUuid)) { + mappedExtension = ext; + break; + } + } + const pack = { uuid: packUuid, packedUuids: uuids, ext: mappedExtension }; assetInfos.add(packUuid, pack); for (let i = 0, l = uuids.length; i < l; i++) { diff --git a/cocos/asset/asset-manager/downloader.ts b/cocos/asset/asset-manager/downloader.ts index fa87cb3fac9..0eeb8240905 100644 --- a/cocos/asset/asset-manager/downloader.ts +++ b/cocos/asset/asset-manager/downloader.ts @@ -68,14 +68,15 @@ const downloadArrayBuffer = (url: string, options: Record, onComple }; const downloadCCON = (url: string, options: Record, onComplete: ((err: Error | null, data?: CCON | null) => void)): void => { - downloader._downloadJson(url, options, (err, json): void => { + const mainFileName = path.mainFileName(url); + downloader._downloadJson(`${mainFileName}.json`, options, (err, json): void => { if (err) { onComplete(err); return; } const cconPreface = parseCCONJson(json); const chunkPromises = Promise.all(cconPreface.chunks.map((chunk): Promise => new Promise((resolve, reject): void => { - downloader._downloadArrayBuffer(`${path.mainFileName(url)}${chunk}`, {}, (errChunk, chunkBuffer: ArrayBuffer): void => { + downloader._downloadArrayBuffer(`${mainFileName}${chunk}`, {}, (errChunk, chunkBuffer: ArrayBuffer): void => { if (err) { reject(err); } else { @@ -93,7 +94,8 @@ const downloadCCON = (url: string, options: Record, onComplete: ((e }; const downloadCCONB = (url: string, options: Record, onComplete: ((err: Error | null, data?: CCON | null) => void)): void => { - downloader._downloadArrayBuffer(url, options, (err, arrayBuffer: ArrayBuffer): void => { + const mainFileName = path.mainFileName(url); + downloader._downloadArrayBuffer(`${mainFileName}.cconb`, options, (err, arrayBuffer: ArrayBuffer): void => { if (err) { onComplete(err); return; diff --git a/cocos/asset/asset-manager/pack-manager.ts b/cocos/asset/asset-manager/pack-manager.ts index cab8fbc8aa7..d70fc0aeea2 100644 --- a/cocos/asset/asset-manager/pack-manager.ts +++ b/cocos/asset/asset-manager/pack-manager.ts @@ -24,7 +24,7 @@ import { ImageAsset } from '../assets/image-asset'; import { Texture2D } from '../assets/texture-2d'; -import { packCustomObjData, unpackJSONs } from '../../serialization/deserialize'; +import { isGeneralPurposePack, packCustomObjData, unpackJSONs } from '../../serialization/deserialize'; import { assertIsTrue, error, errorID, js } from '../../core'; import Cache from './cache'; import downloader from './downloader'; @@ -56,6 +56,7 @@ export class PackManager { private _loading = new Cache(); private _unpackers: Record = { '.json': this.unpackJson, + '.ccon': this.unpackJson, }; /** @@ -87,14 +88,14 @@ export class PackManager { const out: Record = js.createMap(true); let err: Error | null = null; - if (Array.isArray(json)) { - json = unpackJSONs(json as unknown as Parameters[0]); + if (isGeneralPurposePack(json)) { + const unpacked = unpackJSONs(json); - if (json.length !== pack.length) { + if (unpacked.length !== pack.length) { errorID(4915); } for (let i = 0; i < pack.length; i++) { - out[`${pack[i]}@import`] = json[i]; + out[`${pack[i]}@import`] = unpacked[i]; } } else { const textureType = js.getClassId(Texture2D); diff --git a/cocos/serialization/compiled/typed-array.ts b/cocos/serialization/compiled/typed-array.ts new file mode 100644 index 00000000000..efa5ac94d23 --- /dev/null +++ b/cocos/serialization/compiled/typed-array.ts @@ -0,0 +1,129 @@ +import { assertIsTrue, sys } from '../../core'; +import { IRuntimeFileData } from '../deserialize'; + +assertIsTrue(sys.isLittleEndian, `Deserialization system currently suppose little endian.`); + +export const typedArrayTypeTable = Object.freeze([ + Float32Array, + Float64Array, + + Int8Array, + Int16Array, + Int32Array, + + Uint8Array, + Uint16Array, + Uint32Array, + + Uint8ClampedArray, + // BigInt64Array, + // BigUint64Array, +] as const); + +/** + * Describes the serialized data of an typed array. + * - If it's an array, it's `TypedArrayDataJson`. + * - Otherwise, it's `TypedArrayDataPtr`. + */ +export type TypedArrayData = TypedArrayDataJson | TypedArrayDataPtr; + +export type TypedArrayDataJson = [ + /** + * Indicates the constructor of typed array. + * It's index of the constructor in `TypedArrays`. + */ + typeIndex: number, + + /** + * Array element values. + */ + elements: number[], +]; + +/** + * Let `offset` be this value, + * Let `storage` be the binary buffer attached to the deserialized document. + * Then, the data of `storage` started from `offset` + * can be described using the following structure(in C++, assuming fields are packed tightly): + * + * ```cpp + * struct _ { + * /// Indicates the constructor of typed array. + * /// It's index of the constructor in `typedArrayTypeTable`. + * std::uint32_t typeIndex; + * + * /// The typed array's element count. Note this is not "byte length". + * std:: uint32_t length; + * + * /// Automatically padding bytes to align the `arrayBufferBytes`. + * /// See comments on `arrayBufferBytes`. + * std::byte[] _padding; + * + * /// Bytes of the underlying `ArrayBuffer` of this typed array. + * /// Should be aligned to `typedArrayConstructor.BYTES_PER_ELEMENT` + * /// according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray#bytelength_must_be_aligned. + * std::byte[] arrayBufferBytes; + * } + * ``` + */ +export type TypedArrayDataPtr = number; + +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +function getTypedArrayConstructor (typeIndex: number) { + assertIsTrue(typeIndex >= 0 && typeIndex < typedArrayTypeTable.length); + return typedArrayTypeTable[typeIndex]; +} + +function calculatePaddingToAlignAs (v: number, align: number): number { + if (align === 0) { + return 0; + } + const remainder = v % align; + if (remainder !== 0) { + return align - remainder; + } + return 0; +} + +function decodeTypedArray (data: IRuntimeFileData, value: TypedArrayData): ArrayBufferView { + if (Array.isArray(value)) { + const [typeIndex, elements] = value; + const TypedArrayConstructor = getTypedArrayConstructor(typeIndex); + return new TypedArrayConstructor(elements); + } else { + const context = data[0]; + const attachedBinary = context._attachedBinary; + assertIsTrue(attachedBinary, `Incorrect data: binary is expected.`); + const dataView = (context._attachedBinaryDataViewCache + ??= new DataView(attachedBinary.buffer, attachedBinary.byteOffset, attachedBinary.byteLength)); + + let p = value; + const header = dataView.getUint32(p, true); + p += 4; + const length = dataView.getUint32(p, true); + p += 4; + + const typeIndex = header & 0xFF; + const TypedArrayConstructor = getTypedArrayConstructor(typeIndex); + + // The elements must be padded. + p += calculatePaddingToAlignAs(p + attachedBinary.byteOffset, TypedArrayConstructor.BYTES_PER_ELEMENT); + + // Copy the section: + // - Allocates the result. + // - Creates a view on big buffer. + // - Copy using `TypedArray.prototype.set`. + // This manner do not consider the endianness problem. + // + // Here listed the benchmark in various other ways: + // https://jsperf.app/vayeri/2/preview + // + const result = new TypedArrayConstructor(length); + result.set(new TypedArrayConstructor(attachedBinary.buffer, attachedBinary.byteOffset + p, length)); + return result; + } +} + +export function deserializeTypedArray (data: IRuntimeFileData, owner: any, key: string, value: TypedArrayData): void { + owner[key] = decodeTypedArray(data, value); +} diff --git a/cocos/serialization/deserialize.ts b/cocos/serialization/deserialize.ts index 8f88ae4091a..b397a316674 100644 --- a/cocos/serialization/deserialize.ts +++ b/cocos/serialization/deserialize.ts @@ -28,7 +28,9 @@ import { cclegacy, errorID, getError, js, assertIsTrue } from '../core'; import { deserializeDynamic, DeserializeDynamicOptions, parseUuidDependenciesDynamic } from './deserialize-dynamic'; import { Asset } from '../asset/assets/asset'; +import { CCON } from './ccon'; import type { CompiledDeserializeFn } from './deserialize-dynamic'; +import { deserializeTypedArray, TypedArrayData } from './compiled/typed-array'; import { reportMissingClass as defaultReportMissingClass } from './report-missing-class'; @@ -124,6 +126,12 @@ const enum DataTypeID { // Common TypedArray for legacyCC.Node only. Never be null. TRS, + // From the point of view of simplified implementation, + // it is not supported to deserialize TypedArray that is initialized to null in the constructor. + // Also, the length of TypedArray cannot be changed. + // Developers will rarely manually assign a null. + TypedArray, + // ValueType without default value (in arrays, dictionaries). // Developers will rarely manually assign a null. ValueType, @@ -158,6 +166,7 @@ interface DataTypes { [DataTypeID.ValueTypeCreated]: IValueTypeData; [DataTypeID.AssetRefByInnerObj]: number; [DataTypeID.TRS]: ITRSData; + [DataTypeID.TypedArray]: TypedArrayData; [DataTypeID.ValueType]: IValueTypeData; [DataTypeID.Array_Class]: DataTypes[DataTypeID.Class][]; [DataTypeID.CustomizedClass]: ICustomObjectData; @@ -297,6 +306,7 @@ export declare namespace deserialize.Internal { export type ITRSData_ = ITRSData; export type IDictData_ = IDictData; export type IArrayData_ = IArrayData; + export type ITypedArrayData_ = TypedArrayData; } const enum Refs { @@ -339,6 +349,9 @@ const enum File { DependUuidIndices, ARRAY_LENGTH, + + RUNTIME_BEGIN = ARRAY_LENGTH, + BinaryStorage_runtime = RUNTIME_BEGIN, } // Main file structure @@ -379,6 +392,11 @@ type IFileData = MapEnum<{ type IRuntimeFileDataMap = Omit & { [File.Context]: FileInfo & DeserializeContext; + + /** + * The binary storage attached to this document. + */ + [File.BinaryStorage_runtime]: Uint8Array | undefined; } /** @@ -386,7 +404,7 @@ type IRuntimeFileDataMap = Omit & { */ export type IRuntimeFileData = MapEnum<{ [x in keyof IRuntimeFileDataMap as `${x}`]: IRuntimeFileDataMap[x]; -}, 11 /* Currently we should manually specify the enumerators count. */>; +}, 12 /* Currently we should manually specify the enumerators count. */>; type IDeserializeInput = IFileData | IRuntimeFileData; @@ -394,8 +412,15 @@ type ISharedData = TupleSlice; type IPackedFileSection = [ ...document: TupleSlice, + + /** + * This section's binary storage span into packed binary buffer. + */ + binaryStorage: [byteOffset: number, byteLength: number] | Empty, ]; +const PACKED_SECTION_BINARY_STORAGE_INDEX = 6; + const PACKED_SECTIONS = File.Instances; type IPackedFileData = [ @@ -423,6 +448,8 @@ type ClassFinder = deserialize.ClassFinder; interface DeserializeContext extends ICustomHandler { _version?: number; + _attachedBinary?: Uint8Array; + _attachedBinaryDataViewCache?: DataView; } interface IOptions extends Partial { @@ -723,11 +750,13 @@ ASSIGNMENTS[DataTypeID.Class] = parseClass; ASSIGNMENTS[DataTypeID.ValueTypeCreated] = deserializeBuiltinValueTypeInto; ASSIGNMENTS[DataTypeID.AssetRefByInnerObj] = parseAssetRefByInnerObj; ASSIGNMENTS[DataTypeID.TRS] = parseTRS; +ASSIGNMENTS[DataTypeID.TypedArray] = deserializeTypedArray; ASSIGNMENTS[DataTypeID.ValueType] = deserializeBuiltinValueType; ASSIGNMENTS[DataTypeID.Array_Class] = genArrayParser(parseClass); ASSIGNMENTS[DataTypeID.CustomizedClass] = parseCustomClass; ASSIGNMENTS[DataTypeID.Dict] = parseDict; ASSIGNMENTS[DataTypeID.Array] = parseArray; +ASSIGNMENTS[DataTypeID.TypedArray] = deserializeTypedArray; function parseInstances (data: IRuntimeFileData): RootInstanceIndex { const instances = data[File.Instances]; @@ -887,10 +916,21 @@ function parseResult (data: IRuntimeFileData): void { } export function isCompiledJson (json: unknown): boolean { + if (json instanceof CCON) { + // This is a very verbose check. + // Make sure we won't ran in infinite loop due to data error. + assertIsTrue(!(json.document instanceof CCON)); + return isCompiledJson(json.document); + } if (Array.isArray(json)) { const version = json[0]; // array[0] will not be a number in the editor version return typeof version === 'number' || version instanceof FileInfo; + } else if (json instanceof CCON) { + // This is a very verbose check. + // Make sure we won't ran in infinite loop due to data error. + assertIsTrue(!(json.document instanceof CCON)); + return isCompiledJson(json.document); } else { return false; } @@ -898,6 +938,7 @@ export function isCompiledJson (json: unknown): boolean { function initializeDeserializationContext( data: IDeserializeInput, + attachedBinary: Uint8Array | undefined, details: Details, options?: IOptions & DeserializeDynamicOptions, ) { @@ -918,6 +959,7 @@ function initializeDeserializationContext( const context = options as IRuntimeFileData[File.Context]; context._version = version; context.result = details; + context._attachedBinary = attachedBinary; data[File.Context] = context; if (!preprocessed) { @@ -935,7 +977,7 @@ function initializeDeserializationContext( * @param options Deserialization Options. * @return The original object. */ -export function deserialize (data: IDeserializeInput | string | any, details?: Details, options?: IOptions & DeserializeDynamicOptions): unknown { +export function deserialize (data: IDeserializeInput | string | CCON | any, details?: Details, options?: IOptions & DeserializeDynamicOptions): unknown { if (typeof data === 'string') { data = JSON.parse(data); } @@ -953,13 +995,27 @@ export function deserialize (data: IDeserializeInput | string | any, details?: D if (!FORCE_COMPILED && !isCompiledJson(data)) { res = deserializeDynamic(data, details, options); } else { + let input: IDeserializeInput; + let binary: Uint8Array | undefined = undefined; + if (data instanceof CCON) { + input = data.document as IDeserializeInput; + // Currently, a ccon should have only one chunk at most. + assertIsTrue(data.chunks.length === 1); + binary = data.chunks[0]; + } else { + input = data as IDeserializeInput; + binary = input[File.BinaryStorage_runtime]; + } + initializeDeserializationContext( - data, + input, + binary, details, options, ); - const runtimeData = data as IRuntimeFileData; + const runtimeData = input as IRuntimeFileData; + const context = runtimeData[File.Context]; cclegacy.game._isCloning = true; const instances = runtimeData[File.Instances]; @@ -973,6 +1029,12 @@ export function deserialize (data: IDeserializeInput | string | any, details?: D parseResult(runtimeData); res = instances[rootIndex]; + + // Clean up our injections. + { + context._attachedBinary = undefined; + context._attachedBinaryDataViewCache = undefined; + } } if (isBorrowedDetails) { @@ -1005,8 +1067,33 @@ class FileInfo { } } +export type GeneralPurposePack = IPackedFileData | CCON; + +/** + * Decides if the pack is a general-purpose pack. + * If true, it should be unpacked through `unpackJSONs`. + * @param data Pack data. + * @returns Unpacked contents, that's, a list of serialized objects. + */ +export function isGeneralPurposePack(data: unknown): data is GeneralPurposePack { + return Array.isArray(data) || data instanceof CCON; +} + export function unpackJSONs ( - data: IPackedFileData, classFinder?: ClassFinder, reportMissingClass?: deserialize.ReportMissingClass): IDeserializeInput[] { + input: GeneralPurposePack, + classFinder?: ClassFinder, + reportMissingClass?: deserialize.ReportMissingClass, +): IDeserializeInput[] { + let data: IPackedFileData; + let binaryChunk: Uint8Array | undefined = undefined; + if (input instanceof CCON) { + data = input.document as IPackedFileData; + assertIsTrue(input.chunks.length <= 1); + binaryChunk = input.chunks[0]; + } else { + data = input; + } + if (data[File.Version] < SUPPORT_MIN_FORMAT_VERSION) { throw new Error(getError(5304, data[File.Version])); } @@ -1022,7 +1109,23 @@ export function unpackJSONs ( const sections = data[PACKED_SECTIONS]; for (let i = 0; i < sections.length; ++i) { const section = sections[i]; + const binaryStorageSpan = section[PACKED_SECTION_BINARY_STORAGE_INDEX]; (section as any[]).unshift(version, sharedUuids, sharedStrings, sharedClasses, sharedMasks); + if (binaryStorageSpan !== EMPTY_PLACEHOLDER) { + if (!binaryChunk) { + // Bad data: there's section requiring binary storage but the incoming data didn't provide one. + throw new Error(`Bad data: there's section requiring binary storage but the incoming data didn't provide one`); + } + + const [byteOffset, byteLength] = binaryStorageSpan; + + // Note: we do copy here. + // The reason is, if we don't copy instead of directly reference, + // the reference prevents the `binaryChunk` from being gc. + const sliceStart = binaryChunk.byteOffset + byteOffset; + const copy = binaryChunk.buffer.slice(sliceStart, sliceStart + byteLength); + (section as unknown as IRuntimeFileData)[File.BinaryStorage_runtime] = new Uint8Array(copy); + } } return sections as unknown as IDeserializeInput[]; } @@ -1134,6 +1237,7 @@ if (TEST) { CustomizedClass: DataTypeID.CustomizedClass, Dict: DataTypeID.Dict, Array: DataTypeID.Array, + TypedArray: DataTypeID.TypedArray, }, unpackJSONs, }; diff --git a/editor/exports/serialization.ts b/editor/exports/serialization.ts index 00b297fa884..d85f950dc55 100644 --- a/editor/exports/serialization.ts +++ b/editor/exports/serialization.ts @@ -11,3 +11,11 @@ export { export { serializeBuiltinValueType, } from '../../cocos/serialization/compiled/builtin-value-type'; + +export { typedArrayTypeTable } from '../../cocos/serialization/compiled/typed-array'; + +export type { + TypedArrayData, + TypedArrayDataJson, + TypedArrayDataPtr, +} from '../../cocos/serialization/compiled/typed-array';