from direct.directnotify import DirectNotifyGlobal from panda3d.core import * import NametagGlobals class ChatBalloon: notify = DirectNotifyGlobal.directNotify.newCategory('ChatBalloon') def __init__(self, node=None): if isinstance(node, NodePath): node = node.node() self.m_copy_node = None self.m_top_node = None self.m_top_mat = None self.m_middle_node = None self.m_middle_mat = None self.m_bottom_node = None self.m_bottom_mat = None self.m_hscale = 0 self.m_text_height = 0 self.m_text_frame = Vec4(0) self.scan(node) @staticmethod def find_geom_node(node): if node.isGeomNode(): return node for i in xrange(node.getNumChildren()): n = ChatBalloon.find_geom_node(node.getChild(i)) if n: return n return None @staticmethod def find_middle_geom(node): if not node.getNumChildren(): return None child = None for i in xrange(node.getNumChildren()): child = node.getChild(i) if child.getName() == 'middle': return n n = ChatBalloon.find_middle_geom(child) if n: return n return ChatBalloon.find_geom_node(child) def scan(self, node): if node.getName() == 'chatBalloon': return self.scan_balloon(node) for i in xrange(node.getNumChildren()): if self.scan(node.getChild(i)): return True return False def scan_balloon(self, node): self.m_copy_node = node.copySubgraph() for i in xrange(node.getNumChildren()): child = node.getChild(i) if child.getName() == 'top': self.m_top_node = child self.m_top_mat = child.getTransform().getMat() elif child.getName() == 'middle': self.m_middle_node = child self.m_middle_mat = child.getTransform().getMat() elif child.getName() == 'bottom': self.m_bottom_node = child self.m_bottom_mat = child.getTransform().getMat() if self.m_top_node and self.m_middle_node and self.m_bottom_node: return True else: self.notify.warning('ChatBalloon geometry does not include top, middle, and bottom nodes.') return False def generate(self, text, font, wordwrap, text_color, balloon_color, for_3d, has_draw_order, draw_order, page_button, space_for_button, reversed, new_button): # new_button is a pointer, let's use a list hack here chat_node = PandaNode('chat') chat_node.setAttrib(CullFaceAttrib.make(0)) text_node = NametagGlobals.getTextNode() text_node.setFont(font) text_node.setWordwrap(wordwrap) text_node.setAlign(TextNode.ALeft) text_node.setText(text) v116 = NametagGlobals._balloon_text_origin[0] if reversed: v116 = v116 + 9.0 v27 = (text_node.getRight() - text_node.getLeft()) * 0.11111111 self.m_hscale = v27 if v27 < 0.25: self.m_hscale = 0.25 text_node.setAlign(TextNode.ACenter) v29 = v116 if not reversed: v116 = v29 + 4.5 else: v116 = v29 - 4.5 elif reversed: self.m_hscale = -self.m_hscale self.m_text_frame = text_node.getCardActual() _space = 0.2 if space_for_button else 0.0 num_rows = max(1, text_node.getNumRows()) _num_rows = num_rows line_h = text_node.getFont().getLineHeight() num_rows_minus_1 = num_rows - 1 subgraph_copy_mat = Mat4(self.m_hscale, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 1.0) text_h = _num_rows * line_h + _space self.m_text_height = text_h v132 = num_rows_minus_1 * line_h + _space middle_mat = Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, text_h, 0, 0, 0, 0, 1) * self.m_middle_mat top_mat = Mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, text_h - 1.0, 1) * self.m_top_mat v137 = v116 * self.m_hscale v138 = 0.0 v139 = NametagGlobals._balloon_text_origin[2] + v132 + 0.2 self.m_text_frame += Vec4(v137, v137, v139, v139) ''' Correct code: Python won't let us edit this transform, we'll have to copy it all if self.m_top_node: self.m_top_node.setTransform(TransformState.makeMat(top_mat)) if self.m_middle_node: self.m_middle_node.setTransform(TransformState.makeMat(middle_mat)) subgraph_copy = self.m_copy_node.copySubgraph() chat_node.addChild(subgraph_copy) subgraph_copy.setTransform(TransformState.makeMat(subgraph_copy_mat)) ''' # BEGIN PYTHON CODE subgraph_copy = self.m_copy_node.copySubgraph() NodePath.anyPath(subgraph_copy).find('**/top').node().setTransform(TransformState.makeMat(top_mat)) NodePath.anyPath(subgraph_copy).find('**/middle').node().setTransform(TransformState.makeMat(middle_mat)) chat_node.addChild(subgraph_copy) subgraph_copy.setTransform(TransformState.makeMat(subgraph_copy_mat)) # END PYTHON CODE if has_draw_order: bin = config.GetString('nametag-fixed-bin', 'fixed') subgraph_copy.setAttrib(CullBinAttrib.make(bin, draw_order)) subgraph_copy.setAttrib(ColorAttrib.makeFlat(balloon_color)) if balloon_color[3] != 1.0: subgraph_copy.setAttrib(TransparencyAttrib.make(1)) reducer = SceneGraphReducer() reducer.applyAttribs(subgraph_copy) reducer.flatten(chat_node, -1) generated_text = text_node.generate() if for_3d: v86 = ChatBalloon.find_middle_geom(chat_node) if not v86: v86 = ChatBalloon.find_geom_node(chat_node) v86.setEffect(DecalEffect.make()) else: v86 = chat_node if has_draw_order: bin = config.GetString('nametag-fixed-bin', 'fixed') generated_text.setAttrib(CullBinAttrib.make(bin, draw_order + 1)) np = NodePath.anyPath(v86) v144 = np.attachNewNode(generated_text) v144.setPos((v137, v138, v139)) v144.setColor(text_color) v144.setY(-0.01) # Panda3D 1.10 hack to prevent z-fighting. if text_color[3] != 1.0: v144.setTransparency(1) if page_button: v116 = ModelNode('button') new_button[0] = np.attachNewNode(v116) button_copy = page_button.copyTo(new_button[0]) if reversed: button_copy.setPos(self.m_hscale * 1.7, 0, 1.8) else: button_copy.setPos(self.m_hscale * 9.0, 0, 1.8) button_copy.setScale(8.0, 8.0, 8.0) button_copy.setY(-0.01) # Panda3D 1.10 hack to prevent z-fighting. reducer = SceneGraphReducer() reducer.applyAttribs(generated_text) reducer.flatten(chat_node, 1) return chat_node