123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- import * as RE from 'rogue-engine';
- import * as THREE from 'three';
- import CannonBox from '../Shapes/CannonBox.re';
- import CannonSphere from '../Shapes/CannonSphere.re';
- import CannonShape from '../Shapes/CannonShape';
- import CannonCylinder from '../Shapes/CannonCylinder.re';
- import CannonTrimesh from '../Shapes/CannonTrimesh.re';
- export default class CannonBodyWireframe extends RE.Component {
- static isEditorComponent = true;
- selectedObjects: THREE.Object3D[] = [];
- colliders: THREE.Object3D[] = [];
- wireframeMaterial = new THREE.MeshStandardMaterial({wireframe: true, emissive: new THREE.Color("#00FF00"), color: new THREE.Color("#000000")});
- private handleOnComponentAdded = {stop: () => {}};
- private handleOnComponentRemoved = {stop: () => {}};
- private handleOnPlay = {stop: () => {}};
- private resetHandler = (component: RE.Component) => {
- component instanceof CannonShape && this.setupImpostors();
- }
- start() {
- this.handleOnComponentAdded.stop();
- this.handleOnComponentRemoved.stop();
- this.handleOnPlay.stop();
- this.handleOnComponentAdded = RE.onComponentAdded(this.resetHandler);
- this.handleOnComponentRemoved = RE.onComponentRemoved(this.resetHandler);
- this.handleOnPlay = RE.Runtime.onPlay(() => {
- this.handleOnComponentAdded.stop();
- this.handleOnComponentRemoved.stop();
- this.cleanupImpostors();
- });
- }
- afterUpdate() {
- const selectedObjects = window["rogue-editor"].Project.selectedObjects as THREE.Object3D[];
- if (!this.arraysAreEqual(selectedObjects, this.selectedObjects)) {
- this.selectedObjects = selectedObjects.slice(0);
- this.setupImpostors();
- }
- if (this.selectedObjects.length === 0) return;
- this.updateImpostors();
- }
- private updateImpostors() {
- this.colliders.forEach(impostor => {
- this.updateColliderMesh(impostor.userData.cannonShape, impostor as THREE.Mesh);
- });
- }
- private cleanupImpostors() {
- this.colliders.forEach(impostor => {
- impostor.userData.cannonShape = null;
- RE.App.currentScene.remove(impostor);
- RE.dispose(impostor);
- });
- this.colliders = [];
- }
- private setupImpostors() {
- this.cleanupImpostors();
- this.selectedObjects.forEach(selected => {
- selected.traverse(object => {
- const objComponents = RE.components[object.uuid];
- if (!objComponents) return;
- objComponents.forEach(component => {
- if (!(component instanceof CannonShape)) return;
- let impostor = RE.App.currentScene.getObjectByName("EDITOR_OBJECT_BB_" + object.uuid);
- if (impostor) return;
- impostor = this.getColliderMesh(component);
- if (impostor) {
- impostor.name = "EDITOR_OBJECT_BB_" + object.uuid;
- impostor.userData.isEditorObject = true;
- RE.App.currentScene.add(impostor);
- } else {
- return;
- }
- impostor.userData.cannonShape = component;
- this.colliders.push(impostor);
- });
- });
- });
- }
- private arraysAreEqual(array1: any[], array2: any[]) {
- if (array1.length !== array2.length) return false;
- return array1.every((element, i) => {
- return array2[i] === element;
- });
- }
- private getColliderMesh(component: CannonShape): THREE.Mesh | undefined {
- if (component instanceof CannonBox) {
- return new THREE.Mesh(
- new THREE.BoxBufferGeometry(),
- this.wireframeMaterial,
- );
- }
- if (component instanceof CannonCylinder) {
- const radiusTop = component.radiusTopOffset * component.object3d.scale.x;
- const radiusBottom = component.radiusBottomOffset * component.object3d.scale.x;
- const height = component.heightOffset * component.object3d.scale.y;
- return new THREE.Mesh(
- new THREE.CylinderBufferGeometry(radiusTop, radiusBottom, height, component.segments),
- this.wireframeMaterial,
- );
- }
- if (component instanceof CannonSphere) {
- const scale = component.object3d.scale;
- const maxSide = Math.max(scale.x, scale.y, scale.z);
- const radius = component.radiusOffset * (maxSide);
- const compensatedRadius = radius + (radius * 0.01);
- const segments = 15;
- return new THREE.Mesh(
- new THREE.SphereBufferGeometry(compensatedRadius, segments, segments),
- this.wireframeMaterial,
- );
- }
- if (component instanceof CannonTrimesh) {
- if (!component.shape) component.createShape();
- if (component.shape) {
- const geometry = new THREE.BufferGeometry();
- const mesh = new THREE.Mesh(geometry, this.wireframeMaterial);
- const points: THREE.Vector3[] = [];
- for (let i = 0; i < component.shape.vertices.length; i+=3) {
- const point = new THREE.Vector3(
- component.shape.vertices[i],
- component.shape.vertices[i + 1],
- component.shape.vertices[i + 2]
- );
- points.push(point);
- }
- geometry.setFromPoints(points);
- return mesh;
- }
- }
- return;
- }
- private updateColliderMesh(component: CannonShape, mesh: THREE.Mesh) {
- if (component instanceof CannonBox) {
- component.object3d.getWorldScale(mesh.scale);
- mesh.scale.set(
- component.sizeOffset.x * (mesh.scale.x),
- component.sizeOffset.y * (mesh.scale.y),
- component.sizeOffset.z * (mesh.scale.z)
- );
- }
- if (component instanceof CannonCylinder) {
- component.object3d.getWorldScale(mesh.scale);
- const radiusTop = component.radiusTopOffset * mesh.scale.x
- const radiusBottom = component.radiusBottomOffset * mesh.scale.x;
- const height = component.heightOffset * mesh.scale.y;
- if (mesh.geometry instanceof THREE.CylinderBufferGeometry) {
- if (
- mesh.geometry.parameters.radiusTop !== radiusTop ||
- mesh.geometry.parameters.radiusBottom !== radiusBottom ||
- mesh.geometry.parameters.height !== height ||
- mesh.geometry.parameters.radialSegments !== component.segments
- ) {
- mesh.geometry.dispose();
- mesh.geometry = new THREE.CylinderBufferGeometry(radiusTop, radiusBottom, height, component.segments);
- }
- }
- }
- if (component instanceof CannonSphere) {
- const scale = component.object3d.scale;
- const maxSide = Math.max(scale.x, scale.y, scale.z);
- const radius = component.radiusOffset * (maxSide);
- if (mesh.geometry instanceof THREE.SphereBufferGeometry) {
- if (mesh.geometry.parameters.radius !== radius) {
- let segments = 10 * radius;
- if (segments < 15) segments = 15;
- if (segments > 50) segments = 50;
- mesh.geometry.dispose();
- mesh.geometry = new THREE.SphereBufferGeometry(radius, segments, segments);
- }
- }
- }
- component.object3d.getWorldPosition(mesh.position);
- component.object3d.getWorldQuaternion(mesh.quaternion);
- }
- onBeforeRemoved() {
- this.handleOnComponentAdded.stop();
- this.handleOnComponentRemoved.stop();
- this.handleOnPlay.stop();
- this.cleanupImpostors();
- }
- }
- RE.registerComponent(CannonBodyWireframe);
|