class Text(IndicatorPrimitive): def __init__(self, **kwargs): IndicatorPrimitive.__init__(self) self.pointsize = None if "pointsize" in kwargs: self.pointsize = kwargs.get("pointsize") elif self.pointsize is None: self.pointsize = 10 self.text = None if "text" in kwargs: self.text = kwargs.get("text") elif self.text is None: self.text = "Basic text" self.font = None if "font" in kwargs: self.font = kwargs.get("font") elif self.font is None: self.font = "fonts/arial.ttf" self.alignment = None if "alignment" in kwargs: self.alignment = kwargs.get("alignment") elif self.alignment is None: self.alignment = "left" def _set_text_static_graphics_1(self): self.textNode = TextNode('foo') self.textNode.setText(self.text) self._font_p3d = loader.loadFont(self.font) self.pixels_per_unit = engine.tq_graphics_basics.get_font_bmp_pixels_from_height( engine.tq_graphics_basics.get_pts_to_p3d_units(self.pointsize)) self._font_p3d.setPixelsPerUnit(self.pixels_per_unit) self._font_p3d.setPointSize(self.pointsize) self.textNode.setFont(self._font_p3d) self.textNode.setShadow(0.05, 0.05) self.textNode.setShadowColor(0, 0, 0, 1) def _set_text_static_graphics_2(self): self.set_node_p3d(self.textNode) self.set_p3d_nodepath(NodePath(self.textNode.generate())) self._font_p3d.clear() self.setLightOff(1) self.setTwoSided(True) self.set_render_above_all(True) scale = self._get_scale() self.setScale(scale, 1., scale) def _get_scale(self): # --- get_scale_matrix_initial_to_font_size initial_height = self.textNode.getHeight() scale_factor_to_height_1 = 1. / initial_height pixels_per_p3d_length_unit = engine.tq_graphics_basics.get_window_size_y( ) / 2.0 scale_height_1_to_pixels = 1. / pixels_per_p3d_length_unit return scale_height_1_to_pixels * self.pixels_per_unit def _reparentTo_additional_trafo_nodepath(self): self.additional_trafo_nodepath = TQGraphicsNodePath() self.additional_trafo_nodepath.reparentTo_p3d(self.getParent_p3d()) super().reparentTo(self.additional_trafo_nodepath) def _update_textnode_alignment(self): if self.alignment == "right": self.textNode.setAlign(TextNode.ARight) elif self.alignment == "left": self.textNode.setAlign(TextNode.ALeft) elif self.alignment == "center": self.textNode.setAlign(TextNode.ACenter) def get_size(self): height = engine.tq_graphics_basics.get_pts_to_p3d_units(self.pointsize) width = (self.textNode.getWidth() / self.textNode.getHeight()) * height return height, width
class Point3dCursor(TQGraphicsNodePath): """ a white Point3d with a black and a white circle aroud it for accentuation """ def __init__(self, camera_gear, scale=0.05): """ """ self.camera_gear = camera_gear # needed for re-orientation towards the camera whenever it's updated or the camera moves self.scale_total = scale self.rel_scale_point_center = 0.4 self.rel_scale_circle_outer_first = 0.6 self.rel_scale_circle_outer_second = 0.9 # self.rel_scale_circle_outer_third = 1.2 self.num_of_verts = 20 self.color_point_center = Vec4(1., 1., 1., 1.) self.color_circle_outer_first = Vec4(0., 0., 0., 1.) self.color_circle_outer_second = Vec4(1., 1., 1., 1.) # self.color_circle_outer_third = Vec4(0., 0., 0., 1.) self._initial_normal_vector = Vec3(1., 0., 0.) TQGraphicsNodePath.__init__(self) self.point_center = Point3d(scale=self.scale_total * self.rel_scale_point_center) self.point_center.reparentTo(self) self.circle_outer_first = OrientedCircle( target_normal_vector=self._initial_normal_vector, initial_scaling=self.scale_total * self.rel_scale_circle_outer_first, num_of_verts=self.num_of_verts, thickness=3.) self.circle_outer_first.reparentTo(self) self.circle_outer_second = OrientedCircle( target_normal_vector=self._initial_normal_vector, initial_scaling=self.scale_total * self.rel_scale_circle_outer_second, num_of_verts=self.num_of_verts, thickness=3.) self.circle_outer_second.reparentTo(self) # the closest to root node of the cursor saves the translation (along the edgeplayer) (i.e. here the additional_trafo_nodepath) # the edgeplayer node itself actually only has a rotation, which it sets to # always reorient towards the camera. If I didn't separate the two (translation and rotation) # into two separate nodes, I would need to declare additional functions for TQGraphicsNodePath to # set and get Rotation, Position and Scaling components of the Model Matrix independently of each other # (which I guess can be done, since a Model Matrix actually be decomposed) self.additional_trafo_nodepath = TQGraphicsNodePath() self.additional_trafo_nodepath.reparentTo_p3d(self.getParent_p3d()) super().reparentTo(self.additional_trafo_nodepath) self.camera_gear.add_camera_move_hook(self._adjust) self._adjust() def _adjust(self): self.point_center.setColor(self.color_point_center) self.circle_outer_first.setColor(self.color_circle_outer_first) self.circle_outer_second.setColor(self.color_circle_outer_second) self._adjust_rotation_to_camera() def _adjust_rotation_to_camera(self): """ """ x, y, z, up_vector, eye_vector = self.camera_gear.get_spherical_coords( get_up_vector=True, get_eye_vector=True, correct_for_camera_setting=True) heading, pitch, roll = self.camera_gear.p3d_camera.getHpr() roll += 90. pitch += 90. if up_vector == Vec3(0, 0, -1) and eye_vector == Vec3(-1, 0, 0): self.setHpr(heading, pitch, roll + 180.) else: self.setHpr(heading, pitch, roll) def setColor(self, primary_color, color_point_center=False): if color_point_center == True: self.color_point_center = primary_color self.color_circle_outer_second = primary_color self._adjust() def setPos(self, *args, **kwargs): """ """ return self.additional_trafo_nodepath.setPos(*args, **kwargs) def reparentTo(self, *args, **kwargs): """ """ return self.additional_trafo_nodepath.reparentTo(*args, **kwargs)