refactored grabbing.
This commit is contained in:
parent
88668c3d64
commit
d59e75ddc9
@ -14,6 +14,8 @@ import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
|
|||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {Controllers} from "./controllers";
|
import {Controllers} from "./controllers";
|
||||||
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
|
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
|
||||||
|
import {setupTransformNode} from "./functions/setupTransformNode";
|
||||||
|
import {reparent} from "./functions/reparent";
|
||||||
|
|
||||||
export class Base {
|
export class Base {
|
||||||
static stickVector = Vector3.Zero();
|
static stickVector = Vector3.Zero();
|
||||||
@ -92,20 +94,8 @@ export class Base {
|
|||||||
this.controller.pointer.setEnabled(true);
|
this.controller.pointer.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupTransformNode(mesh: TransformNode) {
|
private grab() {
|
||||||
const transformNode = new TransformNode("grabAnchor, this.scene");
|
const mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);
|
||||||
transformNode.id = "grabAnchor";
|
|
||||||
transformNode.position = mesh.position.clone();
|
|
||||||
transformNode.rotationQuaternion = mesh.rotationQuaternion.clone();
|
|
||||||
transformNode.setParent(this.controller.motionController.rootMesh);
|
|
||||||
return transformNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
private grab(mesh: AbstractMesh) {
|
|
||||||
|
|
||||||
if (this.xr.pointerSelection.getMeshUnderPointer) {
|
|
||||||
mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);
|
|
||||||
}
|
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -123,18 +113,20 @@ export class Base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.previousParentId = mesh?.parent?.id;
|
this.previousParentId = mesh?.parent?.id;
|
||||||
|
this.logger.warn("grabbed " + mesh?.id + " parent " + this.previousParentId);
|
||||||
this.previousRotation = mesh?.rotation.clone();
|
this.previousRotation = mesh?.rotation.clone();
|
||||||
this.previousScaling = mesh?.scaling.clone();
|
this.previousScaling = mesh?.scaling.clone();
|
||||||
this.previousPosition = mesh?.position.clone();
|
this.previousPosition = mesh?.position.clone();
|
||||||
|
|
||||||
if ("toolbox" != mesh?.parent?.parent?.id) {
|
if ("toolbox" != mesh?.parent?.parent?.id) {
|
||||||
if (mesh.physicsBody) {
|
if (mesh.physicsBody) {
|
||||||
const transformNode = this.setupTransformNode(mesh);
|
const transformNode = setupTransformNode(mesh, this.controller.motionController.rootMesh);
|
||||||
mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED);
|
mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED);
|
||||||
this.grabbedMeshParentId = transformNode.id;
|
this.grabbedMeshParentId = transformNode.id;
|
||||||
} else {
|
} else {
|
||||||
mesh.setParent(this.controller.motionController.rootMesh);
|
mesh.setParent(this.controller.motionController.rootMesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.grabbedMesh = mesh;
|
this.grabbedMesh = mesh;
|
||||||
} else {
|
} else {
|
||||||
const newMesh = this.diagramManager.createCopy(mesh);
|
const newMesh = this.diagramManager.createCopy(mesh);
|
||||||
@ -148,9 +140,6 @@ export class Base {
|
|||||||
}
|
}
|
||||||
transformNode.setParent(this.controller.motionController.rootMesh);
|
transformNode.setParent(this.controller.motionController.rootMesh);
|
||||||
this.grabbedMeshParentId = transformNode.id;
|
this.grabbedMeshParentId = transformNode.id;
|
||||||
|
|
||||||
|
|
||||||
//newMesh && newMesh.setParent(this.controller.motionController.rootMesh);
|
|
||||||
this.grabbedMesh = newMesh;
|
this.grabbedMesh = newMesh;
|
||||||
this.previousParentId = null;
|
this.previousParentId = null;
|
||||||
const event: DiagramEvent = {
|
const event: DiagramEvent = {
|
||||||
@ -158,14 +147,12 @@ export class Base {
|
|||||||
entity: toDiagramEntity(newMesh)
|
entity: toDiagramEntity(newMesh)
|
||||||
}
|
}
|
||||||
this.diagramManager.onDiagramEventObservable.notifyObservers(event);
|
this.diagramManager.onDiagramEventObservable.notifyObservers(event);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleGrabbed(mesh: AbstractMesh): boolean {
|
private toolboxHandleWasGrabbed(mesh: AbstractMesh): boolean {
|
||||||
if (!mesh?.metadata?.template
|
if (!mesh?.metadata?.template
|
||||||
&& mesh?.id == "handle") {
|
&& mesh?.id == "handle") {
|
||||||
//mesh && mesh.setParent(null);
|
|
||||||
this.grabbedMesh = null;
|
this.grabbedMesh = null;
|
||||||
this.previousParentId = null;
|
this.previousParentId = null;
|
||||||
mesh.setParent(null);
|
mesh.setParent(null);
|
||||||
@ -174,38 +161,18 @@ export class Base {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private reparent(mesh: AbstractMesh) {
|
|
||||||
if (this.previousParentId) {
|
|
||||||
const parent = this.scene.getMeshById(this.previousParentId);
|
|
||||||
if (parent) {
|
|
||||||
//mesh && mesh.setParent(this.scene.getMeshById(this.previousParentId));
|
|
||||||
log.getLogger("Base").warn("Base", "Have not implemented snapping to parent yet");
|
|
||||||
//@note: this is not implemented yet
|
|
||||||
} else {
|
|
||||||
mesh.setParent(null);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const parent = this.scene.getTransformNodeById(this.grabbedMeshParentId);
|
|
||||||
if (parent) {
|
|
||||||
this.grabbedMeshParentId = null;
|
|
||||||
parent.dispose();
|
|
||||||
} else {
|
|
||||||
mesh.setParent(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private drop() {
|
private drop() {
|
||||||
const mesh = this.grabbedMesh;
|
const mesh = this.grabbedMesh;
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.handleGrabbed(mesh)) {
|
if (this.toolboxHandleWasGrabbed(mesh)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.reparent(mesh);
|
reparent(mesh, this.previousParentId, this.grabbedMeshParentId);
|
||||||
|
this.grabbedMeshParentId = null;
|
||||||
|
|
||||||
if (!mesh.physicsBody) {
|
if (!mesh.physicsBody) {
|
||||||
mesh.position = this.diagramManager.config.snapGridVal(mesh.position, this.diagramManager.config.current.gridSnap);
|
mesh.position = this.diagramManager.config.snapGridVal(mesh.position, this.diagramManager.config.current.gridSnap);
|
||||||
mesh.rotation = this.diagramManager.config.snapRotateVal(mesh.rotation, this.diagramManager.config.current.rotateSnap);
|
mesh.rotation = this.diagramManager.config.snapRotateVal(mesh.rotation, this.diagramManager.config.current.rotateSnap);
|
||||||
@ -242,7 +209,7 @@ export class Base {
|
|||||||
grip.onButtonStateChangedObservable.add(() => {
|
grip.onButtonStateChangedObservable.add(() => {
|
||||||
if (grip.changes.pressed) {
|
if (grip.changes.pressed) {
|
||||||
if (grip.pressed) {
|
if (grip.pressed) {
|
||||||
this.grab(this.scene.meshUnderPointer);
|
this.grab();
|
||||||
} else {
|
} else {
|
||||||
this.drop();
|
this.drop();
|
||||||
}
|
}
|
||||||
|
|||||||
26
src/controllers/functions/reparent.ts
Normal file
26
src/controllers/functions/reparent.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import {AbstractMesh} from "@babylonjs/core";
|
||||||
|
import log from "loglevel";
|
||||||
|
|
||||||
|
const logger = log.getLogger('reparent');
|
||||||
|
|
||||||
|
export function reparent(mesh: AbstractMesh, previousParentId: string, grabbedMeshParentId: string) {
|
||||||
|
if (previousParentId) {
|
||||||
|
const parent = mesh.getScene().getMeshById(previousParentId);
|
||||||
|
if (parent) {
|
||||||
|
//mesh && mesh.setParent(this.scene.getMeshById(this.previousParentId));
|
||||||
|
logger.warn('not yet implemented')
|
||||||
|
//@note: this is not implemented yet
|
||||||
|
} else {
|
||||||
|
mesh.setParent(null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const parent = mesh.getScene().getTransformNodeById(grabbedMeshParentId);
|
||||||
|
if (parent) {
|
||||||
|
logger.warn('setting parent to null', grabbedMeshParentId, parent)
|
||||||
|
//this.grabbedMeshParentId = null;
|
||||||
|
parent.dispose();
|
||||||
|
} else {
|
||||||
|
mesh.setParent(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/controllers/functions/setupTransformNode.ts
Normal file
10
src/controllers/functions/setupTransformNode.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import {AbstractMesh, TransformNode} from "@babylonjs/core";
|
||||||
|
|
||||||
|
export function setupTransformNode(mesh: TransformNode, parent: AbstractMesh) {
|
||||||
|
const transformNode = new TransformNode("grabAnchor, this.scene");
|
||||||
|
transformNode.id = "grabAnchor";
|
||||||
|
transformNode.position = mesh.position.clone();
|
||||||
|
transformNode.rotationQuaternion = mesh.rotationQuaternion.clone();
|
||||||
|
transformNode.setParent(parent);
|
||||||
|
return transformNode;
|
||||||
|
}
|
||||||
@ -1,9 +1,14 @@
|
|||||||
import {DiaSounds} from "../../util/diaSounds";
|
import {DiaSounds} from "../../util/diaSounds";
|
||||||
import {AbstractMesh, PhysicsAggregate, PhysicsMotionType, PhysicsShapeType, Scene} from "@babylonjs/core";
|
import {AbstractMesh, PhysicsAggregate, PhysicsBody, PhysicsMotionType, PhysicsShapeType, Scene} from "@babylonjs/core";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
|
|
||||||
export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene, motionType?: PhysicsMotionType) {
|
const logger = log.getLogger('DiagramShapePhysics');
|
||||||
const logger = log.getLogger('DiagramShapePhysics');
|
const MASS_FACTOR = 10;
|
||||||
|
|
||||||
|
export function applyPhysics(sounds: DiaSounds,
|
||||||
|
mesh: AbstractMesh,
|
||||||
|
scene: Scene,
|
||||||
|
motionType?: PhysicsMotionType) {
|
||||||
if (!mesh?.metadata?.template) {
|
if (!mesh?.metadata?.template) {
|
||||||
logger.error("applyPhysics: mesh.metadata.template is null", mesh);
|
logger.error("applyPhysics: mesh.metadata.template is null", mesh);
|
||||||
return;
|
return;
|
||||||
@ -15,11 +20,9 @@ export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene
|
|||||||
logger.error("applyPhysics: mesh or scene is null");
|
logger.error("applyPhysics: mesh or scene is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh.physicsBody) {
|
if (mesh.physicsBody) {
|
||||||
mesh.physicsBody.dispose();
|
mesh.physicsBody.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
let shapeType = PhysicsShapeType.BOX;
|
let shapeType = PhysicsShapeType.BOX;
|
||||||
switch (mesh.metadata.template) {
|
switch (mesh.metadata.template) {
|
||||||
case "#sphere-template":
|
case "#sphere-template":
|
||||||
@ -31,16 +34,32 @@ export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene
|
|||||||
case "#cone-template":
|
case "#cone-template":
|
||||||
shapeType = PhysicsShapeType.CONVEX_HULL;
|
shapeType = PhysicsShapeType.CONVEX_HULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
let mass = mesh.scaling.x * mesh.scaling.y * mesh.scaling.z * 10;
|
const mass = mesh.scaling.x * mesh.scaling.y * mesh.scaling.z * MASS_FACTOR;
|
||||||
|
|
||||||
const aggregate = new PhysicsAggregate(mesh,
|
const aggregate = new PhysicsAggregate(mesh,
|
||||||
shapeType, {mass: mass, restitution: .02, friction: .9}, scene);
|
shapeType, {mass: mass, restitution: .02, friction: .9}, scene);
|
||||||
const body = aggregate.body;
|
const body = aggregate.body;
|
||||||
body.setLinearDamping(1.95);
|
applyMotionType(motionType, body, mesh);
|
||||||
body.setAngularDamping(1.99);
|
|
||||||
|
|
||||||
|
body.setCollisionCallbackEnabled(true);
|
||||||
|
body.getCollisionObservable().add((event) => {
|
||||||
|
if (event.impulse < 10 && event.impulse > 1) {
|
||||||
|
const sound = sounds.bounce;
|
||||||
|
sound.setVolume(event.impulse / 10);
|
||||||
|
sound.attachToMesh(mesh);
|
||||||
|
sound.play();
|
||||||
|
}
|
||||||
|
}, -1, false);
|
||||||
|
applyPhysicsDefaults(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyPhysicsDefaults(body: PhysicsBody) {
|
||||||
|
body.setLinearDamping(.95);
|
||||||
|
body.setAngularDamping(.99);
|
||||||
|
body.setGravityFactor(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyMotionType(motionType: PhysicsMotionType, body: PhysicsBody, mesh: AbstractMesh) {
|
||||||
if (motionType) {
|
if (motionType) {
|
||||||
body
|
body
|
||||||
.setMotionType(motionType);
|
.setMotionType(motionType);
|
||||||
@ -53,18 +72,4 @@ export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene
|
|||||||
.setMotionType(PhysicsMotionType.DYNAMIC);
|
.setMotionType(PhysicsMotionType.DYNAMIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
body.setCollisionCallbackEnabled(true);
|
}
|
||||||
body.getCollisionObservable().add((event) => {
|
|
||||||
|
|
||||||
if (event.impulse < 10 && event.impulse > 1) {
|
|
||||||
const sound = sounds.bounce;
|
|
||||||
sound.setVolume(event.impulse / 10);
|
|
||||||
sound.attachToMesh(mesh);
|
|
||||||
sound.play();
|
|
||||||
}
|
|
||||||
}, -1, false, this);
|
|
||||||
//body.setMotionType(PhysicsMotionType.ANIMATED);
|
|
||||||
body.setLinearDamping(.95);
|
|
||||||
body.setAngularDamping(.99);
|
|
||||||
body.setGravityFactor(0);
|
|
||||||
}
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user