Beispiel #1
0
    def __init__(self, editorSession, *args, **kwargs):
        super(MoveTool, self).__init__(editorSession, *args, **kwargs)
        self.overlayNode = scenenode.Node("moveOverlay")
        self._currentImport = None
        self._currentImportNode = None

        self.toolWidget = QtGui.QWidget()

        self.pointInput = CoordinateWidget()
        self.pointInput.pointChanged.connect(self.pointInputChanged)

        self.rotationInput = RotationWidget()
        self.rotationInput.rotationChanged.connect(self.rotationChanged)

        self.copyOptionsWidget = QtGui.QGroupBox(self.tr("Options"))

        self.copyAirCheckbox = QtGui.QCheckBox(self.tr("Copy Air"))
        self.copyOptionsWidget.setLayout(Column(self.copyAirCheckbox))

        confirmButton = QtGui.QPushButton(
            "Confirm")  # xxxx should be in worldview
        confirmButton.clicked.connect(self.confirmImport)
        self.toolWidget.setLayout(
            Column(self.pointInput, self.rotationInput, self.copyOptionsWidget,
                   confirmButton, None))
Beispiel #2
0
    def __init__(self, editorSession):
        """

        :param editorSession:
        :type editorSession: mcedit2.editorsession.EditorSession
        :return:
        :rtype:
        """
        super(InspectorWidget, self).__init__()
        load_ui("inspector.ui", baseinstance=self)
        self.editorSession = editorSession

        self.blockNBTEditor.editorSession = self.editorSession
        self.entityNBTEditor.editorSession = self.editorSession
        self.chunkNBTEditor.editorSession = self.editorSession

        self.blockEditorWidget = None

        self.tileEntity = None
        self.entity = None

        self.currentChunk = None

        # xxxx unused! how!
        self.selectionNode = None
        self.overlayNode = scenenode.Node()

        self.chunkTabWidget.currentChanged.connect(self.chunkTabDidChange)

        self.terrainPopulatedInput.toggled.connect(
            self.terrainPopulatedDidChange)
        self.lightPopulatedInput.toggled.connect(self.lightPopulatedDidChange)
        self.inhabitedTimeInput.valueChanged.connect(
            self.inhabitedTimeDidChange)
        self.updateTimeInput.valueChanged.connect(self.updateTimeDidChange)
Beispiel #3
0
    def createSceneGraph(self):
        sceneGraph = scenenode.Node("WorldView SceneGraph")
        self.worldScene = self.createWorldScene()
        self.worldScene.setVisibleLayers(
            self.layerToggleGroup.getVisibleLayers())

        clearNode = ClearNode()
        self.skyNode = sky.SkyNode()
        self.loadableChunksNode = loadablechunks.LoadableChunksNode(
            self.dimension)

        self.worldNode = Node("World Container")
        self.matrixState = MatrixState()
        self.worldNode.addState(self.matrixState)
        self._updateMatrices()

        self.worldNode.addChild(self.loadableChunksNode)
        self.worldNode.addChild(self.worldScene)
        self.worldNode.addChild(self.overlayNode)

        sceneGraph.addChild(clearNode)
        sceneGraph.addChild(self.skyNode)
        sceneGraph.addChild(self.worldNode)
        sceneGraph.addChild(self.compassNode)
        if self.cursorNode:
            self.worldNode.addChild(self.cursorNode)

        return sceneGraph
Beispiel #4
0
    def makeChunkVertices(self, chunk, limitBox):
        sceneNode = scenenode.Node("monsters")
        for i, ref in enumerate(chunk.Entities):
            ID = ref.id
            if ID not in models.cookedModels:
                continue

            model = models.cookedModels[ID]
            texturePath = models.getModelTexture(ref)
            if texturePath is None:
                modelTex = None
            else:
                modelTex = self.chunkUpdate.updateTask.getModelTexture(
                    texturePath)

            node = entityModelNode(ref, model, modelTex, chunk)
            sceneNode.addChild(node)
            if ID == "Sheep":
                woolID = "MCEDIT_SheepWool"
                model = models.cookedModels[woolID]
                texturePath = models.getTexture(woolID)
                modelTex = self.chunkUpdate.updateTask.getModelTexture(
                    texturePath)

                node = entityModelNode(ref, model, modelTex, chunk)
                sceneNode.addChild(node)

            yield

        if not sceneNode.childCount():
            return

        self.sceneNode = sceneNode
