Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples cleanup #6005

Merged
merged 16 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions examples/scripts/example-data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ import { toKebabCase } from '../src/app/helpers/strings.mjs';
* It would be possible to *not* pregenerate example-data.js, but then we would include all
* examples only to generate the list in the UI... which would be a waste.
*/

// @ts-ignore
const __filename = fileURLToPath(import.meta.url);
const MAIN_DIR = `${dirname(__filename)}/../`;

/** @type {Record<string, Record<string, { nameSlug: string, categorySlug: string}>>} */
const exampleData = {};

if (!fs.existsSync(`${MAIN_DIR}/dist/`)) {
fs.mkdirSync(`${MAIN_DIR}/dist/`);
}
for (const category_ in realExamples) {
const category = toKebabCase(category_);
exampleData[category] = {};
// @ts-ignore
const examples = realExamples[category_];
for (const exampleName_ in examples) {
const release = process.env.NODE_ENV !== 'development';
Expand All @@ -25,9 +31,10 @@ for (const category_ in realExamples) {
}
const example = toKebabCase(exampleName_).replace('-example', '');
// turn: turn into simple array...
exampleData[category][example] = {};
exampleData[category][example].nameSlug = example;
exampleData[category][example].categorySlug = category;
exampleData[category][example] = {
nameSlug: example,
categorySlug: category
};
}
}
// This will be minified by rollup terser plugin, just keep it readable/debuggable here
Expand Down
38 changes: 21 additions & 17 deletions examples/scripts/example-directory.mjs
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
import fs from 'fs';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import * as realExamples from "../src/examples/index.mjs";
import * as realExamples from '../src/examples/index.mjs';
import { toKebabCase } from '../src/app/helpers/strings.mjs';

