Portals!
This commit is contained in:
parent
4d59654eef
commit
16ed2a012e
|
@ -1,8 +1,8 @@
|
|||
*.js.map
|
||||
/dummykey.crt
|
||||
/dummykey.key
|
||||
/dummykey.pem
|
||||
/index.js
|
||||
/index.js.map
|
||||
/lib
|
||||
/node_modules
|
||||
/src.ts/
|
||||
|
|
|
@ -6,5 +6,7 @@ PortalDestination =
|
|||
/ @remote <remote <ws @url string> @sturdyref sturdy.SturdyRef>
|
||||
.
|
||||
|
||||
Gravity = <gravity @direction shapes.Vector3> .
|
||||
|
||||
; Message
|
||||
Touch = <touch @subject string @object string> .
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
<Scene "lobby" $config>
|
||||
<Room "other">
|
||||
|
||||
? <Room ?name> [
|
||||
let ?scene = dataspace
|
||||
<Scene $name $scene>
|
||||
]
|
|
@ -0,0 +1,9 @@
|
|||
? <Scene ?name ?scene> [
|
||||
$scene [
|
||||
? <Exit ?spriteName ?roomName> [
|
||||
$config ? <Scene $roomName ?ds> [
|
||||
$scene <portal $spriteName $ds>
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
|
@ -0,0 +1,65 @@
|
|||
? <Scene "lobby" ?scene> $scene [
|
||||
<sprite "light" <hemispheric-light <v 0.1 1.0 0.0>>>
|
||||
<gravity <v 0.0 -9.81 0.0>>
|
||||
|
||||
<sprite "ground"
|
||||
<texture ["textures/grass-256x256.jpg"
|
||||
<v 0.01 0.01>
|
||||
<v 0.0 0.0>]
|
||||
<floor <ground <v 300.0 300.0>>>>>
|
||||
|
||||
<sprite "box"
|
||||
<move <v -6.0 1.0 8.0>
|
||||
<scale <v 10.0 0.1 10.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
|
||||
<v 0.1 0.1>
|
||||
<v 0.0 0.0>
|
||||
0.75]
|
||||
<floor <box>>>>>>
|
||||
|
||||
<sprite "box2"
|
||||
<move <v -500.0 0.5 3.0>
|
||||
<floor
|
||||
<color 0.0 0.0 1.0 1.0
|
||||
<scale <v 1000.0 1.0 1.0> <box>>>>>>
|
||||
|
||||
<sprite "steps"
|
||||
<color 0.0 0.5 0.0
|
||||
<move <v 0.0 0.0 3.5>
|
||||
<scale <v 1.0 1.0 3.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"]
|
||||
[
|
||||
<move <v 0.0 0.25 0.0> <box>>
|
||||
<move <v 1.0 0.0 0.0> <box>>
|
||||
<move <v 2.0 -0.25 0.0> <box>>
|
||||
]>>>>>
|
||||
|
||||
<Exit "ball" "other">
|
||||
<sprite "ball"
|
||||
<move <v 0.0 1.5 2.0>
|
||||
<scale <v 1.0 1.0 1.0>
|
||||
<color 0.0 1.0 0.0
|
||||
<floor
|
||||
<touchable
|
||||
<sphere>>>>>>>
|
||||
|
||||
<sprite "plans"
|
||||
<texture ["plans/signal-2022-12-27-125451_002.jpeg"]
|
||||
<move <v 0.0 1.0 -10.0>
|
||||
<rotate <v 0.5 0.0 0.0>
|
||||
<scale <v 2.0 2.0 0.1>
|
||||
<box>>>>>>
|
||||
|
||||
<sprite "tower"
|
||||
<rotate <v 0.6 0.0 0.0>
|
||||
<move <v -10.0 50.0 13.0>
|
||||
<scale <v 3.0 100.0 3.0>
|
||||
<floor
|
||||
<color 0.5 0.5 0.0
|
||||
<box>>>>>>>
|
||||
|
||||
<sprite "house"
|
||||
<scale <v 10.0 4.0 15.0>
|
||||
<floor
|
||||
<move <v 1.5 0.5 -0.5> <box>>>>>
|
||||
]
|
|
@ -0,0 +1,12 @@
|
|||
? <Scene "other" ?scene> $scene [
|
||||
<sprite "light" <hemispheric-light <v 0.1 1.0 0.0>>>
|
||||
|
||||
<sprite "ground2"
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
|
||||
<v 0.01 0.01>
|
||||
<v 0.0 0.0>]
|
||||
<floor <ground <v 300.0 300.0>>>>>
|
||||
|
||||
<Exit "home" "lobby">
|
||||
<sprite "home" <move <v 0.0 1.5 -5.0> <color 0.0 1.0 0.0 <touchable <sphere>>>>>
|
||||
]
|
|
@ -1,66 +0,0 @@
|
|||
<sprite "light" <hemispheric-light <v 0.1 1.0 0.0>>>
|
||||
|
||||
<sprite "ground"
|
||||
<texture ["textures/grass-256x256.jpg"
|
||||
<v 0.01 0.01>
|
||||
<v 0.0 0.0>]
|
||||
<floor <ground <v 300.0 300.0>>>>>
|
||||
|
||||
<sprite "box"
|
||||
<move <v -6.0 1.0 8.0>
|
||||
<scale <v 10.0 0.1 10.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"
|
||||
<v 0.1 0.1>
|
||||
<v 0.0 0.0>
|
||||
0.75]
|
||||
<floor <box>>>>>>
|
||||
|
||||
<sprite "box2"
|
||||
<move <v -500.0 0.5 3.0>
|
||||
<floor
|
||||
<color 0.0 0.0 1.0 1.0
|
||||
<scale <v 1000.0 1.0 1.0> <box>>>>>>
|
||||
|
||||
<sprite "steps"
|
||||
<color 0.0 0.5 0.0
|
||||
<move <v 0.0 0.0 3.5>
|
||||
<scale <v 1.0 1.0 3.0>
|
||||
<texture ["textures/oak-herringbone-5e80fb40b00c9-1200.jpg"]
|
||||
[
|
||||
<move <v 0.0 0.25 0.0> <box>>
|
||||
<move <v 1.0 0.0 0.0> <box>>
|
||||
<move <v 2.0 -0.25 0.0> <box>>
|
||||
]>>>>>
|
||||
|
||||
let ?ballDs = dataspace
|
||||
<portal "ball" $ballDs>
|
||||
|
||||
<sprite "ball"
|
||||
<move <v 0.0 1.5 2.0>
|
||||
<scale <v 1.0 1.0 1.0>
|
||||
<color 0.0 1.0 0.0
|
||||
<floor
|
||||
<touchable
|
||||
<sphere>>>>>>>
|
||||
|
||||
<sprite "plans"
|
||||
<texture ["plans/signal-2022-12-27-125451_002.jpeg"]
|
||||
<move <v 0.0 1.0 -10.0>
|
||||
<rotate <v 0.5 0.0 0.0>
|
||||
<scale <v 2.0 2.0 0.1>
|
||||
<box>>>>>>
|
||||
|
||||
<sprite "tower"
|
||||
<rotate <v 0.6 0.0 0.0>
|
||||
<move <v -10.0 50.0 13.0>
|
||||
<scale <v 3.0 100.0 3.0>
|
||||
<floor
|
||||
<color 0.5 0.5 0.0
|
||||
<box>>>>>>>
|
||||
|
||||
<sprite "house"
|
||||
<scale <v 10.0 4.0 15.0>
|
||||
<floor
|
||||
<move <v 1.5 0.5 -0.5> <box>>>>>
|
||||
|
||||
[]
|
|
@ -45,9 +45,7 @@ if ((navigator as any).oscpu?.startsWith('Linux')) {
|
|||
};
|
||||
}
|
||||
|
||||
export type CreateScene = (engine: Engine) => Promise<CreatedScene>;
|
||||
export type CreatedScene = {
|
||||
scene: Scene,
|
||||
export type Interactivity = {
|
||||
floorMeshes: () => Mesh[],
|
||||
touchableMeshes: () => Mesh[],
|
||||
};
|
||||
|
@ -87,9 +85,9 @@ export class GamepadState {
|
|||
}
|
||||
|
||||
export class RunningEngine {
|
||||
camera: FreeCamera;
|
||||
xrSessionManager: WebXRSessionManager | null;
|
||||
gamepadInput: FreeCameraGamepadInput;
|
||||
camera!: FreeCamera;
|
||||
xrSessionManager: WebXRSessionManager | null = null;
|
||||
gamepadInput!: FreeCameraGamepadInput;
|
||||
|
||||
leanBase: { position: Vector3 } | null = null;
|
||||
recenterBase: { rotation: Quaternion } | null = null;
|
||||
|
@ -97,7 +95,7 @@ export class RunningEngine {
|
|||
padStates: Map<Gamepad, GamepadState> = new Map();
|
||||
|
||||
static async start(
|
||||
createScene: CreateScene,
|
||||
interactivity: Interactivity,
|
||||
options0: Partial<EngineOptions> = {},
|
||||
): Promise<RunningEngine> {
|
||||
const options = Object.assign({
|
||||
|
@ -106,15 +104,16 @@ export class RunningEngine {
|
|||
canvas: document.getElementById("renderCanvas") as HTMLCanvasElement,
|
||||
}, options0);
|
||||
const engine = new Engine(options.canvas, true);
|
||||
const createdScene = await createScene(engine);
|
||||
const xr = await createdScene.scene.createDefaultXRExperienceAsync({});
|
||||
return new RunningEngine(options, engine, createdScene, xr);
|
||||
const scene = new Scene(engine);
|
||||
const xr = await scene.createDefaultXRExperienceAsync({});
|
||||
return new RunningEngine(options, engine, interactivity, scene, xr);
|
||||
}
|
||||
|
||||
private constructor (
|
||||
public options: EngineOptions,
|
||||
public engine: Engine,
|
||||
public createdScene: CreatedScene,
|
||||
public interactivity: Interactivity,
|
||||
public scene: Scene,
|
||||
public xr: WebXRDefaultExperience,
|
||||
) {
|
||||
this.xrSessionManager = this.xr.baseExperience?.sessionManager ?? null;
|
||||
|
@ -124,7 +123,7 @@ export class RunningEngine {
|
|||
} else {
|
||||
this.camera = new FreeCamera("camera",
|
||||
this.options.initialPos,
|
||||
this.createdScene.scene);
|
||||
this.scene);
|
||||
this.camera.rotation = this.options.initialRotation;
|
||||
this.camera.minZ = 0.1;
|
||||
this.camera.inertia = 0.75;
|
||||
|
@ -138,12 +137,13 @@ export class RunningEngine {
|
|||
this.camera.inputs.add(this.gamepadInput);
|
||||
this.gamepadInput.attachControl();
|
||||
|
||||
this.createdScene.scene.gravity = new Vector3(0, -9.81 / 90, 0);
|
||||
this.createdScene.scene.collisionsEnabled = true;
|
||||
this.scene.gravity = new Vector3(0, -9.81 / 90, 0);
|
||||
this.scene.collisionsEnabled = true;
|
||||
|
||||
this.camera.checkCollisions = true;
|
||||
this.camera.applyGravity = true;
|
||||
this.camera.ellipsoid = new Vector3(0.25, 0.8, 0.25);
|
||||
this.camera.applyGravity = false;
|
||||
(this.camera as any)._needMoveForGravity = true;
|
||||
this.camera.ellipsoid = new Vector3(0.25, this.options.initialPos.y / 2, 0.25);
|
||||
|
||||
if (this.options.canvas) {
|
||||
const canvas = this.options.canvas;
|
||||
|
@ -158,8 +158,9 @@ export class RunningEngine {
|
|||
Array.from(navigator.getGamepads()).forEach(gp => {
|
||||
if (gp !== null) this.checkGamepadInput(gp);
|
||||
});
|
||||
this.createdScene.scene.render();
|
||||
this.scene.render();
|
||||
});
|
||||
|
||||
window.addEventListener("resize", () => this.engine.resize());
|
||||
}
|
||||
|
||||
|
@ -226,8 +227,8 @@ export class RunningEngine {
|
|||
|
||||
xrTouch() {
|
||||
const ray = this.xr.baseExperience.camera.getForwardRay();
|
||||
const meshes = this.createdScene.touchableMeshes();
|
||||
const hit = this.createdScene.scene.pickWithRay(ray, m => meshes.indexOf(m as any) !== -1);
|
||||
const meshes = this.interactivity.touchableMeshes();
|
||||
const hit = this.scene.pickWithRay(ray, m => meshes.indexOf(m as any) !== -1);
|
||||
|
||||
if (hit === null) return;
|
||||
if (meshes.indexOf(hit.pickedMesh as any) === -1) return;
|
||||
|
@ -239,8 +240,8 @@ export class RunningEngine {
|
|||
if (!this.xrSessionManager) return;
|
||||
|
||||
const ray = this.xr.baseExperience.camera.getForwardRay();
|
||||
const meshes = this.createdScene.floorMeshes();
|
||||
const hit = this.createdScene.scene.pickWithRay(ray, m => meshes.indexOf(m as any) !== -1);
|
||||
const meshes = this.interactivity.floorMeshes();
|
||||
const hit = this.scene.pickWithRay(ray, m => meshes.indexOf(m as any) !== -1);
|
||||
|
||||
if (hit === null) return;
|
||||
if (meshes.indexOf(hit.pickedMesh as any) === -1) return;
|
||||
|
|
249
src/index.ts
249
src/index.ts
|
@ -1,4 +1,4 @@
|
|||
import { is, Dataspace, Embedded, Reader, Ref, Schemas, Sturdy, Turn } from "@syndicate-lang/core";
|
||||
import { is, embed, stringify, Dataflow, Dataspace, Embedded, Reader, Ref, Schemas, Sturdy, Turn, Value } from "@syndicate-lang/core";
|
||||
import * as html from "@syndicate-lang/html";
|
||||
import * as timer from "@syndicate-lang/timer";
|
||||
import * as wsRelay from "@syndicate-lang/ws-relay";
|
||||
|
@ -14,16 +14,17 @@ import {
|
|||
Mesh,
|
||||
Scene,
|
||||
TargetCamera,
|
||||
Vector3,
|
||||
WebXRCamera,
|
||||
} from '@babylonjs/core/Legacy/legacy';
|
||||
|
||||
import { activeFloorMeshes, activeTouchableMeshes, ShapeTree, builder as B } from './shapes.js';
|
||||
import { RunningEngine, CreatedScene } from './engine.js';
|
||||
import { RunningEngine } from './engine.js';
|
||||
import { uuid } from './uuid.js';
|
||||
|
||||
assertion type SceneHandle(ds: Embedded<Ref>);
|
||||
|
||||
function interpretScene(myId: string, scene: Scene, sceneDs: Ref) {
|
||||
function interpretScene(myId: string, scene: Scene, rootMesh: Mesh, sceneDs: Ref) {
|
||||
at sceneDs {
|
||||
during Shapes.Sprite({ "name": $name: string }) => spawn named `sprite:${name}` {
|
||||
if (name === myId) {
|
||||
|
@ -31,22 +32,153 @@ function interpretScene(myId: string, scene: Scene, sceneDs: Ref) {
|
|||
} else {
|
||||
console.log('+shape', name);
|
||||
on stop console.log('-shape', name);
|
||||
spriteMain(name, scene, sceneDs);
|
||||
spriteMain(name, scene, rootMesh, sceneDs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function spriteMain(spriteName: string, scene: Scene, sceneDs: Ref) {
|
||||
function spriteMain(spriteName: string, scene: Scene, rootMesh: Mesh, sceneDs: Ref) {
|
||||
at sceneDs {
|
||||
let currentShape = ShapeTree.empty(spriteName, scene);
|
||||
currentShape.node.parent = rootMesh;
|
||||
on stop currentShape.remove();
|
||||
during Shapes.Sprite({ "name": spriteName, "shape": $shape: Shapes.Shape }) => {
|
||||
currentShape = currentShape.reconcile(spriteName, spriteName, shape);
|
||||
currentShape.node.parent = rootMesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function enterScene(
|
||||
id: string,
|
||||
runningEngine: RunningEngine,
|
||||
ds: Ref,
|
||||
sceneDs: Ref,
|
||||
email: Dataflow.Field<string>,
|
||||
) {
|
||||
const currentSceneFacet = Turn.activeFacet;
|
||||
|
||||
console.log('enterScene', sceneDs);
|
||||
|
||||
const rootMesh = new Mesh('--root-' + (+new Date()), runningEngine.scene);
|
||||
interpretScene(id, runningEngine.scene, rootMesh, sceneDs);
|
||||
|
||||
const camera = runningEngine.camera;
|
||||
camera.applyGravity = false;
|
||||
camera.position = runningEngine.options.initialPos;
|
||||
|
||||
let lastTouchTime = 0;
|
||||
let lastTouchSpriteName = "";
|
||||
camera.onCollide = (other: AbstractMesh) => {
|
||||
if (other.metadata?.touchable) {
|
||||
const now = +new Date();
|
||||
const touched = other.metadata?.spriteName ?? "";
|
||||
if ((now - lastTouchTime > 500) || (lastTouchSpriteName !== touched)) {
|
||||
currentSceneFacet.turn(() => {
|
||||
at sceneDs {
|
||||
send message SceneProtocol.Touch({
|
||||
subject: id,
|
||||
object: touched,
|
||||
});
|
||||
}
|
||||
});
|
||||
lastTouchTime = now;
|
||||
lastTouchSpriteName = touched;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const currentPosition = () => Shapes.Vector3(camera.position);
|
||||
const currentRotation = () => Shapes.Vector3(
|
||||
camera instanceof WebXRCamera
|
||||
? camera.rotationQuaternion.toEulerAngles()
|
||||
: camera.rotation);
|
||||
|
||||
field position: Shapes.Vector3 = currentPosition();
|
||||
field rotation: Shapes.Vector3 = currentRotation();
|
||||
|
||||
const refreshPeriod = Math.floor(1000 / 10);
|
||||
at ds {
|
||||
on message timer.PeriodicTick(refreshPeriod) => {
|
||||
const newPosition = currentPosition();
|
||||
const newRotation = currentRotation();
|
||||
if (!is(Shapes.fromVector3(position.value), Shapes.fromVector3(newPosition))) {
|
||||
position.value = newPosition;
|
||||
}
|
||||
if (!is(Shapes.fromVector3(rotation.value), Shapes.fromVector3(newRotation))) {
|
||||
rotation.value = newRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
at sceneDs {
|
||||
during SceneProtocol.Gravity($direction: Shapes.Vector3) => {
|
||||
camera.applyGravity = true;
|
||||
on stop camera.applyGravity = false;
|
||||
const frameRate = 60;
|
||||
runningEngine.scene.gravity = new Vector3(direction.x / frameRate,
|
||||
direction.y / frameRate,
|
||||
direction.z / frameRate);
|
||||
}
|
||||
|
||||
on message SceneProtocol.Touch({ "subject": id, "object": $o }) => {
|
||||
console.log('touched', o);
|
||||
react {
|
||||
let needStop = true;
|
||||
on asserted SceneProtocol.Portal({
|
||||
"name": o,
|
||||
"destination": $dest: SceneProtocol.PortalDestination
|
||||
}) => {
|
||||
needStop = false;
|
||||
switch (dest._variant) {
|
||||
case "local":
|
||||
runningEngine.scene.removeMesh(rootMesh, true);
|
||||
Turn.active.stop(currentSceneFacet, () => {
|
||||
react {
|
||||
enterScene(id, runningEngine, ds, dest.value, email);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
const checkFacet = Turn.activeFacet;
|
||||
Turn.active.sync(sceneDs).then(() => checkFacet.turn(() => {
|
||||
if (needStop) {
|
||||
stop {}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
assert Shapes.Sprite({
|
||||
name: id,
|
||||
shape: B.nonphysical(
|
||||
B.move(position.value, B.many([
|
||||
B.move({ x: 0, y: -0.9, z: 0 },
|
||||
B.rotate({ x: 0, y: rotation.value.y, z: 0 },
|
||||
B.scale({ x: 0.4, y: 1.4, z: 0.1 }, B.box()))),
|
||||
B.rotate(rotation.value,
|
||||
B.scale({ x: 0.15, y: 0.23, z: 0.18 }, B.many([
|
||||
B.box(),
|
||||
B.move({ x: 0, y: 0, z: 0.501 },
|
||||
B.texture(
|
||||
Shapes.TextureSpec.uvAlpha({
|
||||
path: `https://www.gravatar.com/avatar/${md5(new TextEncoder().encode(email.value.trim()))}?s=256&d=wavatar`,
|
||||
scale: Shapes.Vector2({ x:1, y:1 }),
|
||||
offset: Shapes.Vector2({ x:0, y:0 }),
|
||||
alpha: 1
|
||||
}),
|
||||
B.rotate({ x: 0, y: Math.PI, z: 0 },
|
||||
B.plane()))),
|
||||
]))),
|
||||
]))),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function wsurl(): string {
|
||||
const scheme = (document.location.protocol.toLowerCase() === 'https:') ? 'wss' : 'ws';
|
||||
return `${scheme}://${document.location.host}/ws`;
|
||||
|
@ -82,99 +214,12 @@ function bootApp(ds: Ref, runningEngine: RunningEngine) {
|
|||
send message wsRelay.ForceRelayDisconnect(relayAddr);
|
||||
}
|
||||
|
||||
at remoteDs {
|
||||
during SceneHandle($sceneDs_e: Embedded) => {
|
||||
const thisFacet = Turn.activeFacet;
|
||||
const sceneDs = sceneDs_e.embeddedValue;
|
||||
interpretScene(id, runningEngine.createdScene.scene, sceneDs);
|
||||
|
||||
const camera = runningEngine.camera;
|
||||
camera.onCollide = (other: AbstractMesh) => {
|
||||
if (other.metadata?.touchable) {
|
||||
thisFacet.turn(() => {
|
||||
at sceneDs {
|
||||
send message SceneProtocol.Touch({
|
||||
subject: id,
|
||||
object: other.metadata?.spriteName,
|
||||
});
|
||||
}
|
||||
});
|
||||
react {
|
||||
at remoteDs {
|
||||
stop on asserted SceneHandle($sceneDs_e: Embedded) => {
|
||||
react {
|
||||
enterScene(id, runningEngine, ds, sceneDs_e.embeddedValue, email);
|
||||
}
|
||||
};
|
||||
|
||||
field position: Shapes.Vector3 = Shapes.Vector3({ x:0, y:0, z:0 });
|
||||
field rotation: Shapes.Vector3 = Shapes.Vector3({ x:0, y:0, z:0 });
|
||||
|
||||
at ds {
|
||||
const refreshPeriod = Math.floor(1000 / 10);
|
||||
on message timer.PeriodicTick(refreshPeriod) => {
|
||||
if (camera instanceof TargetCamera) {
|
||||
const newPosition = Shapes.Vector3(camera.position);
|
||||
const newRotation = Shapes.Vector3(camera instanceof WebXRCamera
|
||||
? camera.rotationQuaternion.toEulerAngles()
|
||||
: camera.rotation);
|
||||
if (!is(Shapes.fromVector3(position.value), Shapes.fromVector3(newPosition))) {
|
||||
position.value = newPosition;
|
||||
}
|
||||
if (!is(Shapes.fromVector3(rotation.value), Shapes.fromVector3(newRotation))) {
|
||||
rotation.value = newRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
at sceneDs {
|
||||
on message SceneProtocol.Touch({ "subject": id, "object": $o }) => {
|
||||
console.log('touch!', o);
|
||||
react {
|
||||
on stop console.log('portal check ending', o);
|
||||
stop on asserted SceneProtocol.Portal({
|
||||
"name": o,
|
||||
"destination": $dest: SceneProtocol.PortalDestination
|
||||
}) => react {
|
||||
console.log('portal!', dest);
|
||||
switch (dest._variant) {
|
||||
case "local":
|
||||
at dest.value {
|
||||
assert 909909909;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
const checkFacet = Turn.activeFacet;
|
||||
Turn.active.sync(sceneDs).then(() => checkFacet.turn(() => {
|
||||
console.log('synced');
|
||||
stop {}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
assert Shapes.Sprite({
|
||||
name: id,
|
||||
shape: B.nonphysical(
|
||||
B.move(position.value, B.many([
|
||||
B.move({ x: 0, y: -0.9, z: 0 },
|
||||
B.rotate({ x: 0, y: rotation.value.y, z: 0 },
|
||||
B.scale({ x: 0.4, y: 1.4, z: 0.1 },
|
||||
B.box()))),
|
||||
B.rotate(rotation.value,
|
||||
B.scale({ x: 0.15, y: 0.23, z: 0.18 }, B.many([
|
||||
B.box(),
|
||||
B.move({ x: 0, y: 0, z: 0.501 },
|
||||
B.texture(
|
||||
Shapes.TextureSpec.uvAlpha({
|
||||
path: `https://www.gravatar.com/avatar/${md5(new TextEncoder().encode(email.value.trim()))}?s=256&d=wavatar`,
|
||||
scale: Shapes.Vector2({ x:1, y:1 }),
|
||||
offset: Shapes.Vector2({ x:0, y:0 }),
|
||||
alpha: 1
|
||||
}),
|
||||
B.rotate({ x: 0, y: Math.PI, z: 0 },
|
||||
B.plane()))),
|
||||
]))),
|
||||
]))),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -184,12 +229,10 @@ function bootApp(ds: Ref, runningEngine: RunningEngine) {
|
|||
}
|
||||
|
||||
window.addEventListener('load', async () => {
|
||||
const runningEngine = await RunningEngine.start(
|
||||
async (engine: Engine): Promise<CreatedScene> => ({
|
||||
scene: new Scene(engine),
|
||||
floorMeshes: () => activeFloorMeshes,
|
||||
touchableMeshes: () => activeTouchableMeshes,
|
||||
}));
|
||||
const runningEngine = await RunningEngine.start({
|
||||
floorMeshes: () => activeFloorMeshes,
|
||||
touchableMeshes: () => activeTouchableMeshes,
|
||||
});
|
||||
Dataspace.boot(ds => {
|
||||
html.boot(ds);
|
||||
timer.boot(ds);
|
||||
|
|
Loading…
Reference in New Issue