From b482e8d952300769021b60e523b8a5688564e0ae Mon Sep 17 00:00:00 2001 From: David Vierra Date: Sun, 31 May 2015 18:04:09 -1000 Subject: [PATCH] Pull masklevel.py, modes.py, shapes.py out of brush/__init__.py Move shapes out of shapewidget.py, too. --- src/mcedit2/editortools/brush/__init__.py | 265 +-------------------- src/mcedit2/editortools/brush/masklevel.py | 108 +++++++++ src/mcedit2/editortools/brush/modes.py | 156 ++++++++++++ src/mcedit2/editortools/brush/shapes.py | 39 +++ src/mcedit2/editortools/select.py | 6 +- src/mcedit2/widgets/shapewidget.py | 34 +-- 6 files changed, 326 insertions(+), 282 deletions(-) create mode 100644 src/mcedit2/editortools/brush/masklevel.py create mode 100644 src/mcedit2/editortools/brush/modes.py create mode 100644 src/mcedit2/editortools/brush/shapes.py diff --git a/src/mcedit2/editortools/brush/__init__.py b/src/mcedit2/editortools/brush/__init__.py index 0926eda..d4116dc 100644 --- a/src/mcedit2/editortools/brush/__init__.py +++ b/src/mcedit2/editortools/brush/__init__.py @@ -4,22 +4,19 @@ from __future__ import absolute_import, division, print_function, unicode_literals import logging -from PySide import QtGui, QtCore -import numpy +from PySide import QtGui from mcedit2.editortools import EditorTool from mcedit2.command import SimplePerformCommand +from mcedit2.editortools.brush.masklevel import FakeBrushSection +from mcedit2.editortools.brush.modes import BrushModes from mcedit2.rendering import worldscene, scenegraph from mcedit2.rendering.depths import DepthOffset from mcedit2.util.load_ui import load_ui, registerCustomWidget from mcedit2.util.settings import Settings from mcedit2.util.showprogress import showProgress from mcedit2.util.worldloader import WorldLoader -from mcedit2.widgets.blockpicker import BlockTypeButton -from mcedit2.widgets.layout import Row, Column -from mceditlib.anvil.biome_types import BiomeTypes -from mceditlib.geometry import Vector -from mceditlib.selection import ShapedSelection, BoundingBox +from mceditlib.selection import ShapedSelection from mceditlib.util import exhaust @@ -47,9 +44,9 @@ class BrushCommand(SimplePerformCommand): self.points = points self.brushSize = options['brushSize'] - self.brushStyle = options['brushStyle'] + self.brushShape = options['brushShape'] self.brushMode = options['brushMode'] - self.setText("%s %s Brush" % (self.brushMode.name, self.brushStyle.ID)) + self.setText("%s %s Brush" % (self.brushMode.name, self.brushShape.ID)) if max(self.brushSize) > BrushTool.maxBrushSize: self.brushSize = (BrushTool.maxBrushSize,) * 3 @@ -74,7 +71,7 @@ class BrushCommand(SimplePerformCommand): yield 0, len(self.points), "Applying {0} brush...".format(self.brushMode.name) try: #xxx combine selections - selections = [ShapedSelection(self.brushMode.brushBoxForPoint(point, self.options), self.brushStyle.shapeFunc) for point in self.points] + selections = [ShapedSelection(self.brushMode.brushBoxForPoint(point, self.options), self.brushShape.shapeFunc) for point in self.points] self.brushMode.applyToSelections(self, selections) except NotImplementedError: for i, point in enumerate(self.points): @@ -88,245 +85,6 @@ class BrushCommand(SimplePerformCommand): self.performed = True -class BrushMode(QtCore.QObject): - optionsWidget = None - - def brushBoundingBox(self, center, options={}): - # Return a box of size options['brushSize'] centered around point. - # also used to position the preview cursor - size = options['brushSize'] - x, y, z = size - origin = Vector(*center) - (Vector(x, y, z) / 2) + Vector((x % 2) * 0.5, (y % 2) * 0.5, (z % 2) * 0.5) - return BoundingBox(origin, size) - - def applyToPoint(self, command, point): - """ - Called by BrushCommand for brush modes that can't be implemented using applyToChunk - :type point: Vector - :type command: BrushCommand - """ - raise NotImplementedError - - def applyToSelections(self, command, selections): - """ - Called by BrushCommand to apply this brush mode to the given selection. Selection is generated - by calling - """ - raise NotImplementedError - - def createOptionsWidget(self, brushTool): - return None - - def createCursorLevel(self, brushTool): - return None - -class Fill(BrushMode): - name = "fill" - - def __init__(self): - super(Fill, self).__init__() - self.displayName = self.tr("Fill") - - def createOptionsWidget(self, brushTool): - if self.optionsWidget: - return self.optionsWidget - - self.optionsWidget = QtGui.QWidget() - label = QtGui.QLabel(self.tr("Fill Block:")) - self.blockTypeButton = BlockTypeButton() - self.blockTypeButton.editorSession = brushTool.editorSession - self.blockTypeButton.block = brushTool.editorSession.worldEditor.blocktypes['minecraft:stone'] - self.blockTypeButton.blocksChanged.connect(brushTool.updateCursor) - - self.optionsWidget.setLayout(Column( - Row(label, self.blockTypeButton, margin=0), - None, margin=0)) - return self.optionsWidget - - def getOptions(self): - return {'blockInfo': self.blockTypeButton.block} - - def applyToSelections(self, command, selections): - """ - - :type command: BrushCommand - """ - fill = command.editorSession.currentDimension.fillBlocksIter(selections[0], command.options['blockInfo']) - showProgress("Applying brush...", fill) - - def brushBoxForPoint(self, point, options): - return self.brushBoundingBox(point, options) - - def createCursorLevel(self, brushTool): - selection = ShapedSelection(self.brushBoxForPoint((0, 0, 0), brushTool.options), brushTool.brushStyle.shapeFunc) - cursorLevel = MaskLevel(selection, - self.blockTypeButton.block, - brushTool.editorSession.worldEditor.blocktypes) - return cursorLevel - -class Biome(BrushMode): - name = "biome" - - def __init__(self, *args, **kwargs): - super(Biome, self).__init__(*args, **kwargs) - self.displayName = self.tr("Biome") - - def getOptions(self): - return {'biomeID': self.biomeTypeBox.itemData(self.biomeTypeBox.currentIndex())} - - def createOptionsWidget(self, brushTool): - if self.optionsWidget: - return self.optionsWidget - - self.optionsWidget = QtGui.QWidget() - label = QtGui.QLabel(self.tr("Fill Biome:")) - self.biomeTypeBox = QtGui.QComboBox() - self.biomeTypes = BiomeTypes() - for biome in self.biomeTypes.types.values(): - self.biomeTypeBox.addItem(biome.name, biome.ID) - - self.biomeTypeBox.activated.connect(brushTool.updateCursor) - self.optionsWidget.setLayout(Column(Row(label, self.biomeTypeBox, margin=0), None, margin=0)) - return self.optionsWidget - - def applyToSelections(self, command, selections): - """ - - :type command: BrushCommand - """ - #task = command.editorSession.currentDimension.fillBlocksIter(selections[0], command.blockInfo) - #showProgress("Applying brush...", task) - selection = selections[0] - biomeID = command.options['biomeID'] - for x, _, z in selection.positions: - command.editorSession.currentDimension.setBiomeID(x, z, biomeID) - - def brushBoxForPoint(self, point, options): - x, y, z = options['brushSize'] - options['brushSize'] = x, 1, z - - return self.brushBoundingBox(point, options) - - def createCursorLevel(self, brushTool): - box = self.brushBoxForPoint((0, 0, 0), brushTool.options) - - selection = ShapedSelection(box, brushTool.brushStyle.shapeFunc) - cursorLevel = MaskLevel(selection, - brushTool.editorSession.worldEditor.blocktypes["minecraft:grass"], - brushTool.editorSession.worldEditor.blocktypes, - biomeID=self.getOptions()['biomeID']) - return cursorLevel - -class BrushModes(object): - # load from plugins here - fill = Fill() - biome = Biome() - allModes = [fill, biome] - modesByName = {mode.name: mode for mode in allModes} - - -class Style(object): - ID = NotImplemented - icon = NotImplemented - shapeFunc = NotImplemented - - -NULL_ID = 255 # xxx - - -class MaskLevel(object): - def __init__(self, selection, fillBlock, blocktypes, biomeID=None): - """ - Level emulator to be used for rendering brushes and selections. - - :type selection: mceditlib.selection.ShapedSelection - :param selection: - :param fillBlock: - :param blocktypes: - """ - self.bounds = self.selection = selection - - self.blocktypes = blocktypes - self.sectionCache = {} - self.fillBlock = fillBlock - self.biomeID = biomeID - self.filename = "Temporary Level (%s %s %s)" % (selection, fillBlock, blocktypes) - - def chunkPositions(self): - return self.bounds.chunkPositions() - - def getChunk(self, cx, cz, create=False): - return FakeBrushChunk(self, cx, cz, self.biomeID) - - def containsChunk(self, cx, cz): - return self.bounds.containsChunk(cx, cz) - -class FakeBrushSection(object): - BlockLight = numpy.empty((16, 16, 16), dtype=numpy.uint8) - BlockLight[:] = 15 - SkyLight = numpy.empty((16, 16, 16), dtype=numpy.uint8) - SkyLight[:] = 15 - pass - -class FakeBrushChunk(object): - Entities = () - TileEntities = () - - def __init__(self, world, cx, cz, biomeID=None): - """ - - :type world: MaskLevel - """ - self.dimension = world - self.cx = cx - self.cz = cz - self.Biomes = numpy.zeros((16, 16), numpy.uint8) - if biomeID: - self.Biomes[:] = biomeID - - @property - def blocktypes(self): - return self.dimension.blocktypes - - @property - def chunkPosition(self): - return self.cx, self.cz - - def sectionPositions(self): - return self.dimension.selection.sectionPositions(self.cx, self.cz) - - @property - def bounds(self): - return BoundingBox((self.cx << 4, self.dimension.bounds.miny, self.cz << 4), - (16, self.dimension.bounds.height, 16)) - - - _sentinel = object() - - def getSection(self, y, create=False): - selection = self.dimension.selection - sectionCache = self.dimension.sectionCache - fillBlock = self.dimension.fillBlock - cx, cz = self.chunkPosition - - section = sectionCache.get((cx, y, cz), self._sentinel) - if section is self._sentinel: - mask = selection.section_mask(cx, y, cz) - if mask is None: - sectionCache[cx, y, cz] = None - return None - - section = FakeBrushSection() - section.Y = y - if fillBlock.ID: - section.Blocks = numpy.array([0, fillBlock.ID], dtype=numpy.uint16)[mask.astype(numpy.uint8)] - section.Data = numpy.array([0, fillBlock.meta], dtype=numpy.uint8)[mask.astype(numpy.uint8)] - else: - section.Blocks = numpy.array([0, NULL_ID])[mask.astype(numpy.uint8)] - - sectionCache[cx, y, cz] = section - - return section class BrushTool(EditorTool): name = "Brush" @@ -336,6 +94,8 @@ class BrushTool(EditorTool): def __init__(self, editorSession, *args, **kwargs): super(BrushTool, self).__init__(editorSession, *args, **kwargs) self.toolWidget = load_ui("editortools/brush.ui") + self.brushMode = None + self.brushLoader = None BrushModeSetting.connectAndCall(self.modeSettingChanged) @@ -361,6 +121,7 @@ class BrushTool(EditorTool): self.toolWidget.zSpinSlider.setValue(self.brushSize[2]) _brushSize = (0, 0, 0) + @property def brushSize(self): return self._brushSize @@ -406,7 +167,7 @@ class BrushTool(EditorTool): @property def options(self): options = {'brushSize': self.brushSize, - 'brushStyle': self.brushStyle, + 'brushShape': self.brushShape, 'brushMode': self.brushMode} options.update(self.brushMode.getOptions()) return options @@ -420,9 +181,8 @@ class BrushTool(EditorTool): if widget: stack.addWidget(widget) - @property - def brushStyle(self): + def brushShape(self): return self.toolWidget.brushShapeInput.currentShape def updateCursor(self): @@ -441,6 +201,7 @@ class BrushTool(EditorTool): self.brushLoader.timer.start() +# xxx button palette? @registerCustomWidget class BrushModeWidget(QtGui.QComboBox): def __init__(self, *args, **kwargs): diff --git a/src/mcedit2/editortools/brush/masklevel.py b/src/mcedit2/editortools/brush/masklevel.py new file mode 100644 index 0000000..09cbd4e --- /dev/null +++ b/src/mcedit2/editortools/brush/masklevel.py @@ -0,0 +1,108 @@ +""" + masklevel +""" +from __future__ import absolute_import, division, print_function, unicode_literals +import numpy + +from mceditlib.selection import BoundingBox + +import logging +log = logging.getLogger(__name__) + +NULL_ID = 255 # xxx WHAT IS THIS FOR? + + +class MaskLevel(object): + def __init__(self, selection, fillBlock, blocktypes, biomeID=None): + """ + Level emulator to be used for rendering brushes and selections. + + :type selection: mceditlib.selection.ShapedSelection + :param selection: + :param fillBlock: + :param blocktypes: + """ + self.bounds = self.selection = selection + + self.blocktypes = blocktypes + self.sectionCache = {} + self.fillBlock = fillBlock + self.biomeID = biomeID + self.filename = "Temporary Level (%s %s %s)" % (selection, fillBlock, blocktypes) + + def chunkPositions(self): + return self.bounds.chunkPositions() + + def getChunk(self, cx, cz, create=False): + return FakeBrushChunk(self, cx, cz, self.biomeID) + + def containsChunk(self, cx, cz): + return self.bounds.containsChunk(cx, cz) + + +class FakeBrushSection(object): + BlockLight = numpy.empty((16, 16, 16), dtype=numpy.uint8) + BlockLight[:] = 15 + SkyLight = numpy.empty((16, 16, 16), dtype=numpy.uint8) + SkyLight[:] = 15 + pass + + +class FakeBrushChunk(object): + Entities = () + TileEntities = () + + def __init__(self, world, cx, cz, biomeID=None): + """ + + :type world: mcedit2.editortools.brush.masklevel.MaskLevel + """ + self.dimension = world + self.cx = cx + self.cz = cz + self.Biomes = numpy.zeros((16, 16), numpy.uint8) + if biomeID: + self.Biomes[:] = biomeID + + @property + def blocktypes(self): + return self.dimension.blocktypes + + @property + def chunkPosition(self): + return self.cx, self.cz + + def sectionPositions(self): + return self.dimension.selection.sectionPositions(self.cx, self.cz) + + @property + def bounds(self): + return BoundingBox((self.cx << 4, self.dimension.bounds.miny, self.cz << 4), + (16, self.dimension.bounds.height, 16)) + + _sentinel = object() + + def getSection(self, y, create=False): + selection = self.dimension.selection + sectionCache = self.dimension.sectionCache + fillBlock = self.dimension.fillBlock + cx, cz = self.chunkPosition + + section = sectionCache.get((cx, y, cz), self._sentinel) + if section is self._sentinel: + mask = selection.section_mask(cx, y, cz) + if mask is None: + sectionCache[cx, y, cz] = None + return None + + section = FakeBrushSection() + section.Y = y + if fillBlock.ID: + section.Blocks = numpy.array([0, fillBlock.ID], dtype=numpy.uint16)[mask.astype(numpy.uint8)] + section.Data = numpy.array([0, fillBlock.meta], dtype=numpy.uint8)[mask.astype(numpy.uint8)] + else: + section.Blocks = numpy.array([0, NULL_ID])[mask.astype(numpy.uint8)] + + sectionCache[cx, y, cz] = section + + return section \ No newline at end of file diff --git a/src/mcedit2/editortools/brush/modes.py b/src/mcedit2/editortools/brush/modes.py new file mode 100644 index 0000000..37c4b56 --- /dev/null +++ b/src/mcedit2/editortools/brush/modes.py @@ -0,0 +1,156 @@ +""" + modes +""" +from __future__ import absolute_import, division, print_function, unicode_literals +import logging +from PySide import QtGui, QtCore +from mcedit2.editortools.brush.masklevel import MaskLevel +from mcedit2.util.showprogress import showProgress +from mcedit2.widgets.blockpicker import BlockTypeButton +from mcedit2.widgets.layout import Column, Row +from mceditlib.anvil.biome_types import BiomeTypes +from mceditlib.geometry import Vector +from mceditlib.selection import ShapedSelection, BoundingBox + +log = logging.getLogger(__name__) + + + +class BrushMode(QtCore.QObject): + optionsWidget = None + + def brushBoundingBox(self, center, options={}): + # Return a box of size options['brushSize'] centered around point. + # also used to position the preview cursor + size = options['brushSize'] + x, y, z = size + origin = Vector(*center) - (Vector(x, y, z) / 2) + Vector((x % 2) * 0.5, (y % 2) * 0.5, (z % 2) * 0.5) + return BoundingBox(origin, size) + + def applyToPoint(self, command, point): + """ + Called by BrushCommand for brush modes that can't be implemented using applyToChunk + :type point: Vector + :type command: BrushCommand + """ + raise NotImplementedError + + def applyToSelections(self, command, selections): + """ + Called by BrushCommand to apply this brush mode to the given selection. Selection is generated + by calling + """ + raise NotImplementedError + + def createOptionsWidget(self, brushTool): + return None + + def createCursorLevel(self, brushTool): + return None + + +class Fill(BrushMode): + name = "fill" + + def __init__(self): + super(Fill, self).__init__() + self.displayName = self.tr("Fill") + + def createOptionsWidget(self, brushTool): + if self.optionsWidget: + return self.optionsWidget + + self.optionsWidget = QtGui.QWidget() + label = QtGui.QLabel(self.tr("Fill Block:")) + self.blockTypeButton = BlockTypeButton() + self.blockTypeButton.editorSession = brushTool.editorSession + self.blockTypeButton.block = brushTool.editorSession.worldEditor.blocktypes['minecraft:stone'] + self.blockTypeButton.blocksChanged.connect(brushTool.updateCursor) + + self.optionsWidget.setLayout(Column( + Row(label, self.blockTypeButton, margin=0), + None, margin=0)) + return self.optionsWidget + + def getOptions(self): + return {'blockInfo': self.blockTypeButton.block} + + def applyToSelections(self, command, selections): + """ + + :type command: BrushCommand + """ + fill = command.editorSession.currentDimension.fillBlocksIter(selections[0], command.options['blockInfo']) + showProgress("Applying brush...", fill) + + def brushBoxForPoint(self, point, options): + return self.brushBoundingBox(point, options) + + def createCursorLevel(self, brushTool): + selection = ShapedSelection(self.brushBoxForPoint((0, 0, 0), brushTool.options), brushTool.brushShape.shapeFunc) + cursorLevel = MaskLevel(selection, + self.blockTypeButton.block, + brushTool.editorSession.worldEditor.blocktypes) + return cursorLevel + + +class Biome(BrushMode): + name = "biome" + + def __init__(self, *args, **kwargs): + super(Biome, self).__init__(*args, **kwargs) + self.displayName = self.tr("Biome") + + def getOptions(self): + return {'biomeID': self.biomeTypeBox.itemData(self.biomeTypeBox.currentIndex())} + + def createOptionsWidget(self, brushTool): + if self.optionsWidget: + return self.optionsWidget + + self.optionsWidget = QtGui.QWidget() + label = QtGui.QLabel(self.tr("Fill Biome:")) + self.biomeTypeBox = QtGui.QComboBox() + self.biomeTypes = BiomeTypes() + for biome in self.biomeTypes.types.values(): + self.biomeTypeBox.addItem(biome.name, biome.ID) + + self.biomeTypeBox.activated.connect(brushTool.updateCursor) + self.optionsWidget.setLayout(Column(Row(label, self.biomeTypeBox, margin=0), None, margin=0)) + return self.optionsWidget + + def applyToSelections(self, command, selections): + """ + + :type command: BrushCommand + """ + #task = command.editorSession.currentDimension.fillBlocksIter(selections[0], command.blockInfo) + #showProgress("Applying brush...", task) + selection = selections[0] + biomeID = command.options['biomeID'] + for x, _, z in selection.positions: + command.editorSession.currentDimension.setBiomeID(x, z, biomeID) + + def brushBoxForPoint(self, point, options): + x, y, z = options['brushSize'] + options['brushSize'] = x, 1, z + + return self.brushBoundingBox(point, options) + + def createCursorLevel(self, brushTool): + box = self.brushBoxForPoint((0, 0, 0), brushTool.options) + + selection = ShapedSelection(box, brushTool.brushShape.shapeFunc) + cursorLevel = MaskLevel(selection, + brushTool.editorSession.worldEditor.blocktypes["minecraft:grass"], + brushTool.editorSession.worldEditor.blocktypes, + biomeID=self.getOptions()['biomeID']) + return cursorLevel + + +class BrushModes(object): + # load from plugins here + fill = Fill() + biome = Biome() + allModes = [fill, biome] + modesByName = {mode.name: mode for mode in allModes} diff --git a/src/mcedit2/editortools/brush/shapes.py b/src/mcedit2/editortools/brush/shapes.py new file mode 100644 index 0000000..3f5020d --- /dev/null +++ b/src/mcedit2/editortools/brush/shapes.py @@ -0,0 +1,39 @@ +""" + shapes +""" +from __future__ import absolute_import, division, print_function, unicode_literals +import logging +from mceditlib import selection + +log = logging.getLogger(__name__) + + +class BrushShape(object): + ID = NotImplemented + icon = NotImplemented + shapeFunc = NotImplemented + +class Round(BrushShape): + ID = "Round" + icon = "shapes/round.png" + shapeFunc = staticmethod(selection.SphereShape) + + +class Square(BrushShape): + ID = "Square" + icon = "shapes/square.png" + shapeFunc = staticmethod(selection.BoxShape) + + +class Diamond(BrushShape): + ID = "Diamond" + icon = "shapes/diamond.png" + shapeFunc = staticmethod(selection.DiamondShape) + + + +# load from plugins here, rename to selection shapes? +allShapes = (Square(), Round(), Diamond()) + +def getShapes(): + return allShapes diff --git a/src/mcedit2/editortools/select.py b/src/mcedit2/editortools/select.py index 12a1de1..5d735f3 100644 --- a/src/mcedit2/editortools/select.py +++ b/src/mcedit2/editortools/select.py @@ -8,6 +8,7 @@ from OpenGL import GL from PySide import QtGui, QtCore from mcedit2.editortools import EditorTool +from mcedit2.editortools.brush import shapes from mcedit2.handles.boxhandle import BoxHandle from mcedit2.rendering import cubes from mcedit2.rendering.selection import SelectionScene, SelectionFaceNode @@ -15,7 +16,6 @@ from mcedit2.util.load_ui import load_ui from mcedit2.util.glutils import gl from mcedit2.rendering.depths import DepthOffset from mcedit2.rendering import scenegraph, rendergraph -from mcedit2.widgets import shapewidget from mcedit2.widgets.layout import Column from mcedit2.widgets.shapewidget import ShapeWidget from mceditlib import faces @@ -282,8 +282,8 @@ class SelectionTool(EditorTool): showPreviousSelection = True def createShapedSelection(self, box): - if self.shapeInput.currentShape is shapewidget.Square: - return box + if self.shapeInput.currentShape is shapes.Square: + return box # ugly hack else: return selection.ShapedSelection(box, self.shapeInput.currentShape.shapeFunc) diff --git a/src/mcedit2/widgets/shapewidget.py b/src/mcedit2/widgets/shapewidget.py index cb51abe..5f7e54f 100644 --- a/src/mcedit2/widgets/shapewidget.py +++ b/src/mcedit2/widgets/shapewidget.py @@ -5,11 +5,11 @@ from __future__ import absolute_import, division, print_function import logging import os from PySide import QtGui, QtCore -from mcedit2.editortools.brush import BrushShapeSetting, Style +from mcedit2.editortools.brush import BrushShapeSetting +from mcedit2.editortools.brush.shapes import getShapes from mcedit2.util.load_ui import registerCustomWidget from mcedit2.util.resources import resourcePath from mcedit2.widgets import flowlayout -from mceditlib import selection log = logging.getLogger(__name__) @@ -24,12 +24,13 @@ class ShapeWidget(QtGui.QWidget): actionGroup.setExclusive(True) iconBase = resourcePath("mcedit2/assets/mcedit2/icons") actions = {} - for shape in Shapes.allShapes: + for shape in getShapes(): filename = os.path.join(iconBase, shape.icon) assert os.path.exists(filename), "%r does not exist" % filename icon = QtGui.QIcon(filename) if icon is None: raise ValueError("Failed to read shape icon file %s" % filename) + def _handler(shape): def handler(): self.currentShape = shape @@ -47,33 +48,12 @@ class ShapeWidget(QtGui.QWidget): actions[shape.ID] = action self.setLayout(layout) - currentID = BrushShapeSetting.value(Shapes.allShapes[0].ID) - shapesByID = {shape.ID:shape for shape in Shapes.allShapes} + currentID = BrushShapeSetting.value(getShapes()[0].ID) + shapesByID = {shape.ID:shape for shape in getShapes()} actions[currentID].setChecked(True) - self.currentShape = shapesByID.get(currentID, Shapes.allShapes[0]) + self.currentShape = shapesByID.get(currentID, getShapes()[0]) shapeChanged = QtCore.Signal() -class Round(Style): - ID = "Round" - icon = "shapes/round.png" - shapeFunc = staticmethod(selection.SphereShape) - - -class Square(Style): - ID = "Square" - icon = "shapes/square.png" - shapeFunc = staticmethod(selection.BoxShape) - - -class Diamond(Style): - ID = "Diamond" - icon = "shapes/diamond.png" - shapeFunc = staticmethod(selection.DiamondShape) - - -class Shapes(object): - # load from plugins here, rename to selection shapes? - allShapes = (Square(), Round(), Diamond())