Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
988f39a
chore: bump eslint-config-next to match nextjs version
julien-moreau May 3, 2026
882b981
fix: deactivate prepass renderer fix when no preview camera active to…
May 6, 2026
9ec85d6
feat: rework UI for gizmo snapping
May 6, 2026
915496d
feat: add support of Audio V2
julien-moreau May 10, 2026
477d69d
v5.4.1-rc.1
julien-moreau May 10, 2026
330139d
fix: dispose sound when disposing SoundNode in babylonjs-editor-tools.
May 11, 2026
600b62e
feat: remove support of old Audio Engine
julien-moreau May 11, 2026
10af61f
v5.4.1-rc.2
julien-moreau May 11, 2026
c9f929d
feat: adding support of database
May 12, 2026
faf2eae
feat: now using indexDB when available to load sound nodes and use in…
julien-moreau May 13, 2026
cf66733
v5.4.1-rc.3
julien-moreau May 13, 2026
4a669d4
feat : exclude sprite manager textures from compressed textures tempo…
julien-moreau May 13, 2026
366538c
fix: synchronously create sound instance when using AdvancedAssetCont…
julien-moreau May 14, 2026
ba2cc00
v5.4.1-rc.4
julien-moreau May 14, 2026
88cd4d7
fix: set spatial sounds updated automatically and all together in bab…
May 15, 2026
091399e
fix: disable sync when cloning meshes
julien-moreau May 15, 2026
6b7bb58
v5.4.1-rc.5
julien-moreau May 15, 2026
da7ed2b
fix: use BC3 instead of BC2 for DXT compressed textures when alpha av…
julien-moreau May 15, 2026
bc6f366
fix: always create clustered light container in babylonjs-editor-tools
julien-moreau May 16, 2026
7442d3d
fix: check if indexDB is enabled in Database before loading sound in …
julien-moreau May 16, 2026
0fb9122
v5.4.1-rc.6
julien-moreau May 16, 2026
5487b0e
fix: dispose and remove from assets cache AdvancedAssetContainer when…
julien-moreau May 18, 2026
6d3f982
fix: keep original IBL intensity when preloading scene components in …
julien-moreau May 19, 2026
c575358
fix: sort assets browser folders and files alphabetically
May 20, 2026
3c0e8e3
fix: assets links update when moving or renaming a file/folder
May 20, 2026
c437c38
feat: add support of assets per scene in babylonjs-editor-cli
May 20, 2026
2c01e13
feat: add support of "doNotExport" for scene assets to avoid editor-o…
julien-moreau May 20, 2026
a7cd94f
fix: stop preloading assets when scene is disposed in babylonjs-edito…
julien-moreau May 20, 2026
030704c
v5.4.1-rc.7
julien-moreau May 20, 2026
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
2 changes: 1 addition & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "babylonjs-editor-cli",
"version": "5.4.1-rc.0",
"version": "5.4.1-rc.7",
"description": "Babylon.js Editor CLI is a command line interface to help you package your scenes made using the Babylon.js Editor",
"productName": "Babylon.js Editor CLI",
"scripts": {
Expand Down
55 changes: 55 additions & 0 deletions cli/src/pack/assets/collect.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { extname, join } from "node:path/posix";

import { pathExists } from "fs-extra";

import { supportedExtensions } from "./process.mjs";
import { allKtxFormats, getCompressedTextureFilename, ktxSupportedextensions } from "./ktx.mjs";

const collectedSupportedExtensions: string[] = [...supportedExtensions, ".babylonbinarymeshdata"];

export async function collectUsedAssetsForScene(scene: any, publicDir: string) {
const result: string[] = [];
const stringValues: string[] = [];

function recursivelyCollect(root: any) {
for (const thing in root) {
if (!root.hasOwnProperty(thing)) {
continue;
}

const value = root[thing];

if (typeof value === "string") {
const extension = extname(value).toLowerCase();
if (extension && collectedSupportedExtensions.includes(extension)) {
stringValues.push(value);
}
} else if (typeof value === "object") {
recursivelyCollect(value);
}
}
}

recursivelyCollect(scene);

await Promise.all(
stringValues.map(async (value) => {
const absolutePath = join(publicDir, value);
if (await pathExists(absolutePath)) {
result.push(value);

const extension = extname(value).toLowerCase();
if (ktxSupportedextensions.includes(extension)) {
for (const format of allKtxFormats) {
const compressedTexturePath = join(publicDir, getCompressedTextureFilename(value, format));
if (await pathExists(compressedTexturePath)) {
result.push(getCompressedTextureFilename(value, format));
}
}
}
}
})
);

return result;
}
2 changes: 1 addition & 1 deletion cli/src/pack/assets/ktx.mts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export async function compressFileToKtxFormat(absolutePath: string, options: Com
break;

case "-dxt.ktx":
command = `"${pvrTexToolAbsolutePath}" -i "${absolutePath}" -flip y -pot + -m -dither -ics lRGB ${hasAlpha ? "-l" : ""} -f ${hasAlpha ? "BC2" : "BC1"},UBN,lRGB -o "${options.destinationFolder}"`;
command = `"${pvrTexToolAbsolutePath}" -i "${absolutePath}" -flip y -pot + -m -dither -ics lRGB ${hasAlpha ? "-l" : ""} -f ${hasAlpha ? "BC3" : "BC1"},UBN,lRGB -o "${options.destinationFolder}"`;
break;

case "-pvrtc.ktx":
Expand Down
2 changes: 1 addition & 1 deletion cli/src/pack/assets/process.mts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const supportedAudioExtensions: string[] = [".mp3", ".wav", ".wave", ".ogg"];
const supportedJsonExtensions: string[] = [".material", ".gui", ".cinematic", ".npss", ".ragdoll", ".json"];
const supportedMiscExtensions: string[] = [".3dl", ".exr", ".hdr"];

const supportedExtensions: string[] = [
export const supportedExtensions: string[] = [
...supportedImagesExtensions,
...supportedCubeTexturesExtensions,
...supportedAudioExtensions,
Expand Down
30 changes: 27 additions & 3 deletions cli/src/pack/pack.mts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { locatePVRTexTool, setPVRTexToolAbsolutePath } from "../tools/ktx.mjs";
import { ensureSceneDirectories, readSceneDirectories } from "../tools/scene.mjs";

import { createBabylonScene } from "./scene.mjs";
import { createAssets } from "./assets/assets.mjs";
import { createScriptsFile } from "./scripts.mjs";
import { createAssets } from "./assets/assets.mjs";
import { createGeometryFiles } from "./geometry.mjs";

export type PackStepType = "assets" | "scenes" | "scripts" | "upload";
Expand Down Expand Up @@ -113,6 +113,8 @@ export async function pack(projectDir: string, options: IPackOptions) {
}

// Pack scenes
const scenesUsedFiles: Record<string, string[]> = {};

const sceneFiles = await normalizedGlob(`${assetsDirectory}/**/*`, {
nodir: false,
ignore: {
Expand All @@ -135,6 +137,8 @@ export async function pack(projectDir: string, options: IPackOptions) {
await ensureSceneDirectories(sceneFile);

const directories = await readSceneDirectories(sceneFile);

// Config
const sceneConfigPath = join(sceneFile, "config.json");
if (!(await pathExists(sceneConfigPath))) {
sceneLog.warn(`Scene ${sceneFilename} does not have a config.json file. Skipping...`);
Expand All @@ -143,11 +147,21 @@ export async function pack(projectDir: string, options: IPackOptions) {

const config = await fs.readJSON(sceneConfigPath);

// Attributes
const attributesPath = join(sceneFile, "attributes.json");
if (await pathExists(attributesPath)) {
const attributes = await fs.readJSON(attributesPath);
if (attributes.doNotExport) {
sceneLog.info(`Skipped scene ${sceneFilename} because scene is marked as doNotExport.`);
continue;
}
}

options.onStepChanged?.("scenes", {
message: `Packing scene ${sceneName}...`,
});

await createBabylonScene({
const sceneUsedFiles = await createBabylonScene({
...options,
...projectConfiguration,
config,
Expand All @@ -159,6 +173,8 @@ export async function pack(projectDir: string, options: IPackOptions) {
babylonjsEditorToolsVersion,
});

scenesUsedFiles[`${sceneName}.scene`] = sceneUsedFiles.map((asset) => asset.replace(publicDir + "/", ""));

options.onStepChanged?.("scenes", {
message: `Packing scene ${sceneName} geometries...`,
});
Expand Down Expand Up @@ -206,7 +222,7 @@ export async function pack(projectDir: string, options: IPackOptions) {
message: "Collected scripts",
});

// Write list of exported assets
// Write lists of exported assets
const assetsListPath = join(publicDir, "assets-list.json");
await fs.writeJSON(
assetsListPath,
Expand All @@ -219,6 +235,14 @@ export async function pack(projectDir: string, options: IPackOptions) {

exportedAssets.push(assetsListPath);

const scenesUsedFilesPath = join(publicDir, "scenes-used-files.json");
await fs.writeJSON(scenesUsedFilesPath, scenesUsedFiles, {
spaces: "\t",
encoding: "utf-8",
});

exportedAssets.push(scenesUsedFilesPath);

// Clean
if (options.optimize) {
const publicFiles = await normalizedGlob(join(publicDir, "**/*"), {
Expand Down
31 changes: 31 additions & 0 deletions cli/src/pack/scene.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import fs from "fs-extra";
import { readSceneDirectories } from "../tools/scene.mjs";

import { compressFileToKtx } from "./assets/ktx.mjs";
import { collectUsedAssetsForScene } from "./assets/collect.mjs";
import { extractNodeMaterialTextures } from "./assets/material.mjs";
import { getExtractedTextureOutputPath } from "./assets/texture.mjs";
import { extractNodeParticleSystemSetTextures, extractParticleSystemTextures } from "./assets/particle-system.mjs";
Expand Down Expand Up @@ -226,6 +227,7 @@ export async function createBabylonScene(options: ICreateBabylonSceneOptions) {
})
);

// Sprite managers
const spriteManagersResult = await Promise.all(
options.directories.spriteManagerFiles.map(async (file) => {
const data = await fs.readJSON(join(options.sceneFile, "sprite-managers", file));
Expand All @@ -248,6 +250,7 @@ export async function createBabylonScene(options: ICreateBabylonSceneOptions) {
})
);

// Sprite maps
const spriteMapsResult = await Promise.all(
options.directories.spriteMapFiles.map(async (file) => {
const data = await fs.readJSON(join(options.sceneFile, "sprite-maps", file));
Expand All @@ -270,6 +273,29 @@ export async function createBabylonScene(options: ICreateBabylonSceneOptions) {
})
);

// Sound nodes
const soundNodesResults = await Promise.all(
options.directories.soundNodeFiles.map(async (file) => {
const data = await fs.readJSON(join(options.sceneFile, "soundNodes", file));

if (data.metadata?.doNotSerialize) {
return null;
}

if (data.metadata?.parentId) {
data.parentId = data.metadata.parentId;
}

return data;
})
);

transformNodes.push(
...soundNodesResults.filter((soundNode) => {
return soundNode !== null;
})
);

// Lights
const lightsResult = await Promise.all(
options.directories.lightsFiles.map(async (file) => {
Expand Down Expand Up @@ -593,4 +619,9 @@ export async function createBabylonScene(options: ICreateBabylonSceneOptions) {

options.exportedAssets.push(manifestDestination);
}

const usedFiles = await collectUsedAssetsForScene(scene, options.publicDir);
usedFiles.push(`${options.sceneName}.babylon`);

return usedFiles;
}
4 changes: 4 additions & 0 deletions cli/src/tools/scene.mts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export async function ensureSceneDirectories(scenePath: string) {
fs.ensureDir(join(scenePath, "sceneLinks")),
fs.ensureDir(join(scenePath, "gui")),
fs.ensureDir(join(scenePath, "sounds")),
fs.ensureDir(join(scenePath, "soundNodes")),
fs.ensureDir(join(scenePath, "particleSystems")),
fs.ensureDir(join(scenePath, "morphTargetManagers")),
fs.ensureDir(join(scenePath, "morphTargets")),
Expand All @@ -38,6 +39,7 @@ export async function readSceneDirectories(scenePath: string) {
sceneLinkFiles,
guiFiles,
soundFiles,
soundNodeFiles,
particleSystemFiles,
morphTargetManagerFiles,
morphTargetFiles,
Expand All @@ -57,6 +59,7 @@ export async function readSceneDirectories(scenePath: string) {
readdir(join(scenePath, "sceneLinks")),
readdir(join(scenePath, "gui")),
readdir(join(scenePath, "sounds")),
readdir(join(scenePath, "soundNodes")),
readdir(join(scenePath, "particleSystems")),
readdir(join(scenePath, "morphTargetManagers")),
readdir(join(scenePath, "morphTargets")),
Expand All @@ -78,6 +81,7 @@ export async function readSceneDirectories(scenePath: string) {
sceneLinkFiles,
guiFiles,
soundFiles,
soundNodeFiles,
particleSystemFiles,
morphTargetManagerFiles,
morphTargetFiles,
Expand Down
2 changes: 1 addition & 1 deletion editor/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "babylonjs-editor",
"version": "5.4.1-rc.0",
"version": "5.4.1-rc.7",
"description": "Babylon.js Editor is a Web Application helping artists to work with Babylon.js",
"productName": "Babylon.js Editor",
"main": "build/src/index.js",
Expand Down
7 changes: 2 additions & 5 deletions editor/src/editor/dialogs/command-palette/command-palette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { FaCirclePlus } from "react-icons/fa6";
import { IoSparklesSharp } from "react-icons/io5";
import { HiMiniCommandLine } from "react-icons/hi2";

import { Node, IParticleSystem, Sound } from "babylonjs";
import { Node, IParticleSystem } from "babylonjs";

import { normalizedGlob } from "../../../tools/fs";
import { isNodeVisibleInGraph } from "../../../tools/node/metadata";
Expand Down Expand Up @@ -168,10 +168,7 @@ export class CommandPalette extends Component<ICommandPaletteProps, ICommandPale
private _refreshEntities(): void {
const scene = this.props.editor.layout.preview.scene;

let objects = [...scene.meshes, ...scene.lights, ...scene.cameras, ...scene.particleSystems, ...scene.transformNodes] as (Node | IParticleSystem | Sound)[];
scene.soundTracks?.forEach((soundTrack) => {
objects.push(...soundTrack.soundCollection);
});
let objects = [...scene.meshes, ...scene.lights, ...scene.cameras, ...scene.particleSystems, ...scene.transformNodes] as (Node | IParticleSystem)[];

objects = objects.filter((o) => {
if (isNode(o) && !isNodeVisibleInGraph(o)) {
Expand Down
Loading