def draw_line(self, *args): mapview = self.parent self.zoom = mapview.zoom global coordinates global corridors #corridor = corr # When zooming we must undo the current scatter transform # or the animation distorts it scatter = mapview._scatter map_source = mapview.map_source sx,sy,ss = scatter.x, scatter.y, scatter.scale vx,vy,vs = mapview.viewport_pos[0], mapview.viewport_pos[1], mapview.scale # Account for map source tile size and mapview zoom ms = pow(2.0,mapview.zoom) * map_source.dp_tile_size #: Since lat is not a linear transform we must compute manually #line_points = [] with self.canvas: # Clear old line self.canvas.clear() for corridor in corridors: line_points = [] for lat,lon in corridor: line_points.extend((self.get_x(lon),self.get_y(lat))) print("linepointslist:") print (line_points) #line_points.extend(mapview.get_window_xy_from(lat,lon,mapview.zoom)) with self.canvas: # Clear old line #self.canvas.clear() # Undo the scatter animation transform Scale(1/ss,1/ss,1) Translate(-sx,-sy) # Apply the get window xy from transforms Scale(vs,vs,1) Translate(-vx,-vy) # Apply the what we can factor out # of the mapsource long,lat to x,y conversion Scale(ms/360.0,ms/2.0,1) Translate(180,0) # Draw new Color(1, 0, 0, 1) print("linepointslist Line:") print (line_points) Line(points=line_points, width=1)#4/ms)#, joint="round",joint_precision=100) self.canvas.ask_update()
def show_precincts(self): precinct_graphics = self.precinct_graphics = {} with self.canvas: PushMatrix() Translate(self.focus_region_width, 0) for precinct in self.voronoi_mapping.precincts: assert len(precinct.boundary) >= 6 tess = Tesselator() tess.add_contour(precinct.boundary) tess.tesselate(WINDING_ODD, TYPE_POLYGONS) graphics = [ Color(rgba=(0, 0, 0, 1))] for vertices, indices in tess.meshes: graphics.append( Mesh( vertices=vertices, indices=indices, mode="triangle_fan")) graphics.append( Color(rgba=(0, 1, 0, 1))) graphics.append( Line(points=precinct.boundary, width=1)) precinct_graphics[precinct] = graphics PopMatrix()
def screenshot(path, root_widget=None): """ Take screenshot of the current state of the app and save it under ``path``. The sleep- and mainthread-decorator ensure that the app shows the current state properly. """ if root_widget is None: root_widget = MDApp.get_running_app().root fbo = Fbo( size=(root_widget.width, root_widget.height), with_stencilbuffer=True, ) with fbo: ClearColor(*MDApp.get_running_app().theme_cls.bg_normal) ClearBuffers() Scale(1, -1, 1) Translate(-root_widget.x, -root_widget.y - root_widget.height, 0) fbo.add(root_widget.canvas) fbo.draw() img = KivyImage(fbo.texture) img.save(path)
def __init__(self, voronoi_mapping=None, table_mode=False, align_mat=None, screen_offset=(0, 0), ros_bridge=None, district_blocks_fid=None, focus_block_fid=0, focus_block_logical_id=0, district_metrics_fn=None, state_metrics_fn=None, show_voronoi_boundaries=False, focus_metrics=[], focus_metric_width=100, focus_metric_height=100, screen_size=(1920, 1080), max_fiducials_per_district=5, visualize_metric_data=True, **kwargs): super(VoronoiWidget, self).__init__(**kwargs) self.voronoi_mapping = voronoi_mapping self.ros_bridge = ros_bridge self.district_blocks_fid = district_blocks_fid self.focus_block_fid = focus_block_fid self.focus_block_logical_id = focus_block_logical_id self.show_voronoi_boundaries = show_voronoi_boundaries self.max_fiducials_per_district = max_fiducials_per_district self.visualize_metric_data = visualize_metric_data self.focus_metrics = focus_metrics self.focus_metric_width = focus_metric_width self.focus_metric_height = focus_metric_height self.screen_size = screen_size self.n_focus_rows = rows = int(screen_size[1] // focus_metric_height) self.n_focus_cols = cols = int(math.ceil(len(focus_metrics) / rows)) self.focus_region_width = cols * focus_metric_width self.show_district_selection() self.show_focus_region() self.fiducial_graphics = {} self.fiducials_color = {} self.colors = cycle(plt.get_cmap('tab10').colors) self.table_mode = table_mode self.align_mat = align_mat self.district_graphics = [] self.district_metrics_fn = district_metrics_fn self.state_metrics_fn = state_metrics_fn self.screen_offset = screen_offset self.touches = {} with self.canvas.before: PushMatrix() Translate(*[v * Metrics.density for v in screen_offset]) with self.canvas.after: PopMatrix() self.show_precincts()
def _set_view(self): fx, fy = self.map.viewport.origin # clear any previous before/after instructions self.canvas.before.clear() self.canvas.after.clear() with self.canvas.before: PushMatrix('projection_mat') Translate(-fx, -fy) with self.canvas.after: PopMatrix('projection_mat')
def render(self, canvas, size, dt): ratio = 1.0 width_is_bigger = True if size[0] > size[1]: ratio = size[1] / self.root else: width_is_bigger = False ratio = size[0] / self.root with canvas: if width_is_bigger: Translate(size[0] / 2.0 - self.root / 2.0 * ratio, 0.0) else: Translate(0.0, size[1] / 2.0 - self.root / 2.0 * ratio) Scale(ratio, ratio, 1.0) Color(0.6, 0.2, 0.2, 1.0) Rectangle(pos=(0, 0), size=(self.root, self.root)) self.player1.render(canvas, dt) self.player2.render(canvas, dt) self.ball.render(canvas, dt)
def _draw_line(self, *args): mapview = self.parent self.zoom = mapview.zoom # When zooming we must undo the current scatter transform # or the animation distorts it scatter = mapview._scatter sx, sy, ss = scatter.x, scatter.y, scatter.scale # Account for map source tile size and mapview zoom vx, vy, vs = mapview.viewport_pos[0], mapview.viewport_pos[ 1], mapview.scale with self.canvas: # Clear old line self.canvas.clear() # Offset by the MapView's position in the window Translate(*mapview.pos) # Undo the scatter animation transform Scale(1 / ss, 1 / ss, 1) Translate(-sx, -sy) # Apply the get window xy from transforms Scale(vs, vs, 1) Translate(-vx, -vy) # Apply the what we can factor out of the mapsource long, lat to x, y conversion Translate(self.ms / 2, 0) # Translate by the offset of the line points (this keeps the points closer to the origin) Translate(*self.line_points_offset) # Draw line Color(0, 0.2, 0.7, 0.25) Line(points=self.line_points, width=6.5 / 2) Color(0, 0.2, 0.7, 1) Line(points=self.line_points, width=6 / 2) Color(0, 0.3, 1, 1) Line(points=self.line_points, width=4 / 2)
def process_voronoi_output(self, districts, fiducial_identity, fiducial_pos, error=[], post_callback=None, largs=(), data_is_old=False): if data_is_old: return if post_callback is not None: post_callback(*largs) if not error: fid_ids = [self.district_blocks_fid[i] for i in fiducial_identity] if self.ros_bridge is not None: self.ros_bridge.update_voronoi(fiducial_pos, fid_ids, fiducial_identity, districts, self.district_metrics_fn, self.state_metrics_fn) if self.visualize_metric_data and self.current_focus_metric: for graphics in self.precinct_graphics.values(): graphics[0].a = 1. # undo possible previous error display else: if not districts: self.clear_voronoi() else: self.paint_precinct_by_district() if error: for precinct in error: self.precinct_graphics[precinct][0].a = 0 for item in self.district_graphics: self.canvas.remove(item) self.district_graphics = [] if self.show_voronoi_boundaries: with self.canvas: PushMatrix() Translate(self.focus_region_width, 0) Scale(Metrics.density) self.district_graphics.append(Color(1, 1, 0, 1)) for district in districts: if not district.boundary: continue self.district_graphics.append( Line(points=district.boundary + district.boundary[:2], width=2)) PopMatrix()
def process_voronoi_output( self, districts, fiducial_identity, fiducial_pos, error=[], post_callback=None, largs=(), data_is_old=False): if data_is_old: return if post_callback is not None: post_callback(*largs) if not error: self.district_metrics_fn(districts) state_metrics = self.state_metrics_fn(districts) fid_ids = [self.district_blocks_fid[i] for i in fiducial_identity] if self.ros_bridge is not None: self.ros_bridge.update_voronoi( fiducial_pos, fid_ids, fiducial_identity, districts, state_metrics) if not districts: self.clear_voronoi() return colors = self.fiducials_color for district in districts: color = colors[district.identity] for precinct in district.precincts: self.precinct_graphics[precinct][0].rgba = color + [1., ] if error: for precinct in error: self.precinct_graphics[precinct][0].a = .3 for item in self.district_graphics: self.canvas.remove(item) self.district_graphics = [] if self.show_voronoi_boundaries: PushMatrix() Translate(self.focus_region_width, 0) with self.canvas: self.district_graphics.append(Color(1, 1, 0, 1)) for district in districts: self.district_graphics.append( Line(points=district.boundary + district.boundary[:2], width=2)) PopMatrix()
def setup_scene(self): Color(1, 0, 1, 1) PushMatrix() self.translate = Translate(0, -3, -10) self.rotx = Rotate(0, 1, 0, 0) self.rot = Rotate(0.5, 0, 1, 0) self.scale = Scale(1.0) #m = random.sample(xrange(10), 10)#list(self.scene.objects.values())[0] #m = list(self.scene.objects.values())[0] self.mesh = self.generateMesh() #Mesh( UpdateNormalMatrix() #self.mesh = Mesh( # vertices=m.vertices, # indices=m.indices, # fmt=m.vertex_format, # mode='triangles', #) PopMatrix()
def Render(self, matrix, colorTransform, renderingIndex, renderingCount, visible): if not visible or colorTransform.multi.alpha == 0: return # print(matrix) # print("") self.m_color.rgba = (colorTransform.multi.red, colorTransform.multi.green, colorTransform.multi.blue, colorTransform.multi.alpha) self.m_matrix.set(flat=[ matrix.scaleX, -matrix.skew0, 0, 0, # matrix.skew0, -matrix.skew0 -matrix.skew1, matrix.scaleY, 0, 0, # matrix.scaleX, matrix.scaleY 0, 0, 1, 0, matrix.translateX, matrix.translateY, 0, 1 ]) # matrix.translateX, matrix.translateY self.m_inst.matrix = self.m_matrix self.canvas.add(PushMatrix()) self.canvas.add(Color(1, 0, 0, 1)) self.canvas.add(Translate(575, 300)) self.canvas.add(Ellipse(size=(5, 5))) self.canvas.add(self.m_origin_transform) self.canvas.add(Ellipse(size=(5, 5))) self.canvas.add(Scale(1, -1, 1, origin=(0, 0))) self.canvas.add(self.m_inst) self.canvas.add(self.m_color) self.canvas.add(self.m_mesh) self.canvas.add(PopMatrix()) self.canvas.ask_update()
def __init__(self, cx, cy, **kwargs): super(Canvas, self).__init__(**kwargs) img = get_image(map) with self.canvas: # translate the center of canvas from bottom left corner to the center Translate(1024 / 2, 512 / 2) Rectangle(texture=img.texture, pos=(-1024 / 2, -512 / 2), size=(1024, 512)) data = earthquake_data(earthquake) # create web mercators for the center of the map cx = mercX(cx) cy = mercY(cy) # loop trough the earthquakes data for drawing them on the map for i in range(0, len(data)): x = mercX(data["longitude"][i]) - cx y = mercY(data["latitude"][i]) - cy mag = data["mag"][i] # mag squared for better differentiation of the radius of circles on the map mag = math.pow(mag, 2) / 2 # drawing the circles rapresentating the earthquakes using the magnitude for the radius and for translate the origin of the circle from bottom left to center Line(ellipse=(x - mag / 2, y - mag / 2, mag, mag))
def create_image(self): parent = self.parent if parent: canvas_parent_index = parent.canvas.indexof(self.canvas) if canvas_parent_index > -1: parent.canvas.remove(self.canvas) fbo = Fbo(size=self.size, with_stencilbuffer=True) with fbo: ClearColor(0, 0, 0, 0) ClearBuffers() Scale(1, -1, 1) Translate(-self.x, -self.y - self.height, 0) fbo.add(self.canvas) fbo.draw() image = Image.frombytes('RGBA', list(map(int, self.size)), fbo.texture.pixels, 'raw', 'RGBA', 0, 1) fbo.remove(self.canvas) if parent is not None and canvas_parent_index > -1: parent.canvas.insert(canvas_parent_index, self.canvas) return image
def draw_line(self, *args): mapview = self.parent self.zoom = mapview.zoom point_list = [] filename = "map_data.mbtiles" db_mbtiles = sqlite3.connect(filename) c_mbtiles = db_mbtiles.cursor() sql = "SELECT * FROM route_coordinates WHERE day = ?" day = (self.day, ) c_mbtiles.execute(sql, day) myresult = c_mbtiles.fetchall() if self.day == '6': coordinates_list = eval(myresult[0][1][2:-2]) else: coordinates_list = eval(myresult[0][1][2:-1]) db_mbtiles.close() for index, geo_coordinates in enumerate(coordinates_list): screen_coordinates = mapview.get_window_xy_from( coordinates_list[2 * index + 1], coordinates_list[2 * index], mapview.zoom) point_list.append(screen_coordinates[0]) point_list.append(screen_coordinates[1]) if index == int((len(coordinates_list)) / 2 - 1): break # When zooming we must undo the current scatter transform # or the animation makes the line misplaced scatter = mapview._scatter x, y, s = scatter.x, scatter.y, scatter.scale with self.canvas: self.canvas.clear() Scale(1 / s, 1 / s, 1) Translate(-x, -y) Color(1, 0, 0, 1) Line(points=point_list, width=2, joint="miter")
def __init__(self, lwf, bitmap, canvas): b = lwf.data.bitmaps[bitmap.objectId] if b.textureFragmentId == -1: return bx = FormatBitmapEx() bx.matrixId = b.matrixId bx.textureFragmentId = b.textureFragmentId bx.u = 0 bx.v = 0 bx.w = 1 bx.h = 1 f = lwf.data.textureFragments[b.textureFragmentId] t = lwf.data.textures[f.textureId] texturePath = t.filename filename = lwf.data.path + texturePath rect_coords, tex_coords = self.get_vertices(t, f, bx, False, False) # print(f"Looking for {filename}") texture = Image(filename).texture # self.m_mesh = Rectangle(pos=(rect_coords[0], rect_coords[1]), size=(rect_coords[2], rect_coords[3])) self.m_origin_transform = Translate( lwf.render_offset[0] * (lwf.scaleX / lwf.width), lwf.render_offset[1] * (lwf.scaleY / lwf.height)) self.m_mesh = Rectangle(pos=(rect_coords[0], rect_coords[1]), size=(rect_coords[2], rect_coords[3]), tex_coords=tex_coords, texture=texture) # self.m_mesh = Mesh(vertices=coordinates, indices=[1, 3, 2, 0, 1], mode='triangle_fan', texture=texture) self.m_color = Color(1, 1, 1, 1) self.m_matrix = Matrix() self.m_inst = MatrixInstruction() # self.m_mesh = Mesh(vertices=vertices, indices=[1, 3, 2, 0, 1], texture=texture, mode='triangle_fan') self.canvas = canvas
def _setup_canvas(self): self.canvas.clear() self.canvas.add(Translate(0, self.height)) self.canvas.add(Scale(1, -1, -1))
def generate_movie(self, filename, out_fmt='yuv420p', codec='libx264', lib_opts={'crf': '0'}, video_fmt='mp4', start=None, end=None, canvas_size=(0, 0), canvas_size_hint=(1, 1), projector_pos=(0, 0), projector_pos_hint=(None, None), paint_funcs=(), stimulation_transparency=1., lum=1., speed=1., hidden_shapes=None): from kivy.graphics import (Canvas, Translate, Fbo, ClearColor, ClearBuffers, Scale) from kivy.core.window import Window rate = float(self.view_controller.frame_rate) rate_int = int(rate) if rate != rate_int: raise ValueError('Frame rate should be integer') orig_w, orig_h = (self.view_controller.screen_width, self.view_controller.screen_height) canvas_w, canvas_h = canvas_size cv_hint_w, cv_hint_h = canvas_size_hint w = int(canvas_w if cv_hint_w is None else orig_w * cv_hint_w) h = int(canvas_h if cv_hint_h is None else orig_h * cv_hint_h) projector_x, projector_y = projector_pos projector_hint_x, projector_hint_y = projector_pos_hint x = int(projector_x if projector_hint_x is None else orig_w * projector_hint_x) y = int(projector_y if projector_hint_y is None else orig_h * projector_hint_y) Window.size = w, h intensities = self.shapes_intensity n = len(intensities[next(iter(intensities.keys()))]) if start is not None: start = int(start * rate) if start >= n: raise Exception('Start time is after the end of the data') else: start = 0 if end is not None: end = int(math.ceil(end * rate)) + 1 if end <= start: raise Exception('End time is before or at the start time') else: end = n stream = { 'pix_fmt_in': 'rgba', 'pix_fmt_out': out_fmt, 'width_in': w, 'height_in': h, 'width_out': w, 'height_out': h, 'codec': codec, 'frame_rate': (int(speed * rate_int), 1) } writer = MediaWriter(filename, [stream], fmt=video_fmt, lib_opts=lib_opts) fbo = Fbo(size=(w, h), with_stencilbuffer=True) with fbo: ClearColor(0, 0, 0, 1) ClearBuffers() Scale(1, -1, 1) Translate(0, -h, 0) config = { 'canvas': fbo, 'pos': (x, y), 'size': (w, h), 'orig_size': (orig_w, orig_h), 'rate': rate } paint_funcs = [func(config) for func in paint_funcs] paint_funcs = [func for func in paint_funcs if func is not None] fbo.draw() img = Image(plane_buffers=[fbo.pixels], pix_fmt='rgba', size=(w, h)) writer.write_frame(img, 0.) fbo.add(Translate(x, y)) shape_views = self.stage_factory.get_shapes_gl_color_instructions( fbo, 'stage_replay') fbo.add(Translate(-x, -y)) pbar = tqdm(total=(end - 1 - start) / rate, file=sys.stdout, unit='second', unit_scale=1) # all shapes listed in intensities must be in shape_views. However, # we don't want to show shapes not given values in intensities or if # they are to be hidden unused_shapes = set(shape_views) - set(intensities) unused_shapes.update(set(hidden_shapes or [])) for name in unused_shapes: if name in shape_views: shape_views[name].rgba = 0, 0, 0, 0 for i in range(start, end): pbar.update(1 / rate) for name, intensity in intensities.items(): r, g, b, a = intensity[i] if name in unused_shapes: a = 0 shape_views[name].rgba = \ r * lum, g * lum, b * lum, a * stimulation_transparency try: for func in paint_funcs: func(i) except EndOfDataException: break fbo.draw() img = Image(plane_buffers=[fbo.pixels], pix_fmt='rgba', size=(w, h)) writer.write_frame(img, (i - start + 1) / (rate * speed)) pbar.close()
def _show_image(config, img, scale=None, translation=None, rotation=None, transform_matrix=None): from kivy.graphics.texture import Texture from kivy.graphics.fbo import Fbo from kivy.graphics import (Mesh, StencilPush, StencilUse, StencilUnUse, StencilPop, Rectangle, Color) from kivy.graphics.context_instructions import (PushMatrix, PopMatrix, Rotate, Translate, Scale, MatrixInstruction, BindTexture) from kivy.graphics.transformation import Matrix img_fmt = img.get_pixel_format() img_w, img_h = img.get_size() size = config['orig_size'] pos = config['pos'] canvas = config['canvas'] if img_fmt not in ('yuv420p', 'rgba', 'rgb24', 'gray', 'bgr24', 'bgra'): ofmt = get_best_pix_fmt( img_fmt, ('yuv420p', 'rgba', 'rgb24', 'gray', 'bgr24', 'bgra')) swscale = SWScale(iw=img_w, ih=img_h, ifmt=img_fmt, ow=0, oh=0, ofmt=ofmt) img = swscale.scale(img) img_fmt = img.get_pixel_format() kivy_ofmt = { 'yuv420p': 'yuv420p', 'rgba': 'rgba', 'rgb24': 'rgb', 'gray': 'luminance', 'bgr24': 'bgr', 'bgra': 'bgra' }[img_fmt] if kivy_ofmt == 'yuv420p': w2 = int(img_w / 2) h2 = int(img_h / 2) tex_y = Texture.create(size=(img_w, img_h), colorfmt='luminance') tex_u = Texture.create(size=(w2, h2), colorfmt='luminance') tex_v = Texture.create(size=(w2, h2), colorfmt='luminance') with canvas: fbo = Fbo(size=(img_w, img_h)) with fbo: BindTexture(texture=tex_u, index=1) BindTexture(texture=tex_v, index=2) Rectangle(size=fbo.size, texture=tex_y) fbo.shader.fs = CeedDataReader._YUV_RGB_FS fbo['tex_y'] = 0 fbo['tex_u'] = 1 fbo['tex_v'] = 2 tex = fbo.texture dy, du, dv, _ = img.to_memoryview() tex_y.blit_buffer(dy, colorfmt='luminance') tex_u.blit_buffer(du, colorfmt='luminance') tex_v.blit_buffer(dv, colorfmt='luminance') else: tex = Texture.create(size=(img_w, img_h), colorfmt=kivy_ofmt) tex.blit_buffer(img.to_memoryview()[0], colorfmt=kivy_ofmt) tex.flip_vertical() with canvas: StencilPush() Rectangle(pos=pos, size=size) StencilUse() PushMatrix() center = pos[0] + size[0] / 2, pos[1] + size[1] / 2 if rotation: Rotate(angle=rotation, axis=(0, 0, 1), origin=center) if scale: Scale(scale, scale, 1, origin=center) if translation: Translate(*translation) if transform_matrix is not None: mat = Matrix() mat.set(array=transform_matrix) m = MatrixInstruction() m.matrix = mat Rectangle(size=(img_w, img_h), texture=tex, pos=pos) PopMatrix() StencilUnUse() Rectangle(pos=pos, size=size) StencilPop()
def on_up(self, *args): #on_up references the character's motion. with self.canvas.before: Translate(0, dp(-2))
def on_down(self, *args): with self.canvas.before: Translate(0, dp(2))
def on_right(self, *args): with self.canvas.before: Translate(dp(-2), 0)
def on_left(self, *args): with self.canvas.before: Translate(dp(2), 0)
def __init__( self, voronoi_mapping=None, table_mode=False, align_mat=None, screen_offset=(0, 0), ros_bridge=None, district_blocks_fid=None, focus_block_fid=0, focus_block_logical_id=0, district_metrics_fn=None, state_metrics_fn=None, show_voronoi_boundaries=False, focus_metrics=[], focus_metric_width=100, focus_metric_height=100, screen_size=(1920, 1080), **kwargs): super(VoronoiWidget, self).__init__(**kwargs) self.voronoi_mapping = voronoi_mapping self.ros_bridge = ros_bridge self.district_blocks_fid = district_blocks_fid self.focus_block_fid = focus_block_fid self.focus_block_logical_id = focus_block_logical_id self.show_voronoi_boundaries = show_voronoi_boundaries self.focus_metrics = focus_metrics self.focus_metric_width = focus_metric_width self.focus_metric_height = focus_metric_height self.screen_size = screen_size self.n_focus_rows = rows = int(screen_size[1] // focus_metric_height) self.n_focus_cols = cols = int(math.ceil(len(focus_metrics) / rows)) self.focus_region_width = cols * focus_metric_width if not self.table_mode: spinner = self.gui_touch_spinner = GuiTouchClassSpinner( district_blocks_fid=self.district_blocks_fid, focus_block_logical_id=self.focus_block_logical_id) spinner.pos = self.focus_region_width, 0 spinner.size = '100dp', '34dp' def update_current_fid(*largs): self.current_fid_id = spinner.fid_id spinner.fbind('fid_id', update_current_fid) update_current_fid() self.add_widget(spinner) i = 0 for col in range(cols): for row in range(rows): name = focus_metrics[i] x0 = col * focus_metric_width x1 = x0 + focus_metric_width y0 = row * focus_metric_height y1 = y0 + focus_metric_height self.add_widget(Factory.SizedLabel(text=name, pos=(x0, y0))) with self.canvas: Line(points=[x0, y0, x1, y0, x1, y1, x0, y1], width=2) i += 1 if i >= len(focus_metrics): break if i >= len(focus_metrics): break self.fiducial_graphics = {} self.fiducials_color = {} self.colors = cycle(plt.get_cmap('tab10').colors) self.table_mode = table_mode self.align_mat = align_mat self.district_graphics = [] self.district_metrics_fn = district_metrics_fn self.state_metrics_fn = state_metrics_fn self.screen_offset = screen_offset self.touches = {} with self.canvas.before: PushMatrix() Translate(*screen_offset) with self.canvas.after: PopMatrix() self.show_precincts()
def animate_game_event(self, widget=None, anim_duration=0.2): """ Process a single event from self.animation_queue Read the event and perform the correct actions on widgets (such as update text of log window, create and launch animation, maybe make some sound). The event is removed from self.map.game_events. After the actions required are performed, the method calls itself again, either recursively, or, in case of animations, via Animation's on_complete argument. The recursion is broken when event queue is empty. :return: """ if widget and widget.parent and widget.height == 0: # If the widget was given zero size, this means it should be removed # This entire affair is kinda inefficient and should be rebuilt later widget.parent.remove_widget(widget) if not self.animation_queue == []: event = self.animation_queue.pop(0) if event.event_type == 'moved': final = self.get_screen_pos(event.actor.location, center=True) if final[0] < event.actor.widget.pos[0] and event.actor.widget.direction == 'right'\ or final[0] > event.actor.widget.pos[0] and event.actor.widget.direction == 'left': event.actor.widget.flip() a = Animation(center=final, duration=anim_duration) a.bind(on_start=lambda x, y: self.remember_anim(), on_complete=lambda x, y: self.animate_game_event(widget=y)) a.start(event.actor.widget) elif event.event_type == 'attacked': current = self.get_screen_pos(event.actor.location, center=True) target = self.get_screen_pos(event.location, center=True) if target[0] > current[0] and event.actor.widget.direction == 'left' or\ target[0] < current[0] and event.actor.widget.direction == 'right': event.actor.widget.flip() a = Animation(center_x=current[0]+int((target[0]-current[0])/2), center_y=current[1]+int((target[1]-current[1])/2), duration=anim_duration/2) a += Animation(center_x=current[0], center_y=current[1], duration=anim_duration/2) a.bind(on_start=lambda x, y: self.remember_anim(), on_complete=lambda x, y: self.animate_game_event(widget=y)) a.start(event.actor.widget) self.parent.boombox['attacked'].seek(0) self.parent.boombox['attacked'].play() elif event.event_type == 'was_destroyed': if not event.actor.widget: # If actor is None, that means it was destroyed right after spawning, not getting a # widget. Similar case is covered under 'dropped', see there for example. The check is # different here, because in 'dropped' item is taken from map, where it's None by the time # this method runs. Here, on the other hand, Item object exists (in GameEvent), but has # no widget (and is not placed on map, but that's irrelevant). self.animate_game_event() return a = Animation(size=(0, 0), duration=anim_duration) a.bind(on_start=lambda x, y: self.remember_anim(), on_complete=lambda x, y: self.animate_game_event(widget=y)) a.start(event.actor.widget) elif event.event_type == 'picked_up': # It's assumed that newly added item will be the last in player inventory self.layer_widgets['items'].remove_widget(self.map.actors[0].inventory[-1].widget) self.animate_game_event() elif event.event_type == 'dropped': item = self.map.get_item(location=event.location, layer='items') if not item: # Item could've been destroyed right after being drop, ie it didn't get a widget. Skip. # It's rather likely if someone was killed by landmine, dropped an item and had this item # destroyed in the same explosion self.animate_game_event() return if not item.widget: self.tile_factory.create_widget(item) item.widget.center = self.get_screen_pos(event.location, center=True) self.layer_widgets['items'].add_widget(item.widget) self.animate_game_event() elif event.event_type == 'actor_spawned': if not event.actor.widget: self.tile_factory.create_widget(event.actor) event.actor.widget.center = self.get_screen_pos(event.location, center=True) self.layer_widgets['actors'].add_widget(event.actor.widget) self.animate_game_event() elif event.event_type == 'construction_spawned': if not event.actor.widget: self.tile_factory.create_widget(event.actor) event.actor.widget.center = self.get_screen_pos(event.location, center=True) self.layer_widgets['constructions'].add_widget(event.actor.widget) self.animate_game_event() elif event.event_type == 'exploded': loc = self.get_screen_pos(event.location) loc = (loc[0]+16, loc[1]+16) self.overlay_widget = Image(source='Explosion.png', size=(0, 0), size_hint=(None, None), pos=loc) a = Animation(size=(96, 96), pos=(loc[0]-32, loc[1]-32), duration=0.3) a += Animation(size=(0, 0), pos=loc, duration=0.3) a.bind(on_start=lambda x, y: self.remember_anim(), on_complete=lambda x, y: self.animate_game_event(widget=y)) self.add_widget(self.overlay_widget) self.parent.boombox['exploded'].seek(0) self.parent.boombox['exploded'].play() a.start(self.overlay_widget) elif event.event_type == 'rocket_shot': self.overlay_widget = RelativeLayout(center=self.get_screen_pos(event.actor.location, center=True), size=(64,64), size_hint=(None, None)) i = Image(source='Rocket.png', size=(32, 32), size_hint=(None, None)) self.overlay_widget.add_widget(i) self.overlay_widget.canvas.before.add(Translate(x=16, y=16)) a = degrees(atan2(event.actor.location[1]-event.location[1], event.actor.location[0]-event.location[0])) # if abs(a) >= 90: # self.overlay_widget.center_y += 64 self.overlay_widget.canvas.before.add(Rotate(angle=a+90, axis=(0, 0, 1), origin=i.center)) a = Animation(center=self.get_screen_pos(event.location, center=True), duration=anim_duration) a += Animation(size=(0, 0), duration=0) a.bind(on_start=lambda x, y: self.remember_anim(), on_complete=lambda x, y: self.animate_game_event(widget=y)) self.add_widget(self.overlay_widget) a.start(self.overlay_widget) elif event.event_type == 'shot': self.overlay_widget = Image(source='Shot.png', size=(32, 32), size_hint=(None, None), pos=self.get_screen_pos(event.actor.location)) a = Animation(pos=self.get_screen_pos(event.location), duration=anim_duration) a += Animation(size=(0, 0), duration=0) a.bind(on_start=lambda x, y: self.remember_anim(), on_complete=lambda x, y: self.animate_game_event(widget=y)) self.add_widget(self.overlay_widget) self.parent.boombox['shot'].seek(0) self.parent.boombox['shot'].play() a.start(self.overlay_widget) elif event.event_type in self.non_animated: self.parent.process_nonmap_event(event) self.animate_game_event() else: # Reactivating keyboard after finishing animation self.animating = False # Might as well be time to redraw the Dijkstra widget if DISPLAY_DIJKSTRA_MAP: if self.dijkstra_widget: self.remove_widget(self.dijkstra_widget) # else: # self.map.dijkstras['PC'].rebuild_self() self.dijkstra_widget = DijkstraWidget(parent=self) self.add_widget(self.dijkstra_widget)