react-planner-electron
Version:
react-planner-electron is a React Component for plans design. Draw a 2D floorplan and navigate it in 3D mode.
230 lines (184 loc) • 6.69 kB
JSX
import React from 'react';
import * as Three from 'three';
import { loadObjWithMaterial } from '../../utils/load-obj';
import path from 'path';
let cached3DWindow = null;
const STYLE_HOLE_BASE = { stroke: '#000', strokeWidth: '3px', fill: '#000' };
const STYLE_HOLE_SELECTED = { stroke: '#0096fd', strokeWidth: '3px', fill: '#0096fd', cursor: 'move' };
const EPSILON = 3;
export default {
name: 'window-curtain',
prototype: 'holes',
info: {
tag: ['Finestre'],
title: 'Curtain window',
description: 'Curtain window',
image: require('./window-curtain.jpg')
},
properties: {
width: {
label: 'width',
type: 'length-measure',
defaultValue: {
length: 90
}
},
height: {
label: 'height',
type: 'length-measure',
defaultValue: {
length: 100
}
},
altitude: {
label: 'altitudine',
type: 'length-measure',
defaultValue: {
length: 90
}
},
thickness: {
label: 'spessore',
type: 'length-measure',
defaultValue: {
length: 10
}
},
flip: {
label: 'flip',
type: 'checkbox',
defaultValue: 'none',
values: {
'none': 'none',
'yes': 'yes'
}
},
},
render2D: function (element, layer, scene) {
let holeWidth = element.properties.get('width').get('length');
let holePath = `M${0} ${-EPSILON} L${holeWidth} ${-EPSILON} L${holeWidth} ${EPSILON} L${0} ${EPSILON} z`;
let holeStyle = element.selected ? STYLE_HOLE_SELECTED : STYLE_HOLE_BASE;
let length = element.properties.get('width').get('length');
return (
<g transform={`translate(${-length / 2}, 0)`}>
<path key='1' d={holePath} style={holeStyle} />
<line key='2' x1={holeWidth / 2} y1={-10 - EPSILON} x2={holeWidth / 2} y2={10 + EPSILON} style={holeStyle} />
</g>
);
},
render3D: function (element, layer, scene) {
let width = element.properties.get('width').get('length');
let height = element.properties.get('height').get('length');
let thickness = element.properties.get('thickness').get('length');
let flip = element.properties.get('flip');
let onLoadItem = (object) => {
let window = new Three.Object3D();
let boundingBox = new Three.Box3().setFromObject(object);
let initialWidth = boundingBox.max.x - boundingBox.min.x;
let initialHeight = boundingBox.max.y - boundingBox.min.y;
let initialThickness = boundingBox.max.z - boundingBox.min.z;
if (element.selected) {
let box = new Three.BoxHelper(object, 0x99c3fb);
box.material.linewidth = 2;
box.material.depthTest = false;
box.renderOrder = 1000;
object.add(box);
}
let width = element.properties.get('width').get('length');
let height = element.properties.get('height').get('length');
let thickness = element.properties.get('thickness').get('length');
object.scale.set(width / initialWidth, height / initialHeight,
thickness / 2 / initialThickness);
window.add(object);
window.add(createTenda());
if (flip === true)
window.rotation.y += Math.PI;
return window;
};
if (cached3DWindow) {
return Promise.resolve(onLoadItem(cached3DWindow.clone()));
}
let mtl = require('./window.mtl');
let obj = require('./window.obj');
let img = require('./texture.png');
return loadObjWithMaterial(mtl, obj, path.dirname(img) + '/')
.then(object => {
cached3DWindow = object;
return onLoadItem(cached3DWindow.clone());
});
function createTenda() {
let radialWave = function (u, v) {
let r = 10;
let x = Math.sin(u) * 3 * r;
let z = Math.sin(v / 2) * 2 * r;
let y = (Math.sin(u * 2 * Math.PI) + Math.cos(v * 2 * Math.PI)) * .5;
return new Three.Vector3(x, y, z);
};
//color
let white = new Three.MeshLambertMaterial({ color: 0xeae6ca });
let Tenda = new Three.Object3D();
let mesh = createMesh(new Three.ParametricGeometry(radialWave, 20, 20));
mesh.rotation.x += Math.PI / 2;
mesh.rotation.y += Math.PI / 2;
mesh.position.y += 3.1;
mesh.position.x += .05;
mesh.scale.set(.125, .125, .125);
let mesh2 = mesh.clone();
mesh2.rotation.x += Math.PI;
mesh2.position.set(1.4, 0, 0.06);
Tenda.add(mesh);
Tenda.add(mesh2);
for (let i = -.7; i > -3.4; i -= .45) {
let geometry = new Three.TorusGeometry(.08, .016, 32, 32, 2 * Math.PI);
let torus = new Three.Mesh(geometry, white);
if (i == -1.15)
torus.position.set(i, 3.14, .045);
else if (i == -2.5)
torus.position.set(i, 3.14, -.01);
else
torus.position.set(i, 3.14, .04);
torus.rotation.y += Math.PI / 2;
Tenda.add(torus);
}
let geometryAsta = new Three.CylinderGeometry(0.02, 0.02, 1.25, 32);
let asta = new Three.Mesh(geometryAsta, white);
asta.position.set(-1.1, 3.18, 0.02);
asta.rotation.z += Math.PI / 2;
Tenda.add(asta);
let asta2 = asta.clone();
asta2.position.set(-2.5, 3.18, 0.02);
Tenda.add(asta2);
let geometrySphereUp = new Three.SphereGeometry(0.04, 32, 32);
let sphere = new Three.Mesh(geometrySphereUp, white);
sphere.position.set(-.5, 3.18, 0.02);
sphere.rotation.x += Math.PI / 2;
sphere.scale.set(0.8, 1, 1);
Tenda.add(sphere);
let sphere2 = sphere.clone();
sphere2.position.x += -1.2;
Tenda.add(sphere2);
let sphere3 = sphere.clone();
sphere3.position.x += -1.4;
Tenda.add(sphere3);
let sphere4 = sphere.clone();
sphere4.position.x += -2.6;
Tenda.add(sphere4);
let valueObject = new Three.Box3().setFromObject(Tenda);
let deltaX = Math.abs(valueObject.max.x - valueObject.min.x);
let deltaY = Math.abs(valueObject.max.y - valueObject.min.y);
let deltaZ = Math.abs(valueObject.max.z - valueObject.min.z);
Tenda.position.x += width / 1.48;
Tenda.position.y += -height / 2.1;
Tenda.position.z += thickness / 1024;
Tenda.scale.set(width / deltaX, height / deltaY, thickness / deltaZ);
return Tenda;
}
function createMesh(geom) {
geom.applyMatrix(new Three.Matrix4().makeTranslation(-25, 0, -25));
let meshMaterial = new Three.MeshLambertMaterial({ color: 0xffffff, opacity: 0.9, transparent: true });
meshMaterial.side = Three.DoubleSide;
let plane = new Three.Mesh(geom, meshMaterial);
return plane;
}
}
};