hud observation for generic game objects
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import { getBoundingBox, getBoundingBoxCenterPoint, getBoundingBoxMaxLength } from "@/lib/MeshUtils";
|
||||||
|
|
||||||
class GenericObject{
|
class GenericObject{
|
||||||
constructor(engine, data){
|
constructor(engine, data){
|
||||||
return new Promise(async(resolve, reject)=>{
|
return new Promise(async(resolve, reject)=>{
|
||||||
@@ -6,9 +8,32 @@ class GenericObject{
|
|||||||
|
|
||||||
if (!data.exclude){
|
if (!data.exclude){
|
||||||
engine.clickable.add(this.object, e=>{
|
engine.clickable.add(this.object, e=>{
|
||||||
if (engine.dashboard && data.description){
|
if (engine.dashboard){
|
||||||
|
if (data.description){
|
||||||
engine.dashboard.update({ hint: data.description })
|
engine.dashboard.update({ hint: data.description })
|
||||||
}
|
}
|
||||||
|
if (data.hud){
|
||||||
|
if (this.object._hud ){
|
||||||
|
engine.dashboard.detach(this.object);
|
||||||
|
}else{
|
||||||
|
let bb = getBoundingBox(this.object);
|
||||||
|
let scale = 0.5/getBoundingBoxMaxLength(bb);
|
||||||
|
let position = getBoundingBoxCenterPoint(bb, this.object.position).multiplyScalar(scale).negate()
|
||||||
|
|
||||||
|
let placement = {
|
||||||
|
quaternion: { x:0, y:0, z:0, w:0 },
|
||||||
|
position,
|
||||||
|
scale: {
|
||||||
|
x: scale*this.object.scale.x,
|
||||||
|
y: scale*this.object.scale.y,
|
||||||
|
z: scale*this.object.scale.z
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
engine.dashboard.attach(this.object, placement, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,34 +34,11 @@ class VideoPlayer {
|
|||||||
})
|
})
|
||||||
vi.addEventListener('play', ()=>{
|
vi.addEventListener('play', ()=>{
|
||||||
if (engine.dashboard?.active){
|
if (engine.dashboard?.active){
|
||||||
data = {
|
engine.dashboard.attach(plane);
|
||||||
parent: plane.parent,
|
|
||||||
location: {
|
|
||||||
position: plane.position.clone(),
|
|
||||||
quaternion: plane.quaternion.clone(),
|
|
||||||
scale: plane.scale.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
engine.dashboard.group.attach(plane);
|
|
||||||
|
|
||||||
engine.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', ()=>{
|
vi.addEventListener('pause', ()=>{
|
||||||
data.parent.attach(plane);
|
engine.dashboard?.detach(plane);
|
||||||
engine.motionQueue.add({
|
|
||||||
o: plane,
|
|
||||||
a: data.location,
|
|
||||||
t: 1
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+88
-5
@@ -1,4 +1,7 @@
|
|||||||
import { PlaneGeometry, CylinderGeometry, CanvasTexture, Group, Mesh, MeshStandardMaterial, DoubleSide } from "three";
|
import {
|
||||||
|
PlaneGeometry, CylinderGeometry, CanvasTexture, Group,
|
||||||
|
Mesh, MeshStandardMaterial, MeshBasicMaterial, DoubleSide
|
||||||
|
} from "three";
|
||||||
import Utils from "./Utils";
|
import Utils from "./Utils";
|
||||||
class DashBoard {
|
class DashBoard {
|
||||||
constructor(engine) {
|
constructor(engine) {
|
||||||
@@ -20,6 +23,7 @@ class DashBoard {
|
|||||||
let texture = new CanvasTexture(canvas)
|
let texture = new CanvasTexture(canvas)
|
||||||
let updating = false;
|
let updating = false;
|
||||||
let params = {}
|
let params = {}
|
||||||
|
let occupied = false;
|
||||||
|
|
||||||
img.addEventListener('load', function () {
|
img.addEventListener('load', function () {
|
||||||
ctx.drawImage(img, 0, 0, engine.w, engine.h);
|
ctx.drawImage(img, 0, 0, engine.w, engine.h);
|
||||||
@@ -28,18 +32,36 @@ class DashBoard {
|
|||||||
updating = false;
|
updating = false;
|
||||||
})
|
})
|
||||||
|
|
||||||
const dash = new Group();
|
const dash = new Group(), hud = new Group(), hudTarget = new Group();
|
||||||
|
hud.visible = false;
|
||||||
|
let hudAnimation, hudPlane;
|
||||||
this.group = dash;
|
this.group = dash;
|
||||||
|
dash.add(hud);
|
||||||
|
hud.add(hudTarget)
|
||||||
dash.visible = false;
|
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 MeshBasicMaterial({
|
||||||
roughness: 0, metalness:0.1, transparent: true,
|
transparent: true,
|
||||||
map: texture
|
map: texture
|
||||||
}))
|
}))
|
||||||
|
|
||||||
dash.add(dashMesh);
|
dash.add(dashMesh);
|
||||||
engine.scene.add(dash)
|
engine.scene.add(dash);
|
||||||
|
|
||||||
|
(async()=>{
|
||||||
|
hudPlane = new Mesh(
|
||||||
|
new PlaneGeometry(engine.aspect, 1),
|
||||||
|
new MeshBasicMaterial({
|
||||||
|
map: await engine.loadTexture('/static/textures/hud.png', ''),
|
||||||
|
opacity: 0.37,
|
||||||
|
transparent:true
|
||||||
|
})
|
||||||
|
);
|
||||||
|
hudPlane.position.z = -0.25;
|
||||||
|
|
||||||
|
hud.add(hudPlane)
|
||||||
|
})()
|
||||||
|
|
||||||
engine.addEventListener('beforeRender', ()=>{
|
engine.addEventListener('beforeRender', ()=>{
|
||||||
dash.quaternion.copy(engine.camera.quaternion)
|
dash.quaternion.copy(engine.camera.quaternion)
|
||||||
@@ -98,6 +120,67 @@ class DashBoard {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.attach = (object, dashPlacement, rotate)=>{
|
||||||
|
hud.visible = true;
|
||||||
|
hudPlane.scale.set(0, .1, 1);
|
||||||
|
hudPlane.material.opacity = 0.5;
|
||||||
|
engine.motionQueue.add([{
|
||||||
|
o:hudPlane, a:{material:{opacity:0.73}}, t:.4, d:.8
|
||||||
|
},{
|
||||||
|
o:hudPlane, a:{scale:{x:1}}, t:.4
|
||||||
|
},{
|
||||||
|
o:hudPlane, a:{scale:{y:1}}, t:.4, d:.4,
|
||||||
|
}])
|
||||||
|
if (occupied) return false;
|
||||||
|
object._hud = {
|
||||||
|
parent: object.parent,
|
||||||
|
placement: {
|
||||||
|
position: object.position.clone(),
|
||||||
|
quaternion: object.quaternion.clone(),
|
||||||
|
scale: object.scale.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hudTarget.attach(object);
|
||||||
|
occupied = true;
|
||||||
|
|
||||||
|
engine.motionQueue.add({
|
||||||
|
o: object,
|
||||||
|
a: dashPlacement || {
|
||||||
|
quaternion: { x:0, y:0, z:0, w:0 },
|
||||||
|
position: { x:0, y:0, z:0 },
|
||||||
|
scale: { x: 1, y:1, z:1 }
|
||||||
|
},
|
||||||
|
t: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
if (rotate){
|
||||||
|
engine.motionQueue.add(hudAnimation = {
|
||||||
|
o: hudTarget,
|
||||||
|
a: {
|
||||||
|
rotation: { y: 2*Math.PI }
|
||||||
|
},
|
||||||
|
t: 4,
|
||||||
|
r: true,
|
||||||
|
d: 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.detach = object=>{
|
||||||
|
engine.motionQueue.remove(hudAnimation);
|
||||||
|
object._hud.parent.attach(object);
|
||||||
|
hud.rotation.y = 0;
|
||||||
|
hud.visible = false;
|
||||||
|
engine.motionQueue.add({
|
||||||
|
o: object,
|
||||||
|
a: object._hud.placement,
|
||||||
|
t: 1
|
||||||
|
});
|
||||||
|
delete object._hud;
|
||||||
|
occupied = false;
|
||||||
|
hudAnimation = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.createProgressBar();
|
this.createProgressBar();
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -485,12 +485,6 @@ class GameEngine extends THREE.EventDispatcher{
|
|||||||
this.hero?.characterControls?.idleReset();
|
this.hero?.characterControls?.idleReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
autoScale(object, mk = 1) {
|
|
||||||
let bb = new THREE.Box3().setFromObject(object);
|
|
||||||
let k = Math.max(bb.max.x - bb.min.x, bb.max.y - bb.min.y, bb.max.z - bb.min.z);
|
|
||||||
object.scale.multiplyScalar(mk / k);
|
|
||||||
}
|
|
||||||
|
|
||||||
setCamera(camera) {
|
setCamera(camera) {
|
||||||
//camera.updateProjectionMatrix();
|
//camera.updateProjectionMatrix();
|
||||||
this.camera = camera;
|
this.camera = camera;
|
||||||
|
|||||||
+25
-2
@@ -1,4 +1,4 @@
|
|||||||
import { TextureLoader } from "three";
|
import { TextureLoader, Box3, Vector3 } from "three";
|
||||||
|
|
||||||
function assignParams(mesh, params){
|
function assignParams(mesh, params){
|
||||||
['scale', 'rotation', 'position'].forEach(p=>params[p] && mesh[p].fromArray(params[p]));
|
['scale', 'rotation', 'position'].forEach(p=>params[p] && mesh[p].fromArray(params[p]));
|
||||||
@@ -26,4 +26,27 @@ function assignMaterial(mesh, params){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { assignParams, assignMaterial }
|
function getBoundingBox(object){
|
||||||
|
return new Box3().setFromObject(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBoundingBoxMaxLength(bb){
|
||||||
|
return Math.max(bb.max.x - bb.min.x, bb.max.y - bb.min.y, bb.max.z - bb.min.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBoundingBoxCenterPoint(bb, relativeTo){
|
||||||
|
relativeTo = relativeTo || new Vector3(0,0,0)
|
||||||
|
return new Vector3(
|
||||||
|
bb.min.x + (bb.max.x - bb.min.x)/2 - relativeTo.x,
|
||||||
|
bb.min.y + (bb.max.y - bb.min.y)/2 - relativeTo.y,
|
||||||
|
bb.min.z + (bb.max.z - bb.min.z)/2 - relativeTo.z
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function autoScale(object, mk = 1) {
|
||||||
|
let bb = getBoundingBox(object);
|
||||||
|
let k = getBoundingBoxMaxLength(bb);
|
||||||
|
object.scale.multiplyScalar(mk / k);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { assignParams, assignMaterial, autoScale, getBoundingBox, getBoundingBoxMaxLength, getBoundingBoxCenterPoint }
|
||||||
@@ -26,6 +26,8 @@ class MotionEngine {
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// a = {o-object, a-action, t-time, f-finish event, d-delay, m-mode, r-repeat,
|
||||||
|
// rd-repeat the delay, rf-reset on finish}
|
||||||
this.add = function (a) {
|
this.add = function (a) {
|
||||||
a = Array.isArray(a) ? a : [a];
|
a = Array.isArray(a) ? a : [a];
|
||||||
a.forEach(e => {
|
a.forEach(e => {
|
||||||
@@ -35,7 +37,7 @@ class MotionEngine {
|
|||||||
|
|
||||||
this.clear = function (object) {
|
this.clear = function (object) {
|
||||||
for (var i = aq.length - 1; i >= 0; i--) {
|
for (var i = aq.length - 1; i >= 0; i--) {
|
||||||
if (object && aq[i].o == object || !object && aq[i].ct == aq[i].t) {
|
if (object && aq[i].o == object || !object && (aq[i].ct == aq[i].t || aq[i].rr)) {
|
||||||
aq.splice(i, 1);
|
aq.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +77,11 @@ class MotionEngine {
|
|||||||
e.ct = e.ct + t;
|
e.ct = e.ct + t;
|
||||||
if (e.ct > e.t) {
|
if (e.ct > e.t) {
|
||||||
e.ct = e.t;
|
e.ct = e.t;
|
||||||
e.f && e.f();
|
e.f?.();
|
||||||
|
if (e.rf){
|
||||||
|
e.ct = t = 0;
|
||||||
|
e.rr = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
calcValues(e.o, e.a, e.iv, e.ct / e.t, e.m || 'value');
|
calcValues(e.o, e.a, e.iv, e.ct / e.t, e.m || 'value');
|
||||||
if (e.ct == e.t && e.r) {
|
if (e.ct == e.t && e.r) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { InteractiveObject } from '@/components/InteractiveObjects/InteractiveObject';
|
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';
|
||||||
|
import { autoScale } from '@/lib/MeshUtils';
|
||||||
let gameEngine = null;
|
let gameEngine = null;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -185,7 +186,7 @@ export default {
|
|||||||
object[p].copy(l[data.id][p])
|
object[p].copy(l[data.id][p])
|
||||||
})
|
})
|
||||||
}else if (!data.type || data.type == 'GenericObject'){
|
}else if (!data.type || data.type == 'GenericObject'){
|
||||||
gameEngine.autoScale(object, autoScaleFactor);
|
autoScale(object, autoScaleFactor);
|
||||||
}
|
}
|
||||||
l[data.id] = l[data.id] || {};
|
l[data.id] = l[data.id] || {};
|
||||||
['position', 'scale', 'rotation', 'visible'].forEach(p=>{
|
['position', 'scale', 'rotation', 'visible'].forEach(p=>{
|
||||||
|
|||||||
Reference in New Issue
Block a user