From d911fab570cdf522235900126d14e9b96b193fff Mon Sep 17 00:00:00 2001 From: KPal <48248865+kpal81xd@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:21:41 +0000 Subject: [PATCH 1/9] Example build fixes (#7083) * Converted example scripts and rollup to using arrow functions * Build examples in same process as rollup plugin --- examples/package.json | 7 +- examples/rollup.config.js | 94 +++++++++---------- ...standalone-html.mjs => build-examples.mjs} | 16 ++-- .../{metadata.mjs => build-metadata.mjs} | 4 +- .../{sharing-html.mjs => build-sharing.mjs} | 8 +- .../{thumbnails.mjs => build-thumbnails.mjs} | 22 ++--- examples/scripts/clean.mjs | 4 +- examples/scripts/utils.mjs | 30 ++++-- ...andalone.mjs => rollup-build-examples.mjs} | 16 ++-- 9 files changed, 103 insertions(+), 98 deletions(-) rename examples/scripts/{standalone-html.mjs => build-examples.mjs} (91%) rename examples/scripts/{metadata.mjs => build-metadata.mjs} (98%) rename examples/scripts/{sharing-html.mjs => build-sharing.mjs} (95%) rename examples/scripts/{thumbnails.mjs => build-thumbnails.mjs} (95%) rename examples/utils/plugins/{rollup-generate-standalone.mjs => rollup-build-examples.mjs} (53%) diff --git a/examples/package.json b/examples/package.json index 7e2ef212572..437bc43224d 100644 --- a/examples/package.json +++ b/examples/package.json @@ -7,10 +7,9 @@ "scripts": { "build": "npm run -s build:pre && cross-env NODE_ENV=production rollup -c", "build:pre": "npm run -s build:metadata && npm run -s build:sharing", - "build:metadata": "node ./scripts/metadata.mjs", - "build:sharing": "node ./scripts/sharing-html.mjs", - "build:standalone": "node ./scripts/standalone-html.mjs", - "build:thumbnails": "node ./scripts/thumbnails.mjs", + "build:metadata": "node ./scripts/build-metadata.mjs", + "build:sharing": "node ./scripts/build-sharing.mjs", + "build:thumbnails": "node ./scripts/build-thumbnails.mjs", "clean": "node ./scripts/clean.mjs", "develop": "cross-env NODE_ENV=development concurrently --kill-others \"npm run watch\" \"npm run serve\"", "lint": "eslint --ext .js,.mjs .", diff --git a/examples/rollup.config.js b/examples/rollup.config.js index cbb117d4122..22e1974c717 100644 --- a/examples/rollup.config.js +++ b/examples/rollup.config.js @@ -10,7 +10,7 @@ import terser from '@rollup/plugin-terser'; // custom plugins import { copyStatic } from './utils/plugins/rollup-copy-static.mjs'; -import { generateStandalone } from './utils/plugins/rollup-generate-standalone.mjs'; +import { buildExamples } from './utils/plugins/rollup-build-examples.mjs'; // engine rollup utils import { treeshakeIgnore } from '../utils/plugins/rollup-treeshake-ignore.mjs'; @@ -23,46 +23,7 @@ const NODE_ENV = process.env.NODE_ENV ?? ''; const ENGINE_PATH = !process.env.ENGINE_PATH && NODE_ENV === 'development' ? '../src/index.js' : process.env.ENGINE_PATH ?? ''; -const STATIC_FILES = [ - // static main page src - { src: './src/static', dest: 'dist/' }, - - // static iframe src - { src: './iframe', dest: 'dist/iframe' }, - - // assets used in examples - { src: './assets', dest: 'dist/static/assets/', once: true }, - - // thumbnails used in examples - { src: './thumbnails', dest: 'dist/thumbnails/', once: true }, - - // external libraries used in examples - { src: './src/lib', dest: 'dist/static/lib/', once: true }, - - // engine scripts - { src: '../scripts', dest: 'dist/static/scripts/' }, - - // playcanvas engine types - { src: '../build/playcanvas.d.ts', dest: 'dist/playcanvas.d.ts' }, - - // playcanvas observer - { - src: './node_modules/@playcanvas/observer/dist/index.mjs', - dest: 'dist/iframe/playcanvas-observer.mjs', - once: true - }, - - // modules (N.B. destination folder is 'modules' as 'node_modules' are automatically excluded by git pages) - { src: './node_modules/monaco-editor/min/vs', dest: 'dist/modules/monaco-editor/min/vs', once: true }, - - // fflate (for when using ENGINE_PATH) - { src: '../node_modules/fflate/esm/', dest: 'dist/modules/fflate/esm', once: true }, - - // engine path - ...getEnginePathFiles() -]; - -function getEnginePathFiles() { +const getEnginePathFiles = () => { if (!ENGINE_PATH) { return []; } @@ -79,18 +40,18 @@ function getEnginePathFiles() { // packed module builds const dest = 'dist/iframe/ENGINE_PATH/index.js'; return [{ src, dest }]; -} +}; -function checkAppEngine() { +const checkAppEngine = () => { // types if (!fs.existsSync('../build/playcanvas.d.ts')) { const cmd = `npm run build target:types --prefix ../`; console.log('\x1b[32m%s\x1b[0m', cmd); execSync(cmd); } -} +}; -function getEngineTargets() { +const getEngineTargets = () => { // Checks for types and engien for app building checkAppEngine(); @@ -135,7 +96,46 @@ function getEngineTargets() { ); } return targets; -} +}; + +const STATIC_FILES = [ + // static main page src + { src: './src/static', dest: 'dist/' }, + + // static iframe src + { src: './iframe', dest: 'dist/iframe' }, + + // assets used in examples + { src: './assets', dest: 'dist/static/assets/', once: true }, + + // thumbnails used in examples + { src: './thumbnails', dest: 'dist/thumbnails/', once: true }, + + // external libraries used in examples + { src: './src/lib', dest: 'dist/static/lib/', once: true }, + + // engine scripts + { src: '../scripts', dest: 'dist/static/scripts/' }, + + // playcanvas engine types + { src: '../build/playcanvas.d.ts', dest: 'dist/playcanvas.d.ts' }, + + // playcanvas observer + { + src: './node_modules/@playcanvas/observer/dist/index.mjs', + dest: 'dist/iframe/playcanvas-observer.mjs', + once: true + }, + + // modules (N.B. destination folder is 'modules' as 'node_modules' are automatically excluded by git pages) + { src: './node_modules/monaco-editor/min/vs', dest: 'dist/modules/monaco-editor/min/vs', once: true }, + + // fflate (for when using ENGINE_PATH) + { src: '../node_modules/fflate/esm/', dest: 'dist/modules/fflate/esm', once: true }, + + // engine path + ...getEnginePathFiles() +]; export default [ { @@ -148,7 +148,7 @@ export default [ skipWrite: true }, treeshake: false, - plugins: [generateStandalone(NODE_ENV, ENGINE_PATH), copyStatic(NODE_ENV, STATIC_FILES)] + plugins: [buildExamples(NODE_ENV, ENGINE_PATH), copyStatic(NODE_ENV, STATIC_FILES)] }, { // A debug build is ~2.3MB and a release build ~0.6MB diff --git a/examples/scripts/standalone-html.mjs b/examples/scripts/build-examples.mjs similarity index 91% rename from examples/scripts/standalone-html.mjs rename to examples/scripts/build-examples.mjs index dfeb12a1c2c..8213365433d 100644 --- a/examples/scripts/standalone-html.mjs +++ b/examples/scripts/build-examples.mjs @@ -29,7 +29,7 @@ export function controls({ fragment }) { * @param {string[]} files - The files in the example directory. * @returns {string} File to write as standalone example. */ -function generateExampleFile(categoryKebab, exampleNameKebab, setEngineType, files) { +const generateExampleFile = (categoryKebab, exampleNameKebab, setEngineType, files) => { let html = EXAMPLE_HTML; // title @@ -48,9 +48,14 @@ function generateExampleFile(categoryKebab, exampleNameKebab, setEngineType, fil } return html; -} +}; + +/** + * @param {Record} env - The environment variables. + */ +export const build = (env = {}) => { + Object.assign(process.env, env); -function main() { if (!fs.existsSync(`${MAIN_DIR}/dist/`)) { fs.mkdirSync(`${MAIN_DIR}/dist/`); } @@ -58,7 +63,7 @@ function main() { fs.mkdirSync(`${MAIN_DIR}/dist/iframe/`); } - exampleMetaData.forEach((data) => { + exampleMetaData.forEach((/** @type {{ categoryKebab: string; exampleNameKebab: string; path: string; }} */ data) => { const { categoryKebab, exampleNameKebab, path } = data; const name = `${categoryKebab}_${exampleNameKebab}`; @@ -115,5 +120,4 @@ function main() { fs.writeFileSync(`${MAIN_DIR}/dist/iframe/${name}.${file}`, script); }); }); -} -main(); +}; diff --git a/examples/scripts/metadata.mjs b/examples/scripts/build-metadata.mjs similarity index 98% rename from examples/scripts/metadata.mjs rename to examples/scripts/build-metadata.mjs index 3b642cb0dc2..003c0fc4a8c 100644 --- a/examples/scripts/metadata.mjs +++ b/examples/scripts/build-metadata.mjs @@ -18,7 +18,7 @@ const MAIN_DIR = `${dirname(__filename)}/../`; */ const exampleMetaData = []; -function main() { +const main = () => { const rootPath = `${MAIN_DIR}/src/examples`; const categories = getDirFiles(rootPath); @@ -54,5 +54,5 @@ function main() { } fs.writeFileSync(`${MAIN_DIR}/cache/metadata.mjs`, `export const exampleMetaData = ${objStringify(exampleMetaData)};\n`); -} +}; main(); diff --git a/examples/scripts/sharing-html.mjs b/examples/scripts/build-sharing.mjs similarity index 95% rename from examples/scripts/sharing-html.mjs rename to examples/scripts/build-sharing.mjs index 2699fbfadb6..bac4411631d 100644 --- a/examples/scripts/sharing-html.mjs +++ b/examples/scripts/build-sharing.mjs @@ -14,7 +14,7 @@ import { exampleMetaData } from '../cache/metadata.mjs'; * @param {string} options.largeThumbnailName - The large thumbnail name. * @returns {string} - The template string. */ -function template({ path, exampleTitle, largeThumbnailName }) { +const template = ({ path, exampleTitle, largeThumbnailName }) => { return ` @@ -30,14 +30,14 @@ function template({ path, exampleTitle, largeThumbnailName }) {

Please follow this link.

`; -} +}; // @ts-ignore const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const MAIN_DIR = `${__dirname}/../`; -function main() { +const main = () => { if (!fs.existsSync(`${MAIN_DIR}/dist/`)) { fs.mkdirSync(`${MAIN_DIR}/dist/`); } @@ -58,5 +58,5 @@ function main() { } fs.writeFileSync(`${dirPath}/index.html`, content); } -} +}; main(); diff --git a/examples/scripts/thumbnails.mjs b/examples/scripts/build-thumbnails.mjs similarity index 95% rename from examples/scripts/thumbnails.mjs rename to examples/scripts/build-thumbnails.mjs index f28489c42f8..2fedb4eea65 100644 --- a/examples/scripts/thumbnails.mjs +++ b/examples/scripts/build-thumbnails.mjs @@ -10,6 +10,7 @@ import { fileURLToPath } from 'url'; import { spawn, execSync } from 'node:child_process'; import { exampleMetaData } from '../cache/metadata.mjs'; +import { sleep } from './utils.mjs'; // @ts-ignore const __filename = fileURLToPath(import.meta.url); @@ -118,7 +119,7 @@ class PuppeteerPool { * @param {string} categoryKebab - Category kebab name. * @param {string} exampleNameKebab - Example kebab name. */ -async function takeThumbnails(pool, categoryKebab, exampleNameKebab) { +const takeThumbnails = async (pool, categoryKebab, exampleNameKebab) => { const poolItem = pool.allocPoolItem(); const page = await pool.newPage(poolItem); if (DEBUG) { @@ -166,12 +167,12 @@ async function takeThumbnails(pool, categoryKebab, exampleNameKebab) { await pool.closePage(poolItem, page); console.log(`screenshot taken for: ${categoryKebab}/${exampleNameKebab}`); -} +}; /** * @param {typeof exampleMetaData} metadata - Example metadata. */ -async function takeScreenshots(metadata) { +const takeScreenshots = async (metadata) => { if (metadata.length === 0) { return; } @@ -207,19 +208,10 @@ async function takeScreenshots(metadata) { // close pool await pool.close(); -} +}; -/** - * @param {number} ms - Milliseconds. - * @returns {Promise} - Sleep promise. - */ -function sleep(ms = 0) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); -} -async function main() { +const main = async () => { console.log('Spawn server on', PORT); // We need this kind of command: // npx serve dist --config ../serve.json @@ -244,5 +236,5 @@ async function main() { } console.log('Killed server on', PORT); return 0; -} +}; main().then(process.exit); diff --git a/examples/scripts/clean.mjs b/examples/scripts/clean.mjs index d043f525d58..1da96b5ad3c 100644 --- a/examples/scripts/clean.mjs +++ b/examples/scripts/clean.mjs @@ -9,8 +9,8 @@ import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const MAIN_DIR = `${dirname(__filename)}/../`; -function main() { +const main = () => { fs.rmSync(`${MAIN_DIR}/dist`, { recursive: true, force: true }); fs.rmSync(`${MAIN_DIR}/cache`, { recursive: true, force: true }); -} +}; main(); diff --git a/examples/scripts/utils.mjs b/examples/scripts/utils.mjs index 3887ac74cef..1cb75d2759e 100644 --- a/examples/scripts/utils.mjs +++ b/examples/scripts/utils.mjs @@ -1,18 +1,28 @@ import fs from 'fs'; +/** + * @param {number} ms - The milliseconds to sleep. + * @returns {Promise} - The sleep promise. + */ +export const sleep = (ms = 0) => { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); +}; + /** * @param {object} obj - The object. * @returns {string} - The stringified object */ -export function objStringify(obj) { +export const objStringify = (obj) => { return JSON.stringify(obj, null, 4).replace(/"(\w+)":/g, '$1:'); -} +}; /** * @param {string} path - The directory path. * @returns {string[]} - The file names in the directory. */ -export function getDirFiles(path) { +export const getDirFiles = (path) => { if (!fs.existsSync(path)) { return []; } @@ -21,7 +31,7 @@ export function getDirFiles(path) { return []; } return fs.readdirSync(path); -} +}; /** * @typedef {'development' | 'performance' | 'debug'} Engine @@ -42,7 +52,7 @@ export function getDirFiles(path) { * @param {string} script - The script to parse. * @returns {ExampleConfig} - The parsed config. */ -export function parseConfig(script) { +export const parseConfig = (script) => { const regex = /\/\/ @config ([^ \n]+) ?([^\n]+)?/g; let match; /** @type {Record} */ @@ -53,7 +63,7 @@ export function parseConfig(script) { config[key] = /true|false/g.test(val) ? val === 'true' : val ?? true; } return config; -} +}; /** * Choose engine based on `Example#ENGINE`, e.g. ClusteredLightingExample picks PERFORMANCE. @@ -61,7 +71,7 @@ export function parseConfig(script) { * @param {Engine | undefined} type - The engine type. * @returns {string} - The build file. */ -export function engineFor(type) { +export const engineFor = (type) => { switch (type) { case 'development': return './ENGINE_PATH/index.js'; @@ -71,15 +81,15 @@ export function engineFor(type) { return './playcanvas.dbg.mjs'; } return './playcanvas.mjs'; -} +}; /** * @param {string} script - The script to be patched. * @returns {string} - The patched script. */ -export function patchScript(script) { +export const patchScript = (script) => { // remove playcanvas imports script = script.replace(/ *import[\s\w*{},]+["']playcanvas["'] *;?[\s\r\n]*/g, ''); return script; -} +}; diff --git a/examples/utils/plugins/rollup-generate-standalone.mjs b/examples/utils/plugins/rollup-build-examples.mjs similarity index 53% rename from examples/utils/plugins/rollup-generate-standalone.mjs rename to examples/utils/plugins/rollup-build-examples.mjs index 390b905aedb..e136d3687a0 100644 --- a/examples/utils/plugins/rollup-generate-standalone.mjs +++ b/examples/utils/plugins/rollup-build-examples.mjs @@ -1,9 +1,10 @@ -import { execSync } from 'child_process'; - // custom plugins import { watch } from '../rollup-watch.mjs'; +import { build } from '../../scripts/build-examples.mjs'; const GREEN_OUT = '\x1b[32m'; +const BOLD_OUT = `\x1b[1m`; +const REGULAR_OUT = `\x1b[22m`; /** * This plugin builds the standalone html files. @@ -12,20 +13,19 @@ const GREEN_OUT = '\x1b[32m'; * @param {string} enginePath - The path to the engine. * @returns {import('rollup').Plugin} The plugin. */ -export function generateStandalone(nodeEnv, enginePath) { +export function buildExamples(nodeEnv, enginePath) { return { - name: 'generate-standalone', + name: 'build-examples', buildStart() { if (nodeEnv === 'development') { watch(this, 'iframe/example.html'); - watch(this, 'scripts/standalone-html.mjs'); + watch(this, 'scripts/build-examples.mjs'); watch(this, 'src/examples'); } }, buildEnd() { - const cmd = `cross-env NODE_ENV=${nodeEnv} ENGINE_PATH=${enginePath} node ./scripts/standalone-html.mjs`; - console.log(`${GREEN_OUT}${cmd}`); - execSync(cmd); + build({ NODE_ENV: nodeEnv, ENGINE_PATH: enginePath }); + console.log(`${GREEN_OUT}built examples using NODE_ENV=${BOLD_OUT}${nodeEnv}${REGULAR_OUT} ENGINE_PATH=${BOLD_OUT}${enginePath}${REGULAR_OUT}`); } }; } From a8cebda6de2fb390e4297396c6cc46728f28a888 Mon Sep 17 00:00:00 2001 From: Martin Valigursky <59932779+mvaligursky@users.noreply.github.com> Date: Mon, 4 Nov 2024 15:32:34 +0000 Subject: [PATCH 2/9] Exposed GraphicsDevice.maxSamples (#7086) Co-authored-by: Martin Valigursky --- src/platform/graphics/graphics-device.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/platform/graphics/graphics-device.js b/src/platform/graphics/graphics-device.js index f35739508e9..11abc43884e 100644 --- a/src/platform/graphics/graphics-device.js +++ b/src/platform/graphics/graphics-device.js @@ -177,6 +177,14 @@ class GraphicsDevice extends EventHandler { */ samples; + /** + * The maximum supported number of hardware anti-aliasing samples. + * + * @readonly + * @type {number} + */ + maxSamples = 1; + /** * True if the main framebuffer contains stencil attachment. * From 34fdda2feaa72c3f575b5478f1d602fa528173ee Mon Sep 17 00:00:00 2001 From: KPal <48248865+kpal81xd@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:53:14 +0000 Subject: [PATCH 3/9] Gizmo hover disabled with no selection on mouse down (#7092) * Disable hover when moving mouse with no selection * Skip hover entirely without having to set value --- src/extras/gizmo/gizmo.js | 7 ++++++- src/extras/gizmo/transform-gizmo.js | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/extras/gizmo/gizmo.js b/src/extras/gizmo/gizmo.js index 17808c4f406..76682053996 100644 --- a/src/extras/gizmo/gizmo.js +++ b/src/extras/gizmo/gizmo.js @@ -396,11 +396,16 @@ class Gizmo extends EventHandler { if (!this.root.enabled || document.pointerLockElement) { return; } + const selection = this._getSelection(e.offsetX, e.offsetY); + if (selection[0]) { + e.preventDefault(); + e.stopPropagation(); + } const { canvas } = this._device; canvas.releasePointerCapture(e.pointerId); - this.fire(Gizmo.EVENT_POINTERUP); + this.fire(Gizmo.EVENT_POINTERUP, e.offsetX, e.offsetY, selection[0]); } /** diff --git a/src/extras/gizmo/transform-gizmo.js b/src/extras/gizmo/transform-gizmo.js index 9323eba00a0..633b605a0b5 100644 --- a/src/extras/gizmo/transform-gizmo.js +++ b/src/extras/gizmo/transform-gizmo.js @@ -194,6 +194,14 @@ class TransformGizmo extends Gizmo { */ _hoverIsPlane = false; + /** + * Internal state of if there is no selection. + * + * @type {boolean} + * @private + */ + _noSelection = false; + /** * Internal currently selected axis. * @@ -278,6 +286,7 @@ class TransformGizmo extends Gizmo { } if (!meshInstance) { + this._noSelection = true; return; } @@ -298,7 +307,9 @@ class TransformGizmo extends Gizmo { return; } - this._hover(meshInstance); + if (!this._noSelection) { + this._hover(meshInstance); + } if (!this._dragging) { return; @@ -313,7 +324,10 @@ class TransformGizmo extends Gizmo { this._hoverIsPlane = false; }); - this.on(Gizmo.EVENT_POINTERUP, () => { + this.on(Gizmo.EVENT_POINTERUP, (x, y, meshInstance) => { + this._noSelection = false; + this._hover(meshInstance); + if (!this._dragging) { return; } From 3a1cbf0f9c1ec25999bad00bea6c73c96c29c321 Mon Sep 17 00:00:00 2001 From: KPal <48248865+kpal81xd@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:39:27 +0000 Subject: [PATCH 4/9] Fixed picker on webgpu (#7094) --- examples/src/examples/misc/editor.selector.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/src/examples/misc/editor.selector.mjs b/examples/src/examples/misc/editor.selector.mjs index bdfcf3ed139..2c9f187b414 100644 --- a/examples/src/examples/misc/editor.selector.mjs +++ b/examples/src/examples/misc/editor.selector.mjs @@ -64,7 +64,7 @@ class Selector extends pc.EventHandler { * @param {MouseEvent} e - The event. * @private */ - _onPointerUp(e) { + async _onPointerUp(e) { if (Math.abs(e.clientX - this._start.x) > EPSILON || Math.abs(e.clientY - this._start.y) > EPSILON) { return; } @@ -73,7 +73,7 @@ class Selector extends pc.EventHandler { this._picker.resize(device.canvas.clientWidth, device.canvas.clientHeight); this._picker.prepare(this._camera, this._scene, this._layers); - const selection = this._picker.getSelection(e.clientX - 1, e.clientY - 1, 2, 2); + const selection = await this._picker.getSelectionAsync(e.clientX - 1, e.clientY - 1, 2, 2); if (!selection[0]) { this.fire('deselect'); From 641ee34bb79c5ab4b01a11b48b8dd93c2c3f3b2e Mon Sep 17 00:00:00 2001 From: Martin Valigursky <59932779+mvaligursky@users.noreply.github.com> Date: Tue, 5 Nov 2024 15:57:40 +0000 Subject: [PATCH 5/9] Exposed Scene.sky properties (#7041) * Exposed Scene.sky properties * lint --------- Co-authored-by: Martin Valigursky --- src/index.js | 3 +++ src/scene/scene.js | 5 +++++ src/scene/skybox/sky.js | 7 ++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index b29d25d4be7..d1b8ac94408 100644 --- a/src/index.js +++ b/src/index.js @@ -193,6 +193,9 @@ export { shaderChunks } from './scene/shader-lib/chunks/chunks.js'; export { shaderChunksLightmapper } from './scene/shader-lib/chunks/chunks-lightmapper.js'; export { ChunkBuilder } from './scene/shader-lib/chunk-builder.js'; // used by shed +// SCENE / SKY +export { Sky } from './scene/skybox/sky.js'; + // SCENE / SPLAT export { GSplatData } from './scene/gsplat/gsplat-data.js'; export { GSplat } from './scene/gsplat/gsplat.js'; diff --git a/src/scene/scene.js b/src/scene/scene.js index 1137d763b0e..dad5a714431 100644 --- a/src/scene/scene.js +++ b/src/scene/scene.js @@ -417,6 +417,11 @@ class Scene extends EventHandler { return this._layers; } + /** + * Gets the {@link Sky} that defines sky properties. + * + * @type {Sky} + */ get sky() { return this._sky; } diff --git a/src/scene/skybox/sky.js b/src/scene/skybox/sky.js index 113688d3039..770f6298dfc 100644 --- a/src/scene/skybox/sky.js +++ b/src/scene/skybox/sky.js @@ -50,6 +50,7 @@ class Sky { * Constructs a new sky. * * @param {Scene} scene - The scene owning the sky. + * @ignore */ constructor(scene) { this.device = scene.device; @@ -76,9 +77,9 @@ class Sky { * The type of the sky. One of the SKYMESH_* constants. Defaults to {@link SKYTYPE_INFINITE}. * Can be: * - * {@link SKYTYPE_INFINITE} - * {@link SKYTYPE_BOX} - * {@link SKYTYPE_DOME} + * - {@link SKYTYPE_INFINITE} + * - {@link SKYTYPE_BOX} + * - {@link SKYTYPE_DOME} * * @type {string} */ From 7dd4b9a0daf28a1be47c2a933b43f5f31bd81b66 Mon Sep 17 00:00:00 2001 From: Martin Valigursky <59932779+mvaligursky@users.noreply.github.com> Date: Wed, 6 Nov 2024 14:39:03 +0000 Subject: [PATCH 6/9] Disable MSAA on Android Firefox version newer than 123.0 (#7096) Co-authored-by: Martin Valigursky --- src/platform/graphics/webgl/webgl-graphics-device.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/platform/graphics/webgl/webgl-graphics-device.js b/src/platform/graphics/webgl/webgl-graphics-device.js index d85fe476eb0..db5f503d74b 100644 --- a/src/platform/graphics/webgl/webgl-graphics-device.js +++ b/src/platform/graphics/webgl/webgl-graphics-device.js @@ -153,16 +153,18 @@ class WebglGraphicsDevice extends GraphicsDevice { Debug.log('Antialiasing has been turned off due to rendering issues on AppleWebKit 15.4'); } - // #5856 - turn off antialiasing on Windows Firefox - if (platform.browserName === 'firefox' && platform.name === 'windows') { + // #5856 - turn off antialiasing on Firefox running on Windows / Android + if (platform.browserName === 'firefox') { const ua = (typeof navigator !== 'undefined') ? navigator.userAgent : ''; const match = ua.match(/Firefox\/(\d+(\.\d+)*)/); const firefoxVersion = match ? match[1] : null; if (firefoxVersion) { const version = parseFloat(firefoxVersion); - if (version >= 120 || version === 115) { + const disableAntialias = (platform.name === 'windows' && (version >= 120 || version === 115)) || + (platform.name === 'android' && version >= 132); + if (disableAntialias) { options.antialias = false; - Debug.log(`Antialiasing has been turned off due to rendering issues on Windows Firefox esr115 and 120+. Current version: ${firefoxVersion}`); + Debug.log(`Antialiasing has been turned off due to rendering issues on Firefox ${platform.name} platform version ${firefoxVersion}`); } } } From 8a136d6b3c6e1ce4ae4d33c57463c56f4e9af8c0 Mon Sep 17 00:00:00 2001 From: MAG-AdrianMeredith <100127317+MAG-AdrianMeredith@users.noreply.github.com> Date: Wed, 6 Nov 2024 15:34:15 +0000 Subject: [PATCH 7/9] fix #7098 missing texture format (#7099) --- src/platform/graphics/webgpu/constants.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/platform/graphics/webgpu/constants.js b/src/platform/graphics/webgpu/constants.js index 11b02486eb8..9cf254dd782 100644 --- a/src/platform/graphics/webgpu/constants.js +++ b/src/platform/graphics/webgpu/constants.js @@ -12,7 +12,8 @@ import { PIXELFORMAT_DXT1_SRGB, PIXELFORMAT_DXT3_SRGBA, PIXELFORMAT_DXT5_SRGBA, PIXELFORMAT_PVRTC_2BPP_SRGB_1, PIXELFORMAT_PVRTC_2BPP_SRGBA_1, PIXELFORMAT_PVRTC_4BPP_SRGB_1, PIXELFORMAT_PVRTC_4BPP_SRGBA_1, PIXELFORMAT_ETC2_SRGB, PIXELFORMAT_ETC2_SRGBA, PIXELFORMAT_SBGRA8, - PIXELFORMAT_BC6F, PIXELFORMAT_BC6UF, PIXELFORMAT_BC7, PIXELFORMAT_BC7_SRGBA + PIXELFORMAT_BC6F, PIXELFORMAT_BC6UF, PIXELFORMAT_BC7, PIXELFORMAT_BC7_SRGBA, + PIXELFORMAT_ASTC_4x4_SRGB } from '../constants.js'; // map of PIXELFORMAT_*** to GPUTextureFormat @@ -87,3 +88,4 @@ gpuTextureFormats[PIXELFORMAT_PVRTC_4BPP_SRGBA_1] = ''; gpuTextureFormats[PIXELFORMAT_ETC2_SRGB] = 'etc2-rgb8unorm-srgb'; gpuTextureFormats[PIXELFORMAT_ETC2_SRGBA] = 'etc2-rgba8unorm-srgb'; gpuTextureFormats[PIXELFORMAT_BC7_SRGBA] = 'bc7-rgba-unorm-srgb'; +gpuTextureFormats[PIXELFORMAT_ASTC_4x4_SRGB] = 'astc-4x4-unorm-srgb'; From cb81f0f4153e3c82d5d07a8b7a8fff8f478c3b12 Mon Sep 17 00:00:00 2001 From: Mark Lundin Date: Wed, 6 Nov 2024 16:20:23 +0000 Subject: [PATCH 8/9] Fix script schema retrieval in ScriptHandler (#7097) --- src/framework/handlers/script.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/framework/handlers/script.js b/src/framework/handlers/script.js index 74e71ed1d3e..6441589f17d 100644 --- a/src/framework/handlers/script.js +++ b/src/framework/handlers/script.js @@ -139,7 +139,7 @@ class ScriptHandler extends ResourceHandler { import(importUrl.toString()).then((module) => { const filename = importUrl.pathname.split('/').pop(); - const scriptSchema = this._app.assets.find(filename, 'script').data.scripts; + const scriptSchema = this._app.assets.find(filename, 'script')?.data?.scripts; for (const key in module) { const scriptClass = module[key]; @@ -153,7 +153,7 @@ class ScriptHandler extends ResourceHandler { registerScript(scriptClass, scriptName); // Store any schema associated with the script - this._app.scripts.addSchema(scriptName, scriptSchema[scriptName]); + if (scriptSchema) this._app.scripts.addSchema(scriptName, scriptSchema[scriptName]); } } From 99aba9e671794f4a149d7f976442236bd90e5eec Mon Sep 17 00:00:00 2001 From: KPal <48248865+kpal81xd@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:42:42 +0000 Subject: [PATCH 9/9] Example controls updates (#7093) * Updated controls interface to use observer correctly * Converted all examples to use controls as arrow functions * Added semicolons --- .../animation/blend-trees-1d.controls.mjs | 4 +-- .../blend-trees-2d-cartesian.controls.mjs | 4 +-- .../blend-trees-2d-directional.controls.mjs | 4 +-- .../component-properties.controls.mjs | 4 +-- .../animation/layer-masks.controls.mjs | 4 +-- .../animation/locomotion.controls.mjs | 4 +-- .../src/examples/camera/multi.controls.mjs | 4 +-- .../gizmos/transform-rotate.controls.mjs | 7 ++-- .../gizmos/transform-scale.controls.mjs | 7 ++-- .../gizmos/transform-translate.controls.mjs | 7 ++-- .../graphics/ambient-occlusion.controls.mjs | 4 +-- .../graphics/asset-viewer.controls.mjs | 4 +-- .../clustered-area-lights.controls.mjs | 4 +-- .../clustered-omni-shadows.controls.mjs | 4 +-- .../clustered-spot-shadows.controls.mjs | 4 +-- .../contact-hardening-shadows.controls.mjs | 4 +-- .../dithered-transparency.controls.mjs | 4 +-- .../examples/graphics/ground-fog.controls.mjs | 4 +-- .../graphics/integer-textures.controls.mjs | 4 +-- .../light-physical-units.controls.mjs | 4 +-- .../graphics/lights-baked-a-o.controls.mjs | 4 +-- .../src/examples/graphics/lights.controls.mjs | 4 +-- .../examples/graphics/multi-view.controls.mjs | 4 +-- .../graphics/particles-mesh.controls.mjs | 4 +-- .../graphics/post-effects.controls.mjs | 4 +-- .../graphics/post-processing.controls.mjs | 4 +-- .../graphics/reflection-box.controls.mjs | 4 +-- .../graphics/shader-hatch.controls.mjs | 4 +-- .../graphics/shadow-cascades.controls.mjs | 4 +-- .../src/examples/graphics/sky.controls.mjs | 4 +-- .../src/examples/graphics/taa.controls.mjs | 4 +-- .../graphics/texture-array.controls.mjs | 4 +-- .../examples/loaders/gltf-export.controls.mjs | 4 +-- .../examples/loaders/gsplat-many.controls.mjs | 4 +-- .../examples/loaders/usdz-export.controls.mjs | 4 +-- .../src/examples/misc/editor.controls.mjs | 36 ++++++++++++++----- examples/src/examples/misc/editor.example.mjs | 26 +++----------- .../src/examples/misc/multi-app.controls.mjs | 4 +-- 38 files changed, 110 insertions(+), 105 deletions(-) diff --git a/examples/src/examples/animation/blend-trees-1d.controls.mjs b/examples/src/examples/animation/blend-trees-1d.controls.mjs index 23ae4e4eaa0..4e037f8cda1 100644 --- a/examples/src/examples/animation/blend-trees-1d.controls.mjs +++ b/examples/src/examples/animation/blend-trees-1d.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx }) { +export const controls = ({ observer, ReactPCUI, React, jsx }) => { const { BindingTwoWay, LabelGroup, SliderInput } = ReactPCUI; class JsxControls extends React.Component { render() { @@ -15,4 +15,4 @@ export function controls({ observer, ReactPCUI, React, jsx }) { } } return jsx(JsxControls); -} +}; diff --git a/examples/src/examples/animation/blend-trees-2d-cartesian.controls.mjs b/examples/src/examples/animation/blend-trees-2d-cartesian.controls.mjs index 935becd36b8..8bd8c440469 100644 --- a/examples/src/examples/animation/blend-trees-2d-cartesian.controls.mjs +++ b/examples/src/examples/animation/blend-trees-2d-cartesian.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ React, jsx, fragment }) { +export const controls = ({ React, jsx, fragment }) => { const { createRef, Component } = React; class JsxControls extends Component { position = new pc.Vec2(); @@ -140,4 +140,4 @@ export function controls({ React, jsx, fragment }) { } } return jsx(JsxControls); -} +}; diff --git a/examples/src/examples/animation/blend-trees-2d-directional.controls.mjs b/examples/src/examples/animation/blend-trees-2d-directional.controls.mjs index ceacf7e03b0..8a4ba4f364f 100644 --- a/examples/src/examples/animation/blend-trees-2d-directional.controls.mjs +++ b/examples/src/examples/animation/blend-trees-2d-directional.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ React, jsx, fragment }) { +export const controls = ({ React, jsx, fragment }) => { const { useEffect, useRef } = React; /** @type {React.MutableRefObject} */ const canvasRef = useRef(null); @@ -80,4 +80,4 @@ export function controls({ React, jsx, fragment }) { canvas.addEventListener('mousedown', mouseEvent); }); return fragment(jsx('canvas', { ref: canvasRef })); -} +}; diff --git a/examples/src/examples/animation/component-properties.controls.mjs b/examples/src/examples/animation/component-properties.controls.mjs index 8a89a6d9e40..a8d0ce201b0 100644 --- a/examples/src/examples/animation/component-properties.controls.mjs +++ b/examples/src/examples/animation/component-properties.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { Button } = ReactPCUI; return fragment( jsx(Button, { @@ -12,4 +12,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { } }) ); -} +}; diff --git a/examples/src/examples/animation/layer-masks.controls.mjs b/examples/src/examples/animation/layer-masks.controls.mjs index 35e4f4482e0..1854343988e 100644 --- a/examples/src/examples/animation/layer-masks.controls.mjs +++ b/examples/src/examples/animation/layer-masks.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, BooleanInput, SelectInput, SliderInput } = ReactPCUI; return fragment( jsx( @@ -98,4 +98,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/animation/locomotion.controls.mjs b/examples/src/examples/animation/locomotion.controls.mjs index ba29faeab1c..d09e74c8bcc 100644 --- a/examples/src/examples/animation/locomotion.controls.mjs +++ b/examples/src/examples/animation/locomotion.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, BooleanInput, Button } = ReactPCUI; const binding = new BindingTwoWay(); const link = { @@ -26,4 +26,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { }) ) ); -} +}; diff --git a/examples/src/examples/camera/multi.controls.mjs b/examples/src/examples/camera/multi.controls.mjs index fbf620c12f2..eb302779c3d 100644 --- a/examples/src/examples/camera/multi.controls.mjs +++ b/examples/src/examples/camera/multi.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, BooleanInput, SliderInput } = ReactPCUI; return fragment( @@ -146,4 +146,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/gizmos/transform-rotate.controls.mjs b/examples/src/examples/gizmos/transform-rotate.controls.mjs index ea1f62f5685..77346ef3d2c 100644 --- a/examples/src/examples/gizmos/transform-rotate.controls.mjs +++ b/examples/src/examples/gizmos/transform-rotate.controls.mjs @@ -4,10 +4,11 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, ColorPicker, SliderInput, SelectInput, BooleanInput } = ReactPCUI; + const { useState } = React; - const [proj, setProj] = React.useState(pc.PROJECTION_PERSPECTIVE); + const [proj, setProj] = useState(pc.PROJECTION_PERSPECTIVE); return fragment( jsx( @@ -176,4 +177,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/gizmos/transform-scale.controls.mjs b/examples/src/examples/gizmos/transform-scale.controls.mjs index aaae894d137..c2c5cfaca5c 100644 --- a/examples/src/examples/gizmos/transform-scale.controls.mjs +++ b/examples/src/examples/gizmos/transform-scale.controls.mjs @@ -4,10 +4,11 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, ColorPicker, SliderInput, SelectInput, BooleanInput } = ReactPCUI; + const { useState } = React; - const [proj, setProj] = React.useState(pc.PROJECTION_PERSPECTIVE); + const [proj, setProj] = useState(pc.PROJECTION_PERSPECTIVE); return fragment( jsx( @@ -198,4 +199,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/gizmos/transform-translate.controls.mjs b/examples/src/examples/gizmos/transform-translate.controls.mjs index 69e75853f3c..9062ce43536 100644 --- a/examples/src/examples/gizmos/transform-translate.controls.mjs +++ b/examples/src/examples/gizmos/transform-translate.controls.mjs @@ -4,10 +4,11 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, ColorPicker, SliderInput, SelectInput, BooleanInput } = ReactPCUI; + const { useState } = React; - const [proj, setProj] = React.useState(pc.PROJECTION_PERSPECTIVE); + const [proj, setProj] = useState(pc.PROJECTION_PERSPECTIVE); return fragment( jsx( @@ -218,4 +219,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/ambient-occlusion.controls.mjs b/examples/src/examples/graphics/ambient-occlusion.controls.mjs index 56ec60a4487..56f8ee3488a 100644 --- a/examples/src/examples/graphics/ambient-occlusion.controls.mjs +++ b/examples/src/examples/graphics/ambient-occlusion.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SelectInput, SliderInput } = ReactPCUI; return fragment( jsx( @@ -95,4 +95,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/asset-viewer.controls.mjs b/examples/src/examples/graphics/asset-viewer.controls.mjs index ed9e31e63cc..dd4914d26f6 100644 --- a/examples/src/examples/graphics/asset-viewer.controls.mjs +++ b/examples/src/examples/graphics/asset-viewer.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { Panel, Button } = ReactPCUI; return jsx( Panel, @@ -16,4 +16,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { onClick: () => observer.emit('next') }) ); -} +}; diff --git a/examples/src/examples/graphics/clustered-area-lights.controls.mjs b/examples/src/examples/graphics/clustered-area-lights.controls.mjs index dd43cb49a11..6a740bc3fcb 100644 --- a/examples/src/examples/graphics/clustered-area-lights.controls.mjs +++ b/examples/src/examples/graphics/clustered-area-lights.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, SliderInput } = ReactPCUI; return fragment( jsx( @@ -32,4 +32,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/clustered-omni-shadows.controls.mjs b/examples/src/examples/graphics/clustered-omni-shadows.controls.mjs index e12df4dd523..febdc1d3173 100644 --- a/examples/src/examples/graphics/clustered-omni-shadows.controls.mjs +++ b/examples/src/examples/graphics/clustered-omni-shadows.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SelectInput, SliderInput } = ReactPCUI; return jsx( Panel, @@ -55,4 +55,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { }) ) ); -} +}; diff --git a/examples/src/examples/graphics/clustered-spot-shadows.controls.mjs b/examples/src/examples/graphics/clustered-spot-shadows.controls.mjs index ddf2954e9e9..91d9350df1f 100644 --- a/examples/src/examples/graphics/clustered-spot-shadows.controls.mjs +++ b/examples/src/examples/graphics/clustered-spot-shadows.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, Button, Label, LabelGroup, Panel, SelectInput, SliderInput } = ReactPCUI; return fragment( jsx( @@ -138,4 +138,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/contact-hardening-shadows.controls.mjs b/examples/src/examples/graphics/contact-hardening-shadows.controls.mjs index b68b0c7b22c..53f4b8ee661 100644 --- a/examples/src/examples/graphics/contact-hardening-shadows.controls.mjs +++ b/examples/src/examples/graphics/contact-hardening-shadows.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, SliderInput, SelectInput, BooleanInput } = ReactPCUI; return fragment( jsx( @@ -163,4 +163,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/dithered-transparency.controls.mjs b/examples/src/examples/graphics/dithered-transparency.controls.mjs index 7c50be3a3cf..7c68c9051b5 100644 --- a/examples/src/examples/graphics/dithered-transparency.controls.mjs +++ b/examples/src/examples/graphics/dithered-transparency.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, SliderInput, BooleanInput, SelectInput } = ReactPCUI; return fragment( jsx( @@ -62,4 +62,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/ground-fog.controls.mjs b/examples/src/examples/graphics/ground-fog.controls.mjs index 04f7c35faaf..2f95835aa8f 100644 --- a/examples/src/examples/graphics/ground-fog.controls.mjs +++ b/examples/src/examples/graphics/ground-fog.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup } = ReactPCUI; return jsx( LabelGroup, @@ -16,4 +16,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { } }) ); -} +}; diff --git a/examples/src/examples/graphics/integer-textures.controls.mjs b/examples/src/examples/graphics/integer-textures.controls.mjs index f80ed7aec21..a76de55caa1 100644 --- a/examples/src/examples/graphics/integer-textures.controls.mjs +++ b/examples/src/examples/graphics/integer-textures.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, jsx, fragment }) => { const { BindingTwoWay, Container, Button, LabelGroup, Panel, SliderInput, SelectInput } = ReactPCUI; return fragment( @@ -47,4 +47,4 @@ export function controls({ observer, ReactPCUI, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/light-physical-units.controls.mjs b/examples/src/examples/graphics/light-physical-units.controls.mjs index c0d533aa40a..0775c8c043d 100644 --- a/examples/src/examples/graphics/light-physical-units.controls.mjs +++ b/examples/src/examples/graphics/light-physical-units.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SliderInput } = ReactPCUI; return fragment( jsx( @@ -132,4 +132,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/lights-baked-a-o.controls.mjs b/examples/src/examples/graphics/lights-baked-a-o.controls.mjs index 1efe64834c5..d878a7a2321 100644 --- a/examples/src/examples/graphics/lights-baked-a-o.controls.mjs +++ b/examples/src/examples/graphics/lights-baked-a-o.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, Label, LabelGroup, Panel, SliderInput } = ReactPCUI; return fragment( jsx( @@ -186,4 +186,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/lights.controls.mjs b/examples/src/examples/graphics/lights.controls.mjs index 7c68ad3608c..21de0d6df7f 100644 --- a/examples/src/examples/graphics/lights.controls.mjs +++ b/examples/src/examples/graphics/lights.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SliderInput } = ReactPCUI; return fragment( jsx( @@ -109,4 +109,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/multi-view.controls.mjs b/examples/src/examples/graphics/multi-view.controls.mjs index d2369b8b52a..d6e7917cdc4 100644 --- a/examples/src/examples/graphics/multi-view.controls.mjs +++ b/examples/src/examples/graphics/multi-view.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, SelectInput } = ReactPCUI; return fragment( jsx( @@ -34,4 +34,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/particles-mesh.controls.mjs b/examples/src/examples/graphics/particles-mesh.controls.mjs index 1efa58a615a..e1afd7b8136 100644 --- a/examples/src/examples/graphics/particles-mesh.controls.mjs +++ b/examples/src/examples/graphics/particles-mesh.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, SliderInput, BooleanInput } = ReactPCUI; return fragment( jsx( @@ -59,4 +59,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/post-effects.controls.mjs b/examples/src/examples/graphics/post-effects.controls.mjs index 1f9b2e44b80..44b7f69cc37 100644 --- a/examples/src/examples/graphics/post-effects.controls.mjs +++ b/examples/src/examples/graphics/post-effects.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SelectInput, SliderInput } = ReactPCUI; return fragment( jsx( @@ -192,4 +192,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/post-processing.controls.mjs b/examples/src/examples/graphics/post-processing.controls.mjs index d1d3d3c3a0a..4bac61b5ae5 100644 --- a/examples/src/examples/graphics/post-processing.controls.mjs +++ b/examples/src/examples/graphics/post-processing.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SelectInput, SliderInput } = ReactPCUI; return fragment( jsx( @@ -248,4 +248,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/reflection-box.controls.mjs b/examples/src/examples/graphics/reflection-box.controls.mjs index 453139f746c..c9c1fcbcabd 100644 --- a/examples/src/examples/graphics/reflection-box.controls.mjs +++ b/examples/src/examples/graphics/reflection-box.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, SelectInput, SliderInput } = ReactPCUI; return fragment( jsx( @@ -69,4 +69,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/shader-hatch.controls.mjs b/examples/src/examples/graphics/shader-hatch.controls.mjs index a8145c130ca..b0b183a24f7 100644 --- a/examples/src/examples/graphics/shader-hatch.controls.mjs +++ b/examples/src/examples/graphics/shader-hatch.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, SliderInput, BooleanInput, SelectInput } = ReactPCUI; return fragment( jsx( @@ -69,4 +69,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/shadow-cascades.controls.mjs b/examples/src/examples/graphics/shadow-cascades.controls.mjs index eb4a2bd4617..4af6a60798a 100644 --- a/examples/src/examples/graphics/shadow-cascades.controls.mjs +++ b/examples/src/examples/graphics/shadow-cascades.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SelectInput, SliderInput } = ReactPCUI; return fragment( jsx( @@ -83,4 +83,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/sky.controls.mjs b/examples/src/examples/graphics/sky.controls.mjs index 4b1123293dc..7ccf8549807 100644 --- a/examples/src/examples/graphics/sky.controls.mjs +++ b/examples/src/examples/graphics/sky.controls.mjs @@ -4,7 +4,7 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, VectorInput, LabelGroup, Panel, SliderInput, SelectInput } = ReactPCUI; return fragment( jsx( @@ -93,4 +93,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/taa.controls.mjs b/examples/src/examples/graphics/taa.controls.mjs index 40ce9c146ee..50d0a3ce918 100644 --- a/examples/src/examples/graphics/taa.controls.mjs +++ b/examples/src/examples/graphics/taa.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SliderInput } = ReactPCUI; return fragment( jsx( @@ -65,4 +65,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/graphics/texture-array.controls.mjs b/examples/src/examples/graphics/texture-array.controls.mjs index abe304ee53c..56129ac6ecc 100644 --- a/examples/src/examples/graphics/texture-array.controls.mjs +++ b/examples/src/examples/graphics/texture-array.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, BooleanInput } = ReactPCUI; return fragment( jsx( @@ -22,4 +22,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/loaders/gltf-export.controls.mjs b/examples/src/examples/loaders/gltf-export.controls.mjs index 638f70a1d03..4424162fc4b 100644 --- a/examples/src/examples/loaders/gltf-export.controls.mjs +++ b/examples/src/examples/loaders/gltf-export.controls.mjs @@ -2,10 +2,10 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { Button } = ReactPCUI; return jsx(Button, { text: 'Download GLTF', onClick: () => observer.emit('download') }); -} +}; diff --git a/examples/src/examples/loaders/gsplat-many.controls.mjs b/examples/src/examples/loaders/gsplat-many.controls.mjs index 2976ef5e0be..fcd6174ab62 100644 --- a/examples/src/examples/loaders/gsplat-many.controls.mjs +++ b/examples/src/examples/loaders/gsplat-many.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { Button } = ReactPCUI; return fragment( jsx(Button, { @@ -12,4 +12,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { } }) ); -} +}; diff --git a/examples/src/examples/loaders/usdz-export.controls.mjs b/examples/src/examples/loaders/usdz-export.controls.mjs index 2ea6247a9ff..9ad2ef4a2f3 100644 --- a/examples/src/examples/loaders/usdz-export.controls.mjs +++ b/examples/src/examples/loaders/usdz-export.controls.mjs @@ -2,10 +2,10 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { Button } = ReactPCUI; return jsx(Button, { text: 'Download USDZ', onClick: () => observer.emit('download') }); -} +}; diff --git a/examples/src/examples/misc/editor.controls.mjs b/examples/src/examples/misc/editor.controls.mjs index 529db36d190..64ed57e3689 100644 --- a/examples/src/examples/misc/editor.controls.mjs +++ b/examples/src/examples/misc/editor.controls.mjs @@ -4,17 +4,35 @@ import * as pc from 'playcanvas'; * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, LabelGroup, Panel, SliderInput, SelectInput } = ReactPCUI; + const { useState } = React; - const [type, setType] = React.useState('translate'); - const [proj, setProj] = React.useState(pc.PROJECTION_PERSPECTIVE); + const [type, setType] = useState('translate'); + const [proj, setProj] = useState(pc.PROJECTION_PERSPECTIVE); - // @ts-ignore - window.setType = (/** @type {string} */ value) => setType(value); - - // @ts-ignore - window.setProj = (/** @type {number} */ value) => setProj(value); + // observe changes to the camera and gizmo type + observer.on('*:set', (/** @type {string} */ path, /** @type {any} */ value) => { + const [category, key] = path.split('.'); + switch (category) { + case 'camera': { + switch (key) { + case 'proj': + setType(value); + break; + } + break; + } + case 'gizmo': { + switch (key) { + case 'type': + setType(value); + break; + } + break; + } + } + }); return fragment( jsx( @@ -98,4 +116,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { ) ) ); -} +}; diff --git a/examples/src/examples/misc/editor.example.mjs b/examples/src/examples/misc/editor.example.mjs index 851959c20b2..0b70e37a5eb 100644 --- a/examples/src/examples/misc/editor.example.mjs +++ b/examples/src/examples/misc/editor.example.mjs @@ -168,22 +168,6 @@ const resize = () => { window.addEventListener('resize', resize); resize(); -// wrappers for control state changes -const setType = (/** @type {string} */ value) => { - data.set('gizmo.type', value); - - // call method from top context (same as controls) - // @ts-ignore - window.top.setType?.(value); -}; -const setProj = (/** @type {number} */ value) => { - data.set('camera.proj', value + 1); - - // call method from top context (same as controls) - // @ts-ignore - window.top.setProj?.(value); -}; - // key event handlers const keydown = (/** @type {KeyboardEvent} */ e) => { gizmoHandler.gizmo.snap = !!e.shiftKey; @@ -199,19 +183,19 @@ const keypress = (/** @type {KeyboardEvent} */ e) => { data.set('gizmo.coordSpace', data.get('gizmo.coordSpace') === 'world' ? 'local' : 'world'); break; case '1': - setType('translate'); + data.set('gizmo.type', 'translate'); break; case '2': - setType('rotate'); + data.set('gizmo.type', 'rotate'); break; case '3': - setType('scale'); + data.set('gizmo.type', 'scale'); break; case 'p': - setProj(pc.PROJECTION_PERSPECTIVE); + data.set('camera.proj', pc.PROJECTION_PERSPECTIVE + 1); break; case 'o': - setProj(pc.PROJECTION_ORTHOGRAPHIC); + data.set('camera.proj', pc.PROJECTION_ORTHOGRAPHIC + 1); break; } }; diff --git a/examples/src/examples/misc/multi-app.controls.mjs b/examples/src/examples/misc/multi-app.controls.mjs index b228940402c..79282ba700a 100644 --- a/examples/src/examples/misc/multi-app.controls.mjs +++ b/examples/src/examples/misc/multi-app.controls.mjs @@ -2,7 +2,7 @@ * @param {import('../../app/components/Example.mjs').ControlOptions} options - The options. * @returns {JSX.Element} The returned JSX Element. */ -export function controls({ observer, ReactPCUI, React, jsx, fragment }) { +export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => { const { BindingTwoWay, Panel, Label, Button } = ReactPCUI; return fragment( jsx( @@ -57,4 +57,4 @@ export function controls({ observer, ReactPCUI, React, jsx, fragment }) { }) ) ); -} +};