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