Source code for editortools.editortool

from OpenGL import GL
import numpy
from depths import DepthOffset
from pymclevel import BoundingBox
from config import config
from albow.translate import _


[docs]class EditorTool(object): surfaceBuild = False panel = None optionsPanel = None toolIconName = None worldTooltipText = None previewRenderer = None tooltipText = "???"
[docs] def levelChanged(self): """ called after a level change """ pass
@property def statusText(self): return "" @property def cameraDistance(self): return self.editor.cameraToolDistance
[docs] def toolEnabled(self): return True
def __init__(self, editor): self.editor = editor self.__hotkey = None @property def hotkey(self): return _(self.__hotkey) @hotkey.setter def hotkey(self, k): self.__hotkey = k
[docs] def toolReselected(self): pass
[docs] def toolSelected(self): pass
[docs] def toolDeselected(self): pass
[docs] def drawTerrainReticle(self): pass
[docs] def drawTerrainMarkers(self): pass
[docs] def drawTerrainPreview(self, origin): if self.previewRenderer is None: return self.previewRenderer.origin = map(lambda a, b: a - b, origin, self.level.bounds.origin) GL.glPolygonOffset(DepthOffset.ClonePreview, DepthOffset.ClonePreview) GL.glEnable(GL.GL_POLYGON_OFFSET_FILL) self.previewRenderer.draw() GL.glDisable(GL.GL_POLYGON_OFFSET_FILL)
[docs] def rotate(self, amount=1, blocksOnly=False): pass
[docs] def roll(self, amount=1, blocksOnly=False): pass
[docs] def flip(self, amount=1, blocksOnly=False): pass
[docs] def mirror(self, amount=1, blocksOnly=False): pass
[docs] def swap(self, amount=1): pass
[docs] def mouseDown(self, evt, pos, direction): '''pos is the coordinates of the block under the cursor, direction indicates which face is under it. the tool performs its action on the specified block''' pass
[docs] def mouseUp(self, evt, pos, direction): pass
[docs] def mouseDrag(self, evt, pos, direction): pass
[docs] def keyDown(self, evt): pass
[docs] def keyUp(self, evt): pass
[docs] def increaseToolReach(self): "Return True if the tool handles its own reach" return False
[docs] def decreaseToolReach(self): "Return True if the tool handles its own reach" return False
[docs] def resetToolReach(self): "Return True if the tool handles its own reach" return False
[docs] def confirm(self): ''' called when user presses enter ''' pass
[docs] def cancel(self): '''cancel the current operation. called when a different tool is picked, escape is pressed, or etc etc''' self.hidePanel() # pass
[docs] def findBestTrackingPlane(self, face): cv = list(self.editor.mainViewport.cameraVector) cv[face >> 1] = 0 cv = map(abs, cv) return cv.index(max(cv))
[docs] def drawToolReticle(self): '''get self.editor.blockFaceUnderCursor for pos and direction. pos is the coordinates of the block under the cursor, direction indicates which face is under it. draw something to let the user know where the tool is going to act. e.g. a transparent block for the block placing tool.''' pass
[docs] def drawToolMarkers(self): ''' draw any markers the tool wants to leave in the field while another tool is out. e.g. the current selection for SelectionTool''' pass
[docs] def selectionChanged(self): """ called when the selection changes due to nudge. other tools can be active. """ pass
edge_factor = 0.1
[docs] def boxFaceUnderCursor(self, box): if self.editor.mainViewport.mouseMovesCamera: return None, None p0 = self.editor.mainViewport.cameraPosition normal = self.editor.mainViewport.mouseVector if normal is None: return None, None points = {} # glPointSize(5.0) # glColor(1.0, 1.0, 0.0, 1.0) # glBegin(GL_POINTS) for dim in range(3): dim1 = dim + 1 dim2 = dim + 2 dim1 %= 3 dim2 %= 3 def pointInBounds(point, x): return box.origin[x] <= point[x] <= box.maximum[x] neg = normal[dim] < 0 for side in 0, 1: d = (box.maximum, box.origin)[side][dim] - p0[dim] if d >= 0 or (neg and d <= 0): if normal[dim]: scale = d / normal[dim] point = map(lambda a, p: (a * scale + p), normal, p0) # glVertex3f(*point) if pointInBounds(point, dim1) and pointInBounds(point, dim2): points[dim * 2 + side] = point # glEnd() if not len(points): return None, None cp = self.editor.mainViewport.cameraPosition distances = dict( (numpy.sum(map(lambda a, b: (b - a) ** 2, cp, point)), (face, point)) for face, point in points.iteritems()) if not len(distances): return None, None # When holding alt, pick the face opposite the camera # if key.get_mods() & KMOD_ALT: # minmax = max # else: face, point = distances[min(distances.iterkeys())] # if the point is near the edge of the face, and the edge is facing away, # return the away-facing face dim = face // 2 dim1, dim2 = dim + 1, dim + 2 dim1, dim2 = dim1 % 3, dim2 % 3 cv = self.editor.mainViewport.cameraVector # determine if a click was within self.edge_factor of the edge of a selection box side. if so, click through # to the opposite side for d in dim1, dim2: edge_width = box.size[d] * self.edge_factor facenormal = [0, 0, 0] cameraBehind = False if point[d] - box.origin[d] < edge_width: facenormal[d] = -1 cameraBehind = cp[d] - box.origin[d] > 0 if point[d] - box.maximum[d] > -edge_width: facenormal[d] = 1 cameraBehind = cp[d] - box.maximum[d] < 0 if numpy.dot(facenormal, cv) > 0 or cameraBehind: # the face adjacent to the clicked edge faces away from the cam return distances[max(distances.iterkeys())] return face, point
[docs] def selectionCorners(self): """ returns the positions of the two selection corners as a pair of 3-tuples, each ordered x,y,z """ if (None != self.editor.selectionTool.bottomLeftPoint and None != self.editor.selectionTool.topRightPoint): return (self.editor.selectionTool.bottomLeftPoint, self.editor.selectionTool.topRightPoint) return None
[docs] def selectionBoxForCorners(self, p1, p2): ''' considers p1,p2 as the marked corners of a selection. returns a BoundingBox containing all the blocks within.''' if self.editor.level is None: return None p1, p2 = list(p1), list(p2) # d = [(a-b) for a,b in zip(p1,p2)] for i in range(3): if p1[i] > p2[i]: t = p2[i] p2[i] = p1[i] p1[i] = t p2[i] += 1 size = map(lambda a, b: a - b, p2, p1) if p1[1] < 0: size[1] += p1[1] p1[1] = 0 h = self.editor.level.Height if p1[1] >= h: p1[1] = h - 1 size[1] = 1 if p1[1] + size[1] >= h: size[1] = h - p1[1] return BoundingBox(p1, size)
[docs] def selectionBox(self): ''' selection corners, ordered, with the greater point moved up one block for use as the ending value of an array slice ''' c = self.selectionCorners() if c: return self.selectionBoxForCorners(*c) return None
[docs] def selectionSize(self): ''' returns a tuple containing the size of the selection (x,y,z)''' c = self.selectionBox() if c is None: return None return c.size
@property def maxBlocks(self): return config.settings.blockBuffer.get() / 2 # assume block buffer in bytes
[docs] def showPanel(self): pass
[docs] def hidePanel(self): if self.panel and self.panel.parent: self.panel.parent.remove(self.panel) self.panel = None