import direct import direct.showbase import direct.showbase.ShowBaseGlobal import panda3d.core as p3d from direct.showbase.ShowBase import ShowBase from panda3d.core import NodePath class GameObject(NodePath): def __init__(self, model: NodePath): self = model self.gameobject = self self.self_active = self.is_hidden() def set_active(self, active: bool): if active:self.show() else:self.hide() @classmethod def create_panel(self) -> NodePath: base = direct.showbase.ShowBaseGlobal.base if not base or not base.render: raise Exception("base or base.render is None") from panda3d.core import CardMaker cm = CardMaker("ground") cm.set_frame(-10, 10, -10, 10) # (left, right, bottom, top) plane_np = base.render.attach_new_node(cm.generate()) plane_np.set_hpr(0, -90, 0) # 躺平(默认是 XY 平面,朝 +Z) plane_np.setTwoSided(True) mat = p3d.Material('unlit') plane_np.set_material(mat) return plane_np @classmethod def set_model_auto_scale(self, model: NodePath,debug_info = False): base = direct.showbase.ShowBaseGlobal.base if not base or not base.render: raise Exception("base or base.render is None") if not model or model.is_empty(): return bmin, bmax = model.get_tight_bounds(base.render) if bmin is None or bmax is None: return size = bmax - bmin max_size = max(size.x, size.y, size.z) if max_size <= 0: return # 目标:让最大边缩放到略小于 10,比如 9.9 target_max = 3 scale_factor = target_max / max_size model.set_scale(scale_factor) if debug_info: print(f"自动缩放:原最大尺寸={max_size:.3f} → 缩放因子={scale_factor:.6f}") @classmethod def get_node_type(self,np: 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 "empty*" if not np.find("**/+CollisionNode").isEmpty(): return "collision_parent*" return "empty" @classmethod def get_child_name(self,node:NodePath): if not node or node.isEmpty() or node.getNumChildren() == 0:return for n in node.getChildren(): print(f"{n.getName()} -> {GameObject.get_node_type(n)}") GameObject.get_child_name(n) return f"empty/transform({node.getType().getName()})"