class PlayerSpawnPositionTool(PlayerPositionTool): surfaceBuild = True toolIconName = "playerspawn" tooltipText = "Move Spawn Point" def __init__(self, *args): PlayerPositionTool.__init__(self, *args) self.optionsPanel = PlayerSpawnPositionOptions(self) def toolEnabled(self): return self.editor.level.dimNo == 0 def showPanel(self): self.panel = Panel() button = Button("Goto Spawn", action=self.gotoSpawn) self.panel.add(button) self.panel.shrink_wrap() self.panel.left = self.editor.left self.panel.centery = self.editor.centery self.editor.add(self.panel) def gotoSpawn(self): cv = self.editor.mainViewport.cameraVector pos = self.editor.level.playerSpawnPosition() pos = map(lambda p, c: p - c * 5, pos, cv) self.editor.mainViewport.cameraPosition = pos self.editor.mainViewport.stopMoving() @property def statusText(self): return "Click to set the spawn position." spawnProtection = SpawnSettings.spawnProtection.configProperty() def drawToolReticle(self): pos, direction = self.editor.blockFaceUnderCursor x, y, z = map(lambda p, d: p + d, pos, direction) color = (1.0, 1.0, 1.0, 0.5) if isinstance(self.editor.level, pymclevel.MCInfdevOldLevel) and self.spawnProtection: if not positionValid(self.editor.level, (x, y, z)): color = (1.0, 0.0, 0.0, 0.5) GL.glColor(*color) GL.glEnable(GL.GL_BLEND) self.drawCage(x, y, z) self.drawCharacterHead(x + 0.5, y + 0.5, z + 0.5) GL.glDisable(GL.GL_BLEND) GL.glEnable(GL.GL_DEPTH_TEST) self.drawCage(x, y, z) self.drawCharacterHead(x + 0.5, y + 0.5, z + 0.5) color2 = map(lambda a: a * 0.4, color) drawTerrainCuttingWire(BoundingBox((x, y, z), (1, 1, 1)), color2, color) GL.glDisable(GL.GL_DEPTH_TEST) def _drawToolMarkers(self): x, y, z = self.editor.level.playerSpawnPosition() GL.glColor(1.0, 1.0, 1.0, 1.0) GL.glEnable(GL.GL_DEPTH_TEST) self.drawCage(x, y, z) self.drawCharacterHead( x + 0.5, y + 0.5 + 0.125 * numpy.sin(self.editor.frames * 0.05), z + 0.5) GL.glDisable(GL.GL_DEPTH_TEST) def drawCage(self, x, y, z): cageTexVerts = numpy.array( pymclevel.MCInfdevOldLevel.materials.blockTextures[52, 0]) pixelScale = 0.5 if self.editor.level.materials.name in ( "Pocket", "Alpha") else 1.0 texSize = 16 * pixelScale cageTexVerts *= pixelScale cageTexVerts = numpy.array([((tx, ty), (tx + texSize, ty), (tx + texSize, ty + texSize), (tx, ty + texSize)) for (tx, ty) in cageTexVerts], dtype='float32') GL.glEnable(GL.GL_ALPHA_TEST) drawCube(BoundingBox((x, y, z), (1, 1, 1)), texture=pymclevel.alphaMaterials.terrainTexture, textureVertices=cageTexVerts) GL.glDisable(GL.GL_ALPHA_TEST) @alertException def mouseDown(self, evt, pos, direction): pos = map(lambda p, d: p + d, pos, direction) op = PlayerSpawnMoveOperation(self, pos) try: op.perform() self.editor.addOperation(op) self.editor.addUnsavedEdit() self.markerList.invalidate() except SpawnPositionInvalid, e: if "Okay" != ask(str(e), responses=["Okay", "Fix it for me!"]): level = self.editor.level status = "" if not okayAt63(level, pos): level.setBlockAt(pos[0], 63, pos[2], 1) status += "Block added at y=63.\n" if 59 < pos[1] < 63: pos[1] = 63 status += "Spawn point moved upward to y=63.\n" if not okayAboveSpawn(level, pos): if pos[1] > 63 or pos[1] < 59: lpos = (pos[0], pos[1] - 1, pos[2]) if level.blockAt(*pos) == 0 and level.blockAt( *lpos) != 0 and okayAboveSpawn(level, lpos): pos = lpos status += "Spawn point shifted down by one block.\n" if not okayAboveSpawn(level, pos): for i in range(1, 4): level.setBlockAt(pos[0], pos[1] + i, pos[2], 0) status += "Blocks above spawn point cleared.\n" self.editor.invalidateChunks([(pos[0] // 16, pos[2] // 16)]) op = PlayerSpawnMoveOperation(self, pos) try: op.perform() except SpawnPositionInvalid, e: alert(str(e)) return self.editor.addOperation(op) self.editor.addUnsavedEdit() self.markerList.invalidate() if len(status): alert("Spawn point fixed. Changes: \n\n" + status)
class PlayerSpawnPositionTool(PlayerPositionTool): surfaceBuild = True toolIconName = "playerspawn" tooltipText = "Move Spawn Point\nRight-click for options" def __init__(self, *args): PlayerPositionTool.__init__(self, *args) self.optionsPanel = PlayerSpawnPositionOptions(self) def toolEnabled(self): return self.editor.level.dimNo == 0 def showPanel(self): self.panel = Panel(name='Panel.PlayerSpawnPositionTool') button = Button("Goto Spawn", action=self.gotoSpawn) self.panel.add(button) self.panel.shrink_wrap() self.panel.left = self.editor.left self.panel.centery = self.editor.centery self.editor.add(self.panel) def gotoSpawn(self): cv = self.editor.mainViewport.cameraVector pos = self.editor.level.playerSpawnPosition() pos = map(lambda p, c: p - c * 5, pos, cv) self.editor.mainViewport.cameraPosition = pos self.editor.mainViewport.stopMoving() @property def statusText(self): return "Click to set the spawn position." spawnProtection = config.spawn.spawnProtection.property() def drawToolReticle(self): pos, direction = self.editor.blockFaceUnderCursor x, y, z = map(lambda p, d: p + d, pos, direction) color = (1.0, 1.0, 1.0, 0.5) if isinstance(self.editor.level, pymclevel.MCInfdevOldLevel) and self.spawnProtection: if not positionValid(self.editor.level, (x, y, z)): color = (1.0, 0.0, 0.0, 0.5) GL.glColor(*color) GL.glEnable(GL.GL_BLEND) self.drawCage(x, y, z) self.drawCharacterHead(x + 0.5, y + 0.5, z + 0.5) GL.glDisable(GL.GL_BLEND) GL.glEnable(GL.GL_DEPTH_TEST) self.drawCage(x, y, z) self.drawCharacterHead(x + 0.5, y + 0.5, z + 0.5) color2 = map(lambda a: a * 0.4, color) drawTerrainCuttingWire(BoundingBox((x, y, z), (1, 1, 1)), color2, color) GL.glDisable(GL.GL_DEPTH_TEST) def _drawToolMarkers(self): x, y, z = self.editor.level.playerSpawnPosition() GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) GL.glEnable(GL.GL_BLEND) color = config.selectionColors.black.get() + (0.35,) GL.glColor(*color) GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE) GL.glLineWidth(2.0) drawCube(FloatBox((x, y, z), (1, 1, 1))) GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL) drawCube(FloatBox((x, y, z), (1, 1, 1))) GL.glDisable(GL.GL_BLEND) GL.glEnable(GL.GL_DEPTH_TEST) GL.glColor(1.0, 1.0, 1.0, 1.0) self.drawCage(x, y, z) self.drawCharacterHead(x + 0.5, y + 0.5 + 0.125 * numpy.sin(self.editor.frames * 0.05), z + 0.5) GL.glDisable(GL.GL_DEPTH_TEST) def drawCage(self, x, y, z): cageTexVerts = numpy.array(pymclevel.MCInfdevOldLevel.materials.blockTextures[52, 0]) pixelScale = 0.5 if self.editor.level.materials.name in ("Pocket", "Alpha") else 1.0 texSize = 16 * pixelScale cageTexVerts = cageTexVerts.astype(float) * pixelScale cageTexVerts = numpy.array( [((tx, ty), (tx + texSize, ty), (tx + texSize, ty + texSize), (tx, ty + texSize)) for (tx, ty) in cageTexVerts], dtype='float32') GL.glEnable(GL.GL_ALPHA_TEST) drawCube(BoundingBox((x, y, z), (1, 1, 1)), texture=pymclevel.alphaMaterials.terrainTexture, textureVertices=cageTexVerts) GL.glDisable(GL.GL_ALPHA_TEST) @alertException def mouseDown(self, evt, pos, direction): pos = map(lambda p, d: p + d, pos, direction) op = PlayerSpawnMoveOperation(self, pos) try: self.editor.addOperation(op) if op.canUndo: self.editor.addUnsavedEdit() self.markerList.invalidate() except SpawnPositionInvalid, e: if "Okay" != ask(str(e), responses=["Okay", "Fix it for me!"]): level = self.editor.level status = "" if not okayAt63(level, pos): level.setBlockAt(pos[0], 63, pos[2], 1) status += _("Block added at y=63.\n") if 59 < pos[1] < 63: pos[1] = 63 status += _("Spawn point moved upward to y=63.\n") if not okayAboveSpawn(level, pos): if pos[1] > 63 or pos[1] < 59: lpos = (pos[0], pos[1] - 1, pos[2]) if level.blockAt(*pos) == 0 and level.blockAt(*lpos) != 0 and okayAboveSpawn(level, lpos): pos = lpos status += _("Spawn point shifted down by one block.\n") if not okayAboveSpawn(level, pos): for i in xrange(1, 4): level.setBlockAt(pos[0], pos[1] + i, pos[2], 0) status += _("Blocks above spawn point cleared.\n") self.editor.invalidateChunks([(pos[0] // 16, pos[2] // 16)]) op = PlayerSpawnMoveOperation(self, pos) try: self.editor.addOperation(op) if op.canUndo: self.editor.addUnsavedEdit() self.markerList.invalidate() except SpawnPositionInvalid, e: alert(str(e)) return if len(status): alert(_("Spawn point fixed. Changes: \n\n") + status)
def askAssignKey(self, configKey, labelString=None): if not self.isConfigKey(configKey): self.enter = 0 return panel = Panel() panel.bg_color = (0.5, 0.5, 0.6, 1.0) if labelString is None: labelString = _("Press a key to assign to the action \"{0}\"\n\nPress ESC to cancel. Press Shift-ESC to unbind.").format(configKey) label = albow.Label(labelString) panel.add(label) panel.shrink_wrap() def panelKeyUp(evt): keyname = self.root.getKey(evt) panel.dismiss(keyname) def panelMouseUp(evt): button = remapMouseButton(evt.button) if button == 3: keyname = "Button 3" elif button == 4: keyname = "Scroll Up" elif button == 5: keyname = "Scroll Down" elif button == 6: keyname = "Button 4" elif button == 7: keyname = "Button 5" if button > 2: panel.dismiss(keyname) panel.key_up = panelKeyUp panel.mouse_up = panelMouseUp keyname = panel.present() if keyname == "Return" and self.enter == 1: self.enter = 0 self.askAssignKey(configKey, _("Press a key to assign to the action \"{0}\"\n\nPress ESC to cancel. Press Shift-ESC to unbind.").format(configKey)) return True self.enter = 0 if keyname != "Escape" and keyname != "Shift-Escape" and keyname not in ["Alt-F4","F1","F2","F3","F4","F5","1","2","3","4","5","6","7","8","9","Ctrl-Alt-F9","Ctrl-Alt-F10"]: if "Modifier" in configKey and keyname != "Ctrl" and keyname != "Alt" and keyname != "Shift": self.askAssignKey(configKey, _("{0} is not a modifier. " "Press a new key.\n\n" "Press ESC to cancel. Press Shift-ESC to unbind.") .format(keyname)) return True if configKey in ['Down','Up','Back','Forward','Left','Right','Pan Down','Pan Up','Pan Left','Pan Right']: if 'Ctrl' in keyname: self.askAssignKey(configKey, _("Movement keys can't use Ctrl. " "Press a new key.\n\n" "Press ESC to cancel. Press Shift-ESC to unbind.")) return True oldkey = config.keys[config.convert(configKey)].get() config.keys[config.convert(configKey)].set(keyname) if configKey not in self.changes: self.changes[configKey] = oldkey self.changesNum = True elif keyname == "Shift-Escape": config.keys[config.convert(configKey)].set("None") elif keyname != "Escape": self.askAssignKey(configKey, _("You can't use the key {0}. " "Press a new key.\n\n" "Press ESC to cancel. Press Shift-ESC to unbind.") .format(keyname)) return True else: return True
class FilterTool(EditorTool): tooltipText = "Filter" toolIconName = "filter" def __init__(self, editor): EditorTool.__init__(self, editor) self.filterModules = {} self.panel = FilterToolPanel(self) @property def statusText(self): return "Choose a filter, then click Filter or press ENTER to apply it." def toolEnabled(self): return not (self.selectionBox() is None) def toolSelected(self): self.showPanel() @alertException def showPanel(self): if self.panel.parent: self.editor.remove(self.panel) self.reloadFilters() # self.panel = FilterToolPanel(self) self.panel.reload() self.panel.midleft = self.editor.midleft self.editor.add(self.panel) self.updatePanel = Panel() updateButton = Button("Update Filters", action=self.updateFilters) self.updatePanel.add(updateButton) self.updatePanel.shrink_wrap() self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft self.editor.add(self.updatePanel) def hidePanel(self): self.panel.saveOptions() if self.panel.parent: self.panel.parent.remove(self.panel) self.updatePanel.parent.remove(self.updatePanel) def updateFilters(self): totalFilters = 0 updatedFilters = 0 try: os.mkdir(mcplatform.filtersDir + "/updates") except OSError: pass for module in self.filterModules.values(): totalFilters = totalFilters + 1 if hasattr(module, "UPDATE_URL") and hasattr(module, "VERSION"): if isinstance(module.UPDATE_URL, (str, unicode)) and isinstance(module.VERSION, (str, unicode)): versionJSON = json.loads(urllib2.urlopen(module.UPDATE_URL).read()) if module.VERSION != versionJSON["Version"]: urllib.urlretrieve(versionJSON["Download-URL"], mcplatform.filtersDir + "/updates/" + versionJSON["Name"]) updatedFilters = updatedFilters + 1 for f in os.listdir(mcplatform.filtersDir + "/updates"): shutil.copy(mcplatform.filtersDir + "/updates/" + f, mcplatform.filtersDir) shutil.rmtree(mcplatform.filtersDir + "/updates/") self.finishedUpdatingWidget = Widget() lbl = Label("Updated " + str(updatedFilters) + " filter(s) out of " + str(totalFilters)) closeBTN = Button("Close this message", action=self.closeFinishedUpdatingWidget) col = Column((lbl, closeBTN)) self.finishedUpdatingWidget.bg_color = (0.0, 0.0, 0.6) self.finishedUpdatingWidget.add(col) self.finishedUpdatingWidget.shrink_wrap() self.finishedUpdatingWidget.present() def closeFinishedUpdatingWidget(self): self.finishedUpdatingWidget.dismiss() def reloadFilters(self): filterDir = mcplatform.filtersDir filterFiles = os.listdir(filterDir) filterPyfiles = filter(lambda x: x.endswith(".py"), filterFiles) def tryImport(name): try: return __import__(name) except Exception, e: print traceback.format_exc() alert(_(u"Exception while importing filter module {}. See console for details.\n\n{}").format(name, e)) return object() filterModules = (tryImport(x[:-3]) for x in filterPyfiles) filterModules = filter(lambda module: hasattr(module, "perform"), filterModules) self.filterModules = collections.OrderedDict(sorted((self.moduleDisplayName(x), x) for x in filterModules)) for m in self.filterModules.itervalues(): try: reload(m) except Exception, e: print traceback.format_exc() alert( _(u"Exception while reloading filter module {}. Using previously loaded module. See console for details.\n\n{}").format( m.__file__, e))
class FilterTool(EditorTool): tooltipText = "Filter" toolIconName = "filter" def __init__(self, editor): EditorTool.__init__(self, editor) self.filterModules = {} self.savedOptions = {} self.updatePanel = Panel() updateButton = Button("Update Filters", action=self.updateFilters) self.updatePanel.add(updateButton) self.updatePanel.shrink_wrap() self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft @property def statusText(self): return "Choose a filter, then click Filter or press Enter to apply it." def toolEnabled(self): return not (self.selectionBox() is None) def toolSelected(self): self.showPanel() @alertException def showPanel(self): self.panel = FilterToolPanel(self) self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft self.editor.add(self.updatePanel) self.reloadFilters() self.panel.reload() height = self.editor.mainViewport.height - self.editor.toolbar.height self.panel.centery = height / 2 + self.editor.subwidgets[0].height self.panel.left = self.editor.left self.editor.add(self.panel) def hidePanel(self): if self.panel is None: return self.panel.close() if self.panel.parent: self.panel.parent.remove(self.panel) self.updatePanel.parent.remove(self.updatePanel) self.panel = None def updateFilters(self): totalFilters = 0 updatedFilters = 0 filtersDir = directories.getFiltersDir() try: os.mkdir(os.path.join(filtersDir, "updates")) except OSError: pass for module in self.filterModules.values(): totalFilters += 1 if hasattr(module, "UPDATE_URL") and hasattr(module, "VERSION"): if isinstance(module.UPDATE_URL, (str, unicode)) and isinstance( module.VERSION, (str, unicode)): versionJSON = json.loads( urllib2.urlopen(module.UPDATE_URL).read()) if module.VERSION != versionJSON["Version"]: urllib.urlretrieve( versionJSON["Download-URL"], os.path.join(filtersDir, "updates", versionJSON["Name"])) updatedFilters += 1 for f in os.listdir(os.path.join(filtersDir, "updates")): shutil.copy(os.path.join(filtersDir, "updates", f), filtersDir) shutil.rmtree(os.path.join(filtersDir, "updates")) finishedUpdatingWidget = Widget() lbl = Label("Updated %s filter(s) out of %s" % (updatedFilters, totalFilters)) closeBTN = Button("Close this message", action=finishedUpdatingWidget.dismiss) col = Column((lbl, closeBTN)) finishedUpdatingWidget.bg_color = (0.0, 0.0, 0.6) finishedUpdatingWidget.add(col) finishedUpdatingWidget.shrink_wrap() finishedUpdatingWidget.present() def reloadFilters(self): filterFiles = [] unicode_module_names = [] def searchForFiltersInDir(searchFolder, stock=False): for root, folders, files in os.walk(os.path.join(searchFolder), True): filter_dir = os.path.basename(root) if filter_dir.startswith('demo') or filter_dir.startswith( 'lib'): continue subFolderString = root.replace(searchFolder, "") if subFolderString.endswith(os.sep): subFolderString = subFolderString[:len(os.sep)] if subFolderString.startswith(os.sep): subFolderString = subFolderString[len(os.sep):] if len(subFolderString) > 0: subFolderString = "[" + subFolderString + "]" try: root = str(root) if root not in sys.path: sys.path.append(root) except UnicodeEncodeError: unicode_module_names.extend( [filter_name for filter_name in files]) for possible_filter in files: if possible_filter.endswith(".py"): filterFiles.append( (root, possible_filter, stock, subFolderString)) searchForFiltersInDir(directories.getFiltersDir(), False) searchForFiltersInDir( os.path.join(directories.getDataDir(), "stock-filters"), True) filterModules = [] # If the path has unicode chars, there's no way of knowing what order to add the # files to the sys.modules. To fix this, we keep trying to import until we import # fail to import all leftover files. shouldContinue = True while shouldContinue: shouldContinue = False for f in filterFiles: module = tryImport(f[0], f[1], f[2], f[3], f[1] in unicode_module_names) if module is None: continue filterModules.append(module) filterFiles.remove(f) shouldContinue |= True displayNames = [] for m in filterModules: while m.displayName in displayNames: m.displayName += "_" displayNames.append(m) filterModules = filter(lambda mod: hasattr(mod, "perform"), filterModules) self.filterModules = collections.OrderedDict( sorted([(FilterTool.moduleDisplayName(x), x) for x in filterModules], key=lambda module_name: (module_name[0].lower(), module_name[1]))) @staticmethod def moduleDisplayName(module): subFolderString = getattr(module, 'foldersForDisplayName', "") subFolderString = subFolderString if len( subFolderString) < 1 else subFolderString + " " return subFolderString + getattr(module, "displayName", module.__name__) @property def filterNames(self): return [ FilterTool.moduleDisplayName(module) for module in self.filterModules.itervalues() ]
def askAssignKey(self, configKey, labelString=None): if not self.isConfigKey(configKey): self.enter = 0 return panel = Panel() panel.bg_color = (0.5, 0.5, 0.6, 1.0) if labelString is None and configKey != "Fast Nudge": labelString = _( "Press a key to assign to the action \"{0}\"\n\nPress ESC to cancel." ).format(_(configKey)) elif labelString is None: labelString = _( "Press a key to assign to the action \"{0}\"\nNo key means right click to fast nudge.\nPress ESC to cancel." ).format(_(configKey)) label = albow.Label(labelString) unbind_button = Button("Press to unbind", action=self.unbind) column = Column((label, unbind_button)) panel.add(column) panel.shrink_wrap() def panelKeyUp(evt): keyname = self.root.getKey(evt) panel.dismiss(keyname) def panelMouseUp(evt): button = remapMouseButton(evt.button) if button == 3: keyname = "Button 3" elif button == 4: keyname = "Scroll Up" elif button == 5: keyname = "Scroll Down" elif button == 6: keyname = "Button 4" elif button == 7: keyname = "Button 5" if button > 2: panel.dismiss(keyname) panel.key_up = panelKeyUp panel.mouse_up = panelMouseUp self.panel = panel keyname = panel.present() if type(keyname) is bool: return True if keyname == "Return" and self.enter == 1: self.enter = 0 self.askAssignKey(configKey) return True self.enter = 0 _keyname = _(keyname) if keyname != "Escape" and keyname not in [ "Alt-F4", "F1", "F2", "F3", "F4", "F5", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Ctrl-Alt-F9", "Ctrl-Alt-F10" ]: if "Modifier" in configKey and keyname != "Ctrl" and keyname != "Alt" and keyname != "Shift": self.askAssignKey( configKey, _("{0} is not a modifier. Press a new key.\n\nPress ESC to cancel." ).format(_keyname)) return True if configKey in [ 'Down', 'Up', 'Back', 'Forward', 'Left', 'Right', 'Pan Down', 'Pan Up', 'Pan Left', 'Pan Right' ]: if 'Ctrl' in keyname or '-' in keyname: self.askAssignKey( configKey, "Movement keys can't use Ctrl or be with modifiers. Press a new key.\n\nPress ESC to cancel." ) return True filter_keys = [ i for (i, j) in config.config._sections["Filter Keys"].items() if j == _keyname ] if filter_keys: self.askAssignKey( configKey, _("Can't bind. {0} is already used by the \"{1}\" filter.\n Press a new key.\n\nPress ESC to cancel." ).format(_keyname, filter_keys[0])) return True oldkey = config.keys[config.convert(configKey)].get() config.keys[config.convert(configKey)].set(keyname) if oldkey != keyname and configKey not in self.changes: self.changes[configKey] = oldkey self.changesNum = True elif keyname != "Escape": self.askAssignKey( configKey, _("You can't use the key {0}. Press a new key.\n\nPress ESC to cancel." ).format(_keyname)) return True else: return True
class FilterTool(EditorTool): tooltipText = "Filter" toolIconName = "filter" def __init__(self, editor): EditorTool.__init__(self, editor) self.filterModules = {} self.savedOptions = {} self.updatePanel = Panel() updateButton = Button("Update Filters", action=self.updateFilters) self.updatePanel.add(updateButton) self.updatePanel.shrink_wrap() self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft @property def statusText(self): return "Choose a filter, then click Filter or press Enter to apply it." def toolEnabled(self): return not (self.selectionBox() is None) def toolSelected(self): self.showPanel() @alertException def showPanel(self): self.panel = FilterToolPanel(self) self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft self.editor.add(self.updatePanel) self.reloadFilters() self.panel.reload() height = self.editor.mainViewport.height - self.editor.toolbar.height self.panel.centery = height / 2 + self.editor.subwidgets[0].height self.panel.left = self.editor.left self.editor.add(self.panel) def hidePanel(self): if self.panel is None: return self.panel.close() if self.panel.parent: self.panel.parent.remove(self.panel) self.updatePanel.parent.remove(self.updatePanel) self.panel = None def updateFilters(self): totalFilters = 0 updatedFilters = 0 filtersDir = directories.getFiltersDir() try: os.mkdir(os.path.join(filtersDir, "updates")) except OSError: pass for module in self.filterModules.values(): totalFilters += 1 if hasattr(module, "UPDATE_URL") and hasattr(module, "VERSION"): if isinstance(module.UPDATE_URL, (str, unicode)) and isinstance(module.VERSION, (str, unicode)): versionJSON = json.loads(urllib2.urlopen(module.UPDATE_URL).read()) if module.VERSION != versionJSON["Version"]: urllib.urlretrieve(versionJSON["Download-URL"], os.path.join(filtersDir, "updates", versionJSON["Name"])) updatedFilters += 1 for f in os.listdir(os.path.join(filtersDir, "updates")): shutil.copy(os.path.join(filtersDir, "updates", f), filtersDir) shutil.rmtree(os.path.join(filtersDir, "updates")) finishedUpdatingWidget = Widget() lbl = Label("Updated %s filter(s) out of %s" % (updatedFilters, totalFilters)) closeBTN = Button("Close this message", action=finishedUpdatingWidget.dismiss) col = Column((lbl, closeBTN)) finishedUpdatingWidget.bg_color = (0.0, 0.0, 0.6) finishedUpdatingWidget.add(col) finishedUpdatingWidget.shrink_wrap() finishedUpdatingWidget.present() def reloadFilters(self): filterFiles = [] unicode_module_names = [] def searchForFiltersInDir(searchFolder, stock=False): for root, folders, files in os.walk(os.path.join(searchFolder), True): filter_dir = os.path.basename(root) if filter_dir.startswith('demo') or filter_dir.startswith('lib'): continue subFolderString = root.replace(searchFolder, "") if subFolderString.endswith(os.sep): subFolderString = subFolderString[:len(os.sep)] if subFolderString.startswith(os.sep): subFolderString = subFolderString[len(os.sep):] if len(subFolderString) > 0: subFolderString = "[" + subFolderString + "]" try: root = str(root) if root not in sys.path: sys.path.append(root) except UnicodeEncodeError: unicode_module_names.extend([filter_name for filter_name in files]) for possible_filter in files: if possible_filter.endswith(".py"): filterFiles.append((root, possible_filter, stock, subFolderString)) searchForFiltersInDir(directories.getFiltersDir(), False) searchForFiltersInDir(os.path.join(directories.getDataDir(), "stock-filters"), True) filterModules = [] org_lang = albow.translate.lang # If the path has unicode chars, there's no way of knowing what order to add the # files to the sys.modules. To fix this, we keep trying to import until we import # fail to import all leftover files. shouldContinue = True while shouldContinue: shouldContinue = False for f in filterFiles: module = tryImport(f[0], f[1], org_lang, f[2], f[3], f[1] in unicode_module_names) if module is None: continue filterModules.append(module) filterFiles.remove(f) shouldContinue |= True displayNames = [] for m in filterModules: while m.displayName in displayNames: m.displayName += "_" displayNames.append(m) filterModules = filter(lambda mod: hasattr(mod, "perform"), filterModules) self.filterModules = collections.OrderedDict(sorted( [(FilterTool.moduleDisplayName(x), x) for x in filterModules], key=lambda module_name: (module_name[0].lower(), module_name[1]))) @staticmethod def moduleDisplayName(module): subFolderString = getattr(module, 'foldersForDisplayName', "") subFolderString = subFolderString if len(subFolderString) < 1 else subFolderString + " " name = getattr(module, "displayName", module.__name__) return subFolderString + _(name[0].upper() + name[1:]) @property def filterNames(self): return [FilterTool.moduleDisplayName(module) for module in self.filterModules.itervalues()]
def bind_key(self, message=None): panel = Panel() panel.bg_color = (0.5, 0.5, 0.6, 1.0) if not message: message = _("Press a key to assign to the filter \"{0}\"\n\n" "Press ESC to cancel.").format(self.selectedName) label = albow.Label(message) unbind_button = Button("Press to unbind", action=self.unbind_key) column = Column((label, unbind_button)) panel.add(column) panel.shrink_wrap() def panelKeyUp(evt): _key_name = self.root.getKey(evt) panel.dismiss(_key_name) def panelMouseUp(evt): button = keys.remapMouseButton(evt.button) _key_name = None if button == 3: _key_name = "Button 3" elif button == 4: _key_name = "Scroll Up" elif button == 5: _key_name = "Scroll Down" elif button == 6: _key_name = "Button 4" elif button == 7: _key_name = "Button 5" if 2 < button < 8: panel.dismiss(_key_name) panel.key_up = panelKeyUp panel.mouse_up = panelMouseUp self.keys_panel = panel key_name = panel.present() if type(key_name) is bool: return True if key_name != "Escape": if key_name in [ "Alt-F4", "F1", "F2", "F3", "F4", "F5", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Ctrl-Alt-F9", "Ctrl-Alt-F10" ]: self.bind_key( _("You can't use the key {0}.\n" "Press a key to assign to the filter \"{1}\"\n\n" "" "Press ESC to cancel.").format(_(key_name), self.selectedName)) return True keysUsed = [(j, i) for (j, i) in config.config.items("Keys") if i == key_name] if keysUsed: self.bind_key( _("Can't bind. {0} is already used by {1}.\n" "Press a key to assign to the filter \"{2}\"\n\n" "" "Press ESC to cancel.").format(_(key_name), keysUsed[0][0], self.selectedName)) return True filter_keys = [ i for (i, j) in config.config.items("Filter Keys") if j == key_name ] if filter_keys: self.bind_key( _("Can't bind. {0} is already used by the \"{1}\" filter.\n" "Press a new key.\n\n" "" "Press ESC to cancel.").format(_(key_name), filter_keys[0])) return True config.config.set("Filter Keys", self.selectedName.lower(), key_name) config.save() self.reload()
def bind_key(self, message=None): panel = Panel() panel.bg_color = (0.5, 0.5, 0.6, 1.0) if not message: message = _("Press a key to assign to the filter \"{0}\"\n\n" "Press ESC to cancel.").format(self.selectedName) label = albow.Label(message) unbind_button = Button("Press to unbind", action=self.unbind_key) column = Column((label, unbind_button)) panel.add(column) panel.shrink_wrap() def panelKeyUp(evt): _key_name = self.root.getKey(evt) panel.dismiss(_key_name) def panelMouseUp(evt): button = keys.remapMouseButton(evt.button) _key_name = None if button == 3: _key_name = "Button 3" elif button == 4: _key_name = "Scroll Up" elif button == 5: _key_name = "Scroll Down" elif button == 6: _key_name = "Button 4" elif button == 7: _key_name = "Button 5" if 2 < button < 8: panel.dismiss(_key_name) panel.key_up = panelKeyUp panel.mouse_up = panelMouseUp self.keys_panel = panel key_name = panel.present() if type(key_name) is bool: return True if key_name != "Escape": if key_name in ["Alt-F4", "F1", "F2", "F3", "F4", "F5", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Ctrl-Alt-F9", "Ctrl-Alt-F10"]: self.bind_key(_("You can't use the key {0}.\n" "Press a key to assign to the filter \"{1}\"\n\n" "" "Press ESC to cancel.").format(_(key_name), self.selectedName)) return True keysUsed = [(j, i) for (j, i) in config.config.items("Keys") if i == key_name] if keysUsed: self.bind_key(_("Can't bind. {0} is already used by {1}.\n" "Press a key to assign to the filter \"{2}\"\n\n" "" "Press ESC to cancel.").format(_(key_name), keysUsed[0][0], self.selectedName)) return True filter_keys = [i for (i, j) in config.config.items("Filter Keys") if j == key_name] if filter_keys: self.bind_key(_("Can't bind. {0} is already used by the \"{1}\" filter.\n" "Press a new key.\n\n" "" "Press ESC to cancel.").format(_(key_name), filter_keys[0])) return True config.config.set("Filter Keys", self.selectedName.lower(), key_name) config.save() self.reload()
class FilterTool(EditorTool): tooltipText = "Filter" toolIconName = "filter" def __init__(self, editor): EditorTool.__init__(self, editor) self.filterModules = {} self.savedOptions = {} self.updatePanel = Panel(name='Panel.FilterTool.updatePanel') updateButton = Button("Update Filters", action=self.updateFilters) self.updatePanel.add(updateButton) self.updatePanel.shrink_wrap() self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft self.optionsPanel = FilterToolOptions(self) @property def statusText(self): return "Choose a filter, then click Filter or press Enter to apply it." def toolEnabled(self): return not (self.selectionBox() is None) def toolSelected(self): self.showPanel() @alertException def showPanel(self): self.panel = FilterToolPanel(self) self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft self.editor.add(self.updatePanel) self.reloadFilters() self.panel.reload() height = self.editor.mainViewport.height - self.editor.toolbar.height self.panel.centery = height / 2 + self.editor.subwidgets[0].height self.panel.left = self.editor.left self.editor.add(self.panel) def hidePanel(self): if self.panel is None: return self.panel.close() if self.panel.parent: self.panel.parent.remove(self.panel) self.updatePanel.parent.remove(self.updatePanel) self.panel = None def updateFilters(self): totalFilters = 0 updatedFilters = 0 filtersDir = directories.getFiltersDir() try: os.mkdir(os.path.join(filtersDir, "updates")) except OSError: pass for module in self.filterModules.values(): totalFilters += 1 if hasattr(module, "UPDATE_URL") and hasattr(module, "VERSION"): if isinstance(module.UPDATE_URL, (str, unicode)) and isinstance(module.VERSION, (str, unicode)): # Pass on URL or network errors. # This is a basic error hadling, need more refinement to sort errors... update = True try: versionJSON = json.loads(urllib2.urlopen(module.UPDATE_URL).read()) except Exception, e: update = False log.warn(" Could not fetch source for %s. System said: %s"%(module.displayName, e)) if update and module.VERSION != versionJSON["Version"]: urllib.urlretrieve(versionJSON["Download-URL"], os.path.join(filtersDir, "updates", versionJSON["Name"])) updatedFilters += 1 for f in os.listdir(os.path.join(filtersDir, "updates")): shutil.copy(os.path.join(filtersDir, "updates", f), filtersDir) shutil.rmtree(os.path.join(filtersDir, "updates")) finishedUpdatingWidget = Widget() lbl = Label("Updated %s filter(s) out of %s" % (updatedFilters, totalFilters)) closeBTN = Button("Close this message", action=finishedUpdatingWidget.dismiss) col = Column((lbl, closeBTN)) finishedUpdatingWidget.bg_color = (0.0, 0.0, 0.6) finishedUpdatingWidget.add(col) finishedUpdatingWidget.shrink_wrap() finishedUpdatingWidget.present()
class FilterTool(EditorTool): tooltipText = "Filter" toolIconName = "filter" def __init__(self, editor): EditorTool.__init__(self, editor) self.filterModules = {} self.savedOptions = {} self.updatePanel = Panel() updateButton = Button("Update Filters", action=self.updateFilters) self.updatePanel.add(updateButton) self.updatePanel.shrink_wrap() self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft @property def statusText(self): return "Choose a filter, then click Filter or press Enter to apply it." def toolEnabled(self): return not (self.selectionBox() is None) def toolSelected(self): self.showPanel() @alertException def showPanel(self): self.panel = FilterToolPanel(self) self.updatePanel.bottomleft = self.editor.viewportContainer.bottomleft self.editor.add(self.updatePanel) self.reloadFilters() self.panel.reload() height = self.editor.mainViewport.height - self.editor.toolbar.height self.panel.centery = height / 2 + self.editor.subwidgets[0].height self.panel.left = self.editor.left self.editor.add(self.panel) def hidePanel(self): if self.panel is None: return self.panel.close() if self.panel.parent: self.panel.parent.remove(self.panel) self.updatePanel.parent.remove(self.updatePanel) self.panel = None def updateFilters(self): totalFilters = 0 updatedFilters = 0 filtersDir = directories.getFiltersDir() try: os.mkdir(os.path.join(filtersDir, "updates")) except OSError: pass for module in self.filterModules.values(): totalFilters += 1 if hasattr(module, "UPDATE_URL") and hasattr(module, "VERSION"): if isinstance(module.UPDATE_URL, (str, unicode)) and isinstance(module.VERSION, (str, unicode)): # Pass on URL or network errors. # This is a basic error hadling, need more refinement to sort errors... update = True try: versionJSON = json.loads(urllib2.urlopen(module.UPDATE_URL).read()) except Exception, e: update = False log.warn(" Could not fetch source for %s. System said: %s"%(module.displayName, e)) if update and module.VERSION != versionJSON["Version"]: urllib.urlretrieve(versionJSON["Download-URL"], os.path.join(filtersDir, "updates", versionJSON["Name"])) updatedFilters += 1 for f in os.listdir(os.path.join(filtersDir, "updates")): shutil.copy(os.path.join(filtersDir, "updates", f), filtersDir) shutil.rmtree(os.path.join(filtersDir, "updates")) finishedUpdatingWidget = Widget() lbl = Label("Updated %s filter(s) out of %s" % (updatedFilters, totalFilters)) closeBTN = Button("Close this message", action=finishedUpdatingWidget.dismiss) col = Column((lbl, closeBTN)) finishedUpdatingWidget.bg_color = (0.0, 0.0, 0.6) finishedUpdatingWidget.add(col) finishedUpdatingWidget.shrink_wrap() finishedUpdatingWidget.present()
def askAssignKey(self, configKey, labelString=None): if not self.isConfigKey(configKey): self.enter = 0 return panel = Panel() panel.bg_color = (0.5, 0.5, 0.6, 1.0) if labelString is None: labelString = _( "Press a key to assign to the action \"{0}\"\n\nPress ESC to cancel. Press Shift-ESC to unbind." ).format(configKey) label = albow.Label(labelString) panel.add(label) panel.shrink_wrap() def panelKeyUp(evt): keyname = self.root.getKey(evt) panel.dismiss(keyname) def panelMouseUp(evt): button = remapMouseButton(evt.button) if button == 3: keyname = "Button 3" elif button == 4: keyname = "Scroll Up" elif button == 5: keyname = "Scroll Down" elif button == 6: keyname = "Button 4" elif button == 7: keyname = "Button 5" if button > 2: panel.dismiss(keyname) panel.key_up = panelKeyUp panel.mouse_up = panelMouseUp keyname = panel.present() if keyname == "Return" and self.enter == 1: self.enter = 0 self.askAssignKey( configKey, _("Press a key to assign to the action \"{0}\"\n\nPress ESC to cancel. Press Shift-ESC to unbind." ).format(configKey)) return True self.enter = 0 if keyname != "Escape" and keyname != "Shift-Escape" and keyname not in [ "Alt-F4", "F1", "F2", "F3", "F4", "F5", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Ctrl-Alt-F9", "Ctrl-Alt-F10" ]: if "Modifier" in configKey and keyname != "Ctrl" and keyname != "Alt" and keyname != "Shift": self.askAssignKey( configKey, _("{0} is not a modifier. " "Press a new key.\n\n" "Press ESC to cancel. Press Shift-ESC to unbind."). format(keyname)) return True if configKey in [ 'Down', 'Up', 'Back', 'Forward', 'Left', 'Right', 'Pan Down', 'Pan Up', 'Pan Left', 'Pan Right' ]: if 'Ctrl' in keyname: self.askAssignKey( configKey, _("Movement keys can't use Ctrl. " "Press a new key.\n\n" "Press ESC to cancel. Press Shift-ESC to unbind.")) return True oldkey = config.keys[config.convert(configKey)].get() config.keys[config.convert(configKey)].set(keyname) if configKey not in self.changes: self.changes[configKey] = oldkey self.changesNum = True elif keyname == "Shift-Escape": config.keys[config.convert(configKey)].set("None") elif keyname != "Escape": self.askAssignKey( configKey, _("You can't use the key {0}. " "Press a new key.\n\n" "Press ESC to cancel. Press Shift-ESC to unbind.").format( keyname)) return True else: return True
def askAssignKey(self, configKey, labelString=None): if not self.isConfigKey(configKey): self.enter = 0 return panel = Panel(name='Panel.KeyConfigPanel') panel.bg_color = (0.3, 0.3, 0.3, 1.0) if labelString is None and configKey != "Fast Nudge": labelString = _("Press a key to assign to the action \"{0}\"\n\nPress ESC to cancel.").format(_(configKey)) elif labelString is None: labelString = _("Press a key to assign to the action \"{0}\"\nNo key means right click to fast nudge.\nPress ESC to cancel.").format(_(configKey)) label = albow.Label(labelString) unbind_button = Button("Press to unbind", action=self.unbind) column = Column((label, unbind_button)) panel.add(column) panel.shrink_wrap() def panelKeyUp(evt): keyname = self.root.getKey(evt) panel.dismiss(keyname) def panelMouseUp(evt): button = remapMouseButton(evt.button) if button == 3: keyname = "Button 3" elif button == 4: keyname = "Scroll Up" elif button == 5: keyname = "Scroll Down" elif button == 6: keyname = "Button 4" elif button == 7: keyname = "Button 5" if button > 2: panel.dismiss(keyname) panel.key_up = panelKeyUp panel.mouse_up = panelMouseUp self.panel = panel keyname = panel.present() if isinstance(keyname, bool): return True if keyname == "Return" and self.enter == 1: self.enter = 0 self.askAssignKey(configKey) return True self.enter = 0 _keyname = _(keyname) if keyname != "Escape" and keyname not in ("Alt-F4","F1","F2","F3","F4","F5","1","2","3","4","5","6","7","8","9","Ctrl-Alt-F9","Ctrl-Alt-F10"): if "Modifier" in configKey and keyname != "Ctrl" and keyname != "Alt" and keyname != "Shift": self.askAssignKey(configKey, _("{0} is not a modifier. Press a new key.\n\nPress ESC to cancel.") .format(_keyname)) return True if configKey in ('Down','Up','Back','Forward','Left','Right','Pan Down','Pan Up','Pan Left','Pan Right'): if 'Ctrl' in keyname or '-' in keyname: self.askAssignKey(configKey, "Movement keys can't use Ctrl or be with modifiers. Press a new key.\n\nPress ESC to cancel.") return True filter_keys = [i for (i, j) in config.config._sections["Filter Keys"].items() if j == _keyname] if filter_keys: self.askAssignKey(configKey, _("Can't bind. {0} is already used by the \"{1}\" filter.\n Press a new key.\n\nPress ESC to cancel.").format(_keyname, filter_keys[0])) return True oldkey = config.keys[config.convert(configKey)].get() config.keys[config.convert(configKey)].set(keyname) if oldkey != keyname and configKey not in self.changes: self.changes[configKey] = oldkey self.changesNum = True elif keyname != "Escape": self.askAssignKey(configKey, _("You can't use the key {0}. Press a new key.\n\nPress ESC to cancel.") .format(_keyname)) return True else: return True