Warning, /firebird/firebird-ng/src/app/utils/three-geometry-editor.ts is written in an unsupported language. File is not indexed.
0001 import {Color, Material, Mesh, Object3D} from "three";
0002 import {createOutline, disposeOriginalMeshesAfterMerge, findObject3DNodes, pruneEmptyNodes} from "./three.utils";
0003 import {mergeBranchGeometries, mergeMeshList, MergeResult} from "./three-geometry-merge";
0004 import * as THREE from "three";
0005 import {ColorRepresentation} from "three/src/math/Color";
0006
0007 export enum EditThreeNodeActions {
0008
0009 Merge, /** Merge children matching patterns (if patterns are provided) or all meshes of the node*/
0010
0011 }
0012
0013 export interface EditThreeNodeRule {
0014
0015 patterns?: string[] | string;
0016 merge?: boolean;
0017 newName?: string;
0018 deleteOrigins?: boolean;
0019 cleanupNodes?: boolean;
0020 outline?: boolean;
0021 outlineThresholdAngle?: number;
0022 /** [degrees] */
0023 outlineColor?: ColorRepresentation;
0024 material?: Material;
0025 color?: ColorRepresentation;
0026
0027 }
0028
0029 function mergeWhatever(node: Object3D, rule: EditThreeNodeRule): MergeResult | undefined {
0030
0031 let newName = !rule.newName ? node.name + "_merged" : rule.newName;
0032
0033 if (!rule.patterns) {
0034 // If user provided patterns only children matching patterns (search goes over whole branch) will be merged,
0035 // But if no patterns given, we will merge whole node
0036 return mergeBranchGeometries(node, newName, rule.material); // Children auto removed
0037 }
0038
0039 // If we are here, we need to collect what to merge first
0040
0041 let mergeSubjects = [];
0042 // merge whole node
0043 if (typeof rule.patterns === "string") {
0044 rule.patterns = [rule.patterns];
0045 }
0046
0047 for (const pattern of rule.patterns) {
0048 mergeSubjects.push(...findObject3DNodes(node, pattern, "Mesh").nodes);
0049 }
0050
0051 let result = mergeMeshList(mergeSubjects, node, newName, rule.material);
0052 const deleteOrigins = rule?.deleteOrigins ?? true;
0053 if (result && deleteOrigins) {
0054 disposeOriginalMeshesAfterMerge(result);
0055 }
0056 return result;
0057 }
0058
0059
0060 export function editThreeNodeContent(node: Object3D, rule: EditThreeNodeRule) {
0061 let {
0062 patterns,
0063 deleteOrigins = true,
0064 cleanupNodes = true,
0065 outline = true,
0066 outlineThresholdAngle = 40,
0067 outlineColor,
0068 material,
0069 color,
0070 merge = true,
0071 newName = ""
0072 } = rule;
0073
0074 let targetMeshes: Mesh[] = [];
0075
0076 if (merge) {
0077 // Existing merge logic
0078 let result = mergeWhatever(node, rule);
0079 if (!result) {
0080 console.warn("didn't find children to merge. Patterns:");
0081 console.log(patterns)
0082 return;
0083 }
0084 targetMeshes = [result.mergedMesh];
0085 } else {
0086 // New logic for when merge is false
0087 // Find all meshes that match the patterns, similar to mergeWhatever
0088 if (!patterns) {
0089 // If no patterns given, collect all meshes with geometry in the node
0090 node.traverse((child) => {
0091 if ((child as any)?.geometry) {
0092 targetMeshes.push(child as Mesh);
0093 }
0094 });
0095 } else {
0096 // If patterns are given, find all meshes that match
0097 if (typeof patterns === "string") {
0098 patterns = [patterns];
0099 }
0100
0101 for (const pattern of patterns) {
0102 targetMeshes.push(...findObject3DNodes(node, pattern, "Mesh").nodes);
0103 }
0104 }
0105 }
0106
0107 // Apply operations to each target mesh
0108 for (const targetMesh of targetMeshes) {
0109 if (color !== undefined && color !== null) {
0110 if (targetMesh.material) {
0111 (targetMesh.material as any).color = new Color(color);
0112 }
0113 }
0114
0115 if (outline) {
0116 createOutline(targetMesh, {color: outlineColor, thresholdAngle: outlineThresholdAngle});
0117 }
0118 }
0119
0120 if (cleanupNodes) {
0121 pruneEmptyNodes(node);
0122 }
0123 }