Mercurial > fife-parpg
comparison tools/editor/plugins/LayerTool.py @ 378:64738befdf3b
bringing in the changes from the build_system_rework branch in preparation for the 0.3.0 release. This commit will require the Jan2010 devkit. Clients will also need to be modified to the new way to import fife.
author | vtchill@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Mon, 11 Jan 2010 23:34:52 +0000 |
parents | |
children | 9d94f4676d17 |
comparison
equal
deleted
inserted
replaced
377:fe6fb0e0ed23 | 378:64738befdf3b |
---|---|
1 # -*- coding: utf-8 -*- | |
2 | |
3 # #################################################################### | |
4 # Copyright (C) 2005-2009 by the FIFE team | |
5 # http://www.fifengine.de | |
6 # This file is part of FIFE. | |
7 # | |
8 # FIFE is free software; you can redistribute it and/or | |
9 # modify it under the terms of the GNU Lesser General Public | |
10 # License as published by the Free Software Foundation; either | |
11 # version 2.1 of the License, or (at your option) any later version. | |
12 # | |
13 # This library is distributed in the hope that it will be useful, | |
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 # Lesser General Public License for more details. | |
17 # | |
18 # You should have received a copy of the GNU Lesser General Public | |
19 # License along with this library; if not, write to the | |
20 # Free Software Foundation, Inc., | |
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 # #################################################################### | |
23 | |
24 """ A layer tool for FIFedit """ | |
25 | |
26 from fife import fife | |
27 from fife.extensions import pychan | |
28 import fife.extensions.pychan.widgets as widgets | |
29 from fife.extensions.pychan.tools import callbackWithArguments as cbwa | |
30 | |
31 import scripts.plugin as plugin | |
32 import scripts.editor | |
33 from scripts.events import * | |
34 from scripts.gui.action import Action | |
35 from scripts.gui.layerdialog import LayerDialog | |
36 | |
37 class LayerTool(plugin.Plugin): | |
38 """ The B{LayerTool} allows to select and show / hide layers of a loaded | |
39 map as well as creating new layers or edit layer properties | |
40 """ | |
41 | |
42 # default should be pychan default, highlight can be choosen (format: r,g,b) | |
43 DEFAULT_BACKGROUND_COLOR = pychan.internal.DEFAULT_STYLE['default']['base_color'] | |
44 HIGHLIGHT_BACKGROUND_COLOR = pychan.internal.DEFAULT_STYLE['default']['selection_color'] | |
45 | |
46 # the dynamicly created widgets have the name scheme prefix + layerid | |
47 LABEL_NAME_PREFIX = "select_" | |
48 | |
49 def __init__(self): | |
50 # Editor instance | |
51 self._editor = None | |
52 | |
53 # Plugin variables | |
54 self._enabled = False | |
55 | |
56 # Current mapview | |
57 self._mapview = None | |
58 | |
59 # Toolbar button to display LayerTool | |
60 self._action_show = None | |
61 | |
62 # GUI | |
63 self._layer_wizard = None | |
64 self._container = None | |
65 self._wrapper = None | |
66 self._remove_layer_button = None | |
67 self._create_layer_button = None | |
68 self._edit_layer_button = None | |
69 | |
70 #--- Plugin functions ---# | |
71 def enable(self): | |
72 """ Enable plugin """ | |
73 if self._enabled is True: | |
74 return | |
75 | |
76 # Fifedit plugin data | |
77 self._editor = scripts.editor.getEditor() | |
78 self._action_show = Action(u"LayerTool", checkable=True) | |
79 scripts.gui.action.activated.connect(self.toggle, sender=self._action_show) | |
80 self._editor._tools_menu.addAction(self._action_show) | |
81 | |
82 self._createGui() | |
83 | |
84 self.toggle() | |
85 | |
86 events.postMapShown.connect(self.update) | |
87 events.preMapClosed.connect(self._mapClosed) | |
88 | |
89 def disable(self): | |
90 """ Disable plugin """ | |
91 if self._enabled is False: | |
92 return | |
93 self._container.setDocked(False) | |
94 self._container.hide() | |
95 | |
96 events.postMapShown.disconnect(self.update) | |
97 events.preMapClosed.disconnect(self._mapClosed) | |
98 | |
99 self._editor._tools_menu.removeAction(self._action_show) | |
100 | |
101 def isEnabled(self): | |
102 """ Returns True if plugin is enabled """ | |
103 return self._enabled; | |
104 | |
105 def getName(self): | |
106 """ Return plugin name """ | |
107 return u"Layertool" | |
108 | |
109 #--- End plugin functions ---# | |
110 def _mapClosed(self): | |
111 self.update(mapview=None) | |
112 | |
113 | |
114 def showLayerWizard(self): | |
115 """ Show layer wizard """ | |
116 if not self._mapview: return | |
117 | |
118 if self._layer_wizard: self._layer_wizard._widget.hide() | |
119 self._layer_wizard = LayerDialog(self._editor.getEngine(), self._mapview.getMap(), callback=self._layerCreated) | |
120 | |
121 def showEditDialog(self): | |
122 """ Show layerdialog for active layer """ | |
123 if not self._mapview: return | |
124 layer = self.getActiveLayer() | |
125 if not layer: return | |
126 | |
127 if self._layer_wizard: self._layer_wizard._widget.hide() | |
128 self._layer_wizard = LayerDialog(self._editor.getEngine(), self._mapview.getMap(), layer=layer, callback=cbwa(self.update, self._mapview)) | |
129 | |
130 def clear(self): | |
131 """ Remove all subwrappers """ | |
132 self._wrapper.removeAllChildren() | |
133 | |
134 def update(self, mapview): | |
135 """ Update layertool with information from mapview | |
136 | |
137 We group one ToggleButton and one Label into a HBox, the main wrapper | |
138 itself is a VBox and we also capture both the Button and the Label to listen | |
139 for mouse actions | |
140 | |
141 @type event: object | |
142 @param event: pychan mouse event | |
143 """ | |
144 layers = [] | |
145 self._mapview = mapview | |
146 if self._mapview is not None: | |
147 layers = self._mapview.getMap().getLayers() | |
148 | |
149 self.clear() | |
150 | |
151 if len(layers) <= 0: | |
152 if not self._mapview: | |
153 layerid = "No map is open" | |
154 else: | |
155 layerid = "No layers" | |
156 subwrapper = pychan.widgets.HBox() | |
157 | |
158 layerLabel = pychan.widgets.Label() | |
159 layerLabel.text = unicode(layerid) | |
160 layerLabel.name = LayerTool.LABEL_NAME_PREFIX + layerid | |
161 subwrapper.addChild(layerLabel) | |
162 | |
163 self._wrapper.addChild(subwrapper) | |
164 | |
165 active_layer = self.getActiveLayer() | |
166 if active_layer: | |
167 active_layer = active_layer.getId() | |
168 for layer in reversed(layers): | |
169 layerid = layer.getId() | |
170 subwrapper = pychan.widgets.HBox() | |
171 | |
172 toggleVisibleButton = pychan.widgets.ToggleButton(hexpand=0, up_image="gui/icons/is_visible.png", down_image="gui/icons/is_visible.png", hover_image="gui/icons/is_visible.png") | |
173 toggleVisibleButton.name = "toggle_" + layerid | |
174 if layer.areInstancesVisible(): | |
175 toggleVisibleButton.toggled = True | |
176 toggleVisibleButton.capture(self.toggleLayerVisibility) | |
177 | |
178 layerLabel = pychan.widgets.Label() | |
179 layerLabel.text = unicode(layerid) | |
180 layerLabel.name = LayerTool.LABEL_NAME_PREFIX + layerid | |
181 layerLabel.capture(self.selectLayer,"mousePressed") | |
182 | |
183 if active_layer == layerid: | |
184 layerLabel.background_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR | |
185 layerLabel.foreground_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR | |
186 layerLabel.base_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR | |
187 | |
188 subwrapper.addChild(toggleVisibleButton) | |
189 subwrapper.addChild(layerLabel) | |
190 | |
191 self._wrapper.addChild(subwrapper) | |
192 | |
193 self._container.adaptLayout() | |
194 | |
195 def toggleLayerVisibility(self, event, widget): | |
196 """ Callback for ToggleButtons | |
197 | |
198 Toggle the chosen layer visible / invisible. If the active layer is hidden, | |
199 it will be deselected. | |
200 | |
201 @type event: object | |
202 @param event: pychan mouse event | |
203 @type widget: object | |
204 @param widget: the pychan widget where the event occurs, transports the layer id in it's name | |
205 """ | |
206 | |
207 layerid = widget.name[len(LayerTool.LABEL_NAME_PREFIX):] | |
208 | |
209 layer = self._mapview.getMap().getLayer(layerid) | |
210 active_layer = self.getActiveLayer() | |
211 if active_layer: | |
212 active_layer = active_layer.getId() | |
213 | |
214 if layer.areInstancesVisible(): | |
215 layer.setInstancesVisible(False) | |
216 else: | |
217 layer.setInstancesVisible(True) | |
218 | |
219 if active_layer == layerid: | |
220 self.resetSelection() | |
221 | |
222 def getActiveLayer(self): | |
223 """ Returns the active layer """ | |
224 if self._mapview: | |
225 return self._mapview.getController()._layer | |
226 | |
227 def selectLayer(self, event, widget=None, layerid=None): | |
228 """ Callback for Labels | |
229 | |
230 We hand the layerid over to the mapeditor module to select a | |
231 new active layer | |
232 | |
233 Additionally, we mark the active layer widget (changing base color) and reseting the previous one | |
234 | |
235 @type event: object | |
236 @param event: pychan mouse event | |
237 @type widget: object | |
238 @param widget: the pychan widget where the event occurs, transports the layer id in it's name | |
239 @type layerid: string | |
240 @param layerid: the layer id | |
241 """ | |
242 | |
243 if not widget and not layerid: | |
244 print "No layer ID or widget passed to LayerTool.selectLayer" | |
245 return | |
246 | |
247 if widget is not None: | |
248 layerid = widget.name[len(LayerTool.LABEL_NAME_PREFIX):] | |
249 | |
250 self.resetSelection() | |
251 | |
252 widget.background_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR | |
253 widget.foreground_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR | |
254 widget.base_color = LayerTool.HIGHLIGHT_BACKGROUND_COLOR | |
255 | |
256 self._mapview.getController().selectLayer(layerid) | |
257 | |
258 def resetSelection(self): | |
259 """ Deselects selected layer """ | |
260 previous_active_layer = self.getActiveLayer() | |
261 if previous_active_layer is not None: | |
262 previous_layer_id = previous_active_layer.getId() | |
263 previous_active_widget = self._container.findChild(name=LayerTool.LABEL_NAME_PREFIX + previous_layer_id) | |
264 previous_active_widget.background_color = LayerTool.DEFAULT_BACKGROUND_COLOR | |
265 previous_active_widget.foreground_color = LayerTool.DEFAULT_BACKGROUND_COLOR | |
266 previous_active_widget.base_color = LayerTool.DEFAULT_BACKGROUND_COLOR | |
267 previous_active_widget.text = unicode(previous_layer_id) | |
268 | |
269 self._mapview.getController().selectLayer(None) | |
270 | |
271 | |
272 def removeSelectedLayer(self): | |
273 """ Deletes the selected layer """ | |
274 if not self._mapview: return | |
275 | |
276 if self._mapview.getMap().getNumLayers() <= 1: | |
277 print "Can't remove the last layer" | |
278 return | |
279 | |
280 layer = self.getActiveLayer() | |
281 if not layer: return | |
282 | |
283 self.resetSelection() | |
284 | |
285 map = self._mapview.getMap() | |
286 | |
287 # FIFE will crash if we try to delete the layer which is in use by a camera | |
288 # so we will set the camera to another layer instead | |
289 for cam in self._editor.getEngine().getView().getCameras(): | |
290 if cam.getLocationRef().getMap().getId() != map.getId(): | |
291 continue | |
292 | |
293 if cam.getLocation().getLayer().getId() != layer.getId(): | |
294 continue | |
295 | |
296 for l in map.getLayers(): | |
297 if l.getId() == layer.getId(): | |
298 continue | |
299 | |
300 cam.getLocationRef().setLayer(l) | |
301 break | |
302 | |
303 map.deleteLayer(layer) | |
304 self.update(self._mapview) | |
305 | |
306 def toggle(self): | |
307 """ Toggles the layertool visible / invisible and sets | |
308 dock status | |
309 """ | |
310 if self._container.isVisible() or self._container.isDocked(): | |
311 self._container.setDocked(False) | |
312 self._container.hide() | |
313 | |
314 self._action_show.setChecked(False) | |
315 else: | |
316 self._container.show() | |
317 self._action_show.setChecked(True) | |
318 self._adjustPosition() | |
319 | |
320 def _createGui(self): | |
321 """ Create the basic gui container """ | |
322 self._container = pychan.loadXML('gui/layertool.xml') | |
323 self._wrapper = self._container.findChild(name="layers_wrapper") | |
324 self._remove_layer_button = self._container.findChild(name="remove_layer_button") | |
325 self._create_layer_button = self._container.findChild(name="add_layer_button") | |
326 self._edit_layer_button = self._container.findChild(name="edit_layer_button") | |
327 | |
328 self._remove_layer_button.capture(self.removeSelectedLayer) | |
329 self._remove_layer_button.capture(cbwa(self._editor.getStatusBar().showTooltip, self._remove_layer_button.helptext), 'mouseEntered') | |
330 self._remove_layer_button.capture(self._editor.getStatusBar().hideTooltip, 'mouseExited') | |
331 | |
332 self._create_layer_button.capture(self.showLayerWizard) | |
333 self._create_layer_button.capture(cbwa(self._editor.getStatusBar().showTooltip, self._create_layer_button.helptext), 'mouseEntered') | |
334 self._create_layer_button.capture(self._editor.getStatusBar().hideTooltip, 'mouseExited') | |
335 | |
336 self._edit_layer_button.capture(self.showEditDialog) | |
337 self._edit_layer_button.capture(cbwa(self._editor.getStatusBar().showTooltip, self._edit_layer_button.helptext), 'mouseEntered') | |
338 self._edit_layer_button.capture(self._editor.getStatusBar().hideTooltip, 'mouseExited') | |
339 | |
340 self.update(None) | |
341 | |
342 def _adjustPosition(self): | |
343 """ Adjusts the position of the container - we don't want to | |
344 let the window appear at the center of the screen. | |
345 (new default position: left, beneath the tools window) | |
346 """ | |
347 self._container.position = (50, 200) | |
348 | |
349 def _layerCreated(self, layer): | |
350 self.update(self._mapview) | |
351 self.selectLayer(None, self._wrapper.findChild(name=LayerTool.LABEL_NAME_PREFIX + layer.getId())) | |
352 | |
353 | |
354 |