feat(web): extend scene render audio and unit authoring
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-29 13:13:04 +08:00
parent b1ec8d29f6
commit ab03be9046
118 changed files with 7549 additions and 44 deletions

View File

@@ -597,6 +597,54 @@ function assertFutureCapability(payload: Extract<WebEngineRequest["command"], {
}
return;
}
case "setSceneProperties": {
const scene = currentSnapshot?.scenes.find((candidate) => candidate.id === payload.dataId);
const properties = payload.properties;
if (!scene || !validPropertyKeys(properties, ["renderEngine", "viewTransform", "look", "exposure", "gamma"])) throw report("RENDER_PROPERTY_INVALID", "Scene target or properties are invalid");
for (const field of ["renderEngine", "viewTransform", "look"] as const) {
const value = properties[field];
if (value !== undefined && (typeof value !== "string" || value.length === 0 || new TextEncoder().encode(value).byteLength > 63)) throw report("RENDER_PROPERTY_INVALID", `Scene ${field} is not a bounded string`);
}
for (const [field, minimum, maximum] of [["exposure", -1000, 1000], ["gamma", 0, 1000]] as const) {
const value = properties[field];
if (value !== undefined && !boundedNumber(value, minimum, maximum)) throw report("RENDER_PROPERTY_INVALID", `Scene ${field} is outside the bounded range`);
}
return;
}
case "setSceneRenderSettings": {
const scene = currentSnapshot?.scenes.find((candidate) => candidate.id === payload.dataId);
const properties = payload.properties;
if (!scene || !validPropertyKeys(properties, ["resolutionX", "resolutionY", "resolutionPercentage", "frameStart", "frameEnd", "outputPath"])) throw report("RENDER_PROPERTY_INVALID", "Scene render target or properties are invalid");
for (const [field, minimum, maximum] of [["resolutionX", 1, 65536], ["resolutionY", 1, 65536], ["resolutionPercentage", 1, 1000], ["frameStart", -1000000, 1000000], ["frameEnd", -1000000, 1000000]] as const) {
const value = properties[field];
if (value !== undefined && (!Number.isSafeInteger(value) || value < minimum || value > maximum)) throw report("RENDER_PROPERTY_INVALID", `Scene ${field} is outside the bounded integer range`);
}
if (properties.frameStart !== undefined && properties.frameEnd !== undefined && properties.frameEnd < properties.frameStart) throw report("RENDER_PROPERTY_INVALID", "Scene frameEnd must not precede frameStart");
if (properties.outputPath !== undefined && (typeof properties.outputPath !== "string" || properties.outputPath.length === 0 || new TextEncoder().encode(properties.outputPath).byteLength > 1023)) throw report("RENDER_PROPERTY_INVALID", "Scene outputPath is not a bounded path");
return;
}
case "setSceneAudioSettings": {
const scene = currentSnapshot?.scenes.find((candidate) => candidate.id === payload.dataId);
const properties = payload.properties;
if (!scene || !validPropertyKeys(properties, ["volume", "speedOfSound", "dopplerFactor", "distanceModel", "muted", "sync"])) throw report("RENDER_PROPERTY_INVALID", "Scene audio target or properties are invalid");
for (const [field, minimum, maximum] of [["volume", 0, 10], ["speedOfSound", 0, 10000], ["dopplerFactor", 0, 100], ["distanceModel", 0, 32]] as const) {
const value = properties[field];
if (value !== undefined && !boundedNumber(value, minimum, maximum)) throw report("RENDER_PROPERTY_INVALID", `Scene ${field} is outside the bounded range`);
}
for (const field of ["muted", "sync"] as const) if (properties[field] !== undefined && typeof properties[field] !== "boolean") throw report("RENDER_PROPERTY_INVALID", `Scene ${field} must be boolean`);
return;
}
case "setSceneUnitSettings": {
const scene = currentSnapshot?.scenes.find((candidate) => candidate.id === payload.dataId);
const properties = payload.properties;
if (!scene || !validPropertyKeys(properties, ["system", "scaleLength", "rotationSystem", "lengthUnit", "massUnit", "timeUnit", "temperatureUnit"])) throw report("RENDER_PROPERTY_INVALID", "Scene unit target or properties are invalid");
for (const [field, minimum, maximum] of [["system", 0, 8], ["rotationSystem", 0, 8], ["lengthUnit", 0, 32], ["massUnit", 0, 32], ["timeUnit", 0, 32], ["temperatureUnit", 0, 32]] as const) {
const value = properties[field];
if (value !== undefined && (!Number.isSafeInteger(value) || value < minimum || value > maximum)) throw report("RENDER_PROPERTY_INVALID", `Scene ${field} is outside the bounded unit enum`);
}
if (properties.scaleLength !== undefined && !boundedNumber(properties.scaleLength, 0, 1_000_000)) throw report("RENDER_PROPERTY_INVALID", "Scene scaleLength is outside the bounded range");
return;
}
case "setGeometryNodeGraph": {
const snapshot = currentSnapshot;
const availableResourceIds = new Set([