UNPKG

awv3

Version:
179 lines (161 loc) 6.32 kB
import * as THREE from 'three' import Plugin from '../../session/plugin' import { buildFeaturePath, normalizeName } from '../../session/helpers' import { Slider, Spacer, Group, Button, Input, Label, Selection, Checkbox, Dropdown, Console, } from '../../session/elements' const resources = ['csys'].reduce( (prev, item) => ({ ...prev, [item]: require('!!url-loader!awv3-icons/32x32/' + item + '.png') }), {}, ) export default class Csys extends Plugin { static persistent = true constructor(session, args) { super(session, { type: 'Csys', icon: 'csys', resources, ...args }) this.origin = new Selection(this, { name: 'Origin', types: ['Point'] }) this.axis = new Selection(this, { name: 'Axis', types: ['Mesh', 'LineSegments'] }) this.secondary = new Selection(this, { name: 'Secondary', types: ['Mesh', 'LineSegments'] }) this.refsGroup = new Group(this, { format: Group.Format.Table, children: [this.origin, this.axis, this.secondary], }) this.collapse = new Group(this, { name: 'References', children: [this.refsGroup], format: Group.Format.Collapse, }) this.addElement(this.collapse) this.offsetInput = new Input(this, { name: 'Offset', value: '0,0,0', format: Input.Format.Vector }) this.sliderX = new Slider(this, { name: 'Rotation X', max: 360, step: 10, positions: { 0: '0°', 90: '90°', 180: '180°', 270: '270°', 360: '360°' }, }) this.sliderY = new Slider(this, { name: 'Rotation Y', max: 360, step: 10, positions: { 0: '0°', 90: '90°', 180: '180°', 270: '270°', 360: '360°' }, }) this.sliderZ = new Slider(this, { name: 'Rotation Z', max: 360, step: 10, positions: { 0: '0°', 90: '90°', 180: '180°', 270: '270°', 360: '360°' }, }) this.main = new Group(this, { format: Group.Format.Table, children: [this.offsetInput, this.sliderX, this.sliderY, this.sliderZ], }) this.addElement(this.main) let coords = args.feature.coordinateSystem this.position = new THREE.Vector3(...coords[0]) this.rotation = new THREE.Euler() let x = new THREE.Vector3(...coords[1]) let y = new THREE.Vector3(...coords[2]) let m = new THREE.Matrix4().makeBasis(x, y, x.clone().cross(y)) this.xAxis = m this.yAxis = new THREE.Matrix4() this.offset = new THREE.Vector3() this.csys = new THREE.AxisHelper(this.pool.getRadius() / 5) this.csys.interactive = false this.csys.matrixAutoUpdate = false this.pool.add(this.csys) this.translate() } onEnabled() { this.apply.observe( state => state.lastEvent, async event => { let feature = this.tree[this.feature] let xAxis = new THREE.Vector3(), yAxis = new THREE.Vector3(), zAxis = new THREE.Vector3() this.csys.matrix.extractBasis(xAxis, yAxis, zAxis) let pos = new THREE.Vector3().setFromMatrixPosition(this.csys.matrix) let path = buildFeaturePath(this.tree, feature.id) await this.connection.execute(`${path}.SetName("${feature.name}");`) path = buildFeaturePath(this.tree, feature.id) this.connection.execute( `${path}.OBJ_SetCoordSystem({${pos.toArray().join(',')}},{${xAxis .toArray() .join(',')}},{${yAxis.toArray().join(',')}});`, ) this.connection.recalc() }, ) this.origin.observe( state => state.children, selection => { if (selection.length) { this.position = this.session.selector.getSelectedElements()[0].meta.position this.translate() } }, ) this.sliderX.observe( state => state.value, value => { this.rotation.x = value * Math.PI / 180 this.translate() }, ) this.sliderY.observe( state => state.value, value => { this.rotation.y = value * Math.PI / 180 this.translate() }, ) this.sliderZ.observe( state => state.value, value => { this.rotation.z = value * Math.PI / 180 this.translate() }, ) this.offsetInput.observe( state => state.value, value => { this.offset = new THREE.Vector3(...value.split(',')) this.translate() }, ) this.axis.observe(state => state.children, selection => this.rotate(selection, 'x')) this.secondary.observe(state => state.children, selection => this.rotate(selection, 'y')) } onDestroyed() { this.csys.destroy() } translate() { this.csys.matrix = new THREE.Matrix4() .setPosition(this.position) .multiply(this.xAxis) .multiply(this.yAxis) .multiply(new THREE.Matrix4().makeRotationFromEuler(this.rotation)) .multiply(new THREE.Matrix4().makeTranslation(...this.offset.toArray())) this.pool.view.invalidate() } rotate(selection, whichAxis) { if (selection.length) { let meta = this.session.selector.getSelectedElements()[0].meta if (meta.type === 'line') var dir = meta.end.clone().sub(meta.start.clone()).normalize() else if (meta.type === 'plane') var dir = meta.normal.clone() let axis = whichAxis === 'x' ? new THREE.Vector3(1, 0, 0) : new THREE.Vector3(0, 1, 0) let rotAxis = axis.clone().cross(dir).normalize() let angle = axis.angleTo(dir) this[`${whichAxis}Axis`] = new THREE.Matrix4().makeRotationAxis(rotAxis, angle) this.translate() } } }