Introduction revamp.

This commit is contained in:
Michael Mainguy 2024-04-24 07:19:15 -05:00
parent c81dd8c24a
commit fbc39f2103
5 changed files with 88 additions and 192 deletions

View File

@ -3,13 +3,14 @@ import {v4 as uuidv4} from 'uuid';
import log, {Logger} from "loglevel"; import log, {Logger} from "loglevel";
import {buildStandardMaterial} from "../materials/functions/buildStandardMaterial"; import {buildStandardMaterial} from "../materials/functions/buildStandardMaterial";
const logger: Logger = log.getLogger('DiagramConnection');
export class DiagramConnection { export class DiagramConnection {
private logger: Logger = log.getLogger('DiagramConnection');
private readonly id: string; private readonly id: string;
constructor(from: string, to: string, id: string, scene?: Scene, gripTransform?: TransformNode, clickPoint?: Vector3) { constructor(from: string, to: string, id: string, scene?: Scene, gripTransform?: TransformNode, clickPoint?: Vector3) {
this.logger.debug('buildConnection constructor'); logger.debug('buildConnection constructor');
if (id) { if (id) {
this.id = id; this.id = id;
} else { } else {
@ -45,7 +46,7 @@ export class DiagramConnection {
this.toAnchor = to; this.toAnchor = to;
} else { } else {
this.logger.info("no fromMesh yet, will build when toMesh is available"); logger.info("no fromMesh yet, will build when toMesh is available");
} }
} }
this.buildConnection(); this.buildConnection();
@ -126,7 +127,7 @@ export class DiagramConnection {
} }
private buildConnection() { private buildConnection() {
this.logger.debug(`buildConnection from ${this._from} to ${this._to}`); logger.debug(`buildConnection from ${this._from} to ${this._to}`);
this._mesh = MeshBuilder.CreateCylinder(this.id + "_connection", {diameter: .025, height: 1}, this.scene); this._mesh = MeshBuilder.CreateCylinder(this.id + "_connection", {diameter: .025, height: 1}, this.scene);
this.transformNode = new TransformNode(this.id + "_transform", this.scene); this.transformNode = new TransformNode(this.id + "_transform", this.scene);
this.transformNode.metadata = {exportable: true}; this.transformNode.metadata = {exportable: true};
@ -158,7 +159,7 @@ export class DiagramConnection {
} }
} }
private removeConnection = () => { private removeConnection = () => {
this.logger.debug("removeConnection"); logger.debug("removeConnection");
this.scene.onBeforeRenderObservable.removeCallback(this.beforeRender); this.scene.onBeforeRenderObservable.removeCallback(this.beforeRender);
this._mesh.onDisposeObservable.removeCallback(this.removeConnection); this._mesh.onDisposeObservable.removeCallback(this.removeConnection);
this.removeObserver(); this.removeObserver();
@ -175,25 +176,22 @@ export class DiagramConnection {
if (this.scene) { if (this.scene) {
this.scene = null; this.scene = null;
} }
if (this.logger) {
this.logger = null;
}
} }
private onMeshAdded = (mesh: AbstractMesh) => { private onMeshAdded = (mesh: AbstractMesh) => {
if (mesh && mesh.id) { if (mesh && mesh.id) {
if (!this.toAnchor || !this.fromAnchor) { if (!this.toAnchor || !this.fromAnchor) {
if (mesh?.id == this?._to) { if (mesh?.id == this?._to) {
this.logger.debug("Found to anchor"); logger.debug("Found to anchor");
this.toAnchor = mesh; this.toAnchor = mesh;
this._mesh.metadata.to = this.to; this._mesh.metadata.to = this.to;
} }
if (mesh?.id == this?._from) { if (mesh?.id == this?._from) {
this.logger.debug("Found from anchor"); logger.debug("Found from anchor");
this.fromAnchor = mesh; this.fromAnchor = mesh;
this._mesh.metadata.from = this.from; this._mesh.metadata.from = this.from;
} }
if (this.toAnchor && this.fromAnchor) { if (this.toAnchor && this.fromAnchor) {
this.logger.debug(`connection built from ${this._from} to ${this._to}`); logger.debug(`connection built from ${this._from} to ${this._to}`);
this.removeObserver(); this.removeObserver();
} }
} }
@ -201,7 +199,7 @@ export class DiagramConnection {
} }
private removeObserver() { private removeObserver() {
this.logger.debug("removing observer"); logger.debug("removing observer");
this.scene.onNewMeshAddedObservable.removeCallback(this.onMeshAdded); this.scene.onNewMeshAddedObservable.removeCallback(this.onMeshAdded);
} }
} }

View File

@ -5,22 +5,18 @@ import {buildTool} from "./buildTool";
export function buildColor(color: Color3, scene: Scene, parent: TransformNode, index: number): Node { export function buildColor(color: Color3, scene: Scene, parent: TransformNode, index: number): Node {
const width = .1; const width = .1;
const depth = .1; const height = .1;
const height = .01;
const material = new StandardMaterial("material-" + color.toHexString(), scene); const material = new StandardMaterial("material-" + color.toHexString(), scene);
material.diffuseColor = color; material.diffuseColor = color;
material.ambientColor = color; material.ambientColor = color;
material.roughness = .1;
material.maxSimultaneousLights = 1;
//material.emissiveColor = new Color3(.1,.1,.1); const colorBoxMesh = MeshBuilder.CreatePlane("toolbox-color-" + color.toHexString(), {
//material.roughness = 1;
//material.specularPower = .0001;
const colorBoxMesh = MeshBuilder.CreateBox("toolbox-color-" + color.toHexString(), {
width: width, width: width,
height: height, height: height
depth: depth
}, scene); }, scene);
colorBoxMesh.rotation.x = Math.PI / 2; //colorBoxMesh.rotation.x = Math.PI / 2;
colorBoxMesh.material = material; colorBoxMesh.material = material;
const rowLength = 8; const rowLength = 8;
colorBoxMesh.position.x = -.45 + ((index % rowLength) / rowLength); colorBoxMesh.position.x = -.45 + ((index % rowLength) / rowLength);

View File

@ -1,88 +1,39 @@
import log from "loglevel";
import { import {
AbstractMesh, AbstractMesh,
ActionEvent,
Color3, Color3,
DynamicTexture,
MeshBuilder, MeshBuilder,
PhysicsAggregate,
PhysicsHelper,
PhysicsShapeType,
Scene, Scene,
StandardMaterial, StandardMaterial,
Vector3, Vector3,
VideoTexture VideoTexture
} from "@babylonjs/core"; } from "@babylonjs/core";
import {Button3D, GUI3DManager, TextBlock} from "@babylonjs/gui"; import {DefaultScene} from "../defaultScene";
import {DiaSounds} from "../util/diaSounds"; import {HtmlButton} from "../../../babylon-html";
import {AppConfig} from "../util/appConfig";
import Hls from "hls.js"; import Hls from "hls.js";
import log, {Logger} from "loglevel";
const logger = log.getLogger('Introduction');
export class Introduction { export class Introduction {
private readonly scene: Scene; private readonly _scene: Scene;
private manager: GUI3DManager;
private physicsHelper: PhysicsHelper;
private current: AbstractMesh[] = [];
private step: number = 0;
private items: AbstractMesh[] = [];
private advance: Button3D;
private sounds: DiaSounds;
private config: AppConfig;
private logger: Logger = log.getLogger('Introduction');
private videoElement: HTMLVideoElement; private videoElement: HTMLVideoElement;
constructor(scene: Scene, config: AppConfig) { constructor() {
this.sounds = new DiaSounds(scene); logger.info('Introduction constructor');
this.scene = scene; this._scene = DefaultScene.Scene;
this.config = config; this.initialize();
this.manager = new GUI3DManager(scene);
this.physicsHelper = new PhysicsHelper(scene);
this.scene.onReadyObservable.add(() => {
setTimeout((s) => {
s.start()
}, 2000, this);
});
} }
public start() { buildVideo(src: string, position: Vector3): AbstractMesh {
this.scene.physicsEnabled = true;
this.manager.controlScaling = .5;
this.advance = new Button3D("advance");
const text = new TextBlock("advance", "Click Me");
text.fontSize = "48px";
text.color = "#ffffff";
text.alpha = 1;
this.advance.content = text;
this.advance.onPointerClickObservable.add(() => {
this.takeStep();
}, -1, false, this, false);
this.manager.addControl(this.advance);
this.advance.isVisible = false;
this.scene.onReadyObservable.add(() => {
this.advance.isVisible = true;
this.advance.node.position = new Vector3(0, .2, -1);
this.advance.node.rotation = new Vector3(0, Math.PI, 0);
});
}
buildVideo(src: string, size: number, position: Vector3): AbstractMesh {
const vid = document.createElement("video"); const vid = document.createElement("video");
this.videoElement = vid; this.videoElement = vid;
vid.setAttribute('autoplay', 'true'); vid.setAttribute('autoplay', 'true');
vid.setAttribute('playsinline', 'true'); vid.setAttribute('playsinline', 'true');
vid.setAttribute('src', src); vid.setAttribute('src', src);
const texture = new VideoTexture("video", vid, this.scene, true);
const mesh = this.makeObject("video", position, size, 16 / 9);
const material = new StandardMaterial("video_material", this.scene);
const texture = new VideoTexture("video", vid, this._scene, true);
const mesh = this.makeObject("video", position);
const material = new StandardMaterial("video_material", this._scene);
material.diffuseTexture = texture; material.diffuseTexture = texture;
material.diffuseColor = new Color3(1, 1, 1); material.diffuseColor = new Color3(1, 1, 1);
material.emissiveColor = new Color3(1, 1, 1); material.emissiveColor = new Color3(1, 1, 1);
@ -104,99 +55,73 @@ export class Introduction {
}); });
}); });
} }
//document.body.appendChild(vid);
mesh.metadata = {video: vid};
return mesh; return mesh;
} }
makeObject(text: string, position: Vector3, size: number, ratio: number = 2): AbstractMesh { private initialize() {
const welcome = MeshBuilder.CreateTiledBox(text + "_box", {width: 1, height: 1, depth: 1}, this.scene); /*
welcome.position = position; const talkTrack = new Sound("talkTrack", "assets/sounds/introTalkTrack.mp3", this._scene, () => {
welcome.scaling = new Vector3(size, size / ratio, size); this.ready();
}, {
const aggregate = new PhysicsAggregate(welcome, PhysicsShapeType.BOX, { loop: false,
friction: 1, autoplay: false,
mass: 1, volume: 1
restitution: .1 });*/
}, this.scene); this.ready();
aggregate.body.getCollisionObservable().add((collider) => {
if (collider.impulse < .5) {
return;
}
let volume = 0;
const sound = this.sounds.bounce;
if (collider.impulse > 1 && collider.impulse < 10) {
volume = collider.impulse / 10;
}
if (volume > 0) {
sound.attachToMesh(aggregate.body.transformNode);
sound.updateOptions({offset: 0, volume: volume, length: .990});
sound.play();
}
});
aggregate.body.setCollisionCallbackEnabled(true);
return welcome;
} }
buildText(text: string, size: number, textureSize: number, position: Vector3): AbstractMesh { private ready() {
const mesh = this.makeObject(text, position, size); const startButton = this.buildButton('Begin Tutorial');
const texture = new DynamicTexture("dynamic texture", { startButton.onPointerObservable.add((eventData: ActionEvent) => {
width: textureSize, if (eventData.sourceEvent.type === "pointerup") {
height: textureSize / 2 this.start(startButton);
}, this.scene, true); }
texture.drawText(text, null, null, "bold 128px Arial", "white", "#00f", true, true); }, -1, true, this, false);
mesh.material = new StandardMaterial(text + "_material", this.scene);
mesh.material.alpha = 1;
(mesh.material as StandardMaterial).diffuseTexture = texture;
texture.update();
return mesh;
} }
private takeStep() { private buildButton(name: string): HtmlButton {
this.current.forEach((mesh) => { const button = new HtmlButton(name, name, this._scene, null,
const pos = mesh.physicsBody.transformNode.absolutePosition.clone(); {html: null, image: {width: 512, height: 512}, width: .5, height: .5});
pos.x = pos.x - .1; button.transform.position.y = .4;
mesh.physicsBody.applyImpulse(new Vector3(0, 10, -12), pos); return button;
}); }
switch (this.step) { private start(prev: HtmlButton) {
case 0: prev.dispose();
this.items.push(this.buildText("Welcome To", 3, 1024, new Vector3(0, 15, -4))); const controllerButton = this.buildButton('Controllers');
this.items.push(this.buildText("Deep Diagram", 5, 1024, new Vector3(0, 10, -4))); const video = this.buildVideo('https://customer-l4pyjzbav11fzy04.cloudflarestream.com/8b906146c75bb5d81e03d199707ed0e9/manifest/video.m3u8', new Vector3(0, 1.8, -.5));
this.current = this.items.slice(-2); controllerButton.onPointerObservable.add((eventData: ActionEvent) => {
break; if (eventData.sourceEvent.type === "pointerup") {
case 1: this.controllers(controllerButton, video);
this.items.push(this.buildText("Let us show you", 3, 1024, new Vector3(2, 16, -5))); }
this.items.push(this.buildText("what you can build", 4, 1200, new Vector3(-1.6, 12, -5))); }, -1, true, this, false);
this.current = this.items.slice(-2);
break;
case 2:
this.items.push(this.buildText("A quick video", 5, 1024, new Vector3(0, 15, -5)));
this.current = this.items.slice(-1);
break;
case 3:
const src = 'https://customer-l4pyjzbav11fzy04.cloudflarestream.com/8b906146c75bb5d81e03d199707ed0e9/manifest/video.m3u8' }
this.items.push(this.buildVideo(src, 7, new Vector3(0, 15, -6)));
this.current = this.items.slice(-1); private controllers(prev: HtmlButton, prevVideo: AbstractMesh) {
break; if (prevVideo.metadata) {
case 4: prevVideo.metadata.video.pause();
this.items.forEach((mesh) => { prevVideo.metadata.video.remove();
mesh.physicsBody.dispose(); prevVideo.dispose();
mesh.dispose();
});
this.advance.dispose();
this.manager.dispose();
this.config.setDemoCompleted(true);
this.items = [];
if (this.videoElement) {
this.videoElement.pause();
this.videoElement.remove();
this.videoElement = null;
}
} }
this.step++; prev.dispose();
const controllerButton = this.buildButton('Controllers 2');
const video = this.buildVideo('https://customer-l4pyjzbav11fzy04.cloudflarestream.com/8b906146c75bb5d81e03d199707ed0e9/manifest/video.m3u8', new Vector3(0, 1.8, -.5));
}
private showVideo(url: string) {
} }
private makeObject(text: string, position: Vector3): AbstractMesh {
const videoScale = 2.8;
const video = MeshBuilder.CreatePlane(text + "_plane", {width: 1.6, height: .9}, this._scene);
video.rotation.y = Math.PI;
video.scaling.set(videoScale, videoScale, videoScale);
video.position = position;
return video;
}
} }

View File

@ -1,24 +0,0 @@
import {AppConfig} from "../util/appConfig";
import {Scene} from "@babylonjs/core";
export class Tutorial {
private scene: Scene;
private config: AppConfig;
constructor(scene: Scene, config: AppConfig) {
this.scene = scene;
this.config = config;
const advance = document.querySelector('#advanceLink');
if (advance) {
advance.addEventListener('click', () => {
this.advance();
});
}
}
private advance() {
window.alert('here');
}
}

View File

@ -29,6 +29,7 @@ export class VrApp {
public async initialize() { public async initialize() {
const scene = DefaultScene.Scene; const scene = DefaultScene.Scene;
const spinner = new Spinner(); const spinner = new Spinner();
spinner.show(); spinner.show();
@ -59,11 +60,11 @@ export class VrApp {
}) })
} }
this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer'); this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer');
//const intro = new Introduction();
this.engine.runRenderLoop(() => { this.engine.runRenderLoop(() => {
scene.render(); scene.render();
}); });
this.logger.info('Render loop started'); this.logger.info('Render loop started');
} }
private async initializeEngine() { private async initializeEngine() {