video player as interactive object + move to HUD
This commit is contained in:
@@ -65,11 +65,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { GameEngine } from '@/lib/GameEngine';
|
|
||||||
import GameEnvironmentMixin from '@/mixins/GameEnvironmentMixin';
|
import GameEnvironmentMixin from '@/mixins/GameEnvironmentMixin';
|
||||||
|
|
||||||
let gameEngine = null;
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [GameEnvironmentMixin],
|
mixins: [GameEnvironmentMixin],
|
||||||
props:{
|
props:{
|
||||||
|
|||||||
@@ -52,12 +52,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { GameEngine } from '@/lib/GameEngine';
|
|
||||||
import { Hero } from '@/lib/Hero';
|
|
||||||
import { Grass } from '@/components/InteractiveObjects/Grass';
|
|
||||||
import { VideoPlayer } from '@/components/InteractiveObjects/VideoPlayer';
|
|
||||||
import { useAppStore } from '@/stores/app';
|
import { useAppStore } from '@/stores/app';
|
||||||
import { MazeQuizGame } from '../InteractiveObjects/MazeQuizGame/MazeQuizGame';
|
|
||||||
|
|
||||||
import GameEnvironmentMixin from '@/mixins/GameEnvironmentMixin';
|
import GameEnvironmentMixin from '@/mixins/GameEnvironmentMixin';
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { PuzzleGame4 } from "./PuzzleGame4";
|
|||||||
// import { Game6 } from "./games/Game6";
|
// import { Game6 } from "./games/Game6";
|
||||||
import { TextObject } from "./TextObject";
|
import { TextObject } from "./TextObject";
|
||||||
import { ImageObject } from "./ImageObject";
|
import { ImageObject } from "./ImageObject";
|
||||||
|
import { VideoPlayer } from "./VideoPlayer";
|
||||||
|
|
||||||
const games = {PuzzleGame1, PuzzleGame2, PuzzleGame4};
|
const games = {PuzzleGame1, PuzzleGame2, PuzzleGame4};
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@ class InteractiveObject {
|
|||||||
this.name = obj.name;
|
this.name = obj.name;
|
||||||
this.ready = new Promise((resolve, reject) => {
|
this.ready = new Promise((resolve, reject) => {
|
||||||
let mesh;
|
let mesh;
|
||||||
switch (obj.type) {
|
switch (obj.id) {
|
||||||
case 'group':
|
case 'group':
|
||||||
mesh = new Group();
|
mesh = new Group();
|
||||||
obj.group.forEach(g => {
|
obj.group.forEach(g => {
|
||||||
@@ -48,7 +49,7 @@ class InteractiveObject {
|
|||||||
resolve(mesh);
|
resolve(mesh);
|
||||||
break;
|
break;
|
||||||
case 'gltf':
|
case 'gltf':
|
||||||
console.log('loadingg', obj.value)
|
//console.log('loadingg', obj.value)
|
||||||
new GLTFLoader().load(obj.value, (gltf) => {
|
new GLTFLoader().load(obj.value, (gltf) => {
|
||||||
let gltfObj = gltf.scene;
|
let gltfObj = gltf.scene;
|
||||||
gltf.scene.traverse(function (object) {
|
gltf.scene.traverse(function (object) {
|
||||||
@@ -81,11 +82,15 @@ class InteractiveObject {
|
|||||||
case 'PuzzleGame4':
|
case 'PuzzleGame4':
|
||||||
case 'PuzzleGame5':
|
case 'PuzzleGame5':
|
||||||
case 'PuzzleGame6':
|
case 'PuzzleGame6':
|
||||||
var game = new games[obj.type](context, obj.args[0], obj.args[1], obj.args[2]);
|
let game = new games[obj.type](context, obj.args[0], obj.args[1], obj.args[2]);
|
||||||
mesh = game.object;
|
mesh = game.object;
|
||||||
mesh.game = game;
|
mesh.game = game;
|
||||||
resolve(mesh);
|
resolve(mesh);
|
||||||
break;
|
break;
|
||||||
|
case 'VideoPlayer':
|
||||||
|
let vp = new VideoPlayer(context, `/asset/default/${obj.$go.asset.name}`);
|
||||||
|
vp.ready.then(resolve);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.ready.then((mesh) => {
|
this.ready.then((mesh) => {
|
||||||
@@ -137,6 +142,6 @@ const InteractiveObjectTypes = [
|
|||||||
}, {
|
}, {
|
||||||
id: 'VideoPlayer', name: 'Video Player'
|
id: 'VideoPlayer', name: 'Video Player'
|
||||||
}
|
}
|
||||||
]
|
];
|
||||||
|
|
||||||
export { InteractiveObject, InteractiveObjectTypes }
|
export { InteractiveObject, InteractiveObjectTypes }
|
||||||
@@ -2,28 +2,78 @@ import * as THREE from 'three';
|
|||||||
|
|
||||||
|
|
||||||
class VideoPlayer {
|
class VideoPlayer {
|
||||||
constructor(context, video, w, h){
|
constructor(context, src){
|
||||||
let geometry = new THREE.PlaneGeometry( w, h );
|
let vi, plane, data;
|
||||||
let map = new THREE.VideoTexture( video );
|
|
||||||
map.colorSpace = THREE.SRGBColorSpace;
|
|
||||||
let material = new THREE.MeshStandardMaterial( {
|
|
||||||
color: 0xffffff,
|
|
||||||
map,
|
|
||||||
transparent: true,
|
|
||||||
opacity: 0.5,
|
|
||||||
} );
|
|
||||||
let plane = new THREE.Mesh( geometry, material );
|
|
||||||
this.object = plane;
|
|
||||||
|
|
||||||
context.clickable.add(plane, ()=>{
|
this.ready = new Promise((resolve, reject)=>{
|
||||||
material.opacity = 0.9
|
vi = document.createElement('video');
|
||||||
if (video.paused){
|
vi.src = src;
|
||||||
video.play();
|
vi.addEventListener('loadedmetadata', ()=>{
|
||||||
}else{
|
this.aspect = vi.videoWidth / vi.videoHeight;
|
||||||
video.pause();
|
let geometry = new THREE.PlaneGeometry( this.aspect, 1 );
|
||||||
}
|
let map = new THREE.VideoTexture( vi );
|
||||||
});
|
map.colorSpace = THREE.SRGBColorSpace;
|
||||||
|
let material = new THREE.MeshStandardMaterial( {
|
||||||
|
color: 0xffffff,
|
||||||
|
map,
|
||||||
|
transparent: true,
|
||||||
|
opacity: 0.5,
|
||||||
|
side: THREE.DoubleSide
|
||||||
|
} );
|
||||||
|
plane = new THREE.Mesh( geometry, material );
|
||||||
|
this.object = plane;
|
||||||
|
context.clickable.add(plane, ()=>{
|
||||||
|
material.opacity = 1
|
||||||
|
if (vi.paused){
|
||||||
|
vi.play();
|
||||||
|
}else{
|
||||||
|
vi.pause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
resolve(plane);
|
||||||
|
})
|
||||||
|
vi.addEventListener('play', ()=>{
|
||||||
|
if (context.dashboard?.active){
|
||||||
|
//console.log(plane);
|
||||||
|
// plane.matrix.multiply(context.dashboard.group.matrix)
|
||||||
|
// plane.applyMatrix4(plane.matrix)
|
||||||
|
|
||||||
|
// let m1 = plane.matrix.clone(), m2 = context.dashboard.group.matrix.clone();
|
||||||
|
// let m = m1.premultiply(m2);
|
||||||
|
data = {
|
||||||
|
parent: plane.parent,
|
||||||
|
location: {
|
||||||
|
position: plane.position.clone(),
|
||||||
|
quaternion: plane.quaternion.clone(),
|
||||||
|
scale: plane.scale.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(data.location)
|
||||||
|
context.dashboard.group.attach(plane);
|
||||||
|
//plane.applyMatrix4(m.invert())
|
||||||
|
|
||||||
|
|
||||||
|
context.motionQueue.add({
|
||||||
|
o: plane,
|
||||||
|
a: {
|
||||||
|
rotation: { x:0, y:0, z:0 },
|
||||||
|
position: { x:0, y:0, z:-0.25 },
|
||||||
|
scale: { x: 1, y:1, z:1 }
|
||||||
|
},
|
||||||
|
t: 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
vi.addEventListener('pause', ()=>{
|
||||||
|
data.parent.attach(plane);
|
||||||
|
context.motionQueue.add({
|
||||||
|
o: plane,
|
||||||
|
a: data.location,
|
||||||
|
t: 1
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {VideoPlayer}
|
export { VideoPlayer }
|
||||||
@@ -29,6 +29,8 @@ class DashBoard {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const dash = new Group();
|
const dash = new Group();
|
||||||
|
this.group = dash;
|
||||||
|
dash.visible = false;
|
||||||
|
|
||||||
const dashGeometry = new PlaneGeometry(engine.aspect, 1);
|
const dashGeometry = new PlaneGeometry(engine.aspect, 1);
|
||||||
const dashMesh = new Mesh(dashGeometry, new MeshStandardMaterial({
|
const dashMesh = new Mesh(dashGeometry, new MeshStandardMaterial({
|
||||||
@@ -81,9 +83,25 @@ class DashBoard {
|
|||||||
progressCylinder.position.x = padLeft - engine.aspect/2 + progressCylinder.scale.y/2
|
progressCylinder.position.x = padLeft - engine.aspect/2 + progressCylinder.scale.y/2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.enable = ()=>{
|
||||||
|
dash.visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.disable = ()=>{
|
||||||
|
dash.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
this.createProgressBar();
|
this.createProgressBar();
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get active(){
|
||||||
|
return this.group.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
set active(v){
|
||||||
|
this.group.visible = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { DashBoard };
|
export { DashBoard };
|
||||||
@@ -14,6 +14,7 @@ import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFa
|
|||||||
import { Physics } from './Physics.js';
|
import { Physics } from './Physics.js';
|
||||||
import { Clickable } from './Clickable.js';
|
import { Clickable } from './Clickable.js';
|
||||||
import { DashBoard } from './Dashboard.js';
|
import { DashBoard } from './Dashboard.js';
|
||||||
|
import { MotionEngine } from './MotionEngine.js';
|
||||||
|
|
||||||
class GameEngine extends THREE.EventDispatcher{
|
class GameEngine extends THREE.EventDispatcher{
|
||||||
async init(domNode, opts = {}) {
|
async init(domNode, opts = {}) {
|
||||||
@@ -99,6 +100,8 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
const dashboard = new DashBoard(this);
|
const dashboard = new DashBoard(this);
|
||||||
this.dashboard = dashboard;
|
this.dashboard = dashboard;
|
||||||
|
|
||||||
|
this.motionQueue = new MotionEngine();
|
||||||
|
|
||||||
this.activeObjects = new THREE.Group();
|
this.activeObjects = new THREE.Group();
|
||||||
scene.add(this.activeObjects);
|
scene.add(this.activeObjects);
|
||||||
|
|
||||||
@@ -129,8 +132,8 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
gameEngine.hero?.update();
|
gameEngine.hero?.update();
|
||||||
gameEngine.mixers.forEach(m => m.update(delta));
|
gameEngine.mixers.forEach(m => m.update(delta));
|
||||||
gameEngine.handleXrAction(gameEngine, delta)
|
gameEngine.handleXrAction(gameEngine, delta)
|
||||||
|
|
||||||
gameEngine.dispatchEvent({type: 'beforeRender'})
|
gameEngine.dispatchEvent({type: 'beforeRender'})
|
||||||
|
this.motionQueue.update();
|
||||||
|
|
||||||
gameEngine.render(scene, gameEngine.camera);
|
gameEngine.render(scene, gameEngine.camera);
|
||||||
if (!renderer.xr.isPresenting) {
|
if (!renderer.xr.isPresenting) {
|
||||||
@@ -140,7 +143,7 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
// dashboard.render();
|
// dashboard.render();
|
||||||
// renderer.autoClear = true;
|
// renderer.autoClear = true;
|
||||||
}
|
}
|
||||||
renderer.setAnimationLoop(animate);
|
renderer.setAnimationLoop(animate.bind(this));
|
||||||
|
|
||||||
const mixer = new THREE.AnimationMixer(this.scene);
|
const mixer = new THREE.AnimationMixer(this.scene);
|
||||||
const clock = new THREE.Clock();
|
const clock = new THREE.Clock();
|
||||||
@@ -162,7 +165,7 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
// scene.background = bck; //new THREE.Color(0.7,0.7,0.7);
|
// scene.background = bck; //new THREE.Color(0.7,0.7,0.7);
|
||||||
scene.environment = texture;
|
scene.environment = texture;
|
||||||
scene.background = new THREE.Color(1, 1, 1);
|
scene.background = new THREE.Color(1, 1, 1);
|
||||||
console.log('GameEngine started')
|
//console.log('GameEngine started')
|
||||||
renderer.domElement.addEventListener('wheel', (event) => {
|
renderer.domElement.addEventListener('wheel', (event) => {
|
||||||
gameEngine.camera.zoom -= event.deltaY / 1000;
|
gameEngine.camera.zoom -= event.deltaY / 1000;
|
||||||
gameEngine.camera.zoom = Math.max(gameEngine.camera.zoom, .4);
|
gameEngine.camera.zoom = Math.max(gameEngine.camera.zoom, .4);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { InteractiveObject } from '@/components/InteractiveObjects/InteractiveObject';
|
||||||
import { GameEngine } from '@/lib/GameEngine';
|
import { GameEngine } from '@/lib/GameEngine';
|
||||||
import { Hero } from '@/lib/Hero';
|
import { Hero } from '@/lib/Hero';
|
||||||
let gameEngine = null;
|
let gameEngine = null;
|
||||||
@@ -13,8 +14,12 @@ export default {
|
|||||||
designMode: this.env == 'GameDesigner',
|
designMode: this.env == 'GameDesigner',
|
||||||
depthSense: this.env == 'GameDesigner' ? false : this.store.prefs.xr.depthSense
|
depthSense: this.env == 'GameDesigner' ? false : this.store.prefs.xr.depthSense
|
||||||
});
|
});
|
||||||
gameEngine.scene.add(gameEngine.transformControls.getHelper());
|
|
||||||
//gameEngine.scene.add(new gameEngine.$.GridHelper(100,100));
|
//gameEngine.scene.add(new gameEngine.$.GridHelper(100,100));
|
||||||
|
if (this.env == 'GameDesigner'){
|
||||||
|
gameEngine.scene.add(gameEngine.transformControls.getHelper());
|
||||||
|
}else{
|
||||||
|
gameEngine.dashboard.enable();
|
||||||
|
}
|
||||||
this.resize();
|
this.resize();
|
||||||
//gameEngine.setCamera(gameEngine.orthographicCamera)
|
//gameEngine.setCamera(gameEngine.orthographicCamera)
|
||||||
//gameEngine.setCameraOrthographic();
|
//gameEngine.setCameraOrthographic();
|
||||||
@@ -63,10 +68,11 @@ export default {
|
|||||||
await this.loadScenario()
|
await this.loadScenario()
|
||||||
},
|
},
|
||||||
currentObject(n){
|
currentObject(n){
|
||||||
gameEngine.transformControls.attach(n.__o);
|
if (this.env == 'GameDesigner'){
|
||||||
gameEngine.gizmo.target = n.__o.position;
|
gameEngine.transformControls.attach(n.__o);
|
||||||
//gameEngine.camera.lookAt(n.__o.position)
|
gameEngine.gizmo.target = n.__o.position;
|
||||||
gameEngine.camera.updateProjectionMatrix()
|
gameEngine.camera.updateProjectionMatrix()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
renderType(v){
|
renderType(v){
|
||||||
gameEngine.renderType = v;
|
gameEngine.renderType = v;
|
||||||
@@ -124,7 +130,11 @@ export default {
|
|||||||
}
|
}
|
||||||
for (let i of this.scene.data.items || []) {
|
for (let i of this.scene.data.items || []) {
|
||||||
if (i.data.io){
|
if (i.data.io){
|
||||||
|
i.data.$io = new InteractiveObject(i.data.io, gameEngine)
|
||||||
|
i.data.$io.ready.then(o=>{
|
||||||
|
this.setObjectAttributes(l, i.data, { scene: o }, 1);
|
||||||
|
gameEngine.activeObjects.add(o);
|
||||||
|
})
|
||||||
}else{
|
}else{
|
||||||
let gltf = await gameEngine.load(`/asset/default/${i.data.$go.asset.name}`);
|
let gltf = await gameEngine.load(`/asset/default/${i.data.$go.asset.name}`);
|
||||||
this.setObjectAttributes(l, i.data, gltf, 1);
|
this.setObjectAttributes(l, i.data, gltf, 1);
|
||||||
@@ -156,17 +166,21 @@ export default {
|
|||||||
this.pointerDownTime = performance.now();
|
this.pointerDownTime = performance.now();
|
||||||
},
|
},
|
||||||
targetClick(e){
|
targetClick(e){
|
||||||
if (performance.now() - this.pointerDownTime < 200){
|
if (this.env == 'GameDesigner'){
|
||||||
let intersects = gameEngine.intersect(e, this.$refs.target, gameEngine.activeObjects.children, true);
|
if (performance.now() - this.pointerDownTime < 200){
|
||||||
//console.log(intersects)
|
let intersects = gameEngine.intersect(e, this.$refs.target, gameEngine.activeObjects.children, true);
|
||||||
if (intersects.length){
|
//console.log(intersects)
|
||||||
//console.log('attaching controls to', intersects[0].object)
|
if (intersects.length){
|
||||||
//gameEngine.transformControls.attach(intersects[0].object);
|
//console.log('attaching controls to', intersects[0].object)
|
||||||
console.log(this.sceneObjects[intersects[0].object.__pn_id])
|
//gameEngine.transformControls.attach(intersects[0].object);
|
||||||
this.objectsList[0] = this.sceneObjects[intersects[0].object.__pn_id]
|
//console.log(this.sceneObjects[intersects[0].object.__pn_id])
|
||||||
}else{
|
this.objectsList[0] = this.sceneObjects[intersects[0].object.__pn_id]
|
||||||
gameEngine.transformControls.detach();
|
}else{
|
||||||
|
gameEngine.transformControls.detach();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
gameEngine.onClick(e, this.$refs.target);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user