Package horizons :: Package gui :: Package mousetools :: Module tearingtool
[hide private]
[frames] | no frames]

Source Code for Module horizons.gui.mousetools.tearingtool

  1  # ################################################### 
  2  # Copyright (C) 2008-2017 The Unknown Horizons Team 
  3  # team@unknown-horizons.org 
  4  # This file is part of Unknown Horizons. 
  5  # 
  6  # Unknown Horizons is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the 
 18  # Free Software Foundation, Inc., 
 19  # 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 20  # ################################################### 
 21   
 22  import weakref 
 23   
 24  from fife import fife 
 25   
 26  import horizons.globals 
 27  from horizons.command.building import Tear 
 28  from horizons.constants import BUILDINGS 
 29  from horizons.gui.mousetools.navigationtool import NavigationTool 
 30  from horizons.i18n import gettext as T, ngettext as NT 
 31  from horizons.messaging import WorldObjectDeleted 
 32  from horizons.util.python.weaklist import WeakList 
 33  from horizons.util.shapes import Point 
 34   
 35   
36 -class TearingTool(NavigationTool):
37 """ 38 Represents a dangling tool to remove (tear) buildings. 39 """ 40 tear_selection_color = (255, 255, 255) 41 nearby_objects_radius = 4 42
43 - def __init__(self, session):
44 super().__init__(session) 45 self._transparent_instances = set() # fife instances modified for transparency 46 self.coords = None 47 self.selected = WeakList() 48 self.oldedges = None 49 self.tear_tool_active = True 50 self.session.ingame_gui.hide_menu() 51 self.session.selected_instances.clear() 52 horizons.globals.fife.set_cursor_image("tearing") 53 self._hovering_over = WeakList() 54 WorldObjectDeleted.subscribe(self._on_object_deleted)
55
56 - def remove(self):
57 self._mark() 58 self.tear_tool_active = False 59 horizons.globals.fife.set_cursor_image("default") 60 WorldObjectDeleted.unsubscribe(self._on_object_deleted) 61 super().remove()
62
63 - def mouseDragged(self, evt):
64 coords = self.get_world_location(evt).to_tuple() 65 if self.coords is None: 66 self.coords = coords 67 self._mark(self.coords, coords) 68 evt.consume()
69
70 - def mouseMoved(self, evt):
71 super().mouseMoved(evt) 72 coords = self.get_world_location(evt).to_tuple() 73 self._mark(coords) 74 evt.consume()
75
76 - def on_escape(self):
78
79 - def mouseReleased(self, evt):
80 """Tear selected instances and set selection tool as cursor""" 81 self.log.debug("TearingTool: mouseReleased") 82 if evt.getButton() == fife.MouseEvent.LEFT and not evt.isConsumedByWidgets(): 83 coords = self.get_world_location(evt).to_tuple() 84 if self.coords is None: 85 self.coords = coords 86 self._mark(self.coords, coords) 87 selection_list_copy = [building for building in self.selected] 88 if self.selected: 89 for building in selection_list_copy: 90 self.session.view.renderer['InstanceRenderer'].removeColored(building._instance) 91 if (building.id not in BUILDINGS.EXPAND_RANGE) or self.confirm_ranged_delete(building): 92 Tear(building).execute(self.session) 93 elif self._hovering_over: 94 # we're hovering over a building, but none is selected, so this tear action isn't allowed 95 warehouses = [b for b in self._hovering_over if 96 b.id == BUILDINGS.WAREHOUSE and b.owner.is_local_player] 97 if warehouses: 98 # tried to tear a warehouse, this is especially non-tearable 99 pos = warehouses[0].position.origin 100 self.session.ingame_gui.message_widget.add(point=pos, string_id="WAREHOUSE_NOT_TEARABLE") 101 102 self.selected = WeakList() 103 self._hovering_over = WeakList() 104 if not evt.isShiftPressed() and not horizons.globals.fife.get_uh_setting('UninterruptedBuilding'): 105 self.tear_tool_active = False 106 self.on_escape() 107 evt.consume()
108
109 - def confirm_ranged_delete(self, building):
110 buildings_to_destroy = len(Tear.additional_removals_after_tear(building)[0]) 111 if buildings_to_destroy == 0: 112 return True 113 114 title = T("Destroy all buildings") 115 msg = T("This will destroy all the buildings that fall outside of" 116 " the settlement range.") 117 msg += "\n\n" 118 msg += NT("%s additional building will be destroyed.", 119 "%s additional buildings will be destroyed", 120 buildings_to_destroy) % buildings_to_destroy 121 return building.session.ingame_gui.open_popup(title, msg, show_cancel_button=True)
122
123 - def mousePressed(self, evt):
124 if evt.getButton() == fife.MouseEvent.RIGHT: 125 self.on_escape() 126 elif evt.getButton() == fife.MouseEvent.LEFT and not evt.isConsumedByWidgets(): 127 self.coords = self.get_world_location(evt).to_tuple() 128 self._mark(self.coords) 129 else: 130 return 131 self.tear_tool_active = False 132 evt.consume()
133
134 - def _mark(self, *edges):
135 """Highights building instances and keeps self.selected up to date.""" 136 self._restore_transparent_instances() 137 self.log.debug("TearingTool: mark") 138 if len(edges) == 1: 139 edges = (edges[0], edges[0]) 140 elif len(edges) == 2: 141 edges = ((min(edges[0][0], edges[1][0]), min(edges[0][1], edges[1][1])), 142 (max(edges[0][0], edges[1][0]), max(edges[0][1], edges[1][1]))) 143 else: 144 edges = None 145 if self.oldedges != edges or edges is None: 146 for i in self.selected: 147 self.session.view.renderer['InstanceRenderer'].removeColored(i._instance) 148 self.selected = WeakList() 149 self.oldedges = edges 150 if edges is not None: 151 self._hovering_over = WeakList() 152 for x in range(edges[0][0], edges[1][0] + 1): 153 for y in range(edges[0][1], edges[1][1] + 1): 154 b = self.session.world.get_building(Point(x, y)) 155 if b is not None: 156 if b not in self._hovering_over: 157 self._hovering_over.append(b) 158 self._make_surrounding_transparent(b) 159 self._remove_object_transparency(Point(x, y)) 160 if b.tearable and b.owner is not None and b.owner.is_local_player: 161 if b not in self.selected: 162 self._make_surrounding_transparent(b) 163 self.selected.append(b) 164 self._remove_object_transparency(Point(x, y)) 165 for i in self.selected: 166 self.session.view.renderer['InstanceRenderer'].addColored(i._instance, 167 *self.tear_selection_color) 168 self.log.debug("TearingTool: mark done")
169
170 - def _remove_object_transparency(self, coords):
171 """helper function, used to remove transparency from object hovered upon, 172 identified through its coordinates""" 173 tile = self.session.world.get_tile(coords) 174 if tile.object is not None and tile.object.buildable_upon: 175 inst = tile.object.fife_instance 176 inst.get2dGfxVisual().setTransparency(0)
177
178 - def _make_surrounding_transparent(self, building):
179 """Makes the surrounding of building_position transparent""" 180 world_contains = self.session.world.map_dimensions.contains_without_border 181 for coord in building.position.get_radius_coordinates(self.nearby_objects_radius, include_self=True): 182 p = Point(*coord) 183 if not world_contains(p): 184 continue 185 tile = self.session.world.get_tile(p) 186 if tile.object is not None and tile.object.buildable_upon: 187 inst = tile.object.fife_instance 188 inst.get2dGfxVisual().setTransparency(BUILDINGS.TRANSPARENCY_VALUE) 189 self._transparent_instances.add(weakref.ref(inst))
190
192 """Removes transparency""" 193 for inst_weakref in self._transparent_instances: 194 fife_instance = inst_weakref() 195 if fife_instance: 196 # remove transparency only if trees aren't supposed to be transparent as default 197 if not hasattr(fife_instance, "keep_translucency") or not fife_instance.keep_translucency: 198 fife_instance.get2dGfxVisual().setTransparency(0) 199 else: 200 # restore regular translucency value, can also be different 201 fife_instance.get2dGfxVisual().setTransparency(BUILDINGS.TRANSPARENCY_VALUE) 202 self._transparent_instances.clear()
203
204 - def _on_object_deleted(self, message):
205 self.log.debug("TearingTool: on deletion notification %s", message.worldid) 206 if message.sender in self.selected: 207 self.log.debug("TearingTool: deleted obj present") 208 self.selected.remove(message.sender)
209