Beispiel #5
0
    def makeChunkVertices(self, chunk, limitBox):
        mapTiles = []
        for i, ref in enumerate(chunk.Entities):
            if ref.id != "ItemFrame":
                continue

            if i % 10 == 0:
                yield

            if limitBox and ref.Position not in limitBox:
                continue

            try:
                item = ref.Item
                if item.itemType.internalName != "minecraft:filled_map":
                    continue
            except KeyError:
                log.exception(
                    "Error while getting ItemFrame item ID in frame at %s",
                    ref.TilePos)
                continue

            mapID = item.Damage

            mapTex = self.chunkUpdate.updateTask.getMapTexture(mapID)
            # xxx if mapTex is None: mapTex = missingNoTex

            # xxxx assumes 1.8 TilePos - fix this in ref??
            mapTiles.append((mapTex, ref.TilePos, ref.Facing))

        if not len(mapTiles):
            return

        nodes = []

        for mapTex, (x, y, z), facing in mapTiles:
            vertexBuffer = QuadVertexArrayBuffer(1,
                                                 lights=False,
                                                 textures=True)

            # chunk is already translated - why?
            x -= chunk.cx << 4
            z -= chunk.cz << 4

            vertexBuffer.vertex[:] = x, y, z
            corners = self.faceCorners[facing]
            vertexBuffer.vertex[:] += corners
            texCorners = [(1, 1), (1, 0), (0, 0), (0, 1)]
            vertexBuffer.texcoord[:] += texCorners

            vertexNode = VertexNode([vertexBuffer])
            if mapTex is not None:
                bindTexture = BindTexture(mapTex)
                vertexNode.addState(bindTexture)
            nodes.append(vertexNode)

        self.sceneNode = scenenode.Node("itemFrames")
        for node in nodes:
            self.sceneNode.addChild(node)
