UNPKG

awv3

Version:
120 lines (108 loc) 4.15 kB
import * as THREE from 'three'; import Object3 from '../../../three/object3'; import Ccref from '../ccref'; import { getArcAngles } from '../geomutils'; import ConstraintGraphics from '../graphics/constraint'; const Mode = Object.freeze({ Never: 0, Hover: 1, Always: 2, }); export default class Visualizer { constructor(sketcher, textures) { this.mode = Mode.Hover; this.sketcher = sketcher; // Set of constraint ids to avoid iterating and filtering sketch.children this.constraints = new Set(); // Reverse mapping from entities to constraints this.entityFor = new Map(); // Used to track constraint positions in all modes this.visiblePositions = new Set(); } addConstraint(constraint) { if (!(constraint.graphics instanceof ConstraintGraphics)) return; this.constraints.add(constraint.id); for (let entity of constraint.entities) { if (!this.entityFor.has(entity.id)) this.entityFor.set(entity.id, []); this.entityFor.get(entity.id).push(constraint.id); } } removeConstraint(constraint, state = constraint.state) { if (!(constraint.graphics instanceof ConstraintGraphics)) return; for (let {value: id} of state.members.entities.members) { const constraints = this.entityFor.get(id); constraints.splice(constraints.indexOf(constraint.id), 1); if (constraints.length === 0) this.entityFor.delete(id); } this.constraints.delete(constraint.id); } updateConstraint(constraint) { this.place(constraint, constraint.entities[0], this.mode === Mode.Always); } updateEntity(entity) { for (let id of this.entityFor.get(entity.id) || []) { const constraint = new Ccref(this.sketcher, id); if (!constraint.state) continue; // if entity is updated just before constraint is deleted (e.g. fillet point) this.updateConstraint(constraint); } } hover(entity, first) { if (this.mode !== Mode.Hover) return; if (entity.isConstraint()) return; if (first) this.unhoverAll(); for (let id of this.entityFor.get(entity.id) || []) this.place(new Ccref(this.sketcher, id), entity, true); } unhover(entity, first) { if (this.mode !== Mode.Hover) return; if (entity.isConstraint()) return; // do nothing } unhoverAll() { if (this.mode !== Mode.Hover) return; if (this.visiblePositions.size === 0) return; this.updateAll(); } place(constraint, entity, visible) { const graphics = constraint.graphics, position = graphics.localMesh.position, gp = entity.geomParams; this.visiblePositions.delete(position); graphics.visible = visible; if (!visible) return; switch (entity.class) { case 'CC_Point': position.copy(gp.start); break; case 'CC_Line': position.lerpVectors(gp.start, gp.end, 0.5); break; case 'CC_Arc': position.copy(getArcAngles(gp).mid); break; case 'CC_Circle': position.copy(gp.center); break; default: position.set(0, 0, 0); break; } const s = graphics.localMesh.scale.y; position.x -= s; position.y += s; triesLoop: for (let tries = 0; tries < 10; ++tries) { for (let visiblePosition of this.visiblePositions) if (position.distanceToSquared(visiblePosition) < s * s) { position.x += s * (1 + 1e-6); continue triesLoop; } break; } this.visiblePositions.add(position); } updateAll(mode = this.mode) { this.mode = mode; this.visiblePositions.clear(); for (let id of this.constraints) this.updateConstraint(new Ccref(this.sketcher, id)); this.sketcher.refresh(); } }