123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /**
- * Outliner.js
- *
- * @author realor
- */
- import { Panel } from './Panel.js'
- import { Tree } from './Tree.js'
- import * as THREE from '../lib/three.module.js'
- class Outliner extends Panel {
- constructor(application) {
- super(application)
- this.id = 'outliner'
- this.position = 'right'
- this.title = 'tool.outliner.label'
- this.tree = new Tree(this.bodyElem)
- this.tree.rootsElem.className = 'tree outliner'
- this.map = new Map()
- this.autoScroll = true
- this.tree.getNodeLabel = object => {
- let objectLabel = object.name
- if (objectLabel === null || objectLabel.trim().length === 0) {
- objectLabel = object.id
- }
- return objectLabel
- }
- application.addEventListener('selection', () => {
- this.updateSelection()
- })
- application.addEventListener('scene', event => {
- if (event.type === 'added') {
- let object = event.object
- let parentTreeNode = this.map.get(event.parent)
- if (parentTreeNode) {
- let treeNode = this.populateObject(object, parentTreeNode)
- this.createMap(treeNode)
- }
- } else if (event.type === 'removed') {
- let object = event.object
- let treeNode = this.map.get(object)
- if (treeNode) {
- this.destroyMap(treeNode)
- treeNode.remove()
- }
- } else if (event.type === 'nodeChanged') {
- for (let object of event.objects) {
- let treeNode = this.map.get(object)
- if (treeNode) {
- treeNode.updateLabel()
- this.updateNodeStyle(treeNode)
- }
- }
- } else if (event.type === 'structureChanged') {
- let objects = this.getRootObjects(event.objects)
- if (objects.length === 1 && objects[0] === this.application.scene) {
- // update all tree
- this.update()
- } else {
- for (let object of objects) {
- let treeNode = this.map.get(object)
- if (treeNode) {
- this.destroyMap(treeNode)
- treeNode.updateLabel()
- treeNode.clear()
- this.populateChildren(treeNode)
- this.createMap(treeNode)
- }
- }
- }
- this.updateSelection()
- } else if (event.type === 'cameraActivated') {
- this.clearNodeStyle('active_camera')
- let camera = event.object
- let treeNode = this.map.get(camera)
- if (treeNode) treeNode.addClass('active_camera')
- } else if (event.type === 'cut') {
- this.clearNodeStyle('cut')
- for (let object of event.objects) {
- let treeNode = this.map.get(object)
- if (treeNode) treeNode.addClass('cut')
- }
- } else if (event.type === 'pasted') {
- this.clearNodeStyle('cut')
- for (let object of event.objects) {
- let treeNode = this.map.get(object)
- if (treeNode) treeNode.expandAncestors(false)
- }
- }
- })
- if (application.scene) this.update()
- }
- update() {
- this.tree.clear()
- this.map.clear()
- let treeNode = this.populateObject(this.application.scene)
- this.createMap(treeNode)
- }
- updateSelection() {
- // clear previous selectes nodes
- this.clearNodeStyle('selected')
- // mark new selection
- const selection = this.application.selection
- const objects = selection.objects
- const lastObject = objects[objects.length - 1]
- for (let object of objects) {
- let treeNode = this.map.get(object)
- if (treeNode) {
- treeNode.addClass('selected')
- let makeVisible = object === lastObject && this.autoScroll
- treeNode.expandAncestors(makeVisible)
- }
- }
- this.bodyElem.scrollLeft = 0
- this.autoScroll = true
- }
- populateObject(object, parentTreeNode) {
- let onClick = event => {
- this.autoScroll = false
- this.application.userSelectObjects([object], event)
- }
- let treeNode
- if (parentTreeNode) {
- treeNode = parentTreeNode.addNode(object, onClick)
- } else {
- treeNode = this.tree.addNode(object, onClick)
- }
- this.updateNodeStyle(treeNode)
- this.populateChildren(treeNode)
- return treeNode
- }
- populateChildren(treeNode) {
- let object = treeNode.value
- for (let child of object.children) {
- let name = child.name || ''
- if (!name.startsWith(THREE.Object3D.HIDDEN_PREFIX)) {
- this.populateObject(child, treeNode)
- }
- }
- }
- getObjectClassNames(object) {
- let classList = [object.type]
- if (object.userData.IFC && object.userData.IFC.ifcClassName) {
- classList.push(object.userData.IFC.ifcClassName)
- }
- if (object.builder) {
- classList.push(object.builder.constructor.name)
- }
- return classList.join(' ')
- }
- updateNodeStyle(treeNode) {
- const object = treeNode.value
- if (object.visible) {
- treeNode.removeClass('hidden')
- } else {
- treeNode.addClass('hidden')
- }
- let expanded = treeNode.isExpanded()
- treeNode.itemElem.className = this.getObjectClassNames(object)
- if (expanded) {
- treeNode.expand()
- } else {
- treeNode.collapse()
- }
- }
- clearNodeStyle(className) {
- let nodes = this.tree.rootsElem.getElementsByClassName(className)
- nodes = [...nodes]
- for (let node of nodes) {
- node.classList.remove(className)
- }
- }
- getRootObjects(objects) {
- const set = new Set()
- for (let object of objects) {
- set.add(object)
- }
- const roots = []
- for (let object of set) {
- let ancestor = object.parent
- while (ancestor && !set.has(ancestor)) {
- ancestor = ancestor.parent
- }
- if (ancestor === null) roots.push(object)
- }
- return roots
- }
- createMap(treeNode) {
- this.map.set(treeNode.value, treeNode)
- for (let childTreeNode of treeNode.children) {
- this.createMap(childTreeNode)
- }
- }
- destroyMap(treeNode) {
- this.map.delete(treeNode.value)
- for (let childTreeNode of treeNode.children) {
- this.destroyMap(childTreeNode)
- }
- }
- }
- export { Outliner }
|