Beispiel #6
0
    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.optionsButton = QtGui.QPushButton(self.tr("Options"))

        self.optionsMenu = QtGui.QMenu()
        self.optionsButton.setMenu(self.optionsMenu)

        classicSelectionAction = self.optionsMenu.addAction(
            self.tr("Classic Selection"))
        stickySelectionAction = self.optionsMenu.addAction(
            self.tr("Sticky Selection"))

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget(addShapes=[ChunkShape()])
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.shapeInput.shapeOptionsChanged.connect(self.shapeDidChange)

        self.toolWidget.setLayout(
            Column(self.optionsButton, self.coordInput, self.shapeInput, None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenenode.Node("selectOverlay")
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        classicSelectionAction.setCheckable(True)
        classicSelectionAction.toggled.connect(ClassicSelectionOption.setValue)
        classicSelectionAction.setChecked(ClassicSelectionOption.value())
        ClassicSelectionOption.connectAndCall(self.setClassicSelection)

        stickySelectionAction.setCheckable(True)
        stickySelectionAction.toggled.connect(StickySelectionOption.setValue)
        stickySelectionAction.setChecked(StickySelectionOption.value())
        StickySelectionOption.connectAndCall(self.setStickySelection)

        editorSession.dimensionChanged.connect(self.dimensionDidChange)
        editorSession.revisionChanged.connect(self.revisionDidChange)
Beispiel #7
0
    def __init__(self, editorSession):
        """

        :param editorSession:
        :type editorSession: mcedit2.editorsession.EditorSession
        :return:
        :rtype:
        """
        super(InspectorWidget, self).__init__()
        self.setupUi(self)

        self.editorSession = editorSession

        self.blockNBTEditor.editorSession = self.editorSession
        self.entityNBTEditor.editorSession = self.editorSession
        self.chunkNBTEditor.editorSession = self.editorSession

        self.blockEditorWidget = None

        self.tileEntity = None
        self.entity = None
        self.blockPos = None

        self.currentChunk = None

        self.overlayNode = scenenode.Node("inspectorOverlay")
        self.selectionNode = SelectionBoxNode()
        self.selectionNode.depth = depths.DepthOffsets.SelectionCursor
        self.selectionNode.filled = False
        self.selectionNode.wireColor = (0.2, 0.9, .2, .8)

        self.overlayNode.addChild(self.selectionNode)

        self.commandBlockVisualsNode = None

        self.chunkTabWidget.currentChanged.connect(self.chunkTabDidChange)

        self.terrainPopulatedInput.toggled.connect(
            self.terrainPopulatedDidChange)
        self.lightPopulatedInput.toggled.connect(self.lightPopulatedDidChange)
        self.inhabitedTimeInput.valueChanged.connect(
            self.inhabitedTimeDidChange)
        self.updateTimeInput.valueChanged.connect(self.updateTimeDidChange)

        self.blockXSpinBox.valueChanged.connect(self.blockXChanged)
        self.blockYSpinBox.valueChanged.connect(self.blockYChanged)
        self.blockZSpinBox.valueChanged.connect(self.blockZChanged)

        self.removeEntityButton.clicked.connect(self.removeEntity)

        self.addTileEntityButton.clicked.connect(self.addTileEntity)
        self.removeTileEntityButton.clicked.connect(self.removeTileEntity)
Beispiel #8
0
    def __init__(self, editorSession, *args, **kwargs):
        super(CloneTool, self).__init__(editorSession, *args, **kwargs)

        self.originPoint = None

        self.pendingClones = []
        self.pendingCloneNodes = []
        self.mainCloneNode = None

        self.overlayNode = scenenode.Node("cloneOverlay")

        self.toolWidget = QtGui.QWidget()
        self.pointInput = CoordinateWidget()
        self.pointInput.pointChanged.connect(self.pointInputChanged)

        self.rotationInput = RotationWidget()
        self.rotationInput.rotationChanged.connect(self.rotationChanged)

        self.scaleInput = ScaleWidget()
        self.scaleInput.scaleChanged.connect(self.scaleChanged)
        
        confirmButton = QtGui.QPushButton(self.tr("Confirm"))  # xxxx should be in worldview
        confirmButton.clicked.connect(self.confirmClone)

        self.repeatCount = 1
        self.repeatCountInput = QtGui.QSpinBox(minimum=1, maximum=10000, value=1)
        self.repeatCountInput.valueChanged.connect(self.setRepeatCount)

        self.rotateRepeatsCheckbox = QtGui.QCheckBox(self.tr("Rotate Repeats"))
        self.rotateRepeatsCheckbox.toggled.connect(self.updateTiling)

        self.rotateOffsetCheckbox = QtGui.QCheckBox(self.tr("Rotate Offset"))
        self.rotateOffsetCheckbox.toggled.connect(self.updateTiling)

        self.toolWidget.setLayout(Column(self.pointInput,
                                         self.rotationInput,
                                         Row(self.rotateRepeatsCheckbox,
                                             self.rotateOffsetCheckbox),
                                         self.scaleInput,
                                         Row(QtGui.QLabel(self.tr("Repeat count: ")), self.repeatCountInput),
                                         confirmButton,
                                         None))

        self.mainPendingClone = None  # Do this after creating pointInput to disable inputs
Beispiel #9
0
    def makeChunkVertices(self, chunk, limitBox):
        sceneNode = scenenode.Node("tileEntityModels")
        chests = {}
        for i, ref in enumerate(chunk.TileEntities):
            ID = ref.id
            if ID not in models.cookedTileEntityModels:
                continue
            if ID == "Chest":
                chests[ref.Position] = ref, {}
                continue

        for (x, y, z), (ref, adj) in chests.iteritems():
            for dx, dz in ((-1, 0), (1, 0), (0, -1), (0, 1)):
                if (x + dx, y, z + dz) in chests:
                    adj[dx, dz] = ref

        for ref, adj in chests.itervalues():
            if (-1, 0) not in adj and (0, -1) not in adj:
                if (1, 0) not in adj and (0, 1) not in adj:
                    model = models.cookedTileEntityModels[ref.id]
                else:
                    model = models.cookedTileEntityModels["MCEDIT_LargeChest"]

                texturePath = model.modelTexture
                if texturePath is None:
                    modelTex = None
                else:
                    modelTex = self.chunkUpdate.updateTask.getModelTexture(
                        texturePath)

                block = chunk.dimension.getBlock(*ref.Position)
                if block.internalName != "minecraft:chest":
                    continue
                blockState = block.blockState[1:-1]
                facing = blockState.split("=")[1]

                node = chestEntityModelNode(ref, model, modelTex, chunk,
                                            facing, (1, 0) in adj, (0, 1)
                                            in adj)
                sceneNode.addChild(node)

                yield

        self.sceneNode = sceneNode
Beispiel #10
0
    def __init__(self, editorSession, *args, **kwargs):
        super(CloneTool, self).__init__(editorSession, *args, **kwargs)

        self.originPoint = None
        self.offsetPoint = None

        self.pendingCloneNodes = []
        self.mainCloneNode = None
        self.overlayNode = scenenode.Node()
        self.overlayNode.name = "Clone Overlay"

        self.toolWidget = QtGui.QWidget()
        self.pointInput = CoordinateWidget()
        self.pointInput.pointChanged.connect(self.pointInputChanged)
        confirmButton = QtGui.QPushButton(
            self.tr("Confirm"))  # xxxx should be in worldview
        confirmButton.clicked.connect(self.confirmClone)

        self.repeatCount = 1
        self.repeatCountInput = QtGui.QSpinBox(minimum=1, maximum=100, value=1)
        self.repeatCountInput.valueChanged.connect(self.setRepeatCount)

        self.tileX = self.tileY = self.tileZ = False

        self.tileXCheckbox = QtGui.QCheckBox(self.tr("Tile X"))
        self.tileXCheckbox.toggled.connect(self.setTileX)

        self.tileYCheckbox = QtGui.QCheckBox(self.tr("Tile Y"))
        self.tileYCheckbox.toggled.connect(self.setTileY)

        self.tileZCheckbox = QtGui.QCheckBox(self.tr("Tile Z"))
        self.tileZCheckbox.toggled.connect(self.setTileZ)

        self.toolWidget.setLayout(
            Column(
                self.pointInput,
                Row(QtGui.QLabel(self.tr("Repeat count: ")),
                    self.repeatCountInput),
                Row(self.tileXCheckbox, self.tileYCheckbox,
                    self.tileZCheckbox), confirmButton, None))

        self.pendingClone = None  # Do this after creating pointInput to disable inputs
Beispiel #11
0
    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()
                        for c in nodes:
                            node.addChild(c)

                    self.overlayNode.addChild(node)
                    self.previewNode = node
Beispiel #12
0
    def __init__(self, editorSession, *args, **kwargs):
        """
        :type editorSession: EditorSession
        """
        super(SelectionTool, self).__init__(editorSession, *args, **kwargs)
        toolWidget = QtGui.QWidget()

        editorSession.selectionChanged.connect(self.selectionDidChange)

        self.toolWidget = toolWidget

        self.coordInput = SelectionCoordinateWidget()
        self.coordInput.boxChanged.connect(self.coordInputChanged)
        self.shapeInput = ShapeWidget(addShapes=[ChunkShape()])
        self.shapeInput.shapeChanged.connect(self.shapeDidChange)
        self.shapeInput.shapeOptionsChanged.connect(self.shapeDidChange)

        self.toolWidget.setLayout(
            Column(self.coordInput, self.shapeInput, None))

        self.cursorNode = SelectionCursor()
        self.overlayNode = scenenode.Node()
        self.faceHoverNode = SelectionFaceNode()
        self.selectionNode = SelectionScene()
        self.overlayNode.addChild(self.selectionNode)
        self.overlayNode.addChild(self.faceHoverNode)

        self.boxHandleNode = BoxHandle()
        self.boxHandleNode.boundsChanged.connect(self.boxHandleResized)
        self.boxHandleNode.boundsChangedDone.connect(self.boxHandleResizedDone)
        self.overlayNode.addChild(self.boxHandleNode)

        self.newSelectionNode = None

        editorSession.dimensionChanged.connect(self.dimensionDidChange)
        editorSession.revisionChanged.connect(self.revisionDidChange)
Beispiel #13
0
    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)
Beispiel #14
0
    def __init__(self,
                 dimension,
                 textureAtlas=None,
                 geometryCache=None,
                 sharedGLWidget=None):
        """

        :param dimension:
        :type dimension: WorldEditorDimension
        :param textureAtlas:
        :type textureAtlas: TextureAtlas
        :param geometryCache:
        :type geometryCache: GeometryCache
        :param sharedGLWidget:
        :type sharedGLWidget: QGLWidget
        :return:
        :rtype:
        """
        QGLWidget.__init__(self, shareWidget=sharedGLWidget)
        self.dimension = None
        self.worldScene = None
        self.loadableChunksNode = None
        self.textureAtlas = None

        validateWidgetQGLContext(self)

        self.bufferSwapDone = True

        if THREADED_BUFFER_SWAP:
            self.setAutoBufferSwap(False)
            self.bufferSwapThread = QtCore.QThread()
            self.bufferSwapper = BufferSwapper(self)
            self.bufferSwapper.moveToThread(self.bufferSwapThread)
            self.doSwapBuffers.connect(self.bufferSwapper.swap)
            self.bufferSwapThread.start()

        self.setAcceptDrops(True)
        self.setSizePolicy(QtGui.QSizePolicy.Policy.Expanding,
                           QtGui.QSizePolicy.Policy.Expanding)
        self.setFocusPolicy(Qt.ClickFocus)

        self.layerToggleGroup = LayerToggleGroup()
        self.layerToggleGroup.layerToggled.connect(self.setLayerVisible)

        self.mouseRay = Ray(Vector(0, 1, 0), Vector(0, -1, 0))

        self.setMouseTracking(True)

        self.lastAutoUpdate = time.time()
        self.autoUpdateInterval = 0.5  # frequency of screen redraws in response to loaded chunks

        self.compassNode = self.createCompass()
        self.compassOrtho = Ortho((1, float(self.height()) / self.width()))
        self.compassNode.addState(self.compassOrtho)

        self.viewActions = []
        self.pressedKeys = set()

        self.setTextureAtlas(textureAtlas)

        if geometryCache is None and sharedGLWidget is not None:
            geometryCache = sharedGLWidget.geometryCache
        if geometryCache is None:
            geometryCache = GeometryCache()
        self.geometryCache = geometryCache

        self.worldNode = None
        self.skyNode = None
        self.overlayNode = scenenode.Node("WorldView Overlay")

        self.sceneGraph = None
        self.renderGraph = None

        self.frameSamples = deque(maxlen=500)
        self.frameSamples.append(time.time())

        self.cursorNode = None

        self.setDimension(dimension)
Beispiel #15
0
    def makeChunkVertices(self, chunk, limitBox):
        """

        :param chunk:
        :type chunk: WorldEditorChunk
        :param limitBox:
        :return: :raise:
        """
        dim = chunk.dimension
        cx, cz = chunk.chunkPosition

        if not hasattr(chunk, 'HeightMap') or chunk.HeightMap is None:
            return

        heightMap = chunk.HeightMap
        chunkWidth = chunkLength = 16
        chunkHeight = chunk.dimension.bounds.height

        z, x = list(numpy.indices((chunkLength, chunkWidth)))
        y = (heightMap - 1)[:chunkLength, :chunkWidth]
        numpy.clip(y, 0, chunkHeight - 1, y)

        nonZeroHeights = y > 0
        heights = y.reshape((16, 16))

        x = x[nonZeroHeights]
        if not len(x):
            return

        z = z[nonZeroHeights]
        y = y[nonZeroHeights]

        # Get the top block in each column
        blockResult = dim.getBlocks(x + (cx * 16),
                                    y,
                                    z + (cz * 16),
                                    return_Data=True)
        topBlocks = blockResult.Blocks
        topBlockData = blockResult.Data

        # Get the block above each column top. We'll recolor the top face of the column if a flower or another
        # transparent block is on top.

        aboveY = y + 1
        numpy.clip(aboveY, 0, chunkHeight - 1, aboveY)
        blocksAbove = dim.getBlocks(x + (cx * 16), aboveY,
                                    z + (cz * 16)).Blocks

        flatcolors = dim.blocktypes.mapColor[topBlocks,
                                             topBlockData][:, numpy.newaxis, :]

        yield
        vertexBuffer = QuadVertexArrayBuffer(len(x),
                                             textures=False,
                                             lights=False)

        vertexBuffer.vertex[..., 0] = x[:, numpy.newaxis]
        vertexBuffer.vertex[..., 1] = y[:, numpy.newaxis]
        vertexBuffer.vertex[..., 2] = z[:, numpy.newaxis]

        va0 = vertexBuffer.copy()

        va0.vertex[:] += standardCubeTemplates[faces.FaceYIncreasing, ..., :3]

        overmask = blocksAbove > 0
        colors = dim.blocktypes.mapColor[:, 0][
            blocksAbove[overmask]][:, numpy.newaxis]
        flatcolors[overmask] = colors

        if self.detailLevel == 2:
            heightfactor = (y /
                            float(chunk.dimension.bounds.height)) * 0.33 + 0.66
            flatcolors[
                ..., :
                3] *= heightfactor[:, numpy.newaxis, numpy.
                                   newaxis]  # xxx implicit cast from byte to float and back

        va0.rgb[:] = flatcolors

        yield
        if self.detailLevel == 2:
            self.sceneNode = VertexNode(va0)
            return

        # Calculate how deep each column needs to go to be flush with the adjacent column;
        # If columns extend all the way down, performance suffers due to fill rate.

        depths = numpy.zeros((chunkWidth, chunkLength), dtype='uint16')
        depths[1:-1, 1:-1] = reduce(numpy.minimum,
                                    (heights[1:-1, :-2], heights[1:-1, 2:],
                                     heights[:-2, 1:-1], heights[2:, 1:-1]))
        depths = depths[nonZeroHeights]
        yield

        va1 = vertexBuffer.copy()
        va1.vertex[..., :3] += standardCubeTemplates[faces.FaceXIncreasing,
                                                     ..., :3]

        va1.vertex[:, 0, 1] = depths
        va1.vertex[:, 0, 1] = depths  # stretch to floor
        va1.vertex[:, (2, 3),
                   1] -= 0.5  # drop down to prevent intersection pixels

        numpy.multiply(flatcolors, 0.8, out=flatcolors, casting='unsafe')
        #flatcolors *= 0.8

        va1.rgb[:] = flatcolors
        grassmask = topBlocks == 2
        # color grass sides with dirt's color
        va1.rgb[grassmask] = dim.blocktypes.mapColor[:, 0][[3]][:,
                                                                numpy.newaxis]

        va2 = va1.copy()
        va1.vertex[:, (1, 2), 0] -= 1.0  # turn diagonally
        va2.vertex[:, (0, 3), 0] -= 1.0  # turn diagonally

        nodes = [VertexNode(v) for v in (va1, va2, va0)]

        self.sceneNode = scenenode.Node()
        for node in nodes:
            self.sceneNode.addChild(node)