Warning, /firebird/firebird-ng/src/app/pages/geometry-tree/scene-tree.component.ts is written in an unsupported language. File is not indexed.
0001 import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
0002 import {
0003 MatNestedTreeNode,
0004 MatTree,
0005 MatTreeNode,
0006 MatTreeNodeDef,
0007 MatTreeNodeOutlet, MatTreeNodePadding,
0008 MatTreeNodeToggle
0009 } from "@angular/material/tree";
0010 import {NestedTreeControl, FlatTreeControl, } from '@angular/cdk/tree';
0011 import {MatTreeFlatDataSource, MatTreeFlattener} from '@angular/material/tree';
0012
0013 import {MatIcon, MatIconModule} from '@angular/material/icon';
0014 import {MatButton, MatButtonModule, MatIconButton} from '@angular/material/button';
0015 import {GeometryService} from "../../services/geometry.service";
0016 import {Mesh, MeshBasicMaterial, Object3D} from "three";
0017 import {EventDisplayService} from "phoenix-ui-components";
0018 import {PhoenixThreeFacade} from "../../utils/phoenix-three-facade";
0019 import {MatTooltip} from "@angular/material/tooltip";
0020
0021 /**
0022 * Food data with nested structure.
0023 * Each node has a name and an optional list of children.
0024 */
0025 interface FoodNode {
0026 name: string;
0027 children?: FoodNode[];
0028 }
0029
0030 const TREE_DATA: FoodNode[] = [
0031 {
0032 name: 'Fruit',
0033 children: [{name: 'Apple'}, {name: 'Banana'}, {name: 'Fruit loops'}],
0034 },
0035 {
0036 name: 'Vegetables',
0037 children: [
0038 {
0039 name: 'Green',
0040 children: [{name: 'Broccoli'}, {name: 'Brussels sprouts'}],
0041 },
0042 {
0043 name: 'Orange',
0044 children: [{name: 'Pumpkins'}, {name: 'Carrots'}],
0045 },
0046 ],
0047 },
0048 ];
0049
0050 /** Flat node with expandable and level information */
0051 interface ExampleFlatNode {
0052 expandable: boolean;
0053 name: string;
0054 level: number;
0055 type: string;
0056 object3D: Object3D;
0057 visible: boolean;
0058 }
0059
0060 @Component({
0061 selector: 'app-geometry-tree',
0062 standalone: true,
0063 imports: [
0064 MatTree,
0065 MatTreeNode,
0066 MatNestedTreeNode,
0067 MatIconButton,
0068 MatTreeNodeToggle,
0069 MatTreeNodeDef,
0070 MatIcon,
0071 MatTreeNodeOutlet,
0072 MatTreeNodePadding,
0073 MatButton,
0074 MatTooltip
0075 ],
0076 templateUrl: './scene-tree.component.html',
0077 styleUrl: './scene-tree.component.scss'
0078 })
0079 export class SceneTreeComponent implements OnInit{
0080
0081 isHighlightingEnabled: boolean = false;
0082
0083 private _transformer = (node: Object3D, level: number) => {
0084 return {
0085 expandable: !!node.children && node.children.length > 0,
0086 name: node.name,
0087 level: level,
0088 type: node.type,
0089 object3D: node,
0090 visible: node.visible
0091 };
0092 };
0093
0094 treeControl = new FlatTreeControl<ExampleFlatNode>(
0095 node => node.level,
0096 node => node.expandable,
0097 );
0098
0099 treeFlattener = new MatTreeFlattener(
0100 this._transformer,
0101 node => node.level,
0102 node => node.expandable,
0103 node => node.children,
0104 );
0105
0106 dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
0107
0108
0109 hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
0110 private threeFacade: PhoenixThreeFacade;
0111
0112 constructor(private geomService: GeometryService,
0113 private eventDisplay: EventDisplayService) {
0114 //this.dataSource.data = TREE_DATA;
0115 this.threeFacade = new PhoenixThreeFacade(this.eventDisplay);
0116
0117
0118 }
0119
0120 ngOnInit(): void {
0121
0122 // if (!this.geomService.geometry) {
0123 // this.geomService.loadGeometry()
0124 // .then(result => {
0125 // if (result.threeGeometry) {
0126 // this.dataSource.data = result.threeGeometry.children;
0127 // } else {
0128 // console.error("this.geomService.loadGeometry() ! result.threeGeometry");
0129 // }
0130 // })
0131 // .catch(reason => {
0132 // console.error("ERROR LOADING GEOMETRY");
0133 // console.log(reason);
0134 // });
0135 // }
0136 this.dataSource.data = this.threeFacade.scene.children;
0137 }
0138
0139 toggleVisibility(node: ExampleFlatNode) {
0140 this.geomService.toggleVisibility(node.object3D);
0141 node.visible = !node.visible;
0142 }
0143
0144 refreshScheneTree() {
0145 this.dataSource.data = [];
0146 this.dataSource.data = this.threeFacade.scene.children;
0147 }
0148
0149 toggleHighlighting(): void {
0150 this.isHighlightingEnabled = !this.isHighlightingEnabled;
0151 console.log(`Highlighting is now ${this.isHighlightingEnabled ? 'enabled' : 'disabled'}`);
0152 }
0153
0154 private isEventDataNode(node: ExampleFlatNode): boolean {
0155 let currentNode: ExampleFlatNode | null = node;
0156
0157 while (currentNode) {
0158 if (currentNode.name.includes('EventData')) {
0159 return true;
0160 }
0161 currentNode = this.getParentNode(currentNode);
0162 }
0163
0164 return false;
0165 }
0166
0167 private getParentNode(node: ExampleFlatNode): ExampleFlatNode | null {
0168 for (let i = 0; i < this.treeControl.dataNodes.length; i++) {
0169 const currentNode = this.treeControl.dataNodes[i];
0170 if (currentNode.expandable && this.treeControl.getLevel(currentNode) < node.level) {
0171 const childNodes = this.treeControl.getDescendants(currentNode);
0172 if (childNodes.includes(node)) {
0173 return currentNode;
0174 }
0175 }
0176 }
0177 return null;
0178 }
0179
0180 highlightNode(node: ExampleFlatNode): void {
0181 if (!this.isHighlightingEnabled) {
0182 return;
0183 }
0184
0185 const isEventData = this.isEventDataNode(node);
0186
0187 node.object3D.traverse((child: Object3D) => {
0188 if (child instanceof Mesh) {
0189 if (!child.userData['originalMaterial']) {
0190 child.userData['originalMaterial'] = child.material;
0191 }
0192
0193 if (isEventData) {
0194 const originalMaterial = child.material as any;
0195 const highlightMaterial = originalMaterial.clone();
0196 highlightMaterial.color.set(0xffff00);
0197 highlightMaterial.wireframe = true;
0198
0199 child.material = highlightMaterial;
0200 } else {
0201 child.material = new MeshBasicMaterial({ color: 0xffff00, wireframe: true });
0202 }
0203 }
0204 });
0205 console.log(`Element highlighted: ${node.name}`);
0206 }
0207
0208
0209 unhighlightElement(node: ExampleFlatNode): void {
0210 if (!this.isHighlightingEnabled) {
0211 return;
0212 }
0213 node.object3D.traverse((child: Object3D) => {
0214 if (child instanceof Mesh && child.userData['originalMaterial']) {
0215 child.material = child.userData['originalMaterial'];
0216 }
0217 });
0218 console.log(`Element unhighlighted: ${node.name}`);
0219 }
0220 }