def highlight_buildable(self, tiles_to_check=None): """Highlights all buildable tiles. @param tiles_to_check: list of tiles to check for coloring.""" self._build_logic.highlight_buildable(self, tiles_to_check) # also distinguish related buildings (lumberjack for tree) related = frozenset(self.session.db.get_inverse_related_building_ids(self._class.id)) renderer = self.session.view.renderer['InstanceRenderer'] if tiles_to_check is None: buildings_to_select = [ buildings_to_select for\ settlement in self.session.world.settlements if \ settlement.owner.is_local_player for \ bid in related for \ buildings_to_select in settlement.buildings_by_id[bid] ] tiles = SelectableBuildingComponent.select_many(buildings_to_select, renderer) self._related_buildings_selected_tiles = frozenset(tiles) else: buildings_to_select = [ tile.object for tile in tiles_to_check if \ tile.object is not None and tile.object.id in related ] for tile in tiles_to_check: # check if we need to recolor the tiles if tile in self._related_buildings_selected_tiles: SelectableBuildingComponent._add_selected_tile(tile, renderer, remember=False) for building in buildings_to_select: self._related_buildings.add(building)
def _draw_preview_building_range(self, building, settlement): """Color the range as if the building was selected""" # get required data from component definition (instance doesn't not # exist yet try: template = self._class.get_component_template(SelectableComponent.NAME) except KeyError: pass else: radius_only_on_island = True if 'range_applies_only_on_island' in template: radius_only_on_island = template['range_applies_only_on_island'] SelectableBuildingComponent.select_building(self.session, building.position, settlement, self._class.radius, radius_only_on_island)
def _color_preview_building(self, building, settlement): """Draw fancy stuff for build preview @param building: return value from buildable, _BuildPosition """ if building.buildable: # Tile might still have not buildable color -> remove it self.renderer.removeColored(self.buildings_fife_instances[building]) self.renderer.addOutlined( self.buildings_fife_instances[building], self.buildable_color[0], self.buildable_color[1], self.buildable_color[2], GFX.BUILDING_OUTLINE_WIDTH, GFX.BUILDING_OUTLINE_THRESHOLD, ) # get required data from component definition (instance doesn't not # exist yet try: template = self._class.get_component_template(SelectableComponent.NAME) except KeyError: pass else: radius_only_on_island = True if "range_applies_only_on_island" in template: radius_only_on_island = template["range_applies_only_on_island"] SelectableBuildingComponent.select_building( self.session, building.position, settlement, self._class.radius, radius_only_on_island ) # highlight directly related buildings (tree for lumberjacks) if settlement is not None: related = frozenset(self.session.db.get_related_building_ids(self._class.id)) for tile in settlement.get_tiles_in_radius( building.position, self._class.radius, include_self=True ): obj = tile.object if (obj is not None) and (obj.id in related) and (obj not in self._highlighted_buildings): self._highlighted_buildings.add( (obj, False) ) # False: was_selected, see _restore_highlighted_buildings # currently same code as highlight_related_buildings inst = obj.fife_instance self.renderer.addOutlined(inst, *self.related_building_outline) self.renderer.addColored(inst, *self.related_building_color) else: # not buildable # must remove other highlight, fife does not support both self.renderer.removeOutlined(self.buildings_fife_instances[building]) self.renderer.addColored(self.buildings_fife_instances[building], *self.not_buildable_color)
def highlight_buildable(self, tiles_to_check=None, new_buildings=True): """Highlights all buildable tiles and select buildings that are inversely related in order to show their range. @param tiles_to_check: list of tiles to check for coloring. @param new_buildings: Set to true if you have set tiles_to_check and there are new buildings. An internal structure for optimisation will be amended.""" self._build_logic.highlight_buildable(self, tiles_to_check) # Also distinguish inversely related buildings (lumberjack for tree). # Highlight their range at all times. # (There is another similar highlight, but it only marks building when # the current build preview is in its range) related = self.session.db.get_inverse_related_building_ids(self._class.id) # If the current buildings has related buildings, also show other buildings # of this class. You usually don't want overlapping ranges of e.g. lumberjacks. if ( self._class.id in self.session.db.get_buildings_with_related_buildings() and self._class.id != BUILDINGS.RESIDENTIAL_CLASS ): # TODO: generalize settler class exclusion, e.g. when refactoring it into components related = related + [self._class.id] # don't += on retrieved data from db related = frozenset(related) renderer = self.session.view.renderer["InstanceRenderer"] if tiles_to_check is None or new_buildings: # first run, check all buildings_to_select = [ buildings_to_select for settlement in self.session.world.settlements if settlement.owner.is_local_player for bid in related for buildings_to_select in settlement.buildings_by_id[bid] ] tiles = SelectableBuildingComponent.select_many(buildings_to_select, renderer) self._related_buildings_selected_tiles = frozenset(tiles) else: # we don't need to check all # duplicates filtered later buildings_to_select = [ tile.object for tile in tiles_to_check if tile.object is not None and tile.object.id in related ] for tile in tiles_to_check: # check if we need to recolor the tiles if tile in self._related_buildings_selected_tiles: SelectableBuildingComponent._add_selected_tile(tile, renderer, remember=False) for building in buildings_to_select: self._related_buildings.add(building)
def _remove_building_instances(self): """Deletes fife instances of buildings""" try: self._class.get_component_template(SelectableComponent.NAME) except KeyError: pass else: deselected_tiles = SelectableBuildingComponent.deselect_building(self.session) # redraw buildables (removal of selection might have tampered with it) self.highlight_buildable(deselected_tiles) for inst_weakref in self._modified_instances: fife_instance = inst_weakref() if fife_instance: # remove everything that might have been added, we don't keep track of the single changes self.renderer.removeOutlined(fife_instance) self.renderer.removeColored(fife_instance) if not hasattr(fife_instance, "keep_translucency") or not fife_instance.keep_translucency: fife_instance.get2dGfxVisual().setTransparency(0) for building in self._related_buildings: # restore selection, removeOutline can destroy it building.get_component(SelectableComponent).set_selection_outline() self._modified_instances.clear() for fife_instance in self.buildings_fife_instances.itervalues(): layer = fife_instance.getLocationRef().getLayer() # layer might not exist, happens for some reason after a build if layer is not None: layer.deleteInstance(fife_instance)
def _remove_building_instances(self): """Deletes fife instances of buildings""" try: self._class.get_component_template(SelectableComponent.NAME) except KeyError: pass else: deselected_tiles = SelectableBuildingComponent.deselect_building(self.session) # redraw buildables (removal of selection might have tampered with it) self.highlight_buildable(deselected_tiles) self._restore_modified_instances() for building in self._related_buildings: # restore selection, removeOutline can destroy it building.get_component(SelectableComponent).set_selection_outline() for fife_instance in self.buildings_fife_instances.itervalues(): layer = fife_instance.getLocationRef().getLayer() # layer might not exist, happens for some reason after a build if layer is not None: layer.deleteInstance(fife_instance) self.buildings_fife_instances = {}
def _clear_caches(self): """Clear all data caches in global namespace related to a session""" WorldObject.reset() NamedComponent.reset() AIPlayer.clear_caches() SelectableBuildingComponent.reset()