UNPKG

awv3

Version:
202 lines (193 loc) 8.18 kB
import * as THREE from 'three' import Plugin from '../../session/plugin' import { Group, Input, Button, Label, Dropdown, Spacer } from '../../session/elements' import React, { Component, connect } from '../../session/renderer' import { actions as globalActions } from '../../session/store/globals' import Hud from '../../core/hud' import Graphics from './graphics' import { PositionHandle, ValueHandle } from './handle' @connect((state, { connection, key }) => ({ day: state.globals.day, dimension: state.connections[connection] && state.connections[connection].tree[key], })) class Dimension extends Component { componentWillMount() { this.info = this.getDimensionInfo(this.props) this.state = { inputValue: this.info.value, inputName: this.info.name } this.graphics = Graphics(this.info.dimension.class, this.plugin) this.plugin.hud.scene.add(this.graphics) this.graphics.updateFromState(this.info) } componentWillUnmount() { this.graphics && this.graphics.destroy() } componentWillReceiveProps(props) { if (props.dimension) { this.info = this.getDimensionInfo(props) if (!this.graphics) this.graphics = Graphics(this.info.dimension.class, this.plugin) this.graphics.updateFromState(this.info) } else { this.graphics.destroy() this.graphics = undefined } // This is kind of a hack. Which value should "win"? The one that the user typed, or the one // that comes through the wire from ClassCAD? The current solution overrides the input value. this.state = { ...this.state, inputValue: this.info.value } } setExpression(target, name, expression) { const expressionSet = target.class === 'CC_ExpressionSet' const flag = this.plugin.recalc && expressionSet ? 1 : 2 this.plugin.connection.execute( `_C.CADApplication.SetExpressions(${target.id},["${name}"],[${JSON.stringify(expression)}],${flag});`, ) this.plugin.afterSetCallback() } setMember(target, name, value) { this.plugin.connection.execute(`VAR o; o = CADH_RealToId(${target.id}); o.${name} = ${JSON.stringify(value)};`) } getDimensionInfo(props) { const scope = this const { dimension, expressions, feature, search } = props dimension.previewValue = undefined const master = dimension.members.master ? this.plugin.tree[dimension.members.master.value] : dimension const driven = (dimension.members.isDriven || {}).value const linkName = master.class === 'CC_Extrusion' ? dimension.name : master.members.userValue ? 'userValue' : 'value' let expression = master.members[linkName].expression const angle = expression.match(/^ *a_r\((.*)\) *$/) if (angle) expression = angle[1] const matches = expression.match(/^ *ExpressionSet\.(\w+) *$/) const target = matches ? expressions : master const memberName = matches ? matches[1] : linkName const owner = (this.plugin.tree[dimension.parent].members.owner || {}).value const visible = (!search || dimension.members.paramName.value.toLowerCase().indexOf(search) != -1) && (!feature || owner === feature) const setMember = this.setMember.bind(this) const setExpression = this.setExpression.bind(this) return { dimension, angle, driven, visible, get name() { return dimension.members.paramName.value }, set name(value) { setMember(dimension, 'paramName', value) }, get value() { return target.members[memberName].value }, set value(value) { setMember(target, memberName, value) }, get expression() { return target.members[memberName].expression || target.members[memberName].value }, set expression(value) { setExpression(target, memberName, value) }, set dimPt(value) { setExpression(dimension, 'dimPt', value) }, } } render() { if (!this.info) return null const { dimension, visible, name, value, driven } = this.info return ( <Group visible={visible} format={Group.Format.Rows}> <Input value={this.state.inputName} onValue={inputName => this.setState({ inputName })} onLastEvent={e => e.key === 'Enter' && (this.info.name = this.state.inputName)} readonly={!!driven} flex={1} /> <Input format={Input.Format.Number} value={this.state.inputValue} onValue={inputValue => this.setState({ inputValue })} onLastEvent={e => e.key === 'Enter' && (this.info.expression = this.state.inputValue)} readonly={!!driven} flex={2} /> <Button name={driven ? '🔒' : '🔓'} disabled={driven === undefined} onLastEvent={() => this.setMember(dimension, 'isDriven', !!driven ? 0 : 1)} flex={0} /> </Group> ) } } @connect((state, props) => { const connection = state.globals.activeConnection if (!state.globals.activeConnection) return {} const tree = state.connections[connection].tree const root = tree[tree.root].item || tree.root const expressions = tree[root].expressionSet const parent = state.plugins[props.id] && state.plugins[props.id].parent const feature = parent && state.plugins[parent] && state.plugins[parent].feature return { connection, root, feature, dimensions: tree[root].dimensions, expressions: tree[expressions] } }) class Root extends Component { state = { search: '' } componentWillReceiveProps(props) { const hud = this.plugin.hud const tree = this.plugin.tree const itemRef = (tree[tree.root].instances || []).find(instance => tree[instance].link === props.root) || props.root const csys = tree[itemRef].coordinateSystem.map(row => new THREE.Vector3().fromArray(row)) hud.scene.matrix .makeBasis(csys[1], csys[2], csys[3]) .setPosition(csys[0]) .decompose(hud.scene.position, hud.scene.quaternion, hud.scene.scale) hud.scene.matrixWorldNeedsUpdate = true } render({ connection, root, feature, expressions, dimensions = [] } = {}, { search }, set) { const commons = { feature, search, expressions, connection } return ( <Group> <Group format={Group.Format.Rows}> <Input value={search} placeholder="Search..." onValue={search => set({ search })} /> <Button name="✘" flex={0} disabled={!search} onLastEvent={() => set({ search: '' })} /> </Group> <Spacer /> {dimensions.map(id => <Dimension key={id} {...commons} />)} </Group> ) } } const resources = ['dimension'].reduce( (prev, item) => ({ ...prev, [item]: require('!!url-loader!awv3-icons/32x32/' + item + '.png') }), {}, ) export default class extends Plugin { constructor(session, args) { super(session, { type: 'Dimensions', icon: 'dimension', recalc: true, handlePrototypes: [PositionHandle, ValueHandle], resources, ...args, }) this.selector = undefined this.afterSetCallback = () => {} } render() { return <Root id={this.id} /> } onEnabled() { this.hud = new Hud(this.view) this.view.addHud(this.hud) } onDisabled() { this.view.removeHud(this.hud) this.hud.destroy() } }