UNPKG

react-planner-electron

Version:

react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.

233 lines (179 loc) 6.38 kB
import * as Three from 'three'; import React from 'react'; const WIDTH=30; const DEPTH=40; const HEIGHT=70; const textureLoader = new Three.TextureLoader(); const Image = textureLoader.load(require('./bronze-texture.jpg')); const material = new Three.MeshLambertMaterial( {map:Image} ); const objectMaxLOD = makeObjectMaxLOD(); const objectMinLOD = makeObjectMinLOD(); function makeObjectMaxLOD() { let umbrellaStand = new Three.Mesh(); let roundedRectShape = new Three.Shape(); let x=0; let y=0; let width=.45; let height=.7; roundedRectShape.moveTo( x, y ); roundedRectShape.lineTo( x + width, y); roundedRectShape.lineTo( x + width, y+height ); roundedRectShape.lineTo( x, y + height) ; let holePath = new Three.Path(); holePath.moveTo( width/2, height/2 ); holePath.absellipse( .225, .15, .100, .025, .025, Math.PI*2, false ); roundedRectShape.holes.push( holePath ); let extrudeSettings = { steps: 2, depth: .05, bevelEnabled: false, bevelThickness: 1, bevelSize: 1, bevelSegments: 1 }; let SideGeometry = new Three.ExtrudeGeometry( roundedRectShape, extrudeSettings ); let Side1 = new Three.Mesh( SideGeometry, material ) ; Side1.position.set(.05,1.2,0); Side1.rotation.z+=Math.PI; umbrellaStand.add(Side1); let Side2 = new Three.Mesh( SideGeometry, material ) ; Side2.position.set(.05,1.2,-.4); Side2.rotation.z+=Math.PI; umbrellaStand.add(Side2); let Side3 = new Three.Mesh( SideGeometry, material ) ; Side3.position.set(.05,1.2,-.4); Side3.rotation.z+=Math.PI; Side3.rotation.y+=Math.PI/2; umbrellaStand.add(Side3); let Side4 = new Three.Mesh( SideGeometry, material ) ; Side4.position.set(-.45,1.2,-.4); Side4.rotation.z+=Math.PI; Side4.rotation.y+=Math.PI/2; umbrellaStand.add(Side4); let geometryBox = new Three.BoxGeometry(.55, .45, .05 ); let downPlane = new Three.Mesh( geometryBox, material ); downPlane.rotation.x+=Math.PI/2; downPlane.position.set(-.175,.475,-.175); umbrellaStand.add(downPlane); return umbrellaStand } function makeObjectMinLOD() { let umbrellaStand = new Three.Mesh(); let roundedRectShape = new Three.Shape(); let x=0; let y=0; let width=.45; let height=.7; roundedRectShape.moveTo( x, y ); roundedRectShape.lineTo( x + width, y); roundedRectShape.lineTo( x + width, y+height ); roundedRectShape.lineTo( x, y + height) ; let extrudeSettings = { steps: 2, depth: .05, bevelEnabled: false, bevelThickness: 1, bevelSize: 1, bevelSegments: 1 }; let SideGeometry = new Three.ExtrudeGeometry( roundedRectShape, extrudeSettings ); let Side1 = new Three.Mesh( SideGeometry, material ) ; Side1.position.set(.05,1.2,0); Side1.rotation.z+=Math.PI; umbrellaStand.add(Side1); let Side2 = new Three.Mesh( SideGeometry, material ) ; Side2.position.set(.05,1.2,-.4); Side2.rotation.z+=Math.PI; umbrellaStand.add(Side2); let Side3 = new Three.Mesh( SideGeometry, material ) ; Side3.position.set(.05,1.2,-.4); Side3.rotation.z+=Math.PI; Side3.rotation.y+=Math.PI/2; umbrellaStand.add(Side3); let Side4 = new Three.Mesh( SideGeometry, material ) ; Side4.position.set(-.45,1.2,-.4); Side4.rotation.z+=Math.PI; Side4.rotation.y+=Math.PI/2; umbrellaStand.add(Side4); let geometryBox = new Three.BoxGeometry(.55, .45, .05 ); let downPlane = new Three.Mesh( geometryBox, material ); downPlane.rotation.x+=Math.PI/2; downPlane.position.set(-.175,.475,-.175); umbrellaStand.add(downPlane); return umbrellaStand } export default { name: "umbrella-stand", prototype: "items", info: { tag: ['furnishings', 'metal'], title: "umbrella stand", description: "umbrella stand", image: require('./umbrellaStand.png') }, properties: { altitude: { label: "altitude", type: "length-measure", defaultValue: { length: 0, unit: 'cm' } } }, render2D: function (element, layer, scene) { let angle = element.rotation + 90; let textRotation = 0; if (Math.sin(angle * Math.PI / 180) < 0) { textRotation = 180; } return ( <g transform={`translate(${-WIDTH / 2},${-DEPTH / 2})`}> <rect key="1" x="0" y="0" width={WIDTH} height={DEPTH} style={{stroke: element.selected ? '#0096fd' : '#000', strokeWidth: "2px", fill: "#84e1ce"}}/> <text key="2" x="0" y="0" transform={`translate(${WIDTH / 2}, ${DEPTH / 2}) scale(1,-1) rotate(${textRotation})`} style={{textAnchor: "middle", fontSize: "11px"}}> {element.type} </text> </g> ) }, render3D: function (element, layer, scene) { let newAltitude = element.properties.get('altitude').get('length'); /***************** lod max *******************/ let umbrellaStandMaxLOD = new Three.Object3D(); umbrellaStandMaxLOD.add(objectMaxLOD.clone()); let value = new Three.Box3().setFromObject(umbrellaStandMaxLOD); let deltaX = Math.abs(value.max.x - value.min.x); let deltaY = Math.abs(value.max.y - value.min.y); let deltaZ = Math.abs(value.max.z - value.min.z); umbrellaStandMaxLOD.position.x+= -WIDTH/1.5; umbrellaStandMaxLOD.position.z+= DEPTH/4; umbrellaStandMaxLOD.position.y+= -HEIGHT/1.6 + newAltitude; umbrellaStandMaxLOD.rotation.y+= -Math.PI/2; umbrellaStandMaxLOD.scale.set(WIDTH / deltaZ, HEIGHT / deltaY, DEPTH / deltaX); /**************** lod min *******************/ let umbrellaStandMinLOD = new Three.Object3D(); umbrellaStandMinLOD.add(objectMinLOD.clone()); umbrellaStandMinLOD.position.x+= -WIDTH/1.5; umbrellaStandMinLOD.position.z+= DEPTH/4; umbrellaStandMinLOD.position.y+= -HEIGHT/1.6 + newAltitude; umbrellaStandMinLOD.rotation.y+= -Math.PI/2; umbrellaStandMinLOD.scale.set(WIDTH / deltaZ, HEIGHT / deltaY, DEPTH / deltaX); /**** all level of detail ***/ let lod = new Three.LOD(); lod.addLevel(umbrellaStandMaxLOD, 200); lod.addLevel(umbrellaStandMinLOD, 900); lod.updateMatrix(); lod.matrixAutoUpdate = false; if (element.selected) { let bbox = new Three.BoxHelper(lod, 0x99c3fb); bbox.material.linewidth = 5; bbox.renderOrder = 1000; bbox.material.depthTest = false; lod.add(bbox); } return Promise.resolve(lod); } };