awv3
Version:
⚡ AWV3 embedded CAD
239 lines (220 loc) • 9.34 kB
JavaScript
import * as THREE from 'three'
import { actions as connectionActions } from '../../session/store/connections'
import { actions as elementActions } from '../../session/store/elements'
import Plugin from '../../session/plugin'
import Element from '../../session/element'
import React, { Component, connect } from '../../session/renderer'
import { Spacer, Group, Button, Input, Label, Selection, Dropdown, Link, Checkbox } from '../../session/elements'
import Members from '../members/'
const resources = ['isometric'].reduce(
(prev, item) => ({ ...prev, [item]: require('!!url-loader!awv3-icons/32x32/' + item + '.png') }),
{},
)
class CreatePanel extends Component {
constructor(props) {
super(props)
this.state = { items: props.defaultSelection, type: 'Fillet', radius: 1, offset1: 1, offset2: 1 }
}
render({ visible, createFillet }, { type, items, radius, offset1, offset2 }, set) {
return (
<Group format={Group.Format.Table}>
<Group name="Target" format={Group.Format.Rows}>
<Selection
types={['LineSegments']}
limit={1}
visible={visible}
items={items}
onItems={items => set({ items })}
/>
<Button
name="✔︎"
color="blue"
visible={items.length != 0}
flex={0}
onLastEvent={() => createFillet(this.state)}
/>
</Group>
<Dropdown name="Type" items={['Fillet', 'Chamfer']} value={type} onValue={type => set({ type })} />
<Input
name="Radius"
format={Input.Format.Number}
visible={type === 'Fillet'}
hint="expression"
value={radius}
onValue={radius => set({ radius })}
onLastEvent={e => e.key === 'Enter' && createFillet(this.state)}
/>
<Input
name="Offset1"
format={Input.Format.Number}
visible={type === 'Chamfer'}
hint="expression"
value={offset1}
onValue={offset1 => set({ offset1 })}
onLastEvent={e => e.key === 'Enter' && createFillet(this.state)}
/>
<Input
name="Offset2"
format={Input.Format.Number}
visible={type === 'Chamfer'}
hint="expression"
value={offset2}
onValue={offset2 => set({ offset2 })}
onLastEvent={e => e.key === 'Enter' && createFillet(this.state)}
/>
</Group>
)
}
}
((state, { connection, key }) => {
connection = state.connections[connection]
const tree = connection ? connection.tree : {}
return { feature: tree[key] }
})
class FeaturePlugin extends Component {
state = { flip: false, color: undefined }
componentWillMount() {
this.proto = new Members(this.plugin.session, {
icon: 'isometric',
name: this.props.feature.name,
filter: ['radius', 'offset1', 'offset2'],
collapsed: true,
closeable: false,
parent: this.plugin.id,
feature: this.props.feature,
pool: new THREE.Group(),
connection: this.plugin.connection,
})
this.proto.enabled = true
}
componentWillUnmount() {
this.proto.destroy()
}
flip = flip => {
this.setState({ flip })
const offset1 = this.proto.findElementClass(el => el.type === Element.Type.Input && el.name === 'offset1')
const offset2 = this.proto.findElementClass(el => el.type === Element.Type.Input && el.name === 'offset2')
if (offset1 && offset2) {
const temp = offset1.value
offset1.value = offset2.value
offset2.value = temp
this.update(offset1, offset2)
}
}
update = (
offset1 = this.proto.findElementClass(el => el.type === Element.Type.Input && el.name === 'offset1'),
offset2 = this.proto.findElementClass(el => el.type === Element.Type.Input && el.name === 'offset2'),
radius = this.proto.findElementClass(el => el.type === Element.Type.Input && el.name === 'radius'),
) => {
const isFillet = this.props.feature.class.indexOf('Fillet') != -1
const operation = this.props.feature.id
const names = isFillet ? '"radius"' : '"offset1", "offset2"'
const values = isFillet
? parseFloat(radius.value)
: `${parseFloat(offset1.value)}, ${parseFloat(offset2.value)}`
const command = `_C.CADApplication.SetExpressions(${operation}, [${names}], [${values}], 1);`
this.plugin.connection.execute(command)
}
render({ feature, hoverPlugins }, { flip, color }, set) {
if (!feature) return null
let isFillet = feature.class.indexOf('Fillet') != -1
let values = isFillet
? feature.members.radius.value
: `${feature.members.offset1.value}, ${feature.members.offset2.value}`
this.proto.feature = feature.id
return (
<Group
color={color}
name={`${feature.name} = ${values}`}
format={Group.Format.Collapse}
collapsed={true}
onLastEvent={event => hoverPlugins(event, feature)}>
<Link value={this.proto.id} collapsable={false} />
<Group format={Group.Format.Table}>
{!isFillet && <Checkbox name="Flip" value={flip} onValue={this.flip} />}
<Group name="Actions" format={Group.Format.Rows}>
<Button name="✘" color="black" />
<Button name="❙◀︎" color="grey" />
<Button name="✔︎" color="blue" onLastEvent={() => this.update()} />
</Group>
</Group>
</Group>
)
}
}
(state => {
const connection = state.globals.activeConnection
if (!connection) return {}
const tree = state.connections[connection].tree
const root = tree[tree.root]
return { connection, features: root.features }
})
class Features extends Component {
render({ connection, features, hoverPlugins }) {
const items = (features || [])
.filter(
feature =>
this.plugin.tree[feature].class.indexOf('Fillet') != -1 ||
this.plugin.tree[feature].class.indexOf('Chamfer') != -1,
)
return items.map(item => <FeaturePlugin key={item} connection={connection} hoverPlugins={hoverPlugins} />)
}
}
export default class Fillet extends Plugin {
constructor(session, args) {
super(session, {
type: 'Fillet',
icon: 'isometric',
selectionVisible: true,
defaultSelection: [],
resources,
...args,
})
}
render() {
return (
<Group>
<CreatePanel
visible={this.selectionVisible}
defaultSelection={this.defaultSelection}
createFillet={this.createFillet}
/>
<Spacer />
<Features hoverPlugins={this.hoverPlugins} />
</Group>
)
}
createFillet = async props => {
const { items, type, radius, offset1, offset2 } = props
const hit = this.connection.pool.findMaterial(material => material.meta && material.meta.id === items[0])
if (hit && radius > 0) {
const id = hit.material.meta.originalId
const isFillet = type === 'Fillet'
await this.connection.execute(
`_C.CADApplication.NewFeature(${this.tree.root}, "${isFillet
? 'CC_ConstantRadiusFillet'
: 'CC_Chamfer'}", "${isFillet ? 'Fillet' : 'Chamfer'}");`,
)
const operation = this.tree[this.root.features[this.root.features.length - 1]].id
await this.connection.execute(`_C.CADApplication.FeatureBuildReferences(${operation}, [${id}]);`)
await this.connection.execute(
`_C.CADApplication.SetFeatureParams(${operation}, [${isFillet
? radius
: `${offset1}, ${offset2}`}], 1);`,
)
}
}
hoverPlugins = (event, feature) => {
const color = this.session.globals.colors.primary
const hit = this.connection.pool.findMaterial(
material => material.meta && material.meta.operationId === feature.id,
)
if (hit) {
if (event.type === 'mouseenter') {
hit.material.animate({ color: new THREE.Color(color) }).start(500)
} else if (event.type === 'mouseleave') {
hit.material.animate(hit.material.meta.material).start(500)
}
}
}
}