class GenerateTool(EditorTool): name = "Generate" iconName = "generate" instantDisplayChunks = 32 def __init__(self, *args, **kwargs): EditorTool.__init__(self, *args, **kwargs) self.livePreview = False self.blockPreview = False self.glPreview = True toolWidget = QtGui.QWidget() self.toolWidget = toolWidget column = [] self.generatorTypes = [pluginClass(self) for pluginClass in _pluginClasses] self.currentGenerator = None if len(self.generatorTypes): self.currentGenerator = self.generatorTypes[0] self.generatorTypeInput = QtGui.QComboBox() self.generatorTypesChanged() self.generatorTypeInput.currentIndexChanged.connect(self.currentTypeChanged) self.livePreviewCheckbox = QtGui.QCheckBox("Live Preview") self.livePreviewCheckbox.setChecked(self.livePreview) self.livePreviewCheckbox.toggled.connect(self.livePreviewToggled) self.blockPreviewCheckbox = QtGui.QCheckBox("Block Preview") self.blockPreviewCheckbox.setChecked(self.blockPreview) self.blockPreviewCheckbox.toggled.connect(self.blockPreviewToggled) self.glPreviewCheckbox = QtGui.QCheckBox("GL Preview") self.glPreviewCheckbox.setChecked(self.glPreview) self.glPreviewCheckbox.toggled.connect(self.glPreviewToggled) self.optionsHolder = QtGui.QStackedWidget() self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) self.generateButton = QtGui.QPushButton(self.tr("Generate")) self.generateButton.clicked.connect(self.generateClicked) column.append(self.generatorTypeInput) column.append(self.livePreviewCheckbox) column.append(self.blockPreviewCheckbox) column.append(self.glPreviewCheckbox) column.append(self.optionsHolder) column.append(self.generateButton) self.toolWidget.setLayout(Column(*column)) self.overlayNode = scenegraph.Node() self.sceneHolderNode = scenegraph.TranslateNode() self.overlayNode.addChild(self.sceneHolderNode) self.previewNode = None self.boxHandleNode = BoxHandle() self.boxHandleNode.boundsChanged.connect(self.boundsDidChange) self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone) self.overlayNode.addChild(self.boxHandleNode) self.worldScene = None self.loader = None self.previewBounds = None self.schematicBounds = None self.currentSchematic = None self.currentTypeChanged(0) # Name of last selected generator plugin is saved after unloading # so it can be reselected if it is immediately reloaded self._lastTypeName = None _GeneratePlugins.instance.pluginAdded.connect(self.addPlugin) _GeneratePlugins.instance.pluginRemoved.connect(self.removePlugin) def removePlugin(self, cls): self.generatorTypes[:] = [gt for gt in self.generatorTypes if not isinstance(gt, cls)] self.generatorTypesChanged() if self.currentGenerator not in self.generatorTypes: lastTypeName = self.currentGenerator.__class__.__name__ self.currentTypeChanged(0) # resets self._lastTypeName self._lastTypeName = lastTypeName def addPlugin(self, cls): self.generatorTypes.append(cls(self)) self.generatorTypesChanged() if self._lastTypeName is not None: if cls.__name__ == self._lastTypeName: self.currentTypeChanged(len(self.generatorTypes)-1) def generatorTypesChanged(self): for gt in self.generatorTypes: if hasattr(gt, 'displayName'): displayName = gt.displayName else: displayName = gt.__class__.__name__ self.generatorTypeInput.addItem(displayName, gt) def livePreviewToggled(self, value): self.livePreview = value def blockPreviewToggled(self, value): self.blockPreview = value if value: if self.currentSchematic: self.displaySchematic(self.currentSchematic, self.schematicBounds.origin) else: self.updateBlockPreview() else: self.clearSchematic() def glPreviewToggled(self, value): self.glPreview = value if value: self.updateNodePreview() # xxx cache previewNode? else: self.clearNode() def currentTypeChanged(self, index): # user selected generator type after old type was unloaded, so forget the old type self._lastTypeName = None self.optionsHolder.removeWidget(self.optionsHolder.widget(0)) if index < len(self.generatorTypes): self.currentGenerator = self.generatorTypes[index] self.optionsHolder.addWidget(self.currentGenerator.getOptionsWidget()) self.updatePreview() else: self.currentGenerator = None self.clearSchematic() self.clearNode() def mousePress(self, event): self.boxHandleNode.mousePress(event) def mouseMove(self, event): self.boxHandleNode.mouseMove(event) def mouseRelease(self, event): self.boxHandleNode.mouseRelease(event) def boundsDidChange(self, bounds): # box still being resized if not self.currentGenerator: return if not self.livePreview: return self.previewBounds = bounds self.currentGenerator.boundsChanged(bounds) self.updatePreview() def boundsDidChangeDone(self, bounds, newSelection): # box finished resize if not self.currentGenerator: return self.previewBounds = bounds self.schematicBounds = bounds self.currentGenerator.boundsChanged(bounds) self.updatePreview() def clearNode(self): if self.previewNode: self.overlayNode.removeChild(self.previewNode) self.previewNode = None def updatePreview(self): if self.blockPreview: self.updateBlockPreview() else: self.clearSchematic() if self.glPreview: self.updateNodePreview() else: self.clearNode() def updateBlockPreview(self): bounds = self.previewBounds if bounds is not None and bounds.volume > 0: self.generateNextSchematic(bounds) else: self.clearSchematic() def updateNodePreview(self): bounds = self.previewBounds if self.currentGenerator is None: return if bounds is not None and bounds.volume > 0: node = self.currentGenerator.getPreviewNode(bounds) if node is not None: self.clearNode() if isinstance(node, list): nodes = node node = scenegraph.Node() for c in nodes: node.addChild(c) self.overlayNode.addChild(node) self.previewNode = node def generateNextSchematic(self, bounds): if bounds is None: self.clearSchematic() return if self.currentGenerator is None: return try: schematic = self.currentGenerator.generate(bounds, self.editorSession.worldEditor.blocktypes) self.currentSchematic = schematic self.displaySchematic(schematic, bounds.origin) except Exception as e: log.exception("Error while running generator %s: %s", self.currentGenerator, e) QtGui.QMessageBox.warning(qApp.mainWindow, "Error while running generator", "An error occurred while running the generator: \n %s.\n\n" "Traceback: %s" % (e, traceback.format_exc())) self.livePreview = False def displaySchematic(self, schematic, offset): if schematic is not None: dim = schematic.getDimension() if self.worldScene: self.sceneHolderNode.removeChild(self.worldScene) self.loader.timer.stop() self.loader = None atlas = self.editorSession.textureAtlas self.worldScene = WorldScene(dim, atlas) self.sceneHolderNode.translateOffset = offset self.sceneHolderNode.addChild(self.worldScene) self.loader = WorldLoader(self.worldScene) if dim.chunkCount() <= self.instantDisplayChunks: exhaust(self.loader.work()) else: self.loader.timer.start() else: self.clearSchematic() def clearSchematic(self): if self.worldScene: self.sceneHolderNode.removeChild(self.worldScene) self.worldScene = None self.loader.timer.stop() self.loader = None def generateClicked(self): if self.currentGenerator is None: return if self.schematicBounds is None: log.info("schematicBounds is None, not generating") return if self.currentSchematic is None: log.info("Generating new schematic for import") currentSchematic = self.currentGenerator.generate(self.schematicBounds, self.editorSession.worldEditor.blocktypes) else: log.info("Importing previously generated schematic.") currentSchematic = self.currentSchematic command = GenerateCommand(self, self.schematicBounds) try: with command.begin(): if currentSchematic is not None: task = self.editorSession.currentDimension.importSchematicIter(currentSchematic, self.schematicBounds.origin) showProgress(self.tr("Importing generated object..."), task) else: task = self.currentGenerator.generateInWorld(self.schematicBounds, self.editorSession.currentDimension) showProgress(self.tr("Generating object in world..."), task) except Exception as e: log.exception("Error while importing or generating in world: %r" % e) command.undo() else: self.editorSession.pushCommand(command)
class GenerateTool(EditorTool): name = "Generate" iconName = "generate" instantDisplayChunks = 32 modifiesWorld = True def __init__(self, *args, **kwargs): EditorTool.__init__(self, *args, **kwargs) self.livePreview = False self.blockPreview = False self.glPreview = True toolWidget = QtGui.QWidget() self.toolWidget = toolWidget column = [] self.generatorTypes = [ pluginClass(self) for pluginClass in GeneratePlugins.registeredPlugins ] self.currentGenerator = None if len(self.generatorTypes): self.currentGenerator = self.generatorTypes[0] self.generatorTypeInput = QtGui.QComboBox() self.generatorTypesChanged() self.generatorTypeInput.currentIndexChanged.connect( self.currentTypeChanged) self.livePreviewCheckbox = QtGui.QCheckBox("Live Preview") self.livePreviewCheckbox.setChecked(self.livePreview) self.livePreviewCheckbox.toggled.connect(self.livePreviewToggled) self.blockPreviewCheckbox = QtGui.QCheckBox("Block Preview") self.blockPreviewCheckbox.setChecked(self.blockPreview) self.blockPreviewCheckbox.toggled.connect(self.blockPreviewToggled) self.glPreviewCheckbox = QtGui.QCheckBox("GL Preview") self.glPreviewCheckbox.setChecked(self.glPreview) self.glPreviewCheckbox.toggled.connect(self.glPreviewToggled) self.optionsHolder = QtGui.QStackedWidget() self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) self.generateButton = QtGui.QPushButton(self.tr("Generate")) self.generateButton.clicked.connect(self.generateClicked) column.append(self.generatorTypeInput) column.append(self.livePreviewCheckbox) column.append(self.blockPreviewCheckbox) column.append(self.glPreviewCheckbox) column.append(self.optionsHolder) column.append(self.generateButton) self.toolWidget.setLayout(Column(*column)) self.overlayNode = scenenode.Node("generateOverlay") self.sceneHolderNode = Node("sceneHolder") self.sceneTranslate = Translate() self.sceneHolderNode.addState(self.sceneTranslate) self.overlayNode.addChild(self.sceneHolderNode) self.previewNode = None self.boxHandleNode = BoxHandle() self.boxHandleNode.boundsChanged.connect(self.boundsDidChange) self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone) self.overlayNode.addChild(self.boxHandleNode) self.worldScene = None self.loader = None self.previewBounds = None self.schematicBounds = None self.currentSchematic = None self.currentTypeChanged(0) # Name of last selected generator plugin is saved after unloading # so it can be reselected if it is immediately reloaded self._lastTypeName = None GeneratePlugins.pluginAdded.connect(self.addPlugin) GeneratePlugins.pluginRemoved.connect(self.removePlugin) def removePlugin(self, cls): log.info("Removing plugin %s", cls.__name__) self.generatorTypes[:] = [ gt for gt in self.generatorTypes if not isinstance(gt, cls) ] self.generatorTypesChanged() if self.currentGenerator not in self.generatorTypes: lastTypeName = self.currentGenerator.__class__.__name__ self.currentTypeChanged(0) # resets self._lastTypeName self._lastTypeName = lastTypeName def addPlugin(self, cls): log.info("Adding plugin %s", cls.__name__) self.generatorTypes.append(cls(self)) self.generatorTypesChanged() if self._lastTypeName is not None: if cls.__name__ == self._lastTypeName: self.currentTypeChanged(len(self.generatorTypes) - 1) def generatorTypesChanged(self): self.generatorTypeInput.clear() for gt in self.generatorTypes: if hasattr(gt, 'displayName'): displayName = gt.displayName else: displayName = gt.__class__.__name__ self.generatorTypeInput.addItem(displayName, gt) def livePreviewToggled(self, value): self.livePreview = value def blockPreviewToggled(self, value): self.blockPreview = value if value: if self.currentSchematic: self.displaySchematic(self.currentSchematic, self.schematicBounds.origin) else: self.updateBlockPreview() else: self.clearSchematic() def glPreviewToggled(self, value): self.glPreview = value if value: self.updateNodePreview() # xxx cache previewNode? else: self.clearNode() def currentTypeChanged(self, index): # user selected generator type after old type was unloaded, so forget the old type self._lastTypeName = None self.optionsHolder.removeWidget(self.optionsHolder.widget(0)) if index < len(self.generatorTypes): self.currentGenerator = self.generatorTypes[index] self.optionsHolder.addWidget( self.currentGenerator.getOptionsWidget()) self.updatePreview() else: self.currentGenerator = None self.clearSchematic() self.clearNode() log.info("Chose generator %s", repr(self.currentGenerator)) def mousePress(self, event): self.boxHandleNode.mousePress(event) def mouseMove(self, event): self.boxHandleNode.mouseMove(event) def mouseRelease(self, event): self.boxHandleNode.mouseRelease(event) def boundsDidChange(self, bounds): # box still being resized if not self.currentGenerator: return if not self.livePreview: return self.previewBounds = bounds self.currentGenerator.boundsChanged(bounds) self.updatePreview() def boundsDidChangeDone(self, bounds, oldBounds): # box finished resize if not self.currentGenerator: return self.previewBounds = bounds self.schematicBounds = bounds self.currentGenerator.boundsChanged(bounds) self.updatePreview() def clearNode(self): if self.previewNode: self.overlayNode.removeChild(self.previewNode) self.previewNode = None def updatePreview(self): if self.blockPreview: self.updateBlockPreview() else: self.clearSchematic() if self.glPreview: self.updateNodePreview() else: self.clearNode() def updateBlockPreview(self): bounds = self.previewBounds if bounds is not None and bounds.volume > 0: self.generateNextSchematic(bounds) else: self.clearSchematic() def updateNodePreview(self): bounds = self.previewBounds if self.currentGenerator is None: return if bounds is not None and bounds.volume > 0: try: node = self.currentGenerator.getPreviewNode(bounds) except Exception: log.exception( "Error while getting scene nodes from generator:") else: if node is not None: self.clearNode() if isinstance(node, list): nodes = node node = scenenode.Node("generatePreviewHolder") for c in nodes: node.addChild(c) self.overlayNode.addChild(node) self.previewNode = node def generateNextSchematic(self, bounds): if bounds is None: self.clearSchematic() return if self.currentGenerator is None: return try: schematic = self.currentGenerator.generate( bounds, self.editorSession.worldEditor.blocktypes) self.currentSchematic = schematic self.displaySchematic(schematic, bounds.origin) except Exception as e: log.exception("Error while running generator %s: %s", self.currentGenerator, e) QtGui.QMessageBox.warning( QtGui.qApp.mainWindow, "Error while running generator", "An error occurred while running the generator: \n %s.\n\n" "Traceback: %s" % (e, traceback.format_exc())) self.livePreview = False def displaySchematic(self, schematic, offset): if schematic is not None: dim = schematic.getDimension() if self.worldScene: self.sceneHolderNode.removeChild(self.worldScene) self.loader.timer.stop() self.loader = None atlas = self.editorSession.textureAtlas self.worldScene = WorldScene(dim, atlas) self.sceneTranslate.translateOffset = offset self.sceneHolderNode.addChild(self.worldScene) self.loader = WorldLoader(self.worldScene) if dim.chunkCount() <= self.instantDisplayChunks: exhaust(self.loader.work()) else: self.loader.startLoader() else: self.clearSchematic() def clearSchematic(self): if self.worldScene: self.sceneHolderNode.removeChild(self.worldScene) self.worldScene = None self.loader.timer.stop() self.loader = None def generateClicked(self): if self.currentGenerator is None: return if self.schematicBounds is None: log.info("schematicBounds is None, not generating") return if self.currentSchematic is None: log.info("Generating new schematic for import") currentSchematic = self.currentGenerator.generate( self.schematicBounds, self.editorSession.worldEditor.blocktypes) else: log.info("Importing previously generated schematic.") currentSchematic = self.currentSchematic command = GenerateCommand(self, self.schematicBounds) try: with command.begin(): if currentSchematic is not None: task = self.editorSession.currentDimension.importSchematicIter( currentSchematic, self.schematicBounds.origin) showProgress(self.tr("Importing generated object..."), task) else: task = self.currentGenerator.generateInWorld( self.schematicBounds, self.editorSession.currentDimension) showProgress(self.tr("Generating object in world..."), task) except Exception as e: log.exception("Error while importing or generating in world: %r" % e) command.undo() else: self.editorSession.pushCommand(command)
class GenerateTool(EditorTool): name = "Generate" iconName = "generate" instantDisplayChunks = 32 def __init__(self, *args, **kwargs): EditorTool.__init__(self, *args, **kwargs) self.createToolWidget() def createToolWidget(self): toolWidget = QtGui.QWidget() self.toolWidget = toolWidget column = [] self.generatorTypes = [TreeGen()] self.currentType = self.generatorTypes[0] self.generatorTypeInput = QtGui.QComboBox() for gt in self.generatorTypes: self.generatorTypeInput.addItem(gt.displayName, gt) self.generatorTypeInput.currentIndexChanged.connect( self.generatorTypeChanged) self.optionsHolder = QtGui.QStackedWidget() self.optionsHolder.setSizePolicy(QtGui.QSizePolicy.Preferred, QtGui.QSizePolicy.Expanding) column.append(self.generatorTypeInput) column.append(self.optionsHolder) self.toolWidget.setLayout(Column(*column)) self.overlayNode = scenegraph.Node() self.sceneHolderNode = scenegraph.TranslateNode() self.overlayNode.addChild(self.sceneHolderNode) self.boxHandleNode = BoxHandle() self.boxHandleNode.boundsChanged.connect(self.boundsDidChange) self.boxHandleNode.boundsChangedDone.connect(self.boundsDidChangeDone) self.overlayNode.addChild(self.boxHandleNode) self.worldScene = None self.schematicBounds = None def generatorTypeChanged(self, index): self.currentType = self.generatorTypes[index] self.optionsHolder.removeWidget(self.optionsHolder.widget(0)) self.optionsHolder.addWidget(self.currentType.getOptionsWidget()) def mousePress(self, event): self.boxHandleNode.mousePress(event) def mouseMove(self, event): self.boxHandleNode.mouseMove(event) def mouseRelease(self, event): self.boxHandleNode.mouseRelease(event) def boundsDidChange(self, bounds): if bounds is not None and bounds.volume: node = self.currentType.getPreviewNode() if node is not None: pass else: if self.schematicBounds is None or self.schematicBounds.size != bounds.size: schematic = self.currentType.generatePreview( bounds, self.editorSession.worldEditor.blocktypes) self.displaySchematic(schematic, bounds.origin) else: self.sceneHolderNode.translateOffset = bounds.origin self.schematicBounds = bounds def boundsDidChangeDone(self, bounds, newSelection): if bounds is not None and bounds.volume: if self.schematicBounds is None or self.schematicBounds.size != bounds.size: schematic = self.currentType.generate( bounds, self.editorSession.worldEditor.blocktypes) offset = bounds.origin self.displaySchematic(schematic, offset) else: self.sceneHolderNode.translateOffset = bounds.origin else: self.displaySchematic(None, None) self.schematicBounds = bounds def displaySchematic(self, schematic, offset): if schematic is not None: dim = schematic.getDimension() if self.worldScene: self.sceneHolderNode.removeChild(self.worldScene) self.loader.timer.stop() self.loader = None atlas = self.editorSession.textureAtlas self.worldScene = WorldScene(dim, atlas) self.sceneHolderNode.translateOffset = offset self.sceneHolderNode.addChild(self.worldScene) self.loader = WorldLoader(self.worldScene) if dim.chunkCount() <= self.instantDisplayChunks: for _ in self.loader.work(): pass else: self.loader.timer.start() else: if self.worldScene: self.sceneHolderNode.removeChild(self.worldScene) self.worldScene = None self.loader.timer.stop() self.loader = None