Reorganize WorldView methods
This commit is contained in:
parent
bbc3263ad7
commit
1b6d9d07fb
@ -21,7 +21,7 @@ from mceditlib import faces
|
|||||||
from mceditlib.geometry import Vector
|
from mceditlib.geometry import Vector
|
||||||
from mceditlib.util.lazyprop import lazyprop
|
from mceditlib.util.lazyprop import lazyprop
|
||||||
from mcedit2.worldview.viewcontrols import ViewControls
|
from mcedit2.worldview.viewcontrols import ViewControls
|
||||||
from mcedit2.worldview.worldview import WorldView, iterateChunks
|
from mcedit2.worldview.worldview import WorldView, iterateChunks, anglesToVector
|
||||||
from mcedit2.worldview.viewaction import ViewAction
|
from mcedit2.worldview.viewaction import ViewAction
|
||||||
|
|
||||||
|
|
||||||
@ -371,7 +371,7 @@ class CameraWorldView(WorldView):
|
|||||||
|
|
||||||
@lazyprop
|
@lazyprop
|
||||||
def cameraVector(self):
|
def cameraVector(self):
|
||||||
return self._anglesToVector(*self.yawPitch)
|
return anglesToVector(*self.yawPitch)
|
||||||
|
|
||||||
def makeChunkIter(self):
|
def makeChunkIter(self):
|
||||||
radius = self.viewDistance
|
radius = self.viewDistance
|
||||||
|
@ -7,7 +7,7 @@ import math
|
|||||||
from PySide import QtGui
|
from PySide import QtGui
|
||||||
from PySide.QtCore import Qt
|
from PySide.QtCore import Qt
|
||||||
from mcedit2.widgets.layout import Row, Column
|
from mcedit2.widgets.layout import Row, Column
|
||||||
from mcedit2.worldview.worldview import WorldView, iterateChunks
|
from mcedit2.worldview.worldview import WorldView, iterateChunks, anglesToVector
|
||||||
from mcedit2.worldview.viewaction import ViewAction, MoveViewMouseAction, ZoomWheelAction
|
from mcedit2.worldview.viewaction import ViewAction, MoveViewMouseAction, ZoomWheelAction
|
||||||
from mceditlib.geometry import Ray
|
from mceditlib.geometry import Ray
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ class IsoWorldView(WorldView):
|
|||||||
))
|
))
|
||||||
|
|
||||||
def cameraVector(self):
|
def cameraVector(self):
|
||||||
return self._anglesToVector(self.yrot, self.xrot)
|
return anglesToVector(self.yrot, self.xrot)
|
||||||
|
|
||||||
def centerOnPoint(self, pos, distance=None):
|
def centerOnPoint(self, pos, distance=None):
|
||||||
#self.rotateView(45., math.degrees(math.atan(1/math.sqrt(2))))
|
#self.rotateView(45., math.degrees(math.atan(1/math.sqrt(2))))
|
||||||
|
@ -37,6 +37,7 @@ from mceditlib.geometry import Vector, Ray
|
|||||||
from mceditlib.exceptions import LevelFormatError, ChunkNotPresent
|
from mceditlib.exceptions import LevelFormatError, ChunkNotPresent
|
||||||
from mceditlib.util import displayName
|
from mceditlib.util import displayName
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
def worldMeshVertexSize(worldMesh):
|
def worldMeshVertexSize(worldMesh):
|
||||||
"""
|
"""
|
||||||
@ -56,7 +57,18 @@ def worldMeshVertexSize(worldMesh):
|
|||||||
|
|
||||||
return sum(bufferSizes())
|
return sum(bufferSizes())
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
def anglesToVector(yaw, pitch):
|
||||||
|
def nanzero(x):
|
||||||
|
if math.isnan(x):
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return x
|
||||||
|
|
||||||
|
dx = -math.sin(math.radians(yaw)) * math.cos(math.radians(pitch))
|
||||||
|
dy = -math.sin(math.radians(pitch))
|
||||||
|
dz = math.cos(math.radians(yaw)) * math.cos(math.radians(pitch))
|
||||||
|
return Vector(*map(nanzero, [dx, dy, dz]))
|
||||||
|
|
||||||
|
|
||||||
class BufferSwapper(QtCore.QObject):
|
class BufferSwapper(QtCore.QObject):
|
||||||
@ -176,31 +188,23 @@ class WorldView(QGLWidget):
|
|||||||
|
|
||||||
self.setDimension(dimension)
|
self.setDimension(dimension)
|
||||||
|
|
||||||
acceptableMimeTypes = [
|
def destroy(self):
|
||||||
MimeFormats.MapItem,
|
self.makeCurrent()
|
||||||
]
|
self.renderGraph.destroy()
|
||||||
|
self.bufferSwapThread.quit()
|
||||||
|
super(WorldView, self).destroy()
|
||||||
|
|
||||||
def dragEnterEvent(self, event):
|
def __str__(self):
|
||||||
# xxx show drop preview as scene node
|
try:
|
||||||
print("DRAG ENTER. FORMATS:\n%s" % event.mimeData().formats())
|
if self.dimension:
|
||||||
for mimeType in self.acceptableMimeTypes:
|
dimName = displayName(self.dimension.worldEditor.filename) + ": " + self.dimension.dimName
|
||||||
if event.mimeData().hasFormat(mimeType):
|
else:
|
||||||
event.acceptProposedAction()
|
dimName = "None"
|
||||||
return
|
except Exception as e:
|
||||||
if event.mimeData().hasUrls():
|
return "%s trying to get node name" % e
|
||||||
event.acceptProposedAction()
|
return "%s(%r)" % (self.__class__.__name__, dimName)
|
||||||
|
|
||||||
def dropEvent(self, event):
|
# --- Displayed world ---
|
||||||
mimeData = event.mimeData()
|
|
||||||
x = event.pos().x()
|
|
||||||
y = event.pos().y()
|
|
||||||
ray = self.rayAtPosition(x, y)
|
|
||||||
dropPosition, face = self.rayCastInView(ray)
|
|
||||||
|
|
||||||
if mimeData.hasFormat(MimeFormats.MapItem):
|
|
||||||
self.mapItemDropped.emit(mimeData, dropPosition, face)
|
|
||||||
elif mimeData.hasUrls:
|
|
||||||
self.urlsDropped.emit(mimeData, dropPosition, face)
|
|
||||||
|
|
||||||
def setDimension(self, dimension):
|
def setDimension(self, dimension):
|
||||||
"""
|
"""
|
||||||
@ -230,21 +234,7 @@ class WorldView(QGLWidget):
|
|||||||
textureAtlas.load()
|
textureAtlas.load()
|
||||||
self.resetLoadOrder()
|
self.resetLoadOrder()
|
||||||
|
|
||||||
def destroy(self):
|
# --- Graph construction ---
|
||||||
self.makeCurrent()
|
|
||||||
self.renderGraph.destroy()
|
|
||||||
self.bufferSwapThread.quit()
|
|
||||||
super(WorldView, self).destroy()
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
try:
|
|
||||||
if self.dimension:
|
|
||||||
dimName = displayName(self.dimension.worldEditor.filename) + ": " + self.dimension.dimName
|
|
||||||
else:
|
|
||||||
dimName = "None"
|
|
||||||
except Exception as e:
|
|
||||||
return "%s trying to get node name" % e
|
|
||||||
return "%s(%r)" % (self.__class__.__name__, dimName)
|
|
||||||
|
|
||||||
def createCompass(self):
|
def createCompass(self):
|
||||||
return compass.CompassNode()
|
return compass.CompassNode()
|
||||||
@ -279,11 +269,7 @@ class WorldView(QGLWidget):
|
|||||||
|
|
||||||
return sceneGraph
|
return sceneGraph
|
||||||
|
|
||||||
def initializeGL(self, *args, **kwargs):
|
# --- Tool support ---
|
||||||
GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
|
|
||||||
GL.glAlphaFunc(GL.GL_NOTEQUAL, 0)
|
|
||||||
GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
|
|
||||||
GL.glEnable(GL.GL_DEPTH_TEST)
|
|
||||||
|
|
||||||
def setToolCursor(self, cursorNode):
|
def setToolCursor(self, cursorNode):
|
||||||
if self.cursorNode:
|
if self.cursorNode:
|
||||||
@ -297,6 +283,16 @@ class WorldView(QGLWidget):
|
|||||||
for node in overlayNodes:
|
for node in overlayNodes:
|
||||||
self.overlayNode.addChild(node)
|
self.overlayNode.addChild(node)
|
||||||
|
|
||||||
|
# --- View settings ---
|
||||||
|
|
||||||
|
def setLayerVisible(self, layerName, visible):
|
||||||
|
self.worldScene.setLayerVisible(layerName, visible)
|
||||||
|
self.resetLoadOrder()
|
||||||
|
|
||||||
|
def setDayTime(self, value):
|
||||||
|
if self.skyNode:
|
||||||
|
self.skyNode.setDayTime(value)
|
||||||
|
|
||||||
def _updateMatrices(self):
|
def _updateMatrices(self):
|
||||||
self.updateMatrices()
|
self.updateMatrices()
|
||||||
self.updateFrustum()
|
self.updateFrustum()
|
||||||
@ -331,7 +327,9 @@ class WorldView(QGLWidget):
|
|||||||
:return:
|
:return:
|
||||||
:rtype: list[QVector4D]
|
:rtype: list[QVector4D]
|
||||||
"""
|
"""
|
||||||
corners = [QtGui.QVector4D(x, y, z, 1.) for x, y, z in itertools.product((-1., 1.), (-1., 1.), (0., 1. ))]
|
corners = [QtGui.QVector4D(x, y, z, 1.)
|
||||||
|
for x, y, z in itertools.product((-1., 1.), (-1., 1.), (0., 1.))]
|
||||||
|
|
||||||
matrix = self.matrixState.projection * self.matrixState.modelview
|
matrix = self.matrixState.projection * self.matrixState.modelview
|
||||||
matrix, inverted = matrix.inverted()
|
matrix, inverted = matrix.inverted()
|
||||||
worldCorners = [matrix.map(corner) for corner in corners]
|
worldCorners = [matrix.map(corner) for corner in corners]
|
||||||
@ -359,17 +357,22 @@ class WorldView(QGLWidget):
|
|||||||
|
|
||||||
return sum(pointPairs, ())
|
return sum(pointPairs, ())
|
||||||
|
|
||||||
def resizeGL(self, width, height):
|
scaleChanged = QtCore.Signal(float)
|
||||||
GL.glViewport(0, 0, width, height)
|
|
||||||
|
|
||||||
|
_scale = 1. / 16
|
||||||
|
|
||||||
|
@property
|
||||||
|
def scale(self):
|
||||||
|
return self._scale
|
||||||
|
|
||||||
|
@scale.setter
|
||||||
|
def scale(self, value):
|
||||||
|
self._scale = value
|
||||||
self._updateMatrices()
|
self._updateMatrices()
|
||||||
|
log.debug("update(): scale %s %s", self, value)
|
||||||
def resizeEvent(self, event):
|
self.update()
|
||||||
center = self.viewCenter()
|
self.scaleChanged.emit(value)
|
||||||
self.compassOrtho.size = (1, float(self.height()) / self.width())
|
self.viewportMoved.emit(self)
|
||||||
super(WorldView, self).resizeEvent(event)
|
|
||||||
# log.info("WorldView: resized. moving to %s", center)
|
|
||||||
# self.centerOnPoint(center)
|
|
||||||
|
|
||||||
_centerPoint = Vector(0, 0, 0)
|
_centerPoint = Vector(0, 0, 0)
|
||||||
|
|
||||||
@ -388,23 +391,6 @@ class WorldView(QGLWidget):
|
|||||||
self.resetLoadOrder()
|
self.resetLoadOrder()
|
||||||
self.viewportMoved.emit(self)
|
self.viewportMoved.emit(self)
|
||||||
|
|
||||||
scaleChanged = QtCore.Signal(float)
|
|
||||||
|
|
||||||
_scale = 1. / 16
|
|
||||||
|
|
||||||
@property
|
|
||||||
def scale(self):
|
|
||||||
return self._scale
|
|
||||||
|
|
||||||
@scale.setter
|
|
||||||
def scale(self, value):
|
|
||||||
self._scale = value
|
|
||||||
self._updateMatrices()
|
|
||||||
log.debug("update(): scale %s %s", self, value)
|
|
||||||
self.update()
|
|
||||||
self.scaleChanged.emit(value)
|
|
||||||
self.viewportMoved.emit(self)
|
|
||||||
|
|
||||||
def centerOnPoint(self, pos, distance=None):
|
def centerOnPoint(self, pos, distance=None):
|
||||||
"""Center the view on the given position"""
|
"""Center the view on the given position"""
|
||||||
# delta = self.viewCenter() - self.centerPoint
|
# delta = self.viewCenter() - self.centerPoint
|
||||||
@ -423,19 +409,40 @@ class WorldView(QGLWidget):
|
|||||||
# return point or ray.point
|
# return point or ray.point
|
||||||
return self.centerPoint
|
return self.centerPoint
|
||||||
|
|
||||||
def _anglesToVector(self, yaw, pitch):
|
# --- Events ---
|
||||||
def nanzero(x):
|
|
||||||
if math.isnan(x):
|
|
||||||
return 0
|
|
||||||
else:
|
|
||||||
return x
|
|
||||||
|
|
||||||
dx = -math.sin(math.radians(yaw)) * math.cos(math.radians(pitch))
|
def resizeEvent(self, event):
|
||||||
dy = -math.sin(math.radians(pitch))
|
center = self.viewCenter()
|
||||||
dz = math.cos(math.radians(yaw)) * math.cos(math.radians(pitch))
|
self.compassOrtho.size = (1, float(self.height()) / self.width())
|
||||||
return Vector(*map(nanzero, [dx, dy, dz]))
|
super(WorldView, self).resizeEvent(event)
|
||||||
|
# log.info("WorldView: resized. moving to %s", center)
|
||||||
|
# self.centerOnPoint(center)
|
||||||
|
|
||||||
dragStart = None
|
acceptableMimeTypes = [
|
||||||
|
MimeFormats.MapItem,
|
||||||
|
]
|
||||||
|
|
||||||
|
def dragEnterEvent(self, event):
|
||||||
|
# xxx show drop preview as scene node
|
||||||
|
print("DRAG ENTER. FORMATS:\n%s" % event.mimeData().formats())
|
||||||
|
for mimeType in self.acceptableMimeTypes:
|
||||||
|
if event.mimeData().hasFormat(mimeType):
|
||||||
|
event.acceptProposedAction()
|
||||||
|
return
|
||||||
|
if event.mimeData().hasUrls():
|
||||||
|
event.acceptProposedAction()
|
||||||
|
|
||||||
|
def dropEvent(self, event):
|
||||||
|
mimeData = event.mimeData()
|
||||||
|
x = event.pos().x()
|
||||||
|
y = event.pos().y()
|
||||||
|
ray = self.rayAtPosition(x, y)
|
||||||
|
dropPosition, face = self.rayCastInView(ray)
|
||||||
|
|
||||||
|
if mimeData.hasFormat(MimeFormats.MapItem):
|
||||||
|
self.mapItemDropped.emit(mimeData, dropPosition, face)
|
||||||
|
elif mimeData.hasUrls:
|
||||||
|
self.urlsDropped.emit(mimeData, dropPosition, face)
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
self.augmentKeyEvent(event)
|
self.augmentKeyEvent(event)
|
||||||
@ -504,7 +511,6 @@ class WorldView(QGLWidget):
|
|||||||
for i in range(abs(clicks)):
|
for i in range(abs(clicks)):
|
||||||
action.keyPressEvent(event)
|
action.keyPressEvent(event)
|
||||||
|
|
||||||
|
|
||||||
def augmentMouseEvent(self, event):
|
def augmentMouseEvent(self, event):
|
||||||
x, y = event.x(), event.y()
|
x, y = event.x(), event.y()
|
||||||
return self.augmentEvent(x, y, event)
|
return self.augmentEvent(x, y, event)
|
||||||
@ -534,24 +540,18 @@ class WorldView(QGLWidget):
|
|||||||
self.mouseBlockFace = event.blockFace = face
|
self.mouseBlockFace = event.blockFace = face
|
||||||
self.mouseRay = ray
|
self.mouseRay = ray
|
||||||
|
|
||||||
def rayCastInView(self, ray):
|
# --- OpenGL support ---
|
||||||
try:
|
|
||||||
result = raycast.rayCastInBounds(ray, self.dimension, maxDistance=200)
|
|
||||||
position, face = result
|
|
||||||
|
|
||||||
except (raycast.MaxDistanceError, ValueError):
|
def initializeGL(self, *args, **kwargs):
|
||||||
# GL.glReadBuffer(GL.GL_BACK)
|
GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
|
||||||
# pixel = GL.glReadPixels(x, self.height() - y, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT)
|
GL.glAlphaFunc(GL.GL_NOTEQUAL, 0)
|
||||||
# depth = -1 + 2 * pixel[0, 0]
|
GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
|
||||||
# p = self.pointsAtPositions((x, y, depth))[0]
|
GL.glEnable(GL.GL_DEPTH_TEST)
|
||||||
#
|
|
||||||
# face = faces.FaceYIncreasing
|
|
||||||
# position = p.intfloor()
|
|
||||||
defaultDistance = 200
|
|
||||||
position = (ray.point + ray.vector * defaultDistance).intfloor()
|
|
||||||
face = faces.FaceUp
|
|
||||||
|
|
||||||
return position, face
|
def resizeGL(self, width, height):
|
||||||
|
GL.glViewport(0, 0, width, height)
|
||||||
|
|
||||||
|
self._updateMatrices()
|
||||||
|
|
||||||
maxFPS = 45
|
maxFPS = 45
|
||||||
|
|
||||||
@ -588,6 +588,27 @@ class WorldView(QGLWidget):
|
|||||||
|
|
||||||
return (samples - 1) / (self.frameSamples[-1] - self.frameSamples[-samples])
|
return (samples - 1) / (self.frameSamples[-1] - self.frameSamples[-samples])
|
||||||
|
|
||||||
|
# --- Screen<->world space conversion ---
|
||||||
|
|
||||||
|
def rayCastInView(self, ray):
|
||||||
|
try:
|
||||||
|
result = raycast.rayCastInBounds(ray, self.dimension, maxDistance=200)
|
||||||
|
position, face = result
|
||||||
|
|
||||||
|
except (raycast.MaxDistanceError, ValueError):
|
||||||
|
# GL.glReadBuffer(GL.GL_BACK)
|
||||||
|
# pixel = GL.glReadPixels(x, self.height() - y, 1, 1, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT)
|
||||||
|
# depth = -1 + 2 * pixel[0, 0]
|
||||||
|
# p = self.pointsAtPositions((x, y, depth))[0]
|
||||||
|
#
|
||||||
|
# face = faces.FaceYIncreasing
|
||||||
|
# position = p.intfloor()
|
||||||
|
defaultDistance = 200
|
||||||
|
position = (ray.point + ray.vector * defaultDistance).intfloor()
|
||||||
|
face = faces.FaceUp
|
||||||
|
|
||||||
|
return position, face
|
||||||
|
|
||||||
def rayAtPosition(self, x, y):
|
def rayAtPosition(self, x, y):
|
||||||
"""
|
"""
|
||||||
Given coordinates in screen space, return a ray in 3D space.
|
Given coordinates in screen space, return a ray in 3D space.
|
||||||
@ -637,6 +658,8 @@ class WorldView(QGLWidget):
|
|||||||
ray = self.rayAtPosition(x, y)
|
ray = self.rayAtPosition(x, y)
|
||||||
return ray.atHeight(h)
|
return ray.atHeight(h)
|
||||||
|
|
||||||
|
# --- Chunk loading ---
|
||||||
|
|
||||||
_chunkIter = None
|
_chunkIter = None
|
||||||
|
|
||||||
def resetLoadOrder(self):
|
def resetLoadOrder(self):
|
||||||
@ -701,14 +724,6 @@ class WorldView(QGLWidget):
|
|||||||
|
|
||||||
self.resetLoadOrder()
|
self.resetLoadOrder()
|
||||||
|
|
||||||
def setLayerVisible(self, layerName, visible):
|
|
||||||
self.worldScene.setLayerVisible(layerName, visible)
|
|
||||||
self.resetLoadOrder()
|
|
||||||
|
|
||||||
def setDayTime(self, value):
|
|
||||||
if self.skyNode:
|
|
||||||
self.skyNode.setDayTime(value)
|
|
||||||
|
|
||||||
def iterateChunks(x, z, radius):
|
def iterateChunks(x, z, radius):
|
||||||
"""
|
"""
|
||||||
Yields a list of chunk positions starting from the center and going outward in a square spiral pattern.
|
Yields a list of chunk positions starting from the center and going outward in a square spiral pattern.
|
||||||
|
Reference in New Issue
Block a user