diff --git a/src/mcedit2/rendering/vertexarraybuffer.py b/src/mcedit2/rendering/vertexarraybuffer.py index b4d16de..fa406a7 100644 --- a/src/mcedit2/rendering/vertexarraybuffer.py +++ b/src/mcedit2/rendering/vertexarraybuffer.py @@ -35,7 +35,7 @@ class VertexArrayBuffer(object): bl: float32 (with lights=True) sl: float32 (with lights=True) rgba: - rgba: uint32 (four uint8s packed with r in the most significant byte) + rgba: uint8 (four uint8s packed with r in the most significant byte) Access elements using .vertex, .texcoord, .lightcoord, .rgba diff --git a/src/mcedit2/rendering/workplane.py b/src/mcedit2/rendering/workplane.py new file mode 100644 index 0000000..eb5bed5 --- /dev/null +++ b/src/mcedit2/rendering/workplane.py @@ -0,0 +1,57 @@ +""" + workplane +""" +from __future__ import absolute_import, division, print_function, unicode_literals +import logging +from OpenGL import GL +from mcedit2.rendering import scenegraph, rendergraph +from mcedit2.rendering.vertexarraybuffer import VertexArrayBuffer + +log = logging.getLogger(__name__) + + + +class WorkplaneNode(scenegraph.Node): + + def __init__(self): + super(WorkplaneNode, self).__init__() + self.translateNode = scenegraph.TranslateNode() + self.addChild(self.translateNode) + gridSize = 64 + left = -gridSize//2 + right = gridSize//2 + + gridArrayBuffer = VertexArrayBuffer((gridSize * 4,), + GL.GL_LINES, textures=False, lights=False) + + gridArrayBuffer.rgba[:] = 255, 255, 255, 100 + + # y=0, move by translating + gridArrayBuffer.vertex[:, 1] = 0 + + # left edge + gridArrayBuffer.vertex[0:gridSize*2:2, 2] = left + gridArrayBuffer.vertex[0:gridSize*2:2, 0] = range(left, right) + + # right edge + gridArrayBuffer.vertex[1:gridSize*2:2, 2] = right-1 + gridArrayBuffer.vertex[1:gridSize*2:2, 0] = range(left, right) + + # bottom edge + gridArrayBuffer.vertex[gridSize*2::2, 0] = left + gridArrayBuffer.vertex[gridSize*2::2, 2] = range(left, right) + + # top edge + gridArrayBuffer.vertex[gridSize*2+1::2, 0] = right-1 + gridArrayBuffer.vertex[gridSize*2+1::2, 2] = range(left, right) + + self.vertexNode = scenegraph.VertexNode([gridArrayBuffer]) + self.translateNode.addChild(self.vertexNode) + + @property + def position(self): + return self.translateNode.translateOffset + + @position.setter + def position(self, value): + self.translateNode.translateOffset = value diff --git a/src/mcedit2/worldview/camera.py b/src/mcedit2/worldview/camera.py index c3fadf6..9779a4e 100644 --- a/src/mcedit2/worldview/camera.py +++ b/src/mcedit2/worldview/camera.py @@ -10,10 +10,14 @@ from math import degrees, atan, tan, radians, cos, sin import numpy from PySide.QtCore import Qt from PySide import QtGui, QtCore +from mcedit2.rendering.workplane import WorkplaneNode from mcedit2.util import profiler from mcedit2.util.settings import Settings from mcedit2.widgets.layout import Column, Row +from mcedit2.widgets.spinslider import SpinSlider +from mceditlib import faces +from mceditlib.geometry import Vector from mceditlib.util.lazyprop import lazyprop from mcedit2.worldview.viewcontrols import ViewControls from mcedit2.worldview.worldview import WorldView, iterateChunks @@ -42,17 +46,29 @@ class CameraWorldViewFrame(QtGui.QWidget): PerspectiveSetting.connectAndCall(view.setPerspective) - perspectiveInput = QtGui.QCheckBox("Perspective") + perspectiveInput = QtGui.QCheckBox(self.tr("Perspective")) perspectiveInput.setChecked(view.perspective) perspectiveInput.toggled.connect(PerspectiveSetting.setValue) - showButton = QtGui.QPushButton("Show...") + showButton = QtGui.QPushButton(self.tr("Show...")) showButton.setMenu(view.layerToggleGroup.menu) + workplaneCheckbox = QtGui.QCheckBox(self.tr("Work Plane")) + workplaneSpinSlider = SpinSlider() + workplaneSpinSlider.setValue(64) + workplaneSpinSlider.setMinimum(dimension.bounds.miny) + workplaneSpinSlider.setMaximum(dimension.bounds.maxy) + + workplaneCheckbox.toggled.connect(view.toggleWorkplane) + + workplaneSpinSlider.valueChanged.connect(view.setWorkplaneLevel) + self.setLayout(Column(Row(None, + workplaneCheckbox, + workplaneSpinSlider, showButton, perspectiveInput, - QtGui.QLabel("View Distance:"), + QtGui.QLabel(self.tr("View Distance:")), viewDistanceInput, self.viewControls.getShowHideButton(), margin=0), view, margin=0)) @@ -198,10 +214,13 @@ class CameraWorldView(WorldView): self._yawPitch = -45., 25. self.viewDistance = 32 + self.workplaneNode = WorkplaneNode() + self.workplaneNode.visible = False + WorldView.__init__(self, *a, **kw) self.compassNode.yawPitch = self._yawPitch self.viewActions = [CameraMoveMouseAction(), - CameraPanMouseAction()] + CameraPanMouseAction()] self.cameraControls = CameraKeyControls(self) self.viewActions.extend(self.cameraControls.viewActions) @@ -211,6 +230,48 @@ class CameraWorldView(WorldView): self.discardTimer.setInterval(1000) self.discardTimer.start() + self.workplaneLevel = 0 + self.workplaneEnabled = False + self.viewportMoved.connect(self.updateWorkplane) + + def updateWorkplane(self): + distance = 40 + pos = self.centerPoint + self.cameraVector * distance + pos = pos.intfloor() + + self.workplaneNode.position = Vector(pos[0], self.workplaneLevel, pos[2]) + + def toggleWorkplane(self, enabled): + self.workplaneNode.visible = enabled + self.workplaneEnabled = enabled + + def setWorkplaneLevel(self, level): + self.workplaneLevel = level + self.updateWorkplane() + self.update() + + def createSceneGraph(self): + scenegraph = super(CameraWorldView, self).createSceneGraph() + self.matrixNode.addChild(self.workplaneNode) + return scenegraph + + def augmentEvent(self, x, y, event): + super(CameraWorldView, self).augmentEvent(x, y, event) + if not self.workplaneEnabled: + return + + point = event.ray.atHeight(self.workplaneLevel) + if point != event.ray.point: + direction = point - event.ray.point + if direction.length() >= (event.blockPosition - event.ray.point).length(): + return + + event.blockPosition = point.intfloor() + if direction.y >= 0: + event.blockFace = faces.FaceDown + else: + event.blockFace = faces.FaceUp + def setViewDistance(self, val): self.viewDistance = val self._chunkIter = None