Mercurial > fife-parpg
comparison clients/editor/plugins/mapeditor.py @ 108:0c017b8e4ab2
Added an undo feature to the map editor. Just press u to undo insert placement/removals.
author | jwt@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sat, 26 Jul 2008 03:04:03 +0000 |
parents | adf0f2b6d1b0 |
children | c94c76346027 |
comparison
equal
deleted
inserted
replaced
107:860d81602a2a | 108:0c017b8e4ab2 |
---|---|
156 cbwa(self._setMode, INSERTING), cbwa(self._setMode, REMOVING), | 156 cbwa(self._setMode, INSERTING), cbwa(self._setMode, REMOVING), |
157 self._statusbar.showTooltip, self._statusbar.hideTooltip) | 157 self._statusbar.showTooltip, self._statusbar.hideTooltip) |
158 self._toolbar.show() | 158 self._toolbar.show() |
159 self._setMode(NOTHING_LOADED) | 159 self._setMode(NOTHING_LOADED) |
160 | 160 |
161 self._undoStack = [] | |
162 self._undo = False # tracks whether current action is an undo | |
163 | |
161 def _assert(self, statement, msg): | 164 def _assert(self, statement, msg): |
162 if not statement: | 165 if not statement: |
163 print msg | 166 print msg |
164 raise EditorLogicError(msg) | 167 raise EditorLogicError(msg) |
165 | 168 |
244 self._selection = self._layer.getCellGrid().toLayerCoordinates(self._selection) | 247 self._selection = self._layer.getCellGrid().toLayerCoordinates(self._selection) |
245 loc.setLayerCoordinates(self._selection) | 248 loc.setLayerCoordinates(self._selection) |
246 fife.CellSelectionRenderer.getInstance(self._camera).selectLocation(loc) | 249 fife.CellSelectionRenderer.getInstance(self._camera).selectLocation(loc) |
247 return loc | 250 return loc |
248 | 251 |
249 def _getInstancesFromSelection(self, top_only): | 252 def _getInstancesFromPosition(self, position, top_only): |
250 self._assert(self._layer, 'No layer assigned in _getInstancesFromSelection') | 253 self._assert(self._layer, 'No layer assigned in _getInstancesFromPosition') |
251 self._assert(self._selection, 'No selection assigned in _getInstancesFromSelection') | 254 self._assert(position, 'No position assigned in _getInstancesFromPosition') |
252 self._assert(self._camera, 'No camera assigned in _getInstancesFromSelection') | 255 self._assert(self._camera, 'No camera assigned in _getInstancesFromPosition') |
253 | 256 |
254 loc = fife.Location(self._layer) | 257 loc = fife.Location(self._layer) |
255 if type(self._selection) == fife.ExactModelCoordinate: | 258 if type(position) == fife.ExactModelCoordinate: |
256 loc.setExactLayerCoordinates(self._selection) | 259 loc.setExactLayerCoordinates(position) |
257 else: | 260 else: |
258 loc.setLayerCoordinates(self._selection) | 261 loc.setLayerCoordinates(position) |
259 instances = self._camera.getMatchingInstances(loc) | 262 instances = self._camera.getMatchingInstances(loc) |
260 if top_only and (len(instances) > 0): | 263 if top_only and (len(instances) > 0): |
261 instances = [instances[0]] | 264 instances = [instances[0]] |
262 return instances | 265 return instances |
263 | 266 |
264 def _placeInstance(self): | 267 def undo(self): |
268 if self._undoStack != []: | |
269 # execute inverse of last action | |
270 self._undo = True | |
271 self._undoStack.pop()() | |
272 self._undo = False | |
273 | |
274 def _placeInstance(self,position,object): | |
265 mname = '_placeInstance' | 275 mname = '_placeInstance' |
266 self._assert(self._object, 'No object assigned in %s' % mname) | 276 self._assert(object, 'No object assigned in %s' % mname) |
267 self._assert(self._selection, 'No selection assigned in %s' % mname) | 277 self._assert(position, 'No position assigned in %s' % mname) |
268 self._assert(self._layer, 'No layer assigned in %s' % mname) | 278 self._assert(self._layer, 'No layer assigned in %s' % mname) |
269 self._assert(self._mode == INSERTING, 'No mode is not INSERTING in %s (is instead %s)' % (mname, str(self._mode))) | 279 |
280 print 'Placing instance of ' + object.getId() + ' at ' + str(position) | |
281 print object | |
270 | 282 |
271 # don't place repeat instances | 283 # don't place repeat instances |
272 for i in self._getInstancesFromSelection(False): | 284 for i in self._getInstancesFromPosition(position, False): |
273 if i.getObject().getId() == self._object.getId(): | 285 if i.getObject().getId() == object.getId(): |
274 print 'Warning: attempt to place duplicate instance of object %s. Ignoring request.' % self._object.getId() | 286 print 'Warning: attempt to place duplicate instance of object %s. Ignoring request.' % object.getId() |
275 return | 287 return |
276 | 288 |
277 inst = self._layer.createInstance(self._object, self._selection) | 289 inst = self._layer.createInstance(object, position) |
278 fife.InstanceVisual.create(inst) | 290 fife.InstanceVisual.create(inst) |
279 | 291 if not self._undo: |
280 def _removeInstances(self): | 292 self._undoStack.append(lambda: self._removeInstances(position)) |
293 | |
294 def _removeInstances(self,position): | |
281 mname = '_removeInstances' | 295 mname = '_removeInstances' |
282 self._assert(self._selection, 'No selection assigned in %s' % mname) | 296 self._assert(position, 'No position assigned in %s' % mname) |
283 self._assert(self._layer, 'No layer assigned in %s' % mname) | 297 self._assert(self._layer, 'No layer assigned in %s' % mname) |
284 self._assert(self._mode == REMOVING, 'Mode is not REMOVING in %s (is instead %s)' % (mname, str(self._mode))) | 298 |
285 | 299 for i in self._getInstancesFromPosition(position, top_only=True): |
286 for i in self._getInstancesFromSelection(top_only=True): | 300 print 'Deleting instance ' + str(i) + ' at ' + str(position) |
287 print "deleting " + str(i) | 301 if not self._undo: |
302 print '>>> ' + i.getObject().getId() | |
303 print '>>> ' + str(i.getObject()) | |
304 object = i.getObject() | |
305 self._undoStack.append(lambda: self._placeInstance(position,object)) | |
288 self._layer.deleteInstance(i) | 306 self._layer.deleteInstance(i) |
289 | 307 |
290 def _moveInstances(self): | 308 def _moveInstances(self): |
291 mname = '_removeInstances' | 309 mname = '_moveInstances' |
292 self._assert(self._selection, 'No selection assigned in %s' % mname) | 310 self._assert(self._selection, 'No selection assigned in %s' % mname) |
293 self._assert(self._layer, 'No layer assigned in %s' % mname) | 311 self._assert(self._layer, 'No layer assigned in %s' % mname) |
294 self._assert(self._mode == MOVING, 'Mode is not MOVING in %s (is instead %s)' % (mname, str(self._mode))) | 312 self._assert(self._mode == MOVING, 'Mode is not MOVING in %s (is instead %s)' % (mname, str(self._mode))) |
295 | 313 |
296 loc = fife.Location(self._layer) | 314 loc = fife.Location(self._layer) |
307 def _rotateInstances(self): | 325 def _rotateInstances(self): |
308 mname = '_rotateInstances' | 326 mname = '_rotateInstances' |
309 self._assert(self._selection, 'No selection assigned in %s' % mname) | 327 self._assert(self._selection, 'No selection assigned in %s' % mname) |
310 self._assert(self._layer, 'No layer assigned in %s' % mname) | 328 self._assert(self._layer, 'No layer assigned in %s' % mname) |
311 | 329 |
312 for i in self._getInstancesFromSelection(top_only=True): | 330 for i in self._getInstancesFromPosition(self._selection, top_only=True): |
313 i.setRotation((i.getRotation() + 90) % 360) | 331 i.setRotation((i.getRotation() + 90) % 360) |
314 ## Surprisingly, the following "snap-to-rotation" code is actually incorrect. Object | 332 ## Surprisingly, the following "snap-to-rotation" code is actually incorrect. Object |
315 ## rotation is independent of the camera, whereas the choice of an actual rotation image | 333 ## rotation is independent of the camera, whereas the choice of an actual rotation image |
316 ## depends very much on how the camera is situated. For example, suppose an object has | 334 ## depends very much on how the camera is situated. For example, suppose an object has |
317 ## rotations defined for 45,135,225,315. And suppose the camera position results in an | 335 ## rotations defined for 45,135,225,315. And suppose the camera position results in an |
359 self._dragy = evt.getY() | 377 self._dragy = evt.getY() |
360 else: | 378 else: |
361 if self._camera: | 379 if self._camera: |
362 self._selectCell(evt.getX(), evt.getY(), self._shiftdown) | 380 self._selectCell(evt.getX(), evt.getY(), self._shiftdown) |
363 if self._mode == VIEWING: | 381 if self._mode == VIEWING: |
364 self._instances = self._getInstancesFromSelection(top_only=True) | 382 self._instances = self._getInstancesFromPosition(self._selection, top_only=True) |
365 elif self._mode == INSERTING: | 383 elif self._mode == INSERTING: |
366 self._placeInstance() | 384 self._placeInstance(self._selection,self._object) |
367 elif self._mode == REMOVING: | 385 elif self._mode == REMOVING: |
368 self._removeInstances() | 386 self._removeInstances(self._selection) |
369 elif self._mode == MOVING: | 387 elif self._mode == MOVING: |
370 self._instances = self._getInstancesFromSelection(top_only=True) | 388 self._instances = self._getInstancesFromPosition(self._selection, top_only=True) |
371 else: | 389 else: |
372 self._setMode(self._mode) # refresh status | 390 self._setMode(self._mode) # refresh status |
373 | 391 |
374 def mouseDragged(self, evt): | 392 def mouseDragged(self, evt): |
375 if evt.isConsumedByWidgets(): | 393 if evt.isConsumedByWidgets(): |
381 self._dragx = evt.getX() | 399 self._dragx = evt.getX() |
382 self._dragy = evt.getY() | 400 self._dragy = evt.getY() |
383 else: | 401 else: |
384 if self._mode == INSERTING: | 402 if self._mode == INSERTING: |
385 self._selectCell(evt.getX(), evt.getY()) | 403 self._selectCell(evt.getX(), evt.getY()) |
386 self._placeInstance() | 404 self._placeInstance(self._selection,self._object) |
387 elif self._mode == REMOVING: | 405 elif self._mode == REMOVING: |
388 self._selectCell(evt.getX(), evt.getY()) | 406 self._selectCell(evt.getX(), evt.getY()) |
389 self._removeInstances() | 407 self._removeInstances(self._selection) |
390 elif self._mode == MOVING and self._instances: | 408 elif self._mode == MOVING and self._instances: |
391 self._selectCell(evt.getX(), evt.getY(), self._shiftdown) | 409 self._selectCell(evt.getX(), evt.getY(), self._shiftdown) |
392 self._moveInstances() | 410 self._moveInstances() |
393 | 411 |
394 def mouseReleased(self, evt): | 412 def mouseReleased(self, evt): |
465 if self._selection: | 483 if self._selection: |
466 self._rotateInstances() | 484 self._rotateInstances() |
467 | 485 |
468 elif keystr == 'o': | 486 elif keystr == 'o': |
469 self.changeRotation() | 487 self.changeRotation() |
488 | |
489 elif keystr == 'u': | |
490 self.undo() | |
470 | 491 |
471 def keyReleased(self, evt): | 492 def keyReleased(self, evt): |
472 keyval = evt.getKey().getValue() | 493 keyval = evt.getKey().getValue() |
473 if keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL): | 494 if keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL): |
474 self._ctrldown = False | 495 self._ctrldown = False |