WorldView now accepts dropped map items dragged from Library panel

Map items are placed immediately with no "movable" intermediate.

xxx still need placement preview!
and xxx should allow URLs/schematic files/etc to be dropped from Library's Schematic panel, file explorer, etc!
This commit is contained in:
David Vierra 2015-07-11 11:36:20 -10:00
parent 31aec2a932
commit fd76076689
2 changed files with 96 additions and 5 deletions

View File

@ -17,6 +17,7 @@ from mcedit2.panels.map import MapPanel
from mcedit2.panels.worldinfo import WorldInfoPanel
from mcedit2.util.dialogs import NotImplementedYet
from mcedit2.util.directories import getUserSchematicsDirectory
from mcedit2.util.mimeformats import MimeFormats
from mceditlib.util import exhaust
from mceditlib.util.lazyprop import weakrefprop
from mcedit2.util.raycast import rayCastInBounds
@ -33,13 +34,13 @@ from mcedit2.worldview.camera import CameraWorldViewFrame
from mcedit2.worldview.cutaway import CutawayWorldViewFrame
from mcedit2.worldview.minimap import MinimapWorldView
from mcedit2.worldview.overhead import OverheadWorldViewFrame
from mceditlib import util
from mceditlib import util, nbt, faces
from mceditlib.anvil.biome_types import BiomeTypes
from mceditlib.geometry import Vector
from mceditlib.operations import ComposeOperations
from mceditlib.operations.entity import RemoveEntitiesOperation
from mceditlib.selection import BoundingBox
from mceditlib.exceptions import PlayerNotFound
from mceditlib.exceptions import PlayerNotFound, ChunkNotPresent
from mceditlib.revisionhistory import UndoFolderExists, RevisionChanges
from mceditlib.worldeditor import WorldEditor
from mceditlib.blocktypes import BlockType
@ -367,6 +368,9 @@ class EditorSession(QtCore.QObject):
self.editorTab = EditorTab(self)
self.toolChanged.connect(self.toolDidChange)
self.editorTab.urlsDropped.connect(self.urlsWereDropped)
self.editorTab.mapItemDropped.connect(self.mapItemWasDropped)
self.undoStack.indexChanged.connect(self.undoIndexChanged)
self.findReplaceDialog = FindReplaceDialog(self)
@ -668,6 +672,52 @@ class EditorSession(QtCore.QObject):
schematic = showProgress("Copying...", task)
schematic.saveToFile(filename)
# --- Drag-and-drop ---
def urlsWereDropped(self, mimeData, position, face):
log.info("URLs dropped:\n%s", mimeData.urls())
def mapItemWasDropped(self, mimeData, position, face):
log.info("Map item dropped.")
assert mimeData.hasFormat(MimeFormats.MapItem)
mapIDString = mimeData.data(MimeFormats.MapItem).data()
mapIDs = mapIDString.split(", ")
mapIDs = [int(m) for m in mapIDs]
mapID = mapIDs[0] # xxx only one at a time for now
position = position + face.vector
x, y, z = position
cx = x >> 4
cz = z >> 4
try:
chunk = self.currentDimension.getChunk(cx, cz)
except ChunkNotPresent:
log.info("Refusing to import map into non-existent chunk %s", (cx, cz))
return
ref = self.worldEditor.createEntity("ItemFrame")
if ref is None:
return
facing = ref.facingForMCEditFace(face)
if facing is None:
# xxx by camera vector?
facing = ref.SouthFacing
ref.Item.Damage = mapID
ref.Item.id = "minecraft:filled_map"
ref.Position = position + (0.5, 0.5, 0.5)
ref.TilePos = position # 1.7/1.8 issues should be handled by ref...
ref.Facing = facing
log.info("Created map ItemFrame with ID %s, importing...", mapID)
command = SimpleRevisionCommand(self, self.tr("Import map %(mapID)s") % {"mapID": mapID})
with command.begin():
chunk.addEntity(ref)
log.info(nbt.nested_string(ref.rootTag))
self.pushCommand(command)
# --- Library support ---
def importSchematic(self, filename):
@ -1000,6 +1050,9 @@ class EditorTab(QtGui.QWidget):
editorSession = weakrefprop()
urlsDropped = QtCore.Signal(QtCore.QMimeData, Vector, faces.Face)
mapItemDropped = QtCore.Signal(QtCore.QMimeData, Vector, faces.Face)
def configuredBlocksDidChange(self):
for view in self.views:
view.setTextureAtlas(self.editorSession.textureAtlas)
@ -1057,6 +1110,8 @@ class EditorTab(QtGui.QWidget):
UseToolMouseAction(self),
TrackingMouseAction(self)
])
frame.worldView.urlsDropped.connect(self.urlsDropped.emit)
frame.worldView.mapItemDropped.connect(self.mapItemDropped.emit)
def currentView(self):
"""

View File

@ -23,6 +23,7 @@ from mcedit2.rendering.textureatlas import TextureAtlas
from mcedit2.rendering.vertexarraybuffer import VertexArrayBuffer
from mcedit2.rendering import scenegraph, rendergraph
from mcedit2.util import profiler, raycast
from mcedit2.util.mimeformats import MimeFormats
from mcedit2.util.qglcontext import validateQGLContext
from mcedit2.util.settings import Settings
from mcedit2.widgets.infopanel import InfoPanel
@ -72,6 +73,9 @@ class WorldView(QGLWidget):
viewportMoved = QtCore.Signal(QtGui.QWidget)
cursorMoved = QtCore.Signal(QtGui.QMouseEvent)
urlsDropped = QtCore.Signal(QtCore.QMimeData, Vector, faces.Face)
mapItemDropped = QtCore.Signal(QtCore.QMimeData, Vector, faces.Face)
mouseBlockPos = Vector(0, 0, 0)
mouseBlockFace = faces.FaceYIncreasing
@ -92,6 +96,7 @@ class WorldView(QGLWidget):
QGLWidget.__init__(self, shareWidget=sharedGLWidget)
validateQGLContext(self.context())
self.setAcceptDrops(True)
self.setSizePolicy(QtGui.QSizePolicy.Policy.Expanding, QtGui.QSizePolicy.Policy.Expanding)
self.setFocusPolicy(Qt.ClickFocus)
@ -138,6 +143,32 @@ class WorldView(QGLWidget):
self.setDimension(dimension)
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 setDimension(self, dimension):
"""
@ -456,6 +487,13 @@ class WorldView(QGLWidget):
event.ray = ray
event.view = self
position, face = self.rayCastInView(ray)
self.mouseBlockPos = event.blockPosition = position
self.mouseBlockFace = event.blockFace = face
self.mouseRay = ray
def rayCastInView(self, ray):
try:
result = raycast.rayCastInBounds(ray, self.dimension, maxDistance=2000)
position, face = result
@ -472,9 +510,7 @@ class WorldView(QGLWidget):
position = (ray.point + ray.vector * defaultDistance).intfloor()
face = faces.FaceUp
self.mouseBlockPos = event.blockPosition = position
self.mouseBlockFace = event.blockFace = face
self.mouseRay = ray
return position, face
maxFPS = 30