import * as React from "react"; import { Observable } from "babylonjs/Misc/observable"; import { Tools } from "babylonjs/Misc/tools"; import { Color3, Vector3 } from "babylonjs/Maths/math"; import { Mesh } from "babylonjs/Meshes/mesh"; import { VertexBuffer } from "babylonjs/Meshes/buffer"; import { LinesBuilder } from "babylonjs/Meshes/Builders/linesBuilder"; import { PhysicsImpostor } from "babylonjs/Physics/physicsImpostor"; import { Scene } from "babylonjs/scene"; import { PropertyChangedEvent } from "../../../../propertyChangedEvent"; import { LineContainerComponent } from "../../../lineContainerComponent"; import { TextLineComponent } from "../../../lines/textLineComponent"; import { CheckBoxLineComponent } from "../../../lines/checkBoxLineComponent"; import { Vector3LineComponent } from "../../../lines/vector3LineComponent"; import { SliderLineComponent } from "../../../lines/sliderLineComponent"; import { QuaternionLineComponent } from "../../../lines/quaternionLineComponent"; import { FloatLineComponent } from "../../../lines/floatLineComponent"; import { LockObject } from "../lockObject"; import { GlobalState } from '../../../../globalState'; import { CustomPropertyGridComponent } from '../customPropertyGridComponent'; import { StandardMaterial } from 'babylonjs/Materials/standardMaterial'; import { Color3LineComponent } from '../../../lines/color3LineComponent'; import { MorphTarget } from 'babylonjs/Morph/morphTarget'; import { OptionsLineComponent } from '../../../lines/optionsLineComponent'; import { AbstractMesh } from 'babylonjs/Meshes/abstractMesh'; interface IMeshPropertyGridComponentProps { globalState: GlobalState; mesh: Mesh; lockObject: LockObject; onSelectionChangedObservable?: Observable; onPropertyChangedObservable?: Observable; } export class MeshPropertyGridComponent extends React.Component { constructor(props: IMeshPropertyGridComponentProps) { super(props); this.state = { displayNormals: false, displayVertexColors: false }; } renderWireframeOver() { const mesh = this.props.mesh; const scene = mesh.getScene(); if (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) { mesh.reservedDataStore.wireframeOver.dispose(false, true); mesh.reservedDataStore.wireframeOver = null; this.forceUpdate(); return; } var wireframeOver = mesh.clone()!; wireframeOver.reservedDataStore = { hidden: true }; // Sets up the mesh to be attached to the parent. // So all neutral in local space. wireframeOver.parent = mesh; wireframeOver.position = Vector3.Zero(); wireframeOver.scaling = new Vector3(1, 1, 1); wireframeOver.rotation = Vector3.Zero(); wireframeOver.rotationQuaternion = null; var material = new StandardMaterial("wireframeOver", scene); material.reservedDataStore = { hidden: true }; wireframeOver.material = material; material.zOffset = 1; material.disableLighting = true; material.backFaceCulling = false; material.emissiveColor = Color3.White(); material.wireframe = true; if (!mesh.reservedDataStore) { mesh.reservedDataStore = {}; } mesh.reservedDataStore.wireframeOver = wireframeOver; this.forceUpdate(); } renderNormalVectors() { const mesh = this.props.mesh; const scene = mesh.getScene(); if (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) { mesh.reservedDataStore.normalLines.dispose(); mesh.reservedDataStore.normalLines = null; this.forceUpdate(); return; } var normals = mesh.getVerticesData(VertexBuffer.NormalKind); var positions = mesh.getVerticesData(VertexBuffer.PositionKind); const color = Color3.White(); const size = mesh.getBoundingInfo().diagonalLength * 0.05; var lines = []; for (var i = 0; i < normals!.length; i += 3) { var v1 = Vector3.FromArray(positions!, i); var v2 = v1.add(Vector3.FromArray(normals!, i).scaleInPlace(size)); lines.push([v1, v2]); } var normalLines = LinesBuilder.CreateLineSystem("normalLines", { lines: lines }, scene); normalLines.color = color; normalLines.parent = mesh; normalLines.reservedDataStore = { hidden: true }; if (!mesh.reservedDataStore) { mesh.reservedDataStore = {}; } mesh.reservedDataStore.normalLines = normalLines; this.forceUpdate(); } displayNormals() { const mesh = this.props.mesh; const scene = mesh.getScene(); if (mesh.material && mesh.material.getClassName() === "NormalMaterial") { mesh.material.dispose(); mesh.material = mesh.reservedDataStore.originalMaterial; mesh.reservedDataStore.originalMaterial = null; this.setState({ displayNormals: false }); } else { if (!(BABYLON as any).NormalMaterial) { this.setState({ displayNormals: true }); Tools.LoadScript("https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.js", () => { this.displayNormals(); }); return; } if (!mesh.reservedDataStore) { mesh.reservedDataStore = {}; } if (!mesh.reservedDataStore.originalMaterial) { mesh.reservedDataStore.originalMaterial = mesh.material; } const normalMaterial = new (BABYLON as any).NormalMaterial("normalMaterial", scene); normalMaterial.disableLighting = true; if (mesh.material) { normalMaterial.sideOrientation = mesh.material.sideOrientation; } normalMaterial.reservedDataStore = { hidden: true }; mesh.material = normalMaterial; this.setState({ displayNormals: true }); } } displayVertexColors() { const mesh = this.props.mesh; const scene = mesh.getScene(); if (mesh.material && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial) { mesh.material.dispose(); mesh.material = mesh.reservedDataStore.originalMaterial; mesh.reservedDataStore.originalMaterial = null; this.setState({ displayVertexColors: false }); } else { if (!mesh.reservedDataStore) { mesh.reservedDataStore = {}; } if (!mesh.reservedDataStore.originalMaterial) { mesh.reservedDataStore.originalMaterial = mesh.material; } const vertexColorMaterial = new StandardMaterial("vertex colors", scene); vertexColorMaterial.disableLighting = true; vertexColorMaterial.emissiveColor = Color3.White(); if (mesh.material) { vertexColorMaterial.sideOrientation = mesh.material.sideOrientation; } vertexColorMaterial.reservedDataStore = { hidden: true, isVertexColorMaterial: true }; mesh.useVertexColors = true; mesh.material = vertexColorMaterial; this.setState({ displayVertexColors: true }); } } onMaterialLink() { if (!this.props.onSelectionChangedObservable) { return; } const mesh = this.props.mesh; this.props.onSelectionChangedObservable.notifyObservers(mesh.material); } onSourceMeshLink() { if (!this.props.onSelectionChangedObservable) { return; } const instanceMesh = this.props.mesh as any; this.props.onSelectionChangedObservable.notifyObservers(instanceMesh.sourceMesh); } convertPhysicsTypeToString(): string { const mesh = this.props.mesh; switch (mesh.physicsImpostor!.type) { case PhysicsImpostor.NoImpostor: return "No impostor"; case PhysicsImpostor.SphereImpostor: return "Sphere"; case PhysicsImpostor.BoxImpostor: return "Box"; case PhysicsImpostor.PlaneImpostor: return "Plane"; case PhysicsImpostor.MeshImpostor: return "Mesh"; case PhysicsImpostor.CylinderImpostor: return "Cylinder"; case PhysicsImpostor.ParticleImpostor: return "Particle"; case PhysicsImpostor.HeightmapImpostor: return "Heightmap"; case PhysicsImpostor.ConvexHullImpostor: return "Convex hull"; case PhysicsImpostor.RopeImpostor: return "Rope"; case PhysicsImpostor.SoftbodyImpostor: return "Soft body"; } return "Unknown"; } render() { const mesh = this.props.mesh; const scene = mesh.getScene(); const displayNormals = mesh.material != null && mesh.material.getClassName() === "NormalMaterial"; const displayVertexColors = !!(mesh.material != null && mesh.material.reservedDataStore && mesh.material.reservedDataStore.isVertexColorMaterial); const renderNormalVectors = (mesh.reservedDataStore && mesh.reservedDataStore.normalLines) ? true : false; const renderWireframeOver = (mesh.reservedDataStore && mesh.reservedDataStore.wireframeOver) ? true : false; var morphTargets: MorphTarget[] = []; if (mesh.morphTargetManager) { for (var index = 0; index < mesh.morphTargetManager.numTargets; index++) { morphTargets.push(mesh.morphTargetManager.getTarget(index)); } } var algorithmOptions = [ { label: "Accurate", value: AbstractMesh.OCCLUSION_ALGORITHM_TYPE_ACCURATE }, { label: "Conservative", value: AbstractMesh.OCCLUSION_ALGORITHM_TYPE_CONSERVATIVE }, ]; var occlusionTypeOptions = [ { label: "None", value: AbstractMesh.OCCLUSION_TYPE_NONE }, { label: "Optimistic", value: AbstractMesh.OCCLUSION_TYPE_OPTIMISTIC }, { label: "Strict", value: AbstractMesh.OCCLUSION_TYPE_STRICT }, ]; return (
mesh.isEnabled()} onSelect={(value) => mesh.setEnabled(value)} /> { mesh.material && (!mesh.material.reservedDataStore || !mesh.material.reservedDataStore.hidden) && this.onMaterialLink()} /> } { mesh.isAnInstance && this.onSourceMeshLink()} /> } { !mesh.rotationQuaternion && } { mesh.rotationQuaternion && } { !mesh.isAnInstance && } { mesh.isVerticesDataPresent(VertexBuffer.ColorKind) && } { scene.fogMode !== Scene.FOGMODE_NONE && } { !mesh.parent && } { mesh.morphTargetManager != null && { morphTargets.map((mt, i) => { return ( ) }) } } { mesh.useBones && } { mesh.physicsImpostor != null && } mesh.edgesRenderer != null} onSelect={value => { if (value) { mesh.enableEdgesRendering(); } else { mesh.disableEdgesRendering(); } }} /> displayNormals} onSelect={() => this.displayNormals()} /> displayVertexColors} onSelect={() => this.displayVertexColors()} /> { mesh.isVerticesDataPresent(VertexBuffer.NormalKind) && renderNormalVectors} onSelect={() => this.renderNormalVectors()} /> } renderWireframeOver} onSelect={() => this.renderWireframeOver()} />
); } }