51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
import json
|
||
import panda3d.core as p3d
|
||
from typing import List
|
||
|
||
class TreeInfo:
|
||
def __init__(self, root: p3d.NodePath):
|
||
self.name = root.getName()
|
||
self.root = root
|
||
self.type = self.classify_np(root)
|
||
self.childs: List[TreeInfo] = []
|
||
self._build_children()
|
||
|
||
def classify_np(self,np: p3d.NodePath) -> str:
|
||
node = np.node()
|
||
|
||
if isinstance(node, p3d.GeomNode):
|
||
return "mesh(GeomNode)"
|
||
if isinstance(node, p3d.CollisionNode):
|
||
return "collision(CollisionNode)"
|
||
if isinstance(node, p3d.Camera):
|
||
return "camera"
|
||
if isinstance(node, p3d.Light):
|
||
return "light"
|
||
if isinstance(node, p3d.TextNode):
|
||
return "text"
|
||
|
||
# 不同节点可能是模型根、LOD根等,但核心是:是否包含 Geom/Collision
|
||
if not np.find("**/+GeomNode").isEmpty():
|
||
return "model(has GeomNode children)"
|
||
if not np.find("**/+CollisionNode").isEmpty():
|
||
return "collision_parent(has CollisionNode children)"
|
||
|
||
def _build_children(self):
|
||
if not self.root or self.root.isEmpty():
|
||
return
|
||
for child in self.root.getChildren():
|
||
child_info = TreeInfo(child) # 递归构建子树
|
||
self.childs.append(child_info)
|
||
|
||
def to_dict(self):
|
||
return {
|
||
"name": self.name,
|
||
"type": self.type or "",
|
||
"children": [child.to_dict() for child in self.childs],
|
||
}
|
||
|
||
def save_tree_json(self,path: str):
|
||
"""保存树的 name/type 结构为 JSON。"""
|
||
data = self.to_dict()
|
||
with open(path, "w", encoding="utf-8") as f:
|
||
json.dump(data, f, ensure_ascii=False, indent=2) |