Better sounds; actually run cleanups (!)

This commit is contained in:
Tony Garnock-Jones 2023-01-12 16:34:54 +01:00
parent cb53f9b16f
commit a1f3db6e1b
8 changed files with 74 additions and 24 deletions

View File

@ -8,5 +8,12 @@ PortalDestination =
Gravity = <gravity @direction shapes.Vector3> .
AmbientSound = <ambient-sound @name string @spec SoundSpec> .
SoundSpec =
/ @stream <stream @url string>
/ @loop <loop @url string>
.
; Message
Touch = <touch @subject string @object string> .

View File

@ -34,7 +34,7 @@ Color =
/ @transparent <color @r double @g double @b double @alpha double @shape Shape>
.
Sound = <sound @url string @shape Shape> .
Sound = <sound @spec scene.SoundSpec @shape Shape> .
Name = <name @base string @shape Shape> .

View File

@ -76,14 +76,13 @@
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
<v 1.0 3.0 1.0>
<v 0.0 0.0 0.0>]
<sound "https://streams.95bfm.com/stream95"
<sound <stream "https://streams.95bfm.com/stream95">
<csg
<subtract [
<move <v 0.0 0.0 0.5> <scale <v 1.1 3.1 1.1> <mesh <box>>>>
<move <v 0.0 0.0 0.5> <scale <v 1.0 3.0 1.0> <mesh <box>>>>
]>
>>
>>>
>>>>>
; <Exit "y" "lobby">
; <sprite "y"

View File

@ -2,6 +2,8 @@
;<gravity <v 0.0 -9.81 0.0>>
<sprite "sky" <skybox "textures/eso0932a">>
<ambient-sound "space" <loop "sounds/Space-atmosphere-sound/Space-atmosphere-sound.mp3">>
; <sprite "ground2"
; <texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
; <v 100.0 100.0>

View File

@ -0,0 +1,15 @@
Hello from Orange Free Sounds,
Stock audio - Free sound effects, loops and music.
There are no hidden costs or need to sign-up.
License: The sound effect is permitted for non-commercial use under license “Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
https://orangefreesounds.com/

View File

@ -15,7 +15,7 @@ import {
WebXRCamera,
} from '@babylonjs/core/Legacy/legacy';
import { activeFloorMeshes, activeTouchableMeshes, ShapeTree, scale3, builder as B } from './shapes.js';
import { activeFloorMeshes, activeTouchableMeshes, ShapeTree, scale3, buildSound, builder as B } from './shapes.js';
import { RunningEngine } from './engine.js';
import { uuid } from './uuid.js';
@ -32,6 +32,14 @@ function interpretScene(myId: string, runningEngine: RunningEngine, rootMesh: Me
spriteMain(name, runningEngine, rootMesh, sceneDs);
}
}
during SceneProtocol.AmbientSound({
"name": $name: string,
"spec": $spec: SceneProtocol.SoundSpec
}) => spawn named `sound:${name}` {
const sound = buildSound(name, runningEngine.scene, spec, false);
on stop sound.dispose();
}
}
}

View File

@ -4,6 +4,7 @@ import {
CubeTexture,
CSG,
HemisphericLight,
ISoundOptions,
Material,
Matrix,
Mesh,
@ -22,6 +23,7 @@ import {
import { KeyedDictionary, Value, is } from "@syndicate-lang/core";
import * as Shapes from './gen/shapes.js';
import * as SceneProtocol from './gen/scene.js';
export const activeFloorMeshes: Array<AbstractMesh> = [];
export const activeTouchableMeshes: Array<AbstractMesh> = [];
@ -30,6 +32,7 @@ export class ShapeTree<N extends Node = Node> {
shapePreserve: Value;
cleanups: Array<() => void> = [];
subnodes: Promise<N[]>;
subtrees: ShapeTree[] = [];
constructor (
public scene: Scene,
@ -60,8 +63,15 @@ export class ShapeTree<N extends Node = Node> {
}
}
set parent(t: ShapeTree) {
t.subtrees.push(this);
this.rootnode.parent = t.rootnode;
}
remove() {
this.subtrees.forEach(t => t.remove());
this.allnodes.then(ns => ns.forEach(n => n.dispose()));
this.cleanups.forEach(c => c());
}
static empty(name: string, scene: Scene): ShapeTree {
@ -181,6 +191,26 @@ export function buildMesh(
}
}
export function buildSound(name: string, scene: Scene, spec: SceneProtocol.SoundSpec, spatial: boolean): Sound {
const options: ISoundOptions = {
loop: true,
autoplay: true,
skipCodecCheck: true,
};
if (spatial) {
options.distanceModel = "inverse";
options.rolloffFactor = 0.25;
}
switch (spec._variant) {
case "stream":
options.streaming = true;
break;
case "loop":
break;
}
return new Sound(name, spec.url, scene, null, options);
}
export function build(name: string, scene: Scene, shape: Shapes.Shape, customize: MeshCustomizer): ShapeTree {
switch (shape._variant) {
case "Mesh": {
@ -199,14 +229,14 @@ export function build(name: string, scene: Scene, shape: Shapes.Shape, customize
case "Scale": {
const t = ShapeTree.transform(name, scene, shape);
t.rootnode.scaling = v3(shape.value.v);
build(name + '.inner', scene, shape.value.shape, customize).rootnode.parent = t.rootnode;
build(name + '.inner', scene, shape.value.shape, customize).parent = t;
return t;
}
case "Move": {
const t = ShapeTree.transform(name, scene, shape);
t.rootnode.position = v3(shape.value.v);
build(name + '.inner', scene, shape.value.shape, customize).rootnode.parent = t.rootnode;
build(name + '.inner', scene, shape.value.shape, customize).parent = t;
return t;
}
@ -221,14 +251,14 @@ export function build(name: string, scene: Scene, shape: Shapes.Shape, customize
t.rootnode.rotationQuaternion = q(shape.value.q);
break;
}
build(name + '.inner', scene, shape.value.shape, customize).rootnode.parent = t.rootnode;
build(name + '.inner', scene, shape.value.shape, customize).parent = t;
return t;
}
case "many": {
const t = ShapeTree.transform(name, scene, shape);
shape.value.forEach((s, i) => {
build(name + '[' + i + ']', scene, s, customize).rootnode.parent = t.rootnode;
build(name + '[' + i + ']', scene, s, customize).parent = t;
});
return t;
}
@ -254,24 +284,13 @@ export function build(name: string, scene: Scene, shape: Shapes.Shape, customize
}
case "Sound": {
const sound = new Sound(
name + ".sound",
shape.value.url,
scene,
null,
{
distanceModel: "inverse",
loop: true,
rolloffFactor: 0.25,
autoplay: true,
streaming: true,
skipCodecCheck: true,
});
console.log(sound);
return build(name + ".inner", scene, shape.value.shape, {
const sound = buildSound(name + ".sound", scene, shape.value.spec, true);
const t = build(name + ".inner", scene, shape.value.shape, {
... customize,
sound: async m => sound.attachToMesh(m.rootnode),
});
t.cleanups.push(() => sound.dispose());
return t;
}
case "Name":