def list_all_textures(root, path): try: bam = BamFile() bam.open_read(Filename(path)) obj = NodePath(bam.readNode()) except: return [] textures = [] root = root.lower().replace(':', '') for texture in obj.find_all_textures(): for filename in [texture.get_filename(), texture.get_alpha_filename()]: if not filename: continue filename = filename.get_fullpath() if filename not in textures: textures.append(filename) obj.removeNode() return [remove_root(texture, root) for texture in textures]
class SdfText: def __init__(self, font): self.txt_node = TextNode('sdf_text_node') self.txt_node.set_font(font) self.geom = NodePath(self.txt_node.get_internal_geom()) self.__txt_color = Vec4(1.0, 1.0, 1.0, 1.0) self.__outline_color = Vec4(0.0, 0.0, 0.0, 0.0) self.__outline_offset = Vec2(0.0) self.__outline_power = 1.0 self.parent = None self.__pos = Vec3(0.0) self.__hpr = Vec3(0.0) self.__scale = Vec3(1.0) self.__shader = Shader.make(Shader.SL_GLSL, v_shader, f_shader) self._make_geom() def _make_geom(self): '''Refresh or create the actual geom with the text ''' self.geom = NodePath(self.txt_node.get_internal_geom()) self.geom.set_shader(self.__shader, 1) self.geom.set_shader_input('outline_color', self.__outline_color) self.geom.set_shader_input('outline_offset', self.__outline_offset) self.geom.set_shader_input('outline_power', self.__outline_power) self.geom.set_transparency(TransparencyAttrib.M_alpha, 1) if self.parent: self.geom.reparent_to(self.parent) self.geom.set_pos_hpr_scale(self.__pos, self.__hpr, self.__scale) def set_text(self, text): '''Sets text''' self.txt_node.set_text(text) self._make_geom() def reparent_to(self, node): '''Reparent the text geom to node (as if for NodePath)''' self.geom.reparent_to(node) self.parent = node self._make_geom() def set_hpr(self, *args): '''Set rotation (as if for NodePath)''' self.geom.set_hpr(*args) self.__hpr = self.geom.get_hpr() def set_pos(self, *args): '''Set position (as if for NodePath)''' self.geom.set_pos(*args) self.__pos = self.geom.get_pos() def set_scale(self, *args): '''Set scale (as if for NodePath)''' self.geom.set_scale(*args) self.__scale = self.geom.get_scale() def set_text_color(self, *color): '''Sets text color (rgba) ''' self.__txt_color = Vec4(*color) self.txt_node.set_text_color(self.__txt_color) self._make_geom() def set_outline_color(self, *color): '''Sets text outline color (rgba) ''' self.__outline_color = Vec4(*color) self.geom.set_shader_input('outline_color', self.__outline_color) def set_outline_strength(self, strength): '''Sets outline strength. Values smaller than 1.0 will make the outline less prominent Values greater than 1.0 will make the outline stronger''' self.__outline_power = 1.0 / strength self.geom.set_shader_input('outline_power', self.__outline_power) def set_outline_offset(self, x_offset=0, y_offset=0): '''Outline offset in pixels. Will cause artefacts when larger than the glyph padding in the texture!''' tex = self.geom.find_all_textures()[0] x = tex.get_x_size() y = tex.get_y_size() self.__outline_offset = Vec2(x_offset / x, y_offset / y) self.geom.set_shader_input('outline_offset', self.__outline_offset) #properties: @property def outline_offset(self): return self.__outline_offset @outline_offset.setter def outline_offset(self, value): self.set_outline_offset(value) @property def outline_strength(self): return self.__outline_strength @outline_strength.setter def outline_strength(self, value): self.set_outline_strength(value) @property def outline_color(self): return self.__outline_color @outline_color.setter def outline_color(self, value): self.set_outline_color(value) @property def text_color(self): return self.__text_color @text_color.setter def text_color(self, value): self.set_text_color(value) @property def scale(self): return self.__scale @scale.setter def scale(self, value): self.set_scale(value) @property def pos(self): return self.__pos @pos.setter def pos(self, value): self.set_pos(value) @property def hpr(self): return self.__hpr @hpr.setter def hpr(self, value): self.set_hpr(value) @property def text(self): return self.self.txt_node.get_text() @text.setter def text(self, value): self.set_text(value)
class ObjModel(BaseComponent): name = 'model' entity_type = ENTITY_TYPE_OBJECT def __init__(self, config): model_path = config['model_file'] self.scale = config.get('scale', 1.) self.collider_scale = config.get('collider_scale', 1.) self.is_static = config.get( 'static', False) # TODO 对于静态物体,可以合并模型进行优化. np.flatten_strong() self.model_np = NodePath("unknown_model") G.loader.loadModel(model_path).get_children().reparent_to( self.model_np) if isinstance(self.scale, list): self.model_np.set_scale(self.scale[0], self.scale[1], self.scale[2]) else: self.model_np.set_scale(self.scale) self.model_np.set_pos(Vec3(0, 0, 0)) for tex in self.model_np.find_all_textures(): tex.set_magfilter(Texture.FT_linear_mipmap_linear) tex.set_minfilter(Texture.FT_linear_mipmap_linear) tex.setWrapU(Texture.WM_mirror) tex.setWrapV(Texture.WM_mirror) self.enabled = True if not self.is_static: self.model_np.reparent_to(G.render) physics_config = config.get('physics') self.physical_np = None if physics_config: shape = physics_config.get('shape', 'cylinder') if shape == 'cylinder': self.physical_np, self.half_size = G.physics_world.add_cylinder_collider( self.model_np, mass=0, bit_mask=gconf.BIT_MASK_OBJECT, reparent=False, scale=self.collider_scale, ) elif shape == 'box': self.physical_np, self.half_size = G.physics_world.add_box_collider( self.model_np, mass=0, bit_mask=gconf.BIT_MASK_OBJECT, reparent=False, scale=self.collider_scale, ) else: assert False, (shape, config) body = self.physical_np.node() body.setDeactivationEnabled(True) body.setDeactivationTime(1.0) else: self.half_size = G.physics_world.get_bounding_size( self.model_np) * .5 def on_start(self): if self.physical_np: self.physical_np.set_python_tag("type", "object") self.physical_np.set_python_tag("entity", self._entity_weak_ref) ent = self.get_entity() ent.set_transform(self) ent.set_radius(max(self.half_size[0], self.half_size[1])) self.model_np.setName('%s.model' % ent.get_name()) def set_enabled(self, enabled): assert self.enabled != enabled self.enabled = enabled if self.physical_np: G.physics_world.set_collider_enabled(self.physical_np, enabled) def destroy(self): if self.physical_np: # 重复remove会有warning if self.enabled: G.physics_world.remove_collider(self.physical_np) self.physical_np.remove_node() if self.model_np: self.model_np.remove_node() def on_save(self): if self.physical_np: pos = self.physical_np.get_pos() else: pos = self.model_np.get_pos() return pos.getX(), pos.getY(), pos.getZ() def on_load(self, data): pos = Vec3(data[0], data[1], data[2]) self.set_pos(pos) def get_np(self): return self.model_np def set_pos(self, pos): if self.physical_np: self.physical_np.set_pos(pos) if self.is_static: self.model_np.set_pos(pos) else: self.model_np.set_pos(pos) def get_pos(self): if self.physical_np: return self.physical_np.get_pos() return self.model_np.get_pos() def get_models(self): return [self.model_np] def get_static_models(self): if self.is_static: return [self.model_np] return []