/**
* @param {object} options - The options.
* @param {string} options.path - The path.
* @param {string} options.exampleTitle - The example title.
* @param {string} options.largeThumbnailName - The large thumbnail name.
* @returns {string}
* @returns {string} - The template string.
*/
function template({ path, exampleTitle, largeThumbnailName }) {
return `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url='/#/${path}'" />
<meta name="twitter:card" content="photo" />
<meta name="twitter:site" content="@playcanvas" />
<meta name="twitter:title" content="${exampleTitle}" />
<meta name="twitter:description" content="A PlayCanvas engine example" />
<meta name="twitter:image" content="https://playcanvas.github.io/thumbnails/${largeThumbnailName}.png" />
<meta name="twitter:url" content="https://playcanvas.github.io/${path}" />
</head>
<body>
<p>Please follow <a href="/#/${path}">this link</a>.</p>
</body>
</html>`;
}
<html>
<head>
<meta http-equiv="refresh" content="0; url='/#/${path}'" />
<meta name="twitter:card" content="photo" />
<meta name="twitter:site" content="@playcanvas" />
<meta name="twitter:title" content="${exampleTitle}" />
<meta name="twitter:description" content="A PlayCanvas engine example" />
<meta name="twitter:image" content="https://playcanvas.github.io/thumbnails/${largeThumbnailName}.png" />
<meta name="twitter:url" content="https://playcanvas.github.io/${path}" />
</head>
<body>
<p>Please follow <a href="/#/${path}">this link</a>.</p>
</body>
</html>`;
}

// @ts-ignore
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const MAIN_DIR = `${__dirname}/../`;
Expand All @@ -37,6 +40,7 @@ for (const category_ in realExamples) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
// @ts-ignore
const examples = realExamples[category_];
categoriesList.push({
name: category,
Expand Down
59 changes: 45 additions & 14 deletions examples/scripts/generate-standalone-files.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,19 @@ import { dirname } from 'path';
import { fileURLToPath } from 'url';
import * as realExamples from "../src/examples/index.mjs";
import { toKebabCase } from '../src/app/helpers/strings.mjs';

// @ts-ignore
const __filename = fileURLToPath(import.meta.url);
const MAIN_DIR = `${dirname(__filename)}/../`;
/**
* @type {Record<string, Record<string, {
* example: string,
* nameSlug: string,
* categorySlug: string,
* files: any,
* controls: string
* }>>}
*/
const exampleData = {};
if (!fs.existsSync(`${MAIN_DIR}/dist/`)) {
fs.mkdirSync(`${MAIN_DIR}/dist/`);
Expand All @@ -15,15 +26,19 @@ if (!fs.existsSync(`${MAIN_DIR}/dist/iframe/`)) {
for (const category_ in realExamples) {
const category = toKebabCase(category_);
exampleData[category] = {};
// @ts-ignore
const examples = realExamples[category_];
for (const exampleName_ in examples) {
for (const exampleName_ in examples) {
const exampleClass = examples[exampleName_];
const example = toKebabCase(exampleName_).replace('-example', '');
exampleData[category][example] = {};
const exampleFunc = exampleClass.example.toString();
exampleData[category][example].example = exampleFunc;
exampleData[category][example].nameSlug = example;
exampleData[category][example].categorySlug = category;
exampleData[category][example] = {
example: exampleFunc,
nameSlug: example,
categorySlug: category,
files: undefined,
controls: ''
};
if (exampleClass.FILES) {
exampleData[category][example].files = exampleClass.FILES;
}
Expand All @@ -39,10 +54,12 @@ for (const category_ in realExamples) {
/**
* Choose engine based on `Example#ENGINE`, e.g. ClusteredLightingExample picks:
* static ENGINE = 'PERFORMANCE';
* @param {'PERFORMANCE'|'DEBUG'|undefined} str
*
* @param {'PERFORMANCE'|'DEBUG'|undefined} type - The build type.
* @returns {string} - The build file.
*/
function engineFor(str) {
switch (str) {
function engineFor(type) {
switch (type) {
case 'PERFORMANCE':
return './playcanvas.prf.js';
case 'DEBUG':
Expand All @@ -51,19 +68,33 @@ function engineFor(str) {
return './playcanvas.js';
}

/**
* @typedef {object} ExampleClass
* @property {Function} example - The example function.
* @property {Function} [controls] - The controls function.
* @property {object[]} [imports] - The imports array.
* @property {string[]} [es5libs] - The ES5Libs array.
* @property {string} DESCRIPTION - The example description.
* @property {"PERFORMANCE" | "DEBUG" | undefined} ENGINE - The engine type.
* @property {object} FILES - The object of extra files to include (e.g shaders).
* @property {boolean} INCLUDE_AR_LINK - Include AR link png.
* @property {boolean} NO_DEVICE_SELECTOR - No device selector.
* @property {boolean} NO_CANVAS - No canvas element.
* @property {boolean} NO_MINISTATS - No ministats.
* @property {boolean} WEBGPU_ENABLED - If webGPU is enabled.
*/
/**
* @param {string} category - The category.
* @param {string} example - The example.
* @param {object} exampleClass - The example class.
* @param {object} ministats - Should ministats be enabled?
* @param {ExampleClass} exampleClass - The example class.
* @returns {string} File to write as standalone example.
*/
function generateExampleFile(category, example, exampleClass) {
return `<html>
<head>
<link rel="stylesheet" href="./example.css">
<title>${category}: ${example}</title>
${exampleClass.es5libs?.map(_ => `<script src="${_}"></script>`).join('\n') || '<!-- no es5libs -->'}
${exampleClass.es5libs?.map((/** @type {string} */ src) => `<script src="${src}"></script>`).join('\n') || '<!-- no es5libs -->'}
</head>
<body>
<div id="app">
Expand All @@ -83,7 +114,7 @@ function generateExampleFile(category, example, exampleClass) {
<script src='./pathes.js'></script>
<!-- imports (if any) -->
<script>
${exampleClass.imports?.map(_ => _.toString()).join('\n\n') || ''}
${exampleClass.imports?.map((/** @type {{ toString: () => any; }} */ _) => _.toString()).join('\n\n') || ''}
</script>
<!-- controls (if given) -->
<script>
Expand Down Expand Up @@ -207,7 +238,7 @@ ${exampleClass.example.toString()}
*/
function showStats() {
// examples/misc/mini-stats.mjs creates its own instance of ministats, prevent two mini-stats here
if (${Boolean(exampleClass.NO_MINISTATS)}) {
if (${!!exampleClass.NO_MINISTATS}) {
return;
}
if (typeof pc === 'undefined' || typeof pcx === 'undefined') {
Expand Down Expand Up @@ -294,7 +325,7 @@ ${exampleClass.example.toString()}
// just notify to clean UI, but not during hot-reload
const event = new CustomEvent("exampleLoading", {
detail: {
showDeviceSelector: ${Boolean(exampleClass.NO_DEVICE_SELECTOR !== true)},
showDeviceSelector: ${!exampleClass.NO_DEVICE_SELECTOR},
}
});
window.top.dispatchEvent(event);
Expand Down
Loading