Mercurial > fife-parpg
view clients/editor/plugins/ObjectSelector.py @ 295:faabfaf25f15
Removed the deletion of the search space from the the RoutePatherSearch class. This will fix the path finding so it now will calculate paths correctly. It should not be deleting the search space because it does not own it, it is only using it for calculations. Need to investigate further as to why the memory consumption continually increases when running UH. Also removed the need to store a local pointer in RoutePatherSearch to the singleton instance of a Heuristic, this will eliminate the possibly of having a dangling pointer or deleting something that it shouldn't.
author | vtchill@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Fri, 03 Jul 2009 05:11:54 +0000 |
parents | 51cc05d862f2 |
children | 6add14ebe9f5 |
line wrap: on
line source
# coding: utf-8 import pychan from pychan import widgets, tools, attrs, internal from pychan.tools import callbackWithArguments import scripts import scripts.plugin as plugin from scripts.events import * from scripts.gui.action import Action import fife from fife import Color # TODO: # - Better event handling _DEFAULT_BASE_COLOR = internal.DEFAULT_STYLE['default']['base_color'] _DEFAULT_SELECTION_COLOR = internal.DEFAULT_STYLE['default']['selection_color'] _DEFAULT_COLOR_STEP = Color(10, 10, 10) class ObjectIcon(widgets.VBox): """ The ObjectIcon is used to represent the object in the object selector. """ ATTRIBUTES = widgets.VBox.ATTRIBUTES + [ attrs.Attr("text"), attrs.Attr("image"), attrs.BoolAttr("selected") ] def __init__(self,callback,**kwargs): super(ObjectIcon,self).__init__(**kwargs) self.callback = callback self.capture(self._mouseEntered, "mouseEntered") self.capture(self._mouseExited, "mouseExited") self.capture(self._mouseClicked, "mouseClicked") vbox = widgets.VBox(padding=3) # Icon self.icon = widgets.Icon(**kwargs) self.addChild(self.icon) # Label hbox = widgets.HBox(padding=1) self.addChild(hbox) self.label = widgets.Label(**kwargs) hbox.addChild(self.label) def _setText(self, text): self.label.text = text def _getText(self): return self.label.text text = property(_getText, _setText) def _setImage(self, image): self.icon.image = image def _getImage(self): return self.icon.image image = property(_getImage, _setImage) def _setSelected(self, enabled): if isinstance(self.parent, ObjectIconList): if enabled == True: self.parent.selected_item = self else: if self.selected: self.parent.selected_item = None if self.selected: self.base_color = _DEFAULT_SELECTION_COLOR else: self.base_color = _DEFAULT_BASE_COLOR def _isSelected(self): if isinstance(self.parent, ObjectIconList): return self == self.parent.selected_item return False selected = property(_isSelected, _setSelected) #--- Event handling ---# def _mouseEntered(self, event): self.base_color += _DEFAULT_COLOR_STEP def _mouseExited(self, event): self.base_color -= _DEFAULT_COLOR_STEP def _mouseClicked(self, event): self.selected = True self.callback() class ObjectIconList(widgets.VBox): ATTRIBUTES = widgets.VBox.ATTRIBUTES def __init__(self,**kwargs): super(ObjectIconList, self).__init__(max_size=(5000,500000), **kwargs) self.base_color = self.background_color self.capture(self._keyPressed, "keyPressed") #self.capture(self._keyPressed, "keyReleased") self._selectedItem = None self.is_focusable = True def _keyPressed(self, event): print "KeyEvent", event def clear(self): for c in reversed(self.children): self.removeChild(c) def _setSelectedItem(self, item): if isinstance(item, ObjectIcon) or item is None: if self._selectedItem is not None: tmp = self._selectedItem self._selectedItem = item tmp.selected = False else: self._selectedItem = item def _getSelectedItem(self): return self._selectedItem selected_item = property(_getSelectedItem, _setSelectedItem) class ObjectSelector(plugin.Plugin): """The ObjectSelector class offers a gui Widget that let's you select the object you wish to use to in the editor. @param engine: fife instance @param map: fife.Map instance containing your map @param selectNotify: callback function used to tell the editor you selected an object. """ def __init__(self): self.editor = None self.engine = None self.mode = 'list' # Other mode is 'preview' self._enabled = False def enable(self): if self._enabled is True: return self.editor = scripts.editor.getEditor() self.engine = self.editor.getEngine() self._showAction = Action(u"Object selector", checkable=True) scripts.gui.action.activated.connect(self.toggle, sender=self._showAction) self.editor._toolsMenu.addAction(self._showAction) events.postMapShown.connect(self.update_namespace) events.onObjectSelected.connect(self.setPreview) self.buildGui() def disable(self): if self._enabled is False: return self.gui.hide() self.removeAllChildren() events.postMapShown.disconnect(self.update_namespace) events.onObjectSelected.disconnect(self.setPreview) self.editor._toolsMenu.removeAction(self._showAction) def isEnabled(self): return self._enabled; def getName(self): return "Object selector" def buildGui(self): self.gui = pychan.loadXML('gui/objectselector.xml') # Add search field self._searchfield = self.gui.findChild(name="searchField") self._searchfield.capture(self._search) self._searchfield.capture(self._search, "keyPressed") self.gui.findChild(name="searchButton").capture(self._search) # Add the drop down with list of namespaces self.namespaces = self.gui.findChild(name="namespaceDropdown") self.namespaces.items = self.engine.getModel().getNamespaces() self.namespaces.selected = 0 # TODO: Replace with SelectionEvent, once pychan supports it self.namespaces.capture(self.update_namespace, "action") self.namespaces.capture(self.update_namespace, "mouseWheelMovedUp") self.namespaces.capture(self.update_namespace, "mouseWheelMovedDown") self.namespaces.capture(self.update_namespace, "keyReleased") # Object list self.mainScrollArea = self.gui.findChild(name="mainScrollArea") self.objects = None if self.mode == 'list': self.setTextList() else: # Assuming self.mode is 'preview' self.setImageList() # Action buttons self.gui.findChild(name="toggleModeButton").capture(self.toggleMode) self.gui.findChild(name="closeButton").capture(self.hide) # Preview area self.gui.findChild(name="previewScrollArea").background_color = self.gui.base_color self.preview = self.gui.findChild(name="previewIcon") def toggleMode(self): if self.mode == 'list': self.setImageList() self.mode = 'preview' elif self.mode == 'preview': self.setTextList() self.mode = 'list' self.update() def setImageList(self): """Sets the mainScrollArea to contain a Vbox that can be used to fill in preview Images""" if self.objects is not None: self.mainScrollArea.removeChild(self.objects) self.objects = ObjectIconList(name='list', size=(200,1000)) self.objects.base_color = self.mainScrollArea.background_color self.mainScrollArea.addChild(self.objects) def setTextList(self): """Sets the mainScrollArea to contain a List that can be used to fill in Object names/paths""" if self.objects is not None: self.mainScrollArea.removeChild(self.objects) self.objects = widgets.ListBox(name='list') self.objects.capture(self.listEntrySelected) self.mainScrollArea.addChild(self.objects) def _search(self): self.search(self._searchfield.text) def search(self, str): results = [] # Format search terms terms = [term.lower() for term in str.split()] # Search if len(terms) > 0: namespaces = self.engine.getModel().getNamespaces() for namesp in namespaces: objects = self.engine.getModel().getObjects(namesp) for obj in objects: doAppend = True for term in terms: if obj.getId().lower().find(term) < 0: doAppend = False break if doAppend: results.append(obj) else: results = None if self.mode == 'list': self.fillTextList(results) elif self.mode == 'preview': self.fillPreviewList(results) def fillTextList(self, objects=None): if objects is None: if self.namespaces.selected_item is None: return objects = self.engine.getModel().getObjects(self.namespaces.selected_item) class _ListItem: def __init__( self, name, namespace ): self.name = name self.namespace = namespace def __str__( self ): return self.name if self.namespaces.selected_item: self.objects.items = [_ListItem(obj.getId(), obj.getNamespace()) for obj in objects] if not self.objects.selected_item: self.objects.selected = 0 self.listEntrySelected() def listEntrySelected(self): """This function is used as callback for the TextList.""" if self.objects.selected_item: object_id = self.objects.selected_item.name namespace = self.objects.selected_item.namespace obj = self.engine.getModel().getObject(object_id, namespace) self.objectSelected(obj) def fillPreviewList(self, objects=None): self.objects.clear() if objects is None: if self.namespaces.selected_item is None: return objects = self.engine.getModel().getObjects(self.namespaces.selected_item) for obj in objects: image = self._getImage(obj) if image is None: print 'No image available for selected object' image = "" callback = tools.callbackWithArguments(self.objectSelected, obj) icon = ObjectIcon(callback=callback, image=image, text=unicode(obj.getId())) self.objects.addChild(icon) if len(objects)>0: objects[0].selected = True self.objectSelected(objects[0]) def objectSelected(self, obj): """This is used as callback function to notify the editor that a new object has been selected. @param obj: fife.Object instance""" self.setPreview(obj) self.gui.adaptLayout() events.onObjectSelected.send(sender=self, object=obj) self.objects.adaptLayout() self.gui.adaptLayout() # Set preview image def setPreview(self, object): self.preview.image = self._getImage(object) height = self.preview.image.getHeight(); if height > 200: height = 200 self.preview.parent.max_height = height def update_namespace(self): self.namespaces.items = self.engine.getModel().getNamespaces() if not self.namespaces.selected_item: self.namespaces.selected = 0 if self.mode == 'list': self.setTextList() elif self.mode == 'preview': self.setImageList() self.update() def update(self): if self.mode == 'list': self.fillTextList() elif self.mode == 'preview': self.fillPreviewList() self.gui.adaptLayout() def _getImage(self, obj): """ Returns an image for the given object. @param: fife.Object for which an image is to be returned @return: fife.GuiImage""" visual = None try: visual = obj.get2dGfxVisual() except: print 'Visual Selection created for type without a visual?' raise # Try to find a usable image index = visual.getStaticImageIndexByAngle(0) image = None # if no static image available, try default action if index == -1: action = obj.getDefaultAction() if action: animation_id = action.get2dGfxVisual().getAnimationIndexByAngle(0) animation = self.engine.getAnimationPool().getAnimation(animation_id) image = animation.getFrameByTimestamp(0) index = image.getPoolId() # Construct the new GuiImage that is to be returned if index != -1: image = fife.GuiImage(index, self.engine.getImagePool()) return image def show(self): self.update_namespace() self.gui.show() self._showAction.setChecked(True) def hide(self): self.gui.setDocked(False) self.gui.hide() self._showAction.setChecked(False) def toggle(self): if self.gui.isVisible() or self.gui.isDocked(): self.hide() else: self.show()