def __render_icon(self, instance, group, res, amount): """ This renders the icon. It calculates the position of the icon. Most parts of this were copied from horizons/world/managers/statusiconmanager.py """ # TODO: Try to unify the __render methods of this class and statusiconmanager.py! self.renderer.removeAll(group) pos = instance.position # self.run[group] is used for the moving up animation # use -50 here to get some more offset in height bg_rel = fife.Point(0, -50 - self.run[group]) rel = fife.Point(-14, -50 - self.run[group]) self.run[group] += self.animation_steps loc = fife.Location(self.layer) loc.setExactLayerCoordinates( fife.ExactModelCoordinate( pos.origin.x + float(pos.width) / 4, pos.origin.y + float(pos.height) / 4, )) bg_node = fife.RendererNode(loc, bg_rel) node = fife.RendererNode(loc, rel) bg_image = horizons.globals.fife.imagemanager.load(self.background) res_icon = horizons.globals.fife.imagemanager.load( get_res_icon_path(res)) font = horizons.globals.fife.pychanmanager.getFont('mainmenu') self.renderer.addImage(group, bg_node, bg_image) self.renderer.resizeImage(group, node, res_icon, 24, 24) self.renderer.addText(group, node, font, ' ' * 9 + '{amount:>2d}'.format(amount=amount))
def create_node(instance=None, point=None, layer=None): """ creates a node of one of these types: - attached to an instance - attached to an instance with offset - attached to a point FIXME: - add location node @type: instance: object @param instance: fife instance object @type point: tuple @param point: x,y,z tuple @type layer: object @param layer: fife layer object """ node = None if not layer: return node # node at layer coordinates if point and not instance: point = fife.Point(point[0], point[1]) node = fife.RendererNode(point); # node with offset if instance and point: node = fife.RendererNode(instance, layer, fife.Point(point[0], point[1])) # node attached to instance if instance and not point: node = fife.RendererNode(instance, layer) if node: node.thisown = 0 return node
def lightSourceIntensity(self, value): if self.light_sources + value <= 255 and self.light_sources + value >= 0: self.light_sources = self.light_sources + value renderer = fife.LightRenderer.getInstance(self.cameras['main']) renderer.removeAll("beekeeper_simple_light") renderer.removeAll("hero_simple_light") renderer.removeAll("girl_simple_light") if self.lightmodel == 1: node = fife.RendererNode(self.hero.agent) renderer.addSimpleLight("hero_simple_light", node, self.light_sources, 64, 32, 1, 1, 255, 255, 255) node = fife.RendererNode(self.girl.agent) renderer.addSimpleLight("girl_simple_light", node, self.light_sources, 64, 32, 1, 1, 255, 255, 255) for beekeeper in self.beekeepers: node = fife.RendererNode(beekeeper.agent) renderer.addSimpleLight("beekeeper_simple_light", node, self.light_sources, 120, 32, 1, 1, 255, 255, 255)
def _update_buoy(self, remove_only=False): """Draw a buoy at the move target if the ship is moving.""" if self.owner is None or not self.owner.is_local_player: return move_target = self.get_move_target() ship_id = self.worldid session = self.session # this has to happen here, # cause a reference to self in a temporary function is implemented # as a hard reference, which causes a memory leak def tmp(): session.view.renderer['GenericRenderer'].removeAll("buoy_" + str(ship_id)) tmp() # also remove now if remove_only: return if move_target is not None: # set remove buoy callback self.add_move_callback(tmp) loc = fife.Location(self.session.view.layers[LAYERS.OBJECTS]) loc.thisown = 0 # thisown = 0 because the genericrenderernode might delete it coords = fife.ModelCoordinate(move_target.x, move_target.y) coords.thisown = 1 # thisown = 1 because setLayerCoordinates will create a copy loc.setLayerCoordinates(coords) self.session.view.renderer['GenericRenderer'].addAnimation( "buoy_" + str(self.worldid), fife.RendererNode(loc), horizons.globals.fife.animationloader.loadResource("as_buoy0+idle+45") )
def __render_status(self, instance, status): status_string = self.get_status_string(instance) # Clean icons self.renderer.removeAll(status_string) # pixel-offset on screen (will be constant across zoom-levels) rel = fife.Point(0, -30) pos = instance.position # trial and error has brought me to this (it's supposed to hit the center) loc = fife.Location(self.layer) loc.setExactLayerCoordinates( fife.ExactModelCoordinate( pos.origin.x + float(pos.width) / 4, pos.origin.y + float(pos.height) / 4, )) node = fife.RendererNode(loc, rel) try: # to load an animation anim = horizons.globals.fife.animationloader.loadResource( status.icon) self.renderer.addAnimation(status_string, node, anim) except ValueError: img = horizons.globals.fife.imagemanager.load(status.icon) self.renderer.addImage(status_string, node, img)
def image_light(self): if not self._instances[0]: return self.lightrenderer.removeAll(str(self._widgets["group"]._getText())) image = str(self._widgets["image"]._getText()) if image == "": return img = self.engine.getImageManager().load(image) self._light["image"] = img node = fife.RendererNode(self._instances[0]) self.lightrenderer.addImage( str(self._widgets["group"]._getText()), node, self._light["image"], self._light["src"], self._light["dst"], )
def mouseDragged(self, event): instancerenderer = fife.InstanceRenderer.getInstance( self._test._camera) instancerenderer.removeAllColored() instancerenderer.removeAllOutlines() if event.getButton() == fife.MouseEvent.LEFT and hasattr( self, 'select_begin'): do_multi = ((self.select_begin[0] - event.getX())**2 + (self.select_begin[1] - event.getY())** 2) >= 10 # from 3px (3*3 + 1) genericrenderer = fife.GenericRenderer.getInstance( self._test._camera) genericrenderer.removeAll("selection") if do_multi: # draw a rectangle a = fife.Point(min(self.select_begin[0], event.getX()), \ min(self.select_begin[1], event.getY())) b = fife.Point(max(self.select_begin[0], event.getX()), \ min(self.select_begin[1], event.getY())) c = fife.Point(max(self.select_begin[0], event.getX()), \ max(self.select_begin[1], event.getY())) d = fife.Point(min(self.select_begin[0], event.getX()), \ max(self.select_begin[1], event.getY())) genericrenderer.addLine("selection", \ fife.RendererNode(a), fife.RendererNode(b), 200, 200, 200) genericrenderer.addLine("selection", \ fife.RendererNode(b), fife.RendererNode(c), 200, 200, 200) genericrenderer.addLine("selection", \ fife.RendererNode(d), fife.RendererNode(c), 200, 200, 200) genericrenderer.addLine("selection", \ fife.RendererNode(a), fife.RendererNode(d), 200, 200, 200) instances = self._test._camera.getMatchingInstances(\ fife.Rect(min(self.select_begin[0], event.getX()), \ min(self.select_begin[1], event.getY()), \ abs(event.getX() - self.select_begin[0]), \ abs(event.getY() - self.select_begin[1])) if do_multi else fife.ScreenPoint(event.getX(), event.getY()), self._test._actorlayer, 0) # False for accurate for instance in instances: instancerenderer.addColored(instance, 250, 50, 250) instancerenderer.addOutlined(instance, 255, 255, 0, 2)
def animation_light(self): if not self._instances[0]: return self.lightrenderer.removeAll(str(self._widgets["group"]._getText())) animation = str(self._widgets["animation"]._getText()) if animation == "": return rloc = animation ani = loadXMLAnimation(self.engine, rloc) self._light["animation"] = ani node = fife.RendererNode(self._instances[0]) self.lightrenderer.addAnimation( str(self._widgets["group"]._getText()), node, self._light["animation"], self._light["src"], self._light["dst"], )
def draw(self): """Recalculates and draws the whole minimap of self.session.world or world. The world you specified is reused for every operation until the next draw(). """ if self.world is None and self.session.world is not None: self.world = self.session.world # in case minimap has been constructed before the world if not self.world.inited: return # don't draw while loading if self.transform is None: self.transform = _MinimapTransform(self.world.map_dimensions, self.location, 0, self._get_rotation_setting()) self.update_rotation() self.__class__._instances.append(self) # update cam when view updates if self.view is not None and not self.view.has_change_listener( self.update_cam): self.view.add_change_listener(self.update_cam) if not hasattr(self, "icon"): # add to global generic renderer with id specific to this instance self.renderer.removeAll("minimap_image" + self._id) self.minimap_image.reset() # NOTE: this is for the generic renderer interface, the offrenderer has slightly different methods node = fife.RendererNode( fife.Point(self.location.center.x, self.location.center.y)) self.renderer.addImage("minimap_image" + self._id, node, self.minimap_image.image, False) else: # attach image to pychan icon (recommended) self.minimap_image.reset() self.icon.image = fife.GuiImage(self.minimap_image.image) self.update_cam() self._recalculate() if not self.preview: self._timed_update(force=True) ExtScheduler().rem_all_classinst_calls(self) ExtScheduler().add_new_object(self._timed_update, self, self.SHIP_DOT_UPDATE_INTERVAL, -1)
def simple_light(self): if not self._instances[0]: return self.lightrenderer.removeAll(str(self._widgets["group"]._getText())) node = fife.RendererNode(self._instances[0]) self.lightrenderer.addSimpleLight( str(self._widgets["group"]._getText()), node, self._light["intensity"], self._light["radius"], self._light["subdivisions"], self._light["xstretch"], self._light["ystretch"], self._light["red"], self._light["green"], self._light["blue"], self._light["src"], self._light["dst"], )
def draw_health(self, remove_only=False, auto_remove=False): """Draws the units current health as a healthbar over the unit.""" if not self.has_component(HealthComponent): return render_name = "health_" + str(self.worldid) renderer = self.session.view.renderer['GenericRenderer'] renderer.removeAll(render_name) if remove_only or (auto_remove and not self._last_draw_health_call_on_damage): # only remove on auto_remove if this health was actually displayed as reacton to _on_damage # else we might remove something that the user still wants self._health_displayed = False return self._last_draw_health_call_on_damage = False self._health_displayed = True health_component = self.get_component(HealthComponent) health = health_component.health max_health = health_component.max_health zoom = self.session.view.zoom height = int(5 * zoom) width = int(50 * zoom) y_pos = int(self.health_bar_y * zoom) relative_x = int((width * health) // max_health - (width // 2)) # mid_node is the coord separating healthy (green) and damaged (red) quads mid_node_top = fife.RendererNode(self._instance, fife.Point(relative_x, y_pos - height)) mid_node_btm = fife.RendererNode(self._instance, fife.Point(relative_x, y_pos)) left_upper = fife.RendererNode(self._instance, fife.Point(-width // 2, y_pos - height)) right_upper = fife.RendererNode(self._instance, fife.Point(width // 2, y_pos - height)) left_lower = fife.RendererNode(self._instance, fife.Point(-width // 2, y_pos)) right_lower = fife.RendererNode(self._instance, fife.Point(width // 2, y_pos)) if health > 0: # draw healthy part of health bar renderer.addQuad(render_name, left_upper, left_lower, mid_node_btm, mid_node_top, 0, 255, 0) if health < max_health: # draw damaged part renderer.addQuad(render_name, mid_node_top, mid_node_btm, right_lower, right_upper, 255, 0, 0)
def _draw_rect_line(self, start, end): renderer = self.session.view.renderer['GenericRenderer'] renderer.addLine(self.__class__._SELECTION_RECTANGLE_NAME, fife.RendererNode(start), fife.RendererNode(end), 200, 200, 200)
def __create_render_node(self, agent=None, layer=None, location=None, point=None): """Creatss a fife.RendererNode. Arguments: agent: The name of the agent the light should be attached too. If empty or None this will be ignored. Please note that the layer and location have to be set if this is empty or None. layer: The name of the layer the light originates from. Lights will illuminate lower layers, but not higher ones. If empty or None this will be ignored. location: The relative or absolute location of the light depending on whether the agent was set or not. A list with two or three values. If None this will be ignored. point: The relative or absolute window position of the light as a list with 2 values or a fife.Point. This differs from location as it is in pixels and (0, 0) is the upper left position of the window. """ if agent is not None and agent != "": entity = self.__application.world.get_entity(agent) if entity in self.entities: fifeagent = getattr(entity, FifeAgent.registered_as) agent = fifeagent.instance else: raise TypeError("The map %s has no entity %s" % (self.name, agent)) else: agent = None if layer is not None and layer != "": map_layer = self.get_layer(layer) if map_layer is None: raise TypeError("No such layer: %s" % (layer)) layer = map_layer elif agent is not None: layer = fifeagent.layer else: layer = None if location: if layer is not None: coords = fife.DoublePoint3D(*location) location = fife.Location() location.setLayer(layer) location.setMapCoordinates(coords) else: raise TypeError( "The location was set, but not agent or layer.") else: location = None if point is not None and not isinstance(point, fife.Point): point = fife.Point(*point) arguments = [] if agent is not None: arguments.append(agent) if location is not None: arguments.append(location) if layer is not None: arguments.append(layer) self.get_light_renderer().addActiveLayer(layer) if point is not None: arguments.append(point) if not arguments: raise TypeError("A light needs either an agent" ", a location and a layer" ", or a point") node = fife.RendererNode(*arguments) return node
def update(self): """ Update regiontool We group one ToggleButton and one Label into a HBox, the main wrapper itself is a VBox and we also capture both the Button and the Label to listen for mouse actions """ self.clear_region_list() if len(self.regions) <= 0: if not self._mapview: regionid = "No map is open" else: regionid = "No regions" subwrapper = pychan.widgets.HBox() regionLabel = pychan.widgets.Label() regionLabel.text = unicode(regionid) regionLabel.name = RegionTool.LABEL_NAME_PREFIX + regionid subwrapper.addChild(regionLabel) self.wrapper.addChild(subwrapper) if self._mapview: self.renderer.removeAll("region") for name, region in self.regions.iteritems(): rect = region.rect region_dict = [] point1 = fife.ExactModelCoordinate(rect.x, rect.y) loc1 = fife.Location(self.region_layer) loc1.setExactLayerCoordinates(point1) node1 = fife.RendererNode(loc1) region_dict.append(node1) point2 = fife.ExactModelCoordinate(rect.x, rect.y + rect.h) loc2 = fife.Location(self.region_layer) loc2.setExactLayerCoordinates(point2) node2 = fife.RendererNode(loc2) region_dict.append(node2) point3 = fife.ExactModelCoordinate(rect.x + rect.w, rect.y + rect.h) loc3 = fife.Location(self.region_layer) loc3.setExactLayerCoordinates(point3) node3 = fife.RendererNode(loc3) region_dict.append(node3) point4 = fife.ExactModelCoordinate(rect.x + rect.w, rect.y) loc4 = fife.Location(self.region_layer) loc4.setExactLayerCoordinates(point4) node4 = fife.RendererNode(loc4) region_dict.append(node4) color = [255, 0, 0, 127] if name == self.selected_region: color[3] = 255 self.renderer.addQuad("region", region_dict[0], region_dict[1], region_dict[2], region_dict[3], *color) font = get_manager().getDefaultFont() self.renderer.addText("region", region_dict[0], font, name) for region in self.regions.itervalues(): regionid = region.name subwrapper = pychan.widgets.HBox() regionLabel = pychan.widgets.Label() regionLabel.text = unicode(regionid) regionLabel.name = RegionTool.LABEL_NAME_PREFIX + regionid regionLabel.capture(self.selectRegion, "mousePressed") subwrapper.addChild(regionLabel) self.wrapper.addChild(subwrapper) self.container.adaptLayout()
def updateLighting(self): hour = self.application.world.getHour() # optimization: this method is expensive, so only run it: # - after loading a new map (self.last_hour is None) # - if the hour has changed since the last run # - if new instances were added since the last run (a listener sets self.last_hour to None) # TODO: in the last case: only update the new instances, not all of them if hour == self.last_hour: return self.last_hour = hour day = self.application.world.getDay() # tooltip clock #self.application.gui.tooltip.printMessage("Day " + str(day) # + "; Time: " + str(int(hour)) + ":" + str(int((hour%1.0)*60))) # day-night cycle self.light_renderer.removeAll("pc") cycle = customanimations.light_cycle for next_hour in cycle: if hour < next_hour: factor = (hour - prev_hour) / (next_hour - prev_hour) # global light self.camera.setLightingColor( cycle[prev_hour][0] + factor * (cycle[next_hour][0] - cycle[prev_hour][0]), cycle[prev_hour][1] + factor * (cycle[next_hour][1] - cycle[prev_hour][1]), cycle[prev_hour][2] + factor * (cycle[next_hour][2] - cycle[prev_hour][2])) # local lights #if self.application.current_character: # if self.application.current_character.visual: # for i in xrange(2): # self.light_renderer.addSimpleLight("pc", # fife.RendererNode( # self.application.current_character.visual.instance), # 255, 64, 32, 3.0, 1.875, # int((cycle[prev_hour][3]+factor* # (cycle[next_hour][3]-cycle[prev_hour][3]))*255), # int((cycle[prev_hour][4]+factor* # (cycle[next_hour][4]-cycle[prev_hour][4]))*255), # int((cycle[prev_hour][5]+factor* # (cycle[next_hour][5]-cycle[prev_hour][5]))*255)) for instance in self.application.maplayer.getInstances(): if not instance: print("getInstances() error!", instance) #self.application.maplayer.getInstances() continue if instance.getObject().getId( ) not in customanimations.light_circles: continue circle = customanimations.light_circles[ instance.getObject().getId()] if not ((circle[0] < hour < circle[1]) or (hour < circle[1] < circle[0]) or (circle[1] < circle[0] < hour)): continue for i in xrange(2): # double light power! self.light_renderer.addSimpleLight( group="pc", n=fife.RendererNode( instance, fife.Point( int(circle[7]), #int(circle[7] * self.camera.getZoom()), int(circle[8]))), #int(circle[8] * self.camera.getZoom()))), intensity=255, radius=64, subdivisions=32, xstretch=circle[2], ystretch=circle[3], r=int(circle[4] * 255), g=int(circle[5] * 255), b=int(circle[6] * 255)) break prev_hour = next_hour # set transparency for light overlay instances for instance in self.application.maplayer.getInstances(): if not instance: print("getInstances() error!", instance) #self.application.maplayer.getInstances() continue if instance.getObject().getId( ) in customanimations.light_instances: hours = customanimations.light_instances[ instance.getObject().getId()] if ((hours[0] < hour < hours[1]) or (hour < hours[1] < hours[0]) or (hours[1] < hours[0] < hour)): instance.get2dGfxVisual().setTransparency(0) else: instance.get2dGfxVisual().setTransparency(255)