def main(): base = ShowBase() cm = CardMaker('') cm.set_frame(-.5, .5, -.5, .5) # Node which contains all the cards equally spaced apart and which is # animated to move the cards in front of the camera. cards = base.render.attach_new_node(PandaNode('')) cards.setPos(-2, 5, 0) cards.posInterval(2, Point3(-6, 5, 0)).loop() for i in range(5): card = cards.attach_new_node(cm.generate()) card.setPos(i * 2, 0, 0) def on_every_frame(task): # Time which has elapsed since the last frame measured in units of # the time quota available at 60 fps (e.g. 1/60 second). time_quota = taskMgr.globalClock.get_dt() * 60 # Print time use as percent of the 60-fps-quota. print(f'{round(time_quota * 100):4}', end='', flush=True) return Task.DSCont taskMgr.add(on_every_frame) taskMgr.run()
def create_floor(self): '''Generate flat floor of size, provided to class''' #todo: add fallback values in case size hasnt been specified log.debug(f"Generating the floor") #initializing new cardmaker object #which is essentially our go-to way to create flat models floor = CardMaker('floor') #setting up card size floor.set_frame(*self.map_size) #attaching card to render and creating it's object #I honestly dont understand the difference between #this and card.reparent_to(render) #but both add object to scene graph, making it visible floor_object = render.attach_new_node(floor.generate()) floor_object.set_texture(self.texture) #determining how often do we need to repeat our texture texture_x = self.texture.get_orig_file_x_size() texture_y = self.texture.get_orig_file_y_size() repeats_x = ceil(self.size_x / texture_x) repeats_y = ceil(self.size_y / texture_y) #repeating texture to avoid stretching when possible floor_object.set_tex_scale(TextureStage.getDefault(), repeats_x, repeats_y) #arranging card's angle floor_object.look_at((0, 0, -1)) floor_object.set_pos(0, 0, FLOOR_LAYER)
def __init__(self): super().__init__() x = float(base.win.get_x_size()) y = float(base.win.get_y_size()) y_aspect = y / x inventory_base_width = INVENTORY_VERTICAL_FRACTION * y_aspect inventory_half_width = inventory_base_width * INVENTORY_HORIZONTAL_FACTOR * 0.5 self.region = base.win.make_display_region( 0.5 - inventory_half_width, # left 0.5 + inventory_half_width, # right 0.0, # bottom INVENTORY_VERTICAL_FRACTION, # top ) self.region.set_sort(INVENTORY_DISPLAY_REGION_SORT) self.cam_node = p3d.Camera('inventory_cam') lens = OrthographicLens() lens.set_film_size(INVENTORY_HORIZONTAL_FACTOR, 1) self.cam_node.set_lens(lens) self.cam_np = NodePath(self.cam_node) self.region.set_camera(self.cam_np) self.inventory = NodePath('inventory') self.cam_np.reparentTo(self.inventory) background_maker = CardMaker('inventory') background_maker.set_frame(-INVENTORY_HORIZONTAL_FACTOR / 2.0, INVENTORY_HORIZONTAL_FACTOR / 2.0, 0, 1) background = p3d.NodePath(background_maker.generate()) background.reparent_to(self.inventory) background.set_pos(0, 5, -0.5)
def cardmaker_debug(self): for node in render2d.find_all_matches("pfm"): node.remove_node() for text in base.a2dBottomLeft.find_all_matches("*"): text.remove_node() width = 0.2 # render2d coordinates range: [-1..1] # Pseudo-normalize our PfmFile for better contrast. normalized_pfm = PfmFile(self.RotorPFM) max_p = LVector3() normalized_pfm.calc_min_max(LVector3(), max_p) normalized_pfm *= 1.0 / max_p.x # Put it in a texture tex = Texture() tex.load(normalized_pfm) # Apply the texture to a quad and put it in the lower left corner. cm = CardMaker("pfm") cm.set_frame(0, width, 0, width / normalized_pfm.get_x_size() * normalized_pfm.get_y_size()) card = base.render2d.attach_new_node(cm.generate()) card.set_pos(-1, 0, -1) card.set_texture(tex) # Display max value text self.genLabelText(-3, "Max value: {:.3f} == {:.2f}m".format(max_p.x, max_p.x * self.terrain_scale.z), parent="a2dBottomLeft")
def _create_components(self): """ Internal method to init the widgets components """ card_maker = CardMaker("PixelInspector") card_maker.set_frame(-200, 200, -150, 150) self._zoomer = self._node.attach_new_node(card_maker.generate()) # Defer the further loading Globals.base.taskMgr.doMethodLater( 1.0, self._late_init, "PixelInspectorLateInit") Globals.base.accept("q", self.show) Globals.base.accept("q-up", self.hide)
def create_instance(self): self.instance = NodePath("card") card_maker = CardMaker("card") card_maker.set_frame(-1, 1, -1, 1) node = card_maker.generate() self.card_instance = self.instance.attach_new_node(node) self.card_instance.setBillboardPointWorld() TransparencyBlend.apply(self.blend, self.instance) self.instance.node().setBounds(OmniBoundingVolume()) self.instance.node().setFinal(True) return self.instance
def _create_components(self): """ Internal method to init the widgets components """ card_maker = CardMaker("PixelInspector") card_maker.set_frame(-200, 200, -150, 150) self._zoomer = self._node.attach_new_node(card_maker.generate()) # Defer the further loading Globals.base.taskMgr.doMethodLater(1.0, self._late_init, "PixelInspectorLateInit") Globals.base.accept("q", self.show) Globals.base.accept("q-up", self.hide)
def loadPlane(name, widthX = 30.0, widthY = 30.0): """load plane stuff""" cm = CardMaker("plane") cm.set_frame(-widthX / 2.0, widthX / 2.0, -widthY / 2.0, widthY / 2.0) plane = NodePath(cm.generate()) plane.set_p(-90.0) plane.set_z(0.0) plane.set_color(0.15, 0.35, 0.35) plane.set_collide_mask(mask) plane.set_name(name) return plane
def show_match_sample(self, task): print 'show match sample' print self.color_match[:] # match_image.fill(*self.color_match[:]) card = CardMaker('card') color_match = self.color_match[:] # add alpha channel color_match.append(1) print color_match card.set_color(*color_match[:]) card.set_frame(-12, -8, 0, 4) # log this self.card = self.base.render.attach_new_node(card.generate()) return task.done
def createPlane(self, frame=None, color=VBase4(1, 1, 1, 1)): """ Creates a Plane/Card with the Panda3d Cardmaker() class Keyword Arguments: frame {list} -- The coordinates [x1,y1,x2,y2] of the planes/cards edges (default: {[-1, -1, 1, 1]}) color {VBase4} -- The color of the planes/cards (default: {VBase4(1, 1, 1, 1)}) """ frame = frame or [-1, -1, 1, 1] card = CardMaker("plane") card.set_color(color) card.set_frame(frame[0], frame[1], frame[2], frame[3]) n = NodePath() self.plane = n.attach_new_node(card.generate()) self.plane.reparentTo(self.render) self.plane.setHpr(0, 270, 0)
def make_star(name='star', scale=1, color=Vec3(1), texture_size=64, debug=False): card_maker = CardMaker(name) card_maker.set_frame(-1, 1, -1, 1) node_path = NodePath(name) node = card_maker.generate() final_node_path = node_path.attach_new_node(node) final_node_path.set_billboard_point_eye() from panda3d.core import Filename shaders = Shader.load(Shader.SL_GLSL, Filename('Shader/Star/vertex.glsl'), Filename('Shader/Star/fragment.glsl'), Filename(''), Filename(''), Filename('')) if not shaders: print("WARNING. STAR SHADER FAILED TO LOAD", type(shaders)) else: final_node_path.set_shader_input('cameraSpherePos', 1, 1, 1) final_node_path.set_shader_input('sphereRadius', 1.0) final_node_path.set_shader_input('myCamera', base.camera) final_node_path.set_shader(shaders) final_node_path.set_shader_input('blackbody', color) material = Material() material.set_emission(VBase4(color, 1.0)) final_node_path.set_material(material) xn = PerlinNoise3(0.5, 0.5, 0.5) #yn = PerlinNoise3(0.5, 0.5, 0.5) texture = Texture('star') texture.setup_3d_texture() for z in range(texture_size): p = PNMImage(texture_size, texture_size) for y in range(texture_size): for x in range(texture_size): p.set_gray(x, y, abs(xn.noise(x, y, z))) texture.load(p, z, 0) diffuse = texture diffuse.setMinfilter(Texture.FTLinearMipmapLinear) diffuse.setAnisotropicDegree(4) final_node_path.set_texture(diffuse) normal = sandbox.base.loader.loadTexture('data/empty_textures/empty_normal.png') normalts = TextureStage('normalts') final_node_path.set_texture(normalts, normal) specular = sandbox.base.loader.loadTexture('data/empty_textures/empty_specular.png') spects = TextureStage('spects') final_node_path.set_texture(spects, specular) roughness = sandbox.base.loader.loadTexture('data/empty_textures/empty_roughness.png') roughts= TextureStage('roughts') final_node_path.set_texture(roughts, roughness) return final_node_path
def load_water(self): """ Loads the islands psuedo infinite water plane """ # Create a material for the PBR shaders water_material = Material() water_material.set_base_color(VBase4(0, 0.7, 0.9, 1)) water_card_maker = CardMaker('water_card') water_card_maker.set_frame(-200, 200, -150, 150) self.water_path = self.render.attach_new_node( water_card_maker.generate()) self.water_path.set_material(water_material, 1) self.water_path.set_scale(500)
def __init__(self, name=None, navigation_url=None, browser_settings=None): if name is None: name = self.__class__.__name__ NodePath.__init__(self, name) self._chrome_texture = ChromiumTexture( '%s-ChromiumBrowserTexture' % name, navigation_url=navigation_url, browser_settings=browser_settings) card_maker = CardMaker('chromebrowser2d') card_maker.set_frame(-0.75, 0.75, -0.75, 0.75) self._card = self.attach_new_node(card_maker.generate()) self._card.set_texture(self._chrome_texture)
def make_buffer(self, width, height, texture_format): self.width = width self.height = height self.root = NodePath("root") props = FrameBufferProperties() props.set_srgb_color(False) if texture_format == Texture.F_rgb: props.set_float_color(False) props.set_rgba_bits(8, 8, 8, 0) elif texture_format == Texture.F_rgba: props.set_float_color(False) props.set_rgba_bits(8, 8, 8, 8) elif texture_format == Texture.F_r32: props.set_float_color(True) props.set_rgba_bits(32, 0, 0, 0) elif texture_format == Texture.F_rgb32: props.set_float_color(True) props.set_rgba_bits(32, 32, 32, 0) elif texture_format == Texture.F_rgba32: props.set_float_color(True) props.set_rgba_bits(32, 32, 32, 32) self.buffer = base.win.make_texture_buffer("generatorBuffer", width, height, to_ram=True, fbp=props) #print(self.buffer.get_fb_properties(), self.buffer.get_texture()) self.buffer.setOneShot(True) #the camera for the buffer cam = base.makeCamera(win=self.buffer) cam.reparent_to(self.root) cam.set_pos(width / 2, height / 2, 100) cam.set_p(-90) lens = OrthographicLens() lens.set_film_size(width, height) cam.node().set_lens(lens) #plane with the texture cm = CardMaker("plane") cm.set_frame(0, width, 0, height) x_margin = 1.0 / width / 2.0 y_margin = 1.0 / height / 2.0 cm.set_uv_range((-x_margin, -y_margin), (1 + x_margin, 1 + y_margin)) self.quad = self.root.attach_new_node(cm.generate()) self.quad.look_at(0, 0, -1) taskMgr.add(self.check_generation, 'check_generation', sort=-10000) taskMgr.add(self.callback, 'callback', sort=-9999) print("Created offscreen buffer, size: %dx%d" % (width, height), "format:", Texture.formatFormat(texture_format))
def make_star(name='star', scale=1, color=Vec3(1), texture_size=64, debug=False): card_maker = CardMaker(name) card_maker.set_frame(-1, 1, -1, 1) node_path = NodePath(name) node = card_maker.generate() final_node_path = node_path.attach_new_node(node) final_node_path.set_billboard_point_eye() shaders = Shader.load(Shader.SLGLSL, 'Shader/Star/vertex.glsl', 'Shader/Star/fragment.glsl') final_node_path.set_shader_input(b'cameraSpherePos', 1, 1, 1) final_node_path.set_shader_input(b'sphereRadius', 1.0) final_node_path.set_shader_input(b'myCamera', base.camera) final_node_path.set_shader(shaders) final_node_path.set_shader_input(b'blackbody', color) material = Material() material.set_emission(VBase4(color, 1.0)) final_node_path.set_material(material) xn = PerlinNoise3(0.5, 0.5, 0.5) #yn = PerlinNoise3(0.5, 0.5, 0.5) texture = Texture('star') texture.setup_3d_texture() for z in range(texture_size): p = PNMImage(texture_size, texture_size) for y in range(texture_size): for x in range(texture_size): p.set_gray(x, y, abs(xn.noise(x, y, z))) texture.load(p, z, 0) diffuse = texture diffuse.setMinfilter(Texture.FTLinearMipmapLinear) diffuse.setAnisotropicDegree(4) final_node_path.set_texture(diffuse) normal = base.loader.loadTexture('Data/Textures/EmptyNormalTexture.png') normalts = TextureStage('normalts') final_node_path.set_texture(normalts, normal) specular = base.loader.loadTexture('Data/Textures/EmptySpecularTexture.png') spects = TextureStage('spects') final_node_path.set_texture(spects, specular) roughness = base.loader.loadTexture('Data/Textures/EmptyRoughnessTexture.png') roughts= TextureStage('roughts') final_node_path.set_texture(roughts, roughness) return final_node_path
def enter_filter_sprite(self, entity): model = entity[Model] sprite = entity[Sprite] cardmaker = CardMaker("sprite") cardmaker.set_frame(-1, 1, -1, 1) sprite.node = NodePath(cardmaker.generate()) if sprite.texture is None and sprite.image_name: sprite.texture = loader.load_texture(sprite.image_name) sprite.node.set_texture(sprite.texture) if sprite.pixelated: sprite.texture.setMagfilter(SamplerState.FT_nearest) sprite.texture.setMinfilter(SamplerState.FT_nearest) else: sprite.texture.setMagfilter(SamplerState.FT_linear) sprite.texture.setMinfilter(SamplerState.FT_linear) sprite.node.set_transparency(True) sprite.node.reparent_to(model.node) if sprite.post_attach is not None: sprite.post_attach(entity)
def _make_particle_scene(self): # Create a new scene root self._particle_scene = Globals.base.render.attach_new_node("CloudParticles") self._particle_scene.hide(self._pipeline.tag_mgr.get_gbuffer_mask()) self._particle_scene.hide(self._pipeline.tag_mgr.get_shadow_mask()) self._particle_scene.hide(self._pipeline.tag_mgr.get_voxelize_mask()) cm = CardMaker("") cm.set_frame(-1.0, 1.0, -1.0, 1.0) cm.set_has_normals(False) cm.set_has_uvs(False) card_node = cm.generate() card_node.set_bounds(OmniBoundingVolume()) card_node.set_final(True) self._particle_np = self._particle_scene.attach_new_node(card_node) self._particle_np.set_shader_input("CloudVoxels", self._cloud_voxels.get_texture()) self._particle_np.set_instance_count(self._voxel_res_xy * self._voxel_res_xy * self._voxel_res_z) self._particle_np.set_transparency(TransparencyAttrib.M_multisample, 1000000) self._particle_scene.set_transparency(TransparencyAttrib.M_multisample, 1000000) self._particle_cam = Camera("CloudParticleCam") self._particle_cam.set_lens(Globals.base.camLens) self._particle_cam_np = self._particle_scene.attach_new_node(self._particle_cam) cloud_particle_mask = BitMask32.bit(16) self._particle_cam.set_camera_mask(cloud_particle_mask) render.hide(cloud_particle_mask) self._particle_scene.show_through(cloud_particle_mask) self._particle_target = self._create_target("Clouds:RenderParticles") self._particle_target.add_color_texture(bits=16) self._particle_target.set_source(self._particle_cam_np, Globals.base.win) self._particle_target.set_enable_transparency(True) self._particle_target.prepare_scene_render() self._particle_target.set_clear_color(True, color=Vec4(0, 0, 0, 0))
def create_floor(self): """Generate flat floor of size, provided to class""" # todo: add fallback values in case size hasnt been specified log.debug(f"Generating the floor") # Determining how much full textures we can fit in provided sizes repeats_x = int(self.size_x / self.texture.get_orig_file_x_size()) repeats_y = int(self.size_y / self.texture.get_orig_file_y_size()) # Adjusting map size, to ensure it fits floor's texture perfectly self.size_x = repeats_x * self.texture.get_orig_file_x_size() self.size_y = repeats_y * self.texture.get_orig_file_y_size() self.map_size = ( -self.size_x / 2, self.size_x / 2, -self.size_y / 2, self.size_y / 2, ) # initializing new cardmaker object # which is essentially our go-to way to create flat models floor_card = CardMaker("floor") floor_card.set_frame(self.map_size) # attaching card to render and creating it's object floor_object = self.scene.attach_new_node(floor_card.generate()) floor_object.set_texture(self.texture) # repeating texture to avoid stretching when possible floor_object.set_tex_scale(TextureStage.getDefault(), repeats_x, repeats_y) # arranging card's angle # floor_object.look_at((0, 0, -1)) floor_object.set_p(shared.game_data.floor_angle) floor_object.set_pos(0, 0, shared.game_data.floor_layer) self.floor = floor_object
def make_sprite_node( sprite: Texture, size: tuple = None, name: str = None, is_two_sided: bool = True, is_transparent: bool = True, parent: NodePath = None, position: Vec3 = None, scale: float = 0.0, ) -> NodePath: """Make flat single-sprite node out of provided data""" # Using WM_clamp instead of WM_mirror, to avoid issue with black 1-pixel # bars appearing on top of spritesheet randomly. # Idk if this needs to have possibility to override it #TODO sprite.set_wrap_u(Texture.WM_clamp) sprite.set_wrap_v(Texture.WM_clamp) # Creating CardMaker frame card = CardMaker(name or sprite.get_name() or "sprite") # This will fail if texture has been generated with no set_orig_file_size() size = size or (sprite.get_orig_file_x_size(), sprite.get_orig_file_y_size()) # Been told that its not in pixels, thus accepting either 1, 2 or 4 values # Kinda jank, I know if len(size) > 3: card.set_frame(-size[0], size[1], -size[2], size[3]) elif len(size) > 1: card.set_frame(-size[0], size[0], -size[1], size[1]) else: card.set_frame(-size[0], size[0], -size[0], size[0]) parent = parent or NodePath() node = parent.attach_new_node(card.generate()) node.set_texture(sprite) # Making it possible to utilize texture's alpha channel settings # This is a float from 0 to 1, but I dont think there is a point to only # show half of actual object's transparency. # Do it manually afterwards if thats what you need if is_transparent: node.set_transparency(1) # Enabling ability to render texture on both front and back of card if is_two_sided: node.set_two_sided(True) # Setting object's position. This is done relatively to parent, thus if you # didnt pass any, it may be a bit janky if position: node.set_pos(*position) if scale and scale > 0: node.set_scale(scale) return node
from panda3d.core import (CardMaker, Geom, GeomNode, GeomTriangles, GeomTristrips, GeomVertexData, GeomVertexFormat, GeomVertexWriter, NodePath, TransparencyAttrib) from PIL import Image from pkg_resources import resource_filename from tsim.core.geometry import Vector from tsim.core.network.intersection import ConflictPointType from tsim.core.network.lane import LANE_WIDTH from tsim.core.network.node import Node from tsim.ui import textures from tsim.ui.objects.way import LEVEL_HEIGHT from tsim.ui.textures import create_texture CARD_MAKER = CardMaker('lane_connections_card_maker') CARD_MAKER.set_frame((-16, 16, -16, 16)) COLORS = ('crimson', 'orange', 'gold', 'limegreen', 'turquoise', 'deepskyblue', 'blueviolet', 'hotpink') RESOLUTION = 2048 MIDDLE = Vector(RESOLUTION // 2, -RESOLUTION // 2) PPM = RESOLUTION // 32 VERTEX_FORMAT = GeomVertexFormat.get_v3n3t2() FONT = aggdraw.Font('black', resource_filename('tsim', 'data/fonts/caladea-tsim.otf'), 15) def create(parent: NodePath, node: Node) -> NodePath: """Create node for given node and attach it to the parent.""" geom = _generate_mesh(node) node_ = GeomNode(str(node.id))
class Tmx2Bam(): def __init__(self, input_file, output_file=None, prefabs=""): self.dir = os.path.dirname(input_file) self.depth = 0 self.cardmaker = CardMaker("image") self.cardmaker.set_frame(-0.5, 0.5, -0.5, 0.5) self.linesegs = LineSegs() self.textnode = TextNode("text") self.tilesheets = [] # Every tsx file loaded. self.tiles = {} # Every unique tile/card. self.node = NodePath("tmx_root") # load prefab models self.prefabs = {} if prefabs: loader = Loader.get_global_ptr() for prefab_node in loader.load_sync(prefabs).get_children(): prefab_node.clear_transform() self.prefabs[prefab_node.name] = NodePath(prefab_node) self.tmx = ET.parse(input_file).getroot() self.xscale = int(self.tmx.get("tilewidth")) self.yscale = int(self.tmx.get("tileheight")) self.size = [0, 0] self.load_group(self.tmx) if output_file: self.export_bam(output_file) def attributes_to_tags(self, node, element): if not element == None: for property in element: if property.get("name") and property.get("value"): node.set_tag(property.get("name"), property.get("value")) for key in element.keys(): node.set_tag(key, element.get(key)) def build_text(self, object): self.textnode.set_text(object[0].text) # TODO: set color # TODO: set wrap return self.textnode.generate() def build_polygon(self, object): self.linesegs.reset() points = object[0].get("points").split(" ") points = [tuple(map(float, i.split(","))) for i in points] startx = points[0][0] / self.xscale starty = points[0][1] / self.yscale self.linesegs.move_to(startx, -starty, 0) for point in points: x, y = point[0] / self.xscale, point[1] / self.yscale self.linesegs.draw_to(x, -y, 0) self.linesegs.draw_to(startx, -starty, 0) return self.linesegs.create() def build_rectangle(self, w, h): self.linesegs.reset() self.linesegs.move_to(0, 0, 0) self.linesegs.draw_to(w, 0, 0) self.linesegs.draw_to(w, -h, 0) self.linesegs.draw_to(0, -h, 0) self.linesegs.draw_to(0, 0, 0) return self.linesegs.create() def build_tile(self, tsx, id): tile = None # Cross-reference with self.prefabs in case there's a shape # corresponding with a tile's type use_prefab = False for tile in tsx.findall("tile"): if int(tile.get("id")) == id: type = tile.get("type") if type in self.prefabs: geometry_node = NodePath(str(id)) self.prefabs[type].copy_to(geometry_node) use_prefab = True break # Else we generate a card if not use_prefab: geometry = self.cardmaker.generate() geometry_node = NodePath(geometry) geometry_node.set_texture(tsx.get("texture"), 1) geometry_node.set_p(-90) geometry_node.set_transparency(True) # scale and offset UVs for single sprite columns = int(tsx.get("columns")) rows = int(tsx.get("rows")) w, h = 1 / columns, 1 / rows tile_x, tile_y = int(id % columns), int(id / (columns)) u, v = (tile_x * w), 1 - ((tile_y * h) + h) for stage in geometry_node.find_all_texture_stages(): geometry_node.set_texture(stage, tsx.get("texture"), 1) geometry_node.set_tex_scale(stage, w, h) geometry_node.set_tex_offset(stage, (u, v)) self.attributes_to_tags(geometry_node, tile) return geometry_node def animated_tile(self, tsx, tile): node = NodePath("animated tile") sequence = SequenceNode("animated tile") duration = int(tile[0][0].get("duration")) if duration >= 9000: sequence.set_frame_rate(0) else: sequence.set_frame_rate(1000 / duration) for frame in tile[0]: tileid = int(frame.get("tileid")) tile_node = self.build_tile(tsx, tileid) sequence.add_child(tile_node.node()) sequence.loop(True) node.attach_new_node(sequence) return node def get_tile(self, map_id): tileset, set_id = self.get_tileset(map_id) tsx = tileset.get("tsx") if map_id in self.tiles: # if card is already stored node = self.tiles[map_id] # use that one else: # else build and store it is_special = False node = self.build_tile(tsx, set_id) for element in tsx: if element.tag == "tile": if int(element.get("id")) == set_id: # if it contains an element, it's always an animation if len(element) > 0: node = self.animated_tile(tsx, element) self.attributes_to_tags(node, element) break self.tiles[map_id] = node return node def load_layer(self, layer): layer_node = NodePath(layer.get("name")) static_tiles = NodePath("static") # Static tiles to flatten flat_animated_tiles = NodePath("animated") # Animated tiles to flatten dynamic_tiles = NodePath( "dynamic") # All tiles unless otherwise specified (don't flatten) tile_groups = {} # should we flatten this layer store_data = flatten = False properties = layer.find("properties") if properties: for property in properties: if property.get("name") == "flatten": flatten = True if property.get("name") == "store_data": store_data = True # build all tiles in data as a grid of cards data = layer.find("data").text data = data.replace('\n', '') data = data.split(",") collumns = int(layer.get("width")) rows = int(layer.get("height")) self.size = [collumns, rows] for y in range(rows): for x in range(collumns): id = int(data[(y * collumns) + (x % collumns)]) data[(y * collumns) + (x % collumns)] = id if id > 0: tile = NodePath("tile") self.get_tile(id).copy_to(tile) if flatten: if tile.find("**/+SequenceNode"): tile.reparent_to(flat_animated_tiles) else: tile.reparent_to(static_tiles) else: tile.reparent_to(layer_node) tile.set_pos(x, -y, 0) if flatten: if static_tiles.get_num_children() > 0: clear_all_tags(static_tiles) static_tiles.flatten_strong() if flat_animated_tiles.get_num_children() > 0: clear_all_tags(flat_animated_tiles) flat_animated_tiles = self.flatten_animated_tiles( flat_animated_tiles) for t in (static_tiles, flat_animated_tiles): t.reparent_to(layer_node) if store_data: layer_node.set_python_tag("data", data) self.append_layer(layer_node, properties) def flatten_animated_tiles(self, group_node): # FIXME: hard to read: get_child() everywhere # Makes a new node for each frame using all its tiles # flatten the s*** out of the node and add to a new SequenceNode. tiles = group_node.get_children() flattened_sequence = SequenceNode(tiles[0].name) for a, animation in enumerate(tiles[0].node().get_children()): for f, frame in enumerate(animation.get_child(0).get_children()): combined_frame = NodePath("frame " + str(f)) for tile in tiles: new_np = NodePath("frame") new_np.set_pos(tile.get_pos()) animation = tile.node().get_child(a).get_child(0) new_np.attach_new_node(animation.get_child(f)) new_np.reparent_to(combined_frame) combined_frame.flattenStrong() flattened_sequence.add_child(combined_frame.node()) framerate = animation.get_frame_rate() flattened_sequence.set_frame_rate(framerate) flattened_sequence.loop(True) return NodePath(flattened_sequence) def load_objectgroup(self, objectgroup): layer_node = NodePath(objectgroup.get("name")) for object in objectgroup: name = object.get("name") if not name: name = "object" node = NodePath(name) if len(object) > 0: # Has a type, so it's either a polygon, text, point or ellipse # Points and ellipses are just an empty for now. kind = object[0].tag if kind == "polygon": node.attach_new_node(self.build_polygon(object)) elif kind == "text": node.attach_new_node(self.build_text(object)) node.set_p(-90) self.attributes_to_tags(node, object[0]) else: # Doesn't have a type, so it's either an image or a rectangle node = NodePath(name) w = float(object.get("width")) / self.xscale h = float(object.get("height")) / self.yscale if object.get("gid"): # Has a gid, so it's an image self.get_tile(int(object.get("gid"))).copy_to(node) node.set_scale(w, h, 1) else: # It's none of the above, so it's a rectangle node.attach_new_node(self.build_rectangle(w, h)) x = y = 0 if object.get("x"): x = float(object.get("x")) / self.xscale if object.get("y"): y = float(object.get("y")) / self.yscale node.set_pos(x, -y, 0) self.attributes_to_tags(node, object) node.reparent_to(layer_node) self.append_layer(layer_node, objectgroup.find("properties")) def load_imagelayer(self, imagelayer): # FIXME: A lot of this stuff is repeated in build_tilcard image = imagelayer[0] right = int(image.get("width")) / self.xscale down = int(image.get("height")) / self.yscale self.cardmaker.set_frame(0, right, -down, 0) node = NodePath(self.cardmaker.generate()) self.cardmaker.set_frame(0, 1, -1, 0) texture = Texture() texture.read(os.path.join(self.dir, image.get("source"))) texture.setMagfilter(SamplerState.FT_nearest) texture.setMinfilter(SamplerState.FT_nearest) node.set_texture(texture) node.set_transparency(True) node.reparent_to(self.node) ox = imagelayer.get("offsetx") x, y = 0, 0 if ox: x = float(ox) / self.xscale oy = imagelayer.get("offsety") if oy: y = float(oy) / self.yscale node.set_pos((x, -y, self.depth)) node.set_p(-90) def load_group(self, group): for layer in group: if layer.tag == "tileset": self.load_tsx(layer) elif layer.tag == "layer": self.load_layer(layer) elif layer.tag == "objectgroup": self.load_objectgroup(layer) elif layer.tag == "imagelayer": self.load_imagelayer(layer) elif layer.tag == "group": self.load_group(layer) def append_layer(self, node, properties): self.attributes_to_tags(node, properties) node.set_z(self.depth) self.depth += 1 if properties: for property in properties: if property.get("name") == "z": node.set_z(int(property.get("value"))) self.depth -= 1 break node.reparent_to(self.node) def get_tileset(self, id): for tilesheet in self.tilesheets: if int(tilesheet.get("firstgid")) > id: break else: last = tilesheet id_in_sheet = id - int(last.get("firstgid")) return last, id_in_sheet, def load_tsx(self, layer): tsx_filename = layer.get("source") tsx = ET.parse(os.path.join(self.dir, tsx_filename)).getroot() # Load texture and store in the element tree. img_filename = tsx[0].get("source") texture = Texture() dir = os.path.join(self.dir, tsx_filename) place = os.path.join(os.path.split(dir)[0], img_filename) texture.read(place) texture.setMagfilter(SamplerState.FT_nearest) texture.setMinfilter(SamplerState.FT_nearest) tsx.set("texture", texture) columns = int(tsx.get("columns")) rows = int(tsx.get("tilecount")) // columns tsx.set("rows", str(rows)) layer.set("tsx", tsx) self.tilesheets.append(layer) def export_bam(self, filename): print("Exporting as {}".format(filename)) self.node.writeBamFile("{}".format(filename))
def __init__(self, name, spritesheet=None, sprite_size=None, hitbox_size=None, collision_mask=None, position=None, animations_speed=None): log.debug(f"Initializing {name} object") if not animations_speed: animations_speed = DEFAULT_ANIMATIONS_SPEED self.animations_timer = animations_speed self.animations_speed = animations_speed if not sprite_size: sprite_size = DEFAULT_SPRITE_SIZE if not spritesheet: #I cant link assets above, coz their default value is None texture = base.assets.sprite[name] else: texture = base.assets.sprite[spritesheet] size_x, size_y = sprite_size log.debug(f"{name}'s size has been set to {size_x}x{size_y}") #the magic that allows textures to be mirrored. With that thing being #there, its possible to use values in range 1-2 to get versions of sprites #that will face the opposite direction, removing the requirement to draw #them with hands. Without thing thing being there, 0 and 1 will be threated #as same coordinates, coz "out of box" texture wrap mode is "repeat" texture.set_wrap_u(Texture.WM_mirror) texture.set_wrap_v(Texture.WM_mirror) sprite_data = spritesheet_cutter.cut_spritesheet(texture, sprite_size) horizontal_scale, vertical_scale = sprite_data['offset_steps'] offsets = sprite_data['offsets'] entity_frame = CardMaker(name) #setting frame's size. Say, for 32x32 sprite all of these need to be 16 entity_frame.set_frame(-(size_x / 2), (size_x / 2), -(size_y / 2), (size_y / 2)) entity_object = render.attach_new_node(entity_frame.generate()) entity_object.set_texture(texture) #okay, this does the magic #basically, to show the very first sprite of 2 in row, we set tex scale #to half (coz half is our normal char's size). If we will need to use it #with sprites other than first - then we also should adjust offset accordingly #entity_object.set_tex_offset(TextureStage.getDefault(), 0.5, 0) #entity_object.set_tex_scale(TextureStage.getDefault(), 0.5, 1) entity_object.set_tex_scale(TextureStage.getDefault(), horizontal_scale, vertical_scale) #now, to use the stuff from cut_spritesheet function. #lets say, we need to use second sprite from sheet. Just do: #entity_object.set_tex_offset(TextureStage.getDefault(), *offsets[1]) #but, by default, offset should be always set to 0. In case our object #has just one sprite. Or something like that default_sprite = 0 entity_object.set_tex_offset(TextureStage.getDefault(), *offsets[default_sprite]) #enable support for alpha channel. This is a float, e.g making it non-100% #will require values between 0 and 1 entity_object.set_transparency(1) #if no position has been received - wont set it up if position: entity_object.set_pos(*position) #setting character's collisions entity_collider = CollisionNode(name) #if no collision mask has been received - using defaults if collision_mask: entity_collider.set_from_collide_mask(BitMask32(collision_mask)) entity_collider.set_into_collide_mask(BitMask32(collision_mask)) #TODO: move this to be under character's legs #right now its centered on character's center if hitbox_size: self.hitbox_size = hitbox_size else: #coz its sphere and not oval - it doesnt matter if we use x or y #but, for sake of convenience - we are going for size_y self.hitbox_size = (size_y / 2) entity_collider.add_solid(CollisionSphere(0, 0, 0, self.hitbox_size)) entity_collision = entity_object.attach_new_node(entity_collider) #this will explode if its not, but I dont have a default right now if name in ANIMS: entity_anims = ANIMS[name] self.name = name self.object = entity_object self.collision = entity_collision self.sprites = offsets #setting this to None may cause crashes on few rare cases, but going #for "idle_right" wont work for projectiles... So I technically add it #there for anims updater, but its meant to be overwritten at 100% cases self.current_animation = None #this will always be 0, so regardless of consistency I will live it be self.current_frame = default_sprite self.animations = entity_anims #death status, that may be usefull during cleanup self.dead = False #attaching python tags to object node, so these will be accessible during #collision events and similar stuff self.object.set_python_tag("name", self.name) #I thought to put ctrav there, but for whatever reason it glitched projectile #to fly into left wall. So I moved it to Creature subclass #debug function to show collisions all time #self.collision.show() #do_method_later wont work there, coz its indeed based on frames base.task_mgr.add(self.update_anims, "update entity's animations")
class Base(ShowBase): def __init__(self): ShowBase.__init__(self) add_device_listener( config_file='keybindings.toml', assigner=SinglePlayerAssigner(), ) base.disableMouse() self.sound = SoundManager() self.linefx = LineEffects() self.cardmaker = CardMaker("card") self.cardmaker.set_frame(-1,1,-1,1) self.turn_speed = 0.3 #length of turn animation in seconds self.sequence_player = SequencePlayer() self.transition = Transitions(loader) self.interface = Interface() self.bg_color = VBase4(0, 0, 0, 1) self.innitialize_fov() card, scene, camera, self.buffer = self.make_render_card() card.set_x(-0.25) self.camera = camera self.load_icons() self.texts = Texts(camera) self.pause = True self.instruct = True self.gameover = False self.won = False self.player = Player((0,0,0)) self.map = Map() self.map.new_game() camera.reparent_to(self.player.root) camera.set_pos(4,-4,8) camera.look_at(self.player.root) camera.set_compass() base.task_mgr.add(self.update) card, scene, camera, buffer = self.make_render_card([3,7],[64,256],(0,100)) self.hudgun = Actor("assets/models/hand.bam") self.hudgun.reparent_to(scene) self.hudgun.find("**/hand_healthy").show() self.hudgun.find("**/hand_hurt").hide() self.hudgun.setLODAnimation(1, 0.1, 0.005) self.player.weapon.set_hud_bullets() camera.look_at(self.hudgun) camera.set_pos(0.5,-1.5,10) camera.set_p(-90) card.set_scale(1/4,1,1) card.set_x(1-(1/4)) self.quad = None self.setup_post_effect() def game_over(self): self.pause = True self.gameover = True self.texts.make_gameover() def win_game(self): self.pause = True self.won = True self.texts.make_end() def innitialize_fov(self): render.set_shader_auto() self.fov_point = PointLight("caster") self.fov_point.set_shadow_caster(True, 256*2, 256*2, -1000) self.fov_point.set_camera_mask(0b001) self.fov_point.set_lens_active(4, False) self.fov_point.set_lens_active(5, False) for i in range(6): self.fov_point.get_lens(i).set_near_far(0.5, 10) self.fov_point_np = render.attach_new_node(self.fov_point) self.fov_point_np.set_z(0.5) self.fov_point.set_color(VBase4(1,1,1,1)) def make_render_card(self, ortho_size=[8,5], resolution=[256,256], nearfar=(5,40)): scene = NodePath("Scene") buffer = base.win.make_texture_buffer("Buffer", resolution[0], resolution[1]) texture = buffer.get_texture() texture.set_magfilter(SamplerState.FT_nearest) texture.set_minfilter(SamplerState.FT_nearest) texture.set_wrap_u(SamplerState.WM_clamp) texture.set_wrap_v(SamplerState.WM_clamp) buffer.set_sort(-100) buffer.set_clear_color_active(True) buffer.set_clear_color(self.bg_color) camera = base.make_camera(buffer) lens = OrthographicLens() lens.set_film_size(ortho_size[0], ortho_size[1]) lens.set_near(nearfar[0]) lens.set_far(nearfar[1]) camera.node().set_lens(lens) camera.reparent_to(scene) card = render2d.attach_new_node(self.cardmaker.generate()) card.set_texture(texture) return card, scene, camera, buffer def setup_post_effect(self): self.manager = FilterManager(base.win, base.cam2d) tex = Texture() #tex = loader.load_texture("assets/noise.png") self.quad = self.manager.renderSceneInto(colortex=tex) self.quad.setShader(Shader.load(Shader.SL_GLSL, "crt.vert","crt.frag")) self.quad.setShaderInput("iResolution", (base.win.getXSize(), base.win.getYSize())) self.quad.setShaderInput("pattern", base.loader.load_texture("assets/crt.png")) self.quad.get_texture().set_wrap_u(SamplerState.WM_clamp) self.quad.get_texture().set_wrap_v(SamplerState.WM_clamp) base.accept("window-event", self.on_window_event) def on_window_event(self, win): base.windowEvent(win) self.quad.setShaderInput("iResolution", (base.win.getXSize(), base.win.getYSize())) def load_icons(self): model = loader.load_model("assets/models/icons.bam") self.icons = {} for child in model.get_children(): child.clear_transform() child.detach_node() self.icons[child.name] = child def update(self, task): self.dt = globalClock.get_dt() context = base.device_listener.read_context('ew') if context["quit"]: sys.exit() if not self.pause: if self.player.alive: base.texts.deactivate() if not self.sequence_player.parallel: self.interface.update(context) elif not self.sequence_player.parallel: if self.won: return task.cont if context["select"]: self.texts.deactivate() if self.instruct: self.instruct = False self.texts.make_instructions() else: self.pause = False if self.gameover: base.sound.stop("die") self.gameover = False self.map.destroy() self.map.new_game() else: base.sound.music["opening"].stop() base.sound.music["background"].play() return task.cont
class UpdateSprites(System): entity_filters = { 'sprite': and_filter([ Geometry, Sprite, Clock, ]) } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cardmaker = CardMaker("sprite") # set frame so the bottom edge is centered on 0 self.cardmaker.set_frame(-0.5, 0.5, 0, 1) def enter_filter_sprite(self, entity): sprite = entity[Sprite] geometry = entity[Geometry] sprite.node = NodePath(self.cardmaker.generate()) if sprite.texture is None and sprite.image_name: sprite.texture = loader.load_texture(sprite.image_name) if sprite.texture: sprite.node.set_texture(sprite.texture) # Set min and mag filter. texture = sprite.texture if sprite.pixelated: texture.setMagfilter(SamplerState.FT_nearest) texture.setMinfilter(SamplerState.FT_nearest) else: texture.setMagfilter(SamplerState.FT_linear) texture.setMinfilter(SamplerState.FT_linear) sprite.node.set_transparency(True) geometry.nodes.add(sprite.node) def animate(self, entity): sheet = entity[SpriteSheet] sprite_animation = entity[SpriteAnimation] # Increment animation frame animation = sprite_animation.animations[sprite_animation.animation] sprite_animation.frame += 1 # Manage end of animation if sprite_animation.frame > len(animation) - 1: if sprite_animation.loop: # Start from beginning sprite_animation.frame = 0 else: # Reshow last frame sprite_animation.frame -= 1 sheet.frame = animation[sprite_animation.frame] sheet.update = True def set_frame(self, entity): sprite = entity[Sprite] sheet = entity[SpriteSheet] # get UV transform for current frame w = sheet.sprite_width / sprite.texture.get_orig_file_x_size() h = sheet.sprite_height / sprite.texture.get_orig_file_y_size() rows = 1 / w collumns = 1 / h u = (sheet.frame % rows) * w v = 1 - (((sheet.frame // collumns) * h) + h) # display it stage = sprite.node.find_all_texture_stages()[0] sprite.node.set_tex_scale(stage, w, h) sprite.node.set_tex_offset(stage, (u, v)) sheet.update = False def update(self, entities_by_filter): for entity in entities_by_filter['sprite']: clock = entity[Clock] if SpriteSheet in entity: sheet = entity[SpriteSheet] if SpriteAnimation in entity: sprite = entity[SpriteAnimation] if sprite.animation: animation = sprite.animations[sprite.animation] # Increment frame sprite.timer += clock.game_time if sprite.timer >= 1 / sprite.framerate: sprite.timer -= 1 / sprite.framerate self.animate(entity) if sheet.update: self.set_frame(entity)
from panda3d.core import NodePath from panda3d.core import CardMaker from panda3d.core import Material from panda3d.core import PNMImage from panda3d.core import Texture from panda3d.core import TextureStage from panda3d.core import DirectionalLight from panda3d.core import AmbientLight cm = CardMaker('card') cm.set_frame(-31, 31, -31, 31) map_np = NodePath("map") card = map_np.attach_new_node(cm.generate()) card.set_p(-90) mat = Material() mat.set_base_color((1.0, 1.0, 1.0, 1)) mat.set_emission((1.0, 1.0, 1.0, 1)) mat.set_metallic(1.0) mat.set_roughness(1.0) card.set_material(mat) texture_size = 256 base_color_pnm = PNMImage(texture_size, texture_size) base_color_pnm.fill(0.72, 0.45, 0.2) # Copper base_color_tex = Texture("BaseColor") base_color_tex.load(base_color_pnm) ts = TextureStage('BaseColor') # a.k.a. Modulate ts.set_mode(TextureStage.M_modulate)
class TextFileSelectionNode(DirectObject, TextFileNode): def __init__(self, name, filename=None, **options): DirectObject.__init__(self) TextFileNode.__init__(self, name, None, **options) self.cardmaker = CardMaker('selection cards') self.selection_cards = [] self.selecting = False self.rect_w, self.rect_h = 1, 1 self.accept('shift', self.toggle_select, extraArgs=[True]) self.accept('shift-up', self.toggle_select, extraArgs=[False]) # Selection editing def clear_rects(self): for card in self.selection_cards: if card in list(self.children): self.remove_child(card) self.selection_cards = [] def draw_rect(self, rect, color=(1,1,1,1)): rx, ry, rw, rh = rect l = ((rx)*self.rect_w) r = ((rx+rw+1)*self.rect_w)-0.2 u = ((ry-1)*self.rect_h)+0.5 d = ((ry+rh)*self.rect_h)+0.3 self.cardmaker.set_frame(l,r,-u,-d) self.cardmaker.set_color(color) card = self.cardmaker.generate() self.add_child(card) return card def draw_line_rect(self, line_number, start, end=0): x = self.line_number_width+start y = line_number-self.line_offset w = len(self.lines[line_number])-start if end: w = min(w,end) self.selection_cards.append(self.draw_rect([x,y,w,0])) def remove_range(self): end, start = self.selection_direction() if start[1] == end[1]: a = self.lines[start[1]][:end[0]] b = self.lines[start[1]][start[0]:] self.lines[start[1]] = a + b self.x, self.y = end else: a = self.lines[start[1]][:start[0]] b = self.lines[end[1]][end[0]:] self.lines[start[1]] = a + b for i in range(1, (end[1]-start[1])+2): self.lines.pop(start[1]+1) self.x, self.y = start def select_range(self): self.clear_rects() self.selection_buffer = [] start, end = self.selection_direction() if start[1] == end[1]: self.draw_line_rect(start[1], end[0], start[0]-end[0]) self.selection_buffer.append(self.lines[start[1]][start[0]:end[0]]) else: if start[0] > 0: self.draw_line_rect(start[1], 0, start[0]) self.selection_buffer.append(self.lines[start[1]][:start[0]]) for i in range(1, start[1]-end[1]): i = start[1] - i self.draw_line_rect(i,0) self.selection_buffer.append(self.lines[i]) self.draw_line_rect(end[1], end[0]) self.selection_buffer.append(self.lines[end[1]][start[0]:]) def selection_direction(self): if self.y > self.selection_start[1]: return (self.x, self.y), self.selection_start else: return self.selection_start, (self.x, self.y) def toggle_select(self, on=True): if len(self.selection_buffer) > 0: already_selecting = True else: already_selecting = False self.selecting = on if self.selecting and not already_selecting: self.selection_start = [self.x, self.y]
base.cam.look_at(0, 0, 0) global pipeline pipeline = simplepbr.init( msaa_samples=1, max_lights=8, #enable_shadows=True, ) pipeline.use_normal_maps = False pipeline.use_emission_maps = True pipeline.use_occlusion_maps = True cm = CardMaker('card') cm.set_frame(-1, 1, -1, 1) card_np = base.render.attach_new_node(cm.generate()) mat = Material() mat.set_base_color((1.0, 1.0, 1.0, 1)) mat.set_emission((1.0, 1.0, 1.0, 1)) mat.set_metallic(1.0) mat.set_roughness(1.0) card_np.set_material(mat) texture_size = 256 texture_bands_x = 2 texture_bands_y = 2