feat(web): add audio speaker and particle authoring
This commit is contained in:
@@ -420,6 +420,33 @@ function assertFutureCapability(payload: Extract<WebEngineRequest["command"], {
|
||||
if (typeof payload.source !== "string" || new TextEncoder().encode(payload.source).byteLength > 1_048_576) throw report("NON_MESH_PROPERTY_INVALID", "Text source must be valid UTF-8 within the 1 MiB budget");
|
||||
return;
|
||||
}
|
||||
case "setSoundProperties": {
|
||||
const sound = currentSnapshot?.sounds?.find((candidate) => candidate.id === payload.dataId);
|
||||
if (!sound) throw report("NON_MESH_DATA_UNSUPPORTED", `Sound data block is unavailable: ${payload.dataId}`);
|
||||
if (!validPropertyKeys(payload.properties, ["volume", "attenuation", "pitch", "minGain", "maxGain", "distance", "offsetTime"])) throw report("NON_MESH_PROPERTY_INVALID", "Sound properties are empty or contain unsupported fields");
|
||||
for (const value of Object.values(payload.properties)) if (!boundedNumber(value, 0, 1_000_000)) throw report("NON_MESH_PROPERTY_INVALID", "Sound properties are outside the bounded range");
|
||||
return;
|
||||
}
|
||||
case "setSpeakerProperties": {
|
||||
const speaker = currentSnapshot?.speakers?.find((candidate) => candidate.id === payload.dataId);
|
||||
if (!speaker) throw report("NON_MESH_DATA_UNSUPPORTED", `Speaker data block is unavailable: ${payload.dataId}`);
|
||||
if (!validPropertyKeys(payload.properties, ["volumeMax", "volumeMin", "distanceMax", "distanceReference", "attenuation", "coneAngleOuter", "coneAngleInner", "coneVolumeOuter", "volume", "pitch"])) throw report("NON_MESH_PROPERTY_INVALID", "Speaker properties are empty or contain unsupported fields");
|
||||
for (const [key, value] of Object.entries(payload.properties)) {
|
||||
const maximum = key.startsWith("coneAngle") ? 360 : key === "coneVolumeOuter" ? 1 : 1_000_000;
|
||||
if (!boundedNumber(value, 0, maximum)) throw report("NON_MESH_PROPERTY_INVALID", "Speaker properties are outside the bounded range");
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "setParticleSettings": {
|
||||
const settings = currentSnapshot?.particleSettings?.find((candidate) => candidate.id === payload.dataId);
|
||||
if (!settings) throw report("NON_MESH_DATA_UNSUPPORTED", `ParticleSettings data block is unavailable: ${payload.dataId}`);
|
||||
if (!validPropertyKeys(payload.properties, ["type", "from", "distribution", "physicsType", "totalParticles", "start", "end", "lifetime", "size", "drawSize"])) throw report("NON_MESH_PROPERTY_INVALID", "Particle settings are empty or contain unsupported fields");
|
||||
for (const [key, value] of Object.entries(payload.properties)) {
|
||||
if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1_000_000) throw report("NON_MESH_PROPERTY_INVALID", `Particle setting ${key} is outside the bounded range`);
|
||||
if (["type", "from", "distribution", "physicsType", "totalParticles"].includes(key) && !Number.isSafeInteger(value)) throw report("NON_MESH_PROPERTY_INVALID", `Particle setting ${key} must be an integer`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "setVolumeProperties": {
|
||||
const data = currentSnapshot?.nonMeshData?.find((candidate) => candidate.id === payload.dataId);
|
||||
if (!data || data.type !== "VOLUME") throw report("NON_MESH_DATA_UNSUPPORTED", `N-015 Volume data block is unavailable: ${payload.dataId}`);
|
||||
|
||||
Reference in New Issue
Block a user