def __init__(self, sch, **kw): GLPerspective.__init__(self, **kw) # self, xmin= -32, xmax=32, ymin= -32, ymax=32, near= -1000, far=1000) self.far = 16000 self.schematic = sch self.renderer = PreviewRenderer(sch) self.fboSize = (128, 128) self.root = self.get_root()
def setupPreview(self, alpha=1.0): self.discardPreviewer() if self.level: self.previewRenderer = PreviewRenderer(self.level, alpha) self.previewRenderer.position = self.editor.renderer.position self.editor.addWorker(self.previewRenderer) else: self.editor.toolbar.selectTool(-1)
def __init__(self, sch, **kw): GLPerspective.__init__(self, **kw) # self, xmin= -32, xmax=32, ymin= -32, ymax=32, near= -1000, far=1000) self.p_margin = 0 self.p_spacing = 0 self.widget_index = 0 self.set_position_modifiers() self.far = 16000 self.schematic = sch self.renderer = PreviewRenderer(sch) self.fboSize = (128, 128) self.root = self.get_root()
class CloneTool(EditorTool): surfaceBuild = True toolIconName = "clone" tooltipText = "Clone\nRight-click for options" level = None repeatCount = 1 _scaleFactor = 1.0 _chunkAlign = False @property def scaleFactor(self): return self._scaleFactor @scaleFactor.setter def scaleFactor(self, val): self.rescaleLevel(val) self._scaleFactor = val @property def chunkAlign(self): return self._chunkAlign @chunkAlign.setter def chunkAlign(self, value): self._chunkAlign = value self.alignDestPoint() def alignDestPoint(self): if self.destPoint is not None: x, y, z = self.destPoint self.destPoint = Vector((x >> 4) << 4, y, (z >> 4) << 4) placeImmediately = config.clone.placeImmediately.property() panelClass = CloneToolPanel color = (0.3, 1.0, 0.3, 0.19) def __init__(self, *args): self.rotation = 0 EditorTool.__init__(self, *args) self.previewRenderer = None self.panel = None self.optionsPanel = CloneToolOptions(self) self.destPoint = None self.snapCloneKey = 0 self.root = get_root() @property def statusText(self): if self.destPoint is None: return "Click to set this item down." if self.draggingFace is not None: return _("Mousewheel to move along the third axis. Hold {0} to only move along one axis.").format( _(config.keys.snapCloneToAxis.get()) ) return ( "Click and drag to reposition the item. Double-click to pick it up. Click Clone or press Enter to confirm." ) def quickNudge(self, nudge): if config.fastNudgeSettings.cloneWidth.get(): return map(int.__mul__, nudge, self.selectionBox().size) nudgeWidth = config.fastNudgeSettings.cloneWidthNumber.get() return map(lambda x: x * nudgeWidth, nudge) copyAir = config.clone.copyAir.property() copyWater = config.clone.copyWater.property() copyBiomes = config.clone.copyBiomes.property() staticCommands = config.clone.staticCommands.property() moveSpawnerPos = config.clone.moveSpawnerPos.property() regenerateUUID = config.clone.regenerateUUID.property() def nudge(self, nudge): if self.destPoint is None: if self.selectionBox() is None: return self.destPoint = self.selectionBox().origin if self.chunkAlign: x, y, z = nudge nudge = x << 4, y, z << 4 if self.editor.rightClickNudge: nudge = self.quickNudge(nudge) # self.panel.performButton.enabled = True self.destPoint = self.destPoint + nudge self.updateOffsets() def selectionChanged(self): if self.selectionBox() is not None and "CloneToolPanel" in str(self.panel): self.updateSchematic() self.updateOffsets() def updateOffsets(self): if self.panel and self.panel.useOffsetInput and self.destPoint is not None: self.panel.offsetInput.setCoords(self.destPoint - self.selectionBox().origin) def offsetChanged(self): if self.panel: if not self.panel.useOffsetInput: return box = self.selectionBox() if box is None: return delta = self.panel.offsetInput.coords self.destPoint = box.origin + delta def toolEnabled(self): return not (self.selectionBox() is None) def cancel(self): self.discardPreviewer() if self.panel: self.panel.parent.remove(self.panel) self.panel = None self.destPoint = None self.level = None self.originalLevel = None def toolReselected(self): self.pickUp() def safeToolDistance(self): return numpy.sqrt(sum([self.level.Width ** 2, self.level.Height ** 2, self.level.Length ** 2])) def toolSelected(self): box = self.selectionBox() if box is None: self.editor.toolbar.selectTool(-1) return if box.volume > self.maxBlocks: self.editor.mouseLookOff() alert( _("Selection exceeds {0:n} blocks. Increase the block buffer setting and try again.").format( self.maxBlocks ) ) self.editor.toolbar.selectTool(-1) return self.rotation = 0 self.repeatCount = 1 self._scaleFactor = 1.0 if self.placeImmediately: self.destPoint = box.origin else: self.destPoint = None self.updateSchematic() self.cloneCameraDistance = max(self.cloneCameraDistance, self.safeToolDistance()) self.showPanel() cloneCameraDistance = 0 @property def cameraDistance(self): return self.cloneCameraDistance @alertException def rescaleLevel(self, factor): # if self.level.cloneToolScaleFactor == newFactor: # return # oldfactor = self.level.cloneToolScaleFactor # factor = newFactor / oldfactor if factor == 1: self.level = self.originalLevel self.setupPreview() return oldshape = self.originalLevel.Blocks.shape blocks = self.originalLevel.Blocks data = self.originalLevel.Data roundedShape = oldshape newshape = map(lambda x: int(x * factor), oldshape) for i, part in enumerate(newshape): if part == 0: newshape[i] = 1 xyzshape = newshape[0], newshape[2], newshape[1] newlevel = pymclevel.MCSchematic(xyzshape, mats=self.editor.level.materials) srcgrid = numpy.mgrid[ 0 : roundedShape[0] : 1.0 / factor, 0 : roundedShape[1] : 1.0 / factor, 0 : roundedShape[2] : 1.0 / factor ].astype("uint") dstgrid = numpy.mgrid[0 : newshape[0], 0 : newshape[1], 0 : newshape[2]].astype("uint") srcgrid = srcgrid[map(slice, dstgrid.shape)] dstgrid = dstgrid[map(slice, srcgrid.shape)] def copyArray(dest, src): dest[dstgrid[0], dstgrid[1], dstgrid[2]] = src[srcgrid[0], srcgrid[1], srcgrid[2]] copyArray(newlevel.Blocks, blocks) copyArray(newlevel.Data, data) self.level = newlevel self.setupPreview() # # """ # use array broadcasting to fill in the extra dimensions with copies of the # existing ones, then later change the shape to "fold" the extras back # into the original three # """ # # if factor > 1.0: # sourceSlice = slice(0, 1) # destSlice = slice(None) # # # if factor < 1.0: # # destfactor = factor # srcfactor = 1 # if factor < 1.0: # destfactor = 1.0 # srcfactor = 1.0 / factor # # intershape = newshape[0]/destfactor, destfactor, newshape[1]/destfactor, destfactor, newshape[2]/destfactor, destfactor # srcshape = roundedShape[0]/srcfactor, srcfactor, roundedShape[1]/srcfactor, srcfactor, roundedShape[2]/srcfactor, srcfactor # # newlevel = MCSchematic(xyzshape) # # def copyArray(dest, src): # dest.shape = intershape # src.shape = srcshape # # dest[:, destSlice, :, destSlice, :, destSlice] = src[:, sourceSlice, :, sourceSlice, :, sourceSlice] # dest.shape = newshape # src.shape = roundedShape # # copyArray(newlevel.Blocks, blocks) # copyArray(newlevel.Data, data) # # newlevel.cloneToolScaleFactor = newFactor # @alertException def updateSchematic(self): # extract blocks with setWindowCaption("COPYING - "): self.editor.freezeStatus("Copying to clone buffer...") box = self.selectionBox() self.level = self.editor.level.extractSchematic(box) self.originalLevel = self.level # self.level.cloneToolScaleFactor = 1.0 self.rescaleLevel(self.scaleFactor) self.setupPreview() def showPanel(self): if self.panel: self.panel.set_parent(None) self.panel = self.panelClass(self, self.editor) # self.panel.performButton.enabled = False # max_height = self.tool.editor.mainViewport.height - self.tool.editor.toolbar.height - self.tool.editor.subwidgets[0].height self.panel.centery = ( self.editor.mainViewport.height - self.editor.toolbar.height ) / 2 + self.editor.subwidgets[0].height self.panel.left = self.editor.left self.editor.add(self.panel) def setupPreview(self, alpha=1.0): self.discardPreviewer() if self.level: self.previewRenderer = PreviewRenderer(self.level, alpha) self.previewRenderer.position = self.editor.renderer.position self.editor.addWorker(self.previewRenderer) else: self.editor.toolbar.selectTool(-1) @property def canRotateLevel(self): return not isinstance(self.level, (pymclevel.MCInfdevOldLevel, PocketWorld)) def rotatedSelectionSize(self): if self.canRotateLevel: sizes = self.level.Blocks.shape return sizes[0], sizes[2], sizes[1] else: return self.level.size # =========================================================================== # def getSelectionRanges(self): # return self.editor.selectionTool.selectionBox() # # =========================================================================== @staticmethod def getBlockAt(): return None # use level's blockAt def getReticleOrigin(self): # returns a new origin for the current selection, where the old origin is at the new selection's center. pos, direction = self.editor.blockFaceUnderCursor lev = self.editor.level size = self.rotatedSelectionSize() if not size: return if size[1] >= self.editor.level.Height: direction = ( 0, 1, 0, ) # always use the upward face whenever we're splicing full-height pieces, to avoid "jitter" # print size; raise SystemExit if any(direction) and pos[1] >= 0: x, y, z = map(lambda p, s, d: p - s / 2 + s * d / 2 + (d > 0), pos, size, direction) else: x, y, z = map(lambda p, s: p - s / 2, pos, size) if self.chunkAlign: x &= ~0xF z &= ~0xF sy = size[1] if sy > lev.Height: # don't snap really tall stuff to the height return Vector(x, y, z) if y + sy > lev.Height: y = lev.Height - sy if y < 0: y = 0 if not lev.Width == 0 and lev.Length == 0: sx = size[0] if x + sx > lev.Width: x = lev.Width - sx if x < 0: x = 0 sz = size[2] if z + sz > lev.Length: z = lev.Length - sz if z < 0: z = 0 return Vector(x, y, z) def getReticleBox(self): pos = self.getReticleOrigin() sizes = self.rotatedSelectionSize() if None is sizes: return return BoundingBox(pos, sizes) def getDestBox(self): selectionSize = self.rotatedSelectionSize() return BoundingBox(self.destPoint, selectionSize) def drawTerrainReticle(self): if self.level is None: return if self.destPoint is not None: destPoint = self.destPoint if self.draggingFace is not None: # debugDrawPoint() destPoint = self.draggingOrigin() self.drawTerrainPreview(destPoint) else: self.drawTerrainPreview(self.getReticleBox().origin) draggingColor = (0.77, 1.0, 0.55, 0.05) def drawToolReticle(self): if self.level is None: return GL.glPolygonOffset(DepthOffset.CloneMarkers, DepthOffset.CloneMarkers) color = self.color if self.destPoint is not None: color = (self.color[0], self.color[1], self.color[2], 0.06) box = self.getDestBox() if self.draggingFace is not None: o = list(self.draggingOrigin()) s = list(box.size) for i in range(3): if i == self.draggingFace >> 1: continue o[i] -= 1000 s[i] += 2000 guideBox = BoundingBox(o, s) color = self.draggingColor GL.glColor(1.0, 1.0, 1.0, 0.33) with gl.glEnable(GL.GL_BLEND, GL.GL_TEXTURE_2D, GL.GL_DEPTH_TEST): self.editor.sixteenBlockTex.bind() drawFace(guideBox, self.draggingFace ^ 1) else: box = self.getReticleBox() if box is None: return self.drawRepeatedCube(box, color) GL.glPolygonOffset(DepthOffset.CloneReticle, DepthOffset.CloneReticle) if self.destPoint: box = self.getDestBox() if self.draggingFace is not None: face = self.draggingFace box = BoundingBox(self.draggingOrigin(), box.size) face, point = self.boxFaceUnderCursor(box) if face is not None: GL.glEnable(GL.GL_BLEND) GL.glDisable(GL.GL_DEPTH_TEST) GL.glColor(*self.color) drawFace(box, face) GL.glDisable(GL.GL_BLEND) GL.glEnable(GL.GL_DEPTH_TEST) def drawRepeatedCube(self, box, color): # draw several cubes according to the repeat count # it's not really sensible to repeat a crane because the origin point is literally out of this world. delta = box.origin - self.selectionBox().origin for i in range(self.repeatCount): self.editor.drawConstructionCube(box, color) box = BoundingBox(box.origin + delta, box.size) def drawToolMarkers(self): selectionBox = self.selectionBox() if selectionBox: widg = self.editor.find_widget(pygame.mouse.get_pos()) try: if self.panel and (widg is self.panel.nudgeButton or widg.parent is self.panel.nudgeButton): color = self.color except: try: if self.panel and ( widg is self.panel.offsetInput.nudgeButton or widg.parent is self.panel.offsetInput.nudgeButton ): color = self.color except: pass finally: try: self.editor.drawConstructionCube(self.getDestBox(), color) except: pass def sourceLevel(self): return self.level @alertException def rotate(self, amount=1, blocksOnly=False): if self.canRotateLevel: self.rotation += amount self.rotation &= 0x3 for i in range(amount & 0x3): if blocksOnly: self.level.rotateLeftBlocks() else: self.level.rotateLeft() self.previewRenderer.level = self.level @alertException def roll(self, amount=1, blocksOnly=False): if self.canRotateLevel: for i in range(amount & 0x3): if blocksOnly: self.level.rollBlocks() else: self.level.roll() self.previewRenderer.level = self.level @alertException def flip(self, amount=1, blocksOnly=False): if self.canRotateLevel: for i in range(amount & 0x1): if blocksOnly: self.level.flipVerticalBlocks() else: self.level.flipVertical() self.previewRenderer.level = self.level @alertException def mirror(self, blocksOnly=False): if self.canRotateLevel: yaw = int(self.editor.mainViewport.yaw) % 360 if (45 <= yaw < 135) or (225 < yaw <= 315): if blocksOnly: self.level.flipEastWestBlocks() else: self.level.flipEastWest() else: if blocksOnly: self.level.flipNorthSouthBlocks() else: self.level.flipNorthSouth() self.previewRenderer.level = self.level def option1(self): self.copyAir = not self.copyAir def option2(self): self.copyWater = not self.copyWater def option3(self): self.copyBiomes = not self.copyBiomes def option4(self): self.staticCommands = not self.staticCommands def option5(self): self.moveSpawnerPos = not self.moveSpawnerPos draggingFace = None draggingStartPoint = None def draggingOrigin(self): p = self._draggingOrigin() return p def _draggingOrigin(self): dragPos = map(int, map(numpy.floor, self.positionOnDraggingPlane())) delta = map(lambda s, e: e - int(numpy.floor(s)), self.draggingStartPoint, dragPos) if self.snapCloneKey == 1: ad = map(abs, delta) midx = ad.index(max(ad)) d = [0, 0, 0] d[midx] = delta[midx] dragY = self.draggingFace >> 1 d[dragY] = delta[dragY] delta = d p = self.destPoint + delta if self.chunkAlign: p = [i // 16 * 16 for i in p] return Vector(*p) def positionOnDraggingPlane(self): pos = self.editor.mainViewport.cameraPosition dim = self.draggingFace >> 1 # if key.get_mods() & KMOD_SHIFT: # dim = self.findBestTrackingPlane(self.draggingFace) # distance = self.draggingStartPoint[dim] - pos[dim] distance += self.draggingY mouseVector = self.editor.mainViewport.mouseVector scale = distance / (mouseVector[dim] or 1) point = map(lambda a, b: a * scale + b, mouseVector, pos) return point draggingY = 0 @alertException def mouseDown(self, evt, pos, direction): box = self.selectionBox() if not box: return self.draggingY = 0 if self.destPoint is not None: if evt.num_clicks == 2: self.pickUp() return face, point = self.boxFaceUnderCursor(self.getDestBox()) if face is not None: self.draggingFace = face self.draggingStartPoint = point else: self.destPoint = self.getReticleOrigin() if self.panel and self.panel.useOffsetInput: self.panel.offsetInput.setCoords(self.destPoint - box.origin) print "Destination: ", self.destPoint @alertException def mouseUp(self, evt, pos, direction): if self.draggingFace is not None: self.destPoint = self.draggingOrigin() self.updateOffsets() self.draggingFace = None self.draggingStartPoint = None def keyDown(self, evt): keyname = evt.dict.get("keyname", None) or self.root.getKey(evt) if keyname == config.keys.snapCloneToAxis.get(): self.snapCloneKey = 1 def keyUp(self, evt): keyname = evt.dict.get("keyname", None) or self.root.getKey(evt) if keyname == config.keys.snapCloneToAxis.get(): self.snapCloneKey = 0 def increaseToolReach(self): if self.draggingFace is not None: d = (1, -1)[self.draggingFace & 1] if self.draggingFace >> 1 != 1: # xxxxx y d = -d self.draggingY += d x, y, z = self.editor.mainViewport.cameraPosition pos = [x, y, z] pos[self.draggingFace >> 1] += d self.editor.mainViewport.cameraPosition = tuple(pos) else: self.cloneCameraDistance = self.editor._incrementReach(self.cloneCameraDistance) return True def decreaseToolReach(self): if self.draggingFace is not None: d = (1, -1)[self.draggingFace & 1] if self.draggingFace >> 1 != 1: # xxxxx y d = -d self.draggingY -= d x, y, z = self.editor.mainViewport.cameraPosition pos = [x, y, z] pos[self.draggingFace >> 1] -= d self.editor.mainViewport.cameraPosition = tuple(pos) else: self.cloneCameraDistance = self.editor._decrementReach(self.cloneCameraDistance) return True def resetToolReach(self): if self.draggingFace is not None: x, y, z = self.editor.mainViewport.cameraPosition pos = [x, y, z] pos[self.draggingFace >> 1] += (1, -1)[self.draggingFace & 1] * -self.draggingY self.editor.mainViewport.cameraPosition = tuple(pos) self.draggingY = 0 else: self.cloneCameraDistance = max(self.editor.defaultCameraToolDistance, self.safeToolDistance()) return True def pickUp(self): if self.destPoint is None: return box = self.selectionBox() # pick up the object. reset the tool distance to the object's distance from the camera d = map(lambda a, b, c: abs(a - b - c / 2), self.editor.mainViewport.cameraPosition, self.destPoint, box.size) self.cloneCameraDistance = numpy.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) self.destPoint = None # self.panel.performButton.enabled = False print "Picked up" @alertException def confirm(self): destPoint = self.destPoint if destPoint is None: return sourceLevel = self.sourceLevel() sourceBox = sourceLevel.bounds destLevel = self.editor.level op = CloneOperation( editor=self.editor, sourceLevel=sourceLevel, sourceBox=sourceBox, originSourceBox=self.selectionBox(), destLevel=destLevel, destPoint=self.destPoint, copyAir=self.copyAir, copyWater=self.copyWater, copyBiomes=self.copyBiomes, staticCommands=self.staticCommands, moveSpawnerPos=self.moveSpawnerPos, regenerateUUID=self.regenerateUUID, repeatCount=self.repeatCount, ) self.editor.toolbar.selectTool( -1 ) # deselect tool so that the clone tool's selection change doesn't update its schematic self.editor.addOperation(op) if op.canUndo: self.editor.addUnsavedEdit() dirtyBox = op.dirtyBox() if dirtyBox: self.editor.invalidateBox(dirtyBox) self.editor.renderer.invalidateChunkMarkers() self.editor.currentOperation = None self.destPoint = None self.level = None def discardPreviewer(self): if self.previewRenderer is None: return self.previewRenderer.stopWork() self.previewRenderer.discardAllChunks() self.editor.removeWorker(self.previewRenderer) self.previewRenderer = None
class CloneTool(EditorTool): surfaceBuild = True toolIconName = "clone" tooltipText = "Clone\nRight-click for options" level = None repeatCount = 1 _scaleFactor = 1.0 _chunkAlign = False @property def scaleFactor(self): return self._scaleFactor @scaleFactor.setter def scaleFactor(self, val): self.rescaleLevel(val) self._scaleFactor = val @property def chunkAlign(self): return self._chunkAlign @chunkAlign.setter def chunkAlign(self, value): self._chunkAlign = value self.alignDestPoint() def alignDestPoint(self): if self.destPoint is not None: x, y, z = self.destPoint self.destPoint = Vector((x >> 4) << 4, y, (z >> 4) << 4) placeImmediately = config.clone.placeImmediately.property() panelClass = CloneToolPanel color = (0.3, 1.0, 0.3, 0.19) def __init__(self, *args): self.rotation = 0 EditorTool.__init__(self, *args) self.previewRenderer = None self.panel = None self.optionsPanel = CloneToolOptions(self) self.destPoint = None self.snapCloneKey = 0 self.root = get_root() @property def statusText(self): if self.destPoint is None: return "Click to set this item down." if self.draggingFace is not None: return "Mousewheel to move along the third axis. Hold {0} to only move along one axis.".format( config.keys.snapCloneToAxis.get()) return "Click and drag to reposition the item. Double-click to pick it up. Click Clone or press Enter to confirm." def quickNudge(self, nudge): if config.fastNudgeSettings.cloneWidth.get(): return map(int.__mul__, nudge, self.selectionBox().size) nudgeWidth = config.fastNudgeSettings.cloneWidthNumber.get() return map(lambda x: x * nudgeWidth, nudge) copyAir = config.clone.copyAir.property() copyWater = config.clone.copyWater.property() copyBiomes = config.clone.copyBiomes.property() staticCommands = config.clone.staticCommands.property() moveSpawnerPos = config.clone.moveSpawnerPos.property() regenerateUUID = config.clone.regenerateUUID.property() def nudge(self, nudge): if self.destPoint is None: if self.selectionBox() is None: return self.destPoint = self.selectionBox().origin if self.chunkAlign: x, y, z = nudge nudge = x << 4, y, z << 4 if self.editor.rightClickNudge: nudge = self.quickNudge(nudge) # self.panel.performButton.enabled = True self.destPoint = self.destPoint + nudge self.updateOffsets() def selectionChanged(self): if self.selectionBox() is not None and "CloneToolPanel" in str( self.panel): self.updateSchematic() self.updateOffsets() def updateOffsets(self): if self.panel and self.panel.useOffsetInput and self.destPoint is not None: self.panel.offsetInput.setCoords(self.destPoint - self.selectionBox().origin) def offsetChanged(self): if self.panel: if not self.panel.useOffsetInput: return box = self.selectionBox() if box is None: return delta = self.panel.offsetInput.coords self.destPoint = box.origin + delta def toolEnabled(self): return not (self.selectionBox() is None) def cancel(self): self.discardPreviewer() if self.panel: self.panel.parent.remove(self.panel) self.panel = None self.destPoint = None self.level = None self.originalLevel = None def toolReselected(self): self.pickUp() def safeToolDistance(self): return numpy.sqrt( sum([ self.level.Width**2, self.level.Height**2, self.level.Length**2 ])) def toolSelected(self): box = self.selectionBox() if box is None: self.editor.toolbar.selectTool(-1) return if box.volume > self.maxBlocks: self.editor.mouseLookOff() alert( _("Selection exceeds {0:n} blocks. Increase the block buffer setting and try again." ).format(self.maxBlocks)) self.editor.toolbar.selectTool(-1) return self.rotation = 0 self.repeatCount = 1 self._scaleFactor = 1.0 if self.placeImmediately: self.destPoint = box.origin else: self.destPoint = None self.updateSchematic() self.cloneCameraDistance = max(self.cloneCameraDistance, self.safeToolDistance()) self.showPanel() cloneCameraDistance = 0 @property def cameraDistance(self): return self.cloneCameraDistance @alertException def rescaleLevel(self, factor): # if self.level.cloneToolScaleFactor == newFactor: # return # oldfactor = self.level.cloneToolScaleFactor # factor = newFactor / oldfactor if factor == 1: self.level = self.originalLevel self.setupPreview() return oldshape = self.originalLevel.Blocks.shape blocks = self.originalLevel.Blocks data = self.originalLevel.Data roundedShape = oldshape newshape = map(lambda x: int(x * factor), oldshape) for i, part in enumerate(newshape): if part == 0: newshape[i] = 1 xyzshape = newshape[0], newshape[2], newshape[1] newlevel = pymclevel.MCSchematic(xyzshape, mats=self.editor.level.materials) srcgrid = numpy.mgrid[0:roundedShape[0]:1.0 / factor, 0:roundedShape[1]:1.0 / factor, 0:roundedShape[2]:1.0 / factor].astype('uint') dstgrid = numpy.mgrid[0:newshape[0], 0:newshape[1], 0:newshape[2]].astype('uint') srcgrid = srcgrid[map(slice, dstgrid.shape)] dstgrid = dstgrid[map(slice, srcgrid.shape)] def copyArray(dest, src): dest[dstgrid[0], dstgrid[1], dstgrid[2]] = src[srcgrid[0], srcgrid[1], srcgrid[2]] copyArray(newlevel.Blocks, blocks) copyArray(newlevel.Data, data) self.level = newlevel self.setupPreview() # # """ # use array broadcasting to fill in the extra dimensions with copies of the # existing ones, then later change the shape to "fold" the extras back # into the original three # """ # # if factor > 1.0: # sourceSlice = slice(0, 1) # destSlice = slice(None) # # # if factor < 1.0: # # destfactor = factor # srcfactor = 1 # if factor < 1.0: # destfactor = 1.0 # srcfactor = 1.0 / factor # # intershape = newshape[0]/destfactor, destfactor, newshape[1]/destfactor, destfactor, newshape[2]/destfactor, destfactor # srcshape = roundedShape[0]/srcfactor, srcfactor, roundedShape[1]/srcfactor, srcfactor, roundedShape[2]/srcfactor, srcfactor # # newlevel = MCSchematic(xyzshape) # # def copyArray(dest, src): # dest.shape = intershape # src.shape = srcshape # # dest[:, destSlice, :, destSlice, :, destSlice] = src[:, sourceSlice, :, sourceSlice, :, sourceSlice] # dest.shape = newshape # src.shape = roundedShape # # copyArray(newlevel.Blocks, blocks) # copyArray(newlevel.Data, data) # # newlevel.cloneToolScaleFactor = newFactor # @alertException def updateSchematic(self): # extract blocks with setWindowCaption("COPYING - "): self.editor.freezeStatus("Copying to clone buffer...") box = self.selectionBox() self.level = self.editor.level.extractSchematic(box) self.originalLevel = self.level # self.level.cloneToolScaleFactor = 1.0 self.rescaleLevel(self.scaleFactor) self.setupPreview() def showPanel(self): if self.panel: self.panel.set_parent(None) self.panel = self.panelClass(self, self.editor) # self.panel.performButton.enabled = False # max_height = self.tool.editor.mainViewport.height - self.tool.editor.toolbar.height - self.tool.editor.subwidgets[0].height self.panel.centery = ( self.editor.mainViewport.height - self.editor.toolbar.height) / 2 + self.editor.subwidgets[0].height self.panel.left = self.editor.left self.editor.add(self.panel) def setupPreview(self, alpha=1.0): self.discardPreviewer() if self.level: self.previewRenderer = PreviewRenderer(self.level, alpha) self.previewRenderer.position = self.editor.renderer.position self.editor.addWorker(self.previewRenderer) else: self.editor.toolbar.selectTool(-1) @property def canRotateLevel(self): return not isinstance(self.level, (pymclevel.MCInfdevOldLevel, PocketWorld)) def rotatedSelectionSize(self): if self.canRotateLevel: sizes = self.level.Blocks.shape return sizes[0], sizes[2], sizes[1] else: return self.level.size # =========================================================================== # def getSelectionRanges(self): # return self.editor.selectionTool.selectionBox() # # =========================================================================== @staticmethod def getBlockAt(): return None # use level's blockAt def getReticleOrigin(self): # returns a new origin for the current selection, where the old origin is at the new selection's center. pos, direction = self.editor.blockFaceUnderCursor lev = self.editor.level size = self.rotatedSelectionSize() if not size: return if size[1] >= self.editor.level.Height: direction = ( 0, 1, 0 ) # always use the upward face whenever we're splicing full-height pieces, to avoid "jitter" # print size; raise SystemExit if any(direction) and pos[1] >= 0: x, y, z = map(lambda p, s, d: p - s / 2 + s * d / 2 + (d > 0), pos, size, direction) else: x, y, z = map(lambda p, s: p - s / 2, pos, size) if self.chunkAlign: x &= ~0xf z &= ~0xf sy = size[1] if sy > lev.Height: # don't snap really tall stuff to the height return Vector(x, y, z) if y + sy > lev.Height: y = lev.Height - sy if y < 0: y = 0 if not isinstance(lev, pymclevel.MCInfdevOldLevel): sx = size[0] if x + sx > lev.Width: x = lev.Width - sx if x < 0: x = 0 sz = size[2] if z + sz > lev.Length: z = lev.Length - sz if z < 0: z = 0 return Vector(x, y, z) def getReticleBox(self): pos = self.getReticleOrigin() sizes = self.rotatedSelectionSize() if None is sizes: return return BoundingBox(pos, sizes) def getDestBox(self): selectionSize = self.rotatedSelectionSize() return BoundingBox(self.destPoint, selectionSize) def drawTerrainReticle(self): if self.level is None: return if self.destPoint is not None: destPoint = self.destPoint if self.draggingFace is not None: # debugDrawPoint() destPoint = self.draggingOrigin() self.drawTerrainPreview(destPoint) else: self.drawTerrainPreview(self.getReticleBox().origin) draggingColor = (0.77, 1.0, 0.55, 0.05) def drawToolReticle(self): if self.level is None: return GL.glPolygonOffset(DepthOffset.CloneMarkers, DepthOffset.CloneMarkers) color = self.color if self.destPoint is not None: color = (self.color[0], self.color[1], self.color[2], 0.06) box = self.getDestBox() if self.draggingFace is not None: o = list(self.draggingOrigin()) s = list(box.size) for i in range(3): if i == self.draggingFace >> 1: continue o[i] -= 1000 s[i] += 2000 guideBox = BoundingBox(o, s) color = self.draggingColor GL.glColor(1.0, 1.0, 1.0, 0.33) with gl.glEnable(GL.GL_BLEND, GL.GL_TEXTURE_2D, GL.GL_DEPTH_TEST): self.editor.sixteenBlockTex.bind() drawFace(guideBox, self.draggingFace ^ 1) else: box = self.getReticleBox() if box is None: return self.drawRepeatedCube(box, color) GL.glPolygonOffset(DepthOffset.CloneReticle, DepthOffset.CloneReticle) if self.destPoint: box = self.getDestBox() if self.draggingFace is not None: face = self.draggingFace box = BoundingBox(self.draggingOrigin(), box.size) face, point = self.boxFaceUnderCursor(box) if face is not None: GL.glEnable(GL.GL_BLEND) GL.glDisable(GL.GL_DEPTH_TEST) GL.glColor(*self.color) drawFace(box, face) GL.glDisable(GL.GL_BLEND) GL.glEnable(GL.GL_DEPTH_TEST) def drawRepeatedCube(self, box, color): # draw several cubes according to the repeat count # it's not really sensible to repeat a crane because the origin point is literally out of this world. delta = box.origin - self.selectionBox().origin for i in range(self.repeatCount): self.editor.drawConstructionCube(box, color) box = BoundingBox(box.origin + delta, box.size) def drawToolMarkers(self): selectionBox = self.selectionBox() if selectionBox: widg = self.editor.find_widget(pygame.mouse.get_pos()) try: if self.panel and (widg is self.panel.nudgeButton or widg.parent is self.panel.nudgeButton): color = self.color except: try: if self.panel and ( widg is self.panel.offsetInput.nudgeButton or widg.parent is self.panel.offsetInput.nudgeButton): color = self.color except: pass finally: try: self.editor.drawConstructionCube(self.getDestBox(), color) except: pass def sourceLevel(self): return self.level @alertException def rotate(self, amount=1, blocksOnly=False): if self.canRotateLevel: self.rotation += amount self.rotation &= 0x3 for i in range(amount & 0x3): if blocksOnly: self.level.rotateLeftBlocks() else: self.level.rotateLeft() self.previewRenderer.level = self.level @alertException def roll(self, amount=1, blocksOnly=False): if self.canRotateLevel: for i in range(amount & 0x3): if blocksOnly: self.level.rollBlocks() else: self.level.roll() self.previewRenderer.level = self.level @alertException def flip(self, amount=1, blocksOnly=False): if self.canRotateLevel: for i in range(amount & 0x1): if blocksOnly: self.level.flipVertical() else: self.level.flipVerticalBlocks() self.previewRenderer.level = self.level @alertException def mirror(self, blocksOnly=False): if self.canRotateLevel: yaw = int(self.editor.mainViewport.yaw) % 360 if (45 <= yaw < 135) or (225 < yaw <= 315): if blocksOnly: self.level.flipEastWestBlocks() else: self.level.flipEastWest() else: if blocksOnly: self.level.flipNorthSouthBlocks() else: self.level.flipNorthSouth() self.previewRenderer.level = self.level def option1(self): self.copyAir = not self.copyAir def option2(self): self.copyWater = not self.copyWater def option3(self): self.copyBiomes = not self.copyBiomes def option4(self): self.staticCommands = not self.staticCommands def option5(self): self.moveSpawnerPos = not self.moveSpawnerPos draggingFace = None draggingStartPoint = None def draggingOrigin(self): p = self._draggingOrigin() return p def _draggingOrigin(self): dragPos = map(int, map(numpy.floor, self.positionOnDraggingPlane())) delta = map(lambda s, e: e - int(numpy.floor(s)), self.draggingStartPoint, dragPos) if self.snapCloneKey == 1: ad = map(abs, delta) midx = ad.index(max(ad)) d = [0, 0, 0] d[midx] = delta[midx] dragY = self.draggingFace >> 1 d[dragY] = delta[dragY] delta = d p = self.destPoint + delta if self.chunkAlign: p = [i // 16 * 16 for i in p] return Vector(*p) def positionOnDraggingPlane(self): pos = self.editor.mainViewport.cameraPosition dim = self.draggingFace >> 1 # if key.get_mods() & KMOD_SHIFT: # dim = self.findBestTrackingPlane(self.draggingFace) # distance = self.draggingStartPoint[dim] - pos[dim] distance += self.draggingY mouseVector = self.editor.mainViewport.mouseVector scale = distance / (mouseVector[dim] or 1) point = map(lambda a, b: a * scale + b, mouseVector, pos) return point draggingY = 0 @alertException def mouseDown(self, evt, pos, direction): box = self.selectionBox() if not box: return self.draggingY = 0 if self.destPoint is not None: if evt.num_clicks == 2: self.pickUp() return face, point = self.boxFaceUnderCursor(self.getDestBox()) if face is not None: self.draggingFace = face self.draggingStartPoint = point else: self.destPoint = self.getReticleOrigin() if self.panel and self.panel.useOffsetInput: self.panel.offsetInput.setCoords(self.destPoint - box.origin) print "Destination: ", self.destPoint @alertException def mouseUp(self, evt, pos, direction): if self.draggingFace is not None: self.destPoint = self.draggingOrigin() self.draggingFace = None self.draggingStartPoint = None def keyDown(self, evt): keyname = evt.dict.get('keyname', None) or self.root.getKey(evt) if keyname == config.keys.snapCloneToAxis.get(): self.snapCloneKey = 1 def keyUp(self, evt): keyname = evt.dict.get('keyname', None) or self.root.getKey(evt) if keyname == config.keys.snapCloneToAxis.get(): self.snapCloneKey = 0 def increaseToolReach(self): if self.draggingFace is not None: d = (1, -1)[self.draggingFace & 1] if self.draggingFace >> 1 != 1: # xxxxx y d = -d self.draggingY += d x, y, z = self.editor.mainViewport.cameraPosition pos = [x, y, z] pos[self.draggingFace >> 1] += d self.editor.mainViewport.cameraPosition = tuple(pos) else: self.cloneCameraDistance = self.editor._incrementReach( self.cloneCameraDistance) return True def decreaseToolReach(self): if self.draggingFace is not None: d = (1, -1)[self.draggingFace & 1] if self.draggingFace >> 1 != 1: # xxxxx y d = -d self.draggingY -= d x, y, z = self.editor.mainViewport.cameraPosition pos = [x, y, z] pos[self.draggingFace >> 1] -= d self.editor.mainViewport.cameraPosition = tuple(pos) else: self.cloneCameraDistance = self.editor._decrementReach( self.cloneCameraDistance) return True def resetToolReach(self): if self.draggingFace is not None: x, y, z = self.editor.mainViewport.cameraPosition pos = [x, y, z] pos[self.draggingFace >> 1] += (1, -1)[self.draggingFace & 1] * -self.draggingY self.editor.mainViewport.cameraPosition = tuple(pos) self.draggingY = 0 else: self.cloneCameraDistance = max( self.editor.defaultCameraToolDistance, self.safeToolDistance()) return True def pickUp(self): if self.destPoint is None: return box = self.selectionBox() # pick up the object. reset the tool distance to the object's distance from the camera d = map(lambda a, b, c: abs(a - b - c / 2), self.editor.mainViewport.cameraPosition, self.destPoint, box.size) self.cloneCameraDistance = numpy.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) self.destPoint = None # self.panel.performButton.enabled = False print "Picked up" @alertException def confirm(self): destPoint = self.destPoint if destPoint is None: return sourceLevel = self.sourceLevel() sourceBox = sourceLevel.bounds destLevel = self.editor.level destVolume = BoundingBox(destPoint, sourceBox.size).volume op = CloneOperation(editor=self.editor, sourceLevel=sourceLevel, sourceBox=sourceBox, originSourceBox=self.selectionBox(), destLevel=destLevel, destPoint=self.destPoint, copyAir=self.copyAir, copyWater=self.copyWater, copyBiomes=self.copyBiomes, staticCommands=self.staticCommands, moveSpawnerPos=self.moveSpawnerPos, regenerateUUID=self.regenerateUUID, repeatCount=self.repeatCount) self.editor.toolbar.selectTool( -1 ) # deselect tool so that the clone tool's selection change doesn't update its schematic self.editor.addOperation(op) if op.canUndo: self.editor.addUnsavedEdit() dirtyBox = op.dirtyBox() if dirtyBox: self.editor.invalidateBox(dirtyBox) self.editor.renderer.invalidateChunkMarkers() self.editor.currentOperation = None self.destPoint = None self.level = None def discardPreviewer(self): if self.previewRenderer is None: return self.previewRenderer.stopWork() self.previewRenderer.discardAllChunks() self.editor.removeWorker(self.previewRenderer) self.previewRenderer = None
class ThumbView(GLPerspective): def __init__(self, sch, **kw): GLPerspective.__init__(self, **kw) # self, xmin= -32, xmax=32, ymin= -32, ymax=32, near= -1000, far=1000) self.far = 16000 self.schematic = sch self.renderer = PreviewRenderer(sch) self.fboSize = (128, 128) self.root = self.get_root() # self.renderer.position = (sch.Length / 2, 0, sch.Height / 2) def setup_modelview(self): GLU.gluLookAt(-self.schematic.Width * 2.8, self.schematic.Height * 2.5 + 1, -self.schematic.Length * 1.5, self.schematic.Width, 0, self.schematic.Length, 0, 1, 0) fbo = None def gl_draw_tex(self): self.clear() self.renderer.draw() def clear(self): if self.drawBackground: GL.glClearColor(0.25, 0.27, 0.77, 1.0) else: GL.glClearColor(0.0, 0.0, 0.0, 0.0) GL.glClear(GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT) def gl_draw(self): if self.schematic.chunkCount > len(self.renderer.chunkRenderers): self.gl_draw_thumb() else: if self.fbo is None: w, h = self.fboSize self.fbo = FramebufferTexture(w, h, self.gl_draw_tex) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() GL.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY) GL.glColor(1.0, 1.0, 1.0, 1.0) GL.glVertexPointer(2, GL.GL_FLOAT, 0, array([-1, -1, - 1, 1, 1, 1, 1, -1, ], dtype='float32')) GL.glTexCoordPointer(2, GL.GL_FLOAT, 0, array([0, 0, 0, 256, 256, 256, 256, 0], dtype='float32')) e = (GL.GL_TEXTURE_2D,) if not self.drawBackground: e += (GL.GL_ALPHA_TEST,) with gl.glEnable(*e): self.fbo.bind() GL.glDrawArrays(GL.GL_QUADS, 0, 4) GL.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY) drawBackground = True def gl_draw_thumb(self): GL.glPushAttrib(GL.GL_SCISSOR_BIT) r = self.rect r = r.move(*self.local_to_global_offset()) GL.glScissor(r.x, self.root.height - r.y - r.height, r.width, r.height) with gl.glEnable(GL.GL_SCISSOR_TEST): self.clear() self.renderer.draw() GL.glPopAttrib()
class ThumbView(GLPerspective): def __init__(self, sch, **kw): GLPerspective.__init__(self, **kw) # self, xmin= -32, xmax=32, ymin= -32, ymax=32, near= -1000, far=1000) self.far = 16000 self.schematic = sch self.renderer = PreviewRenderer(sch) self.fboSize = (128, 128) # self.renderer.position = (sch.Length / 2, 0, sch.Height / 2) def setup_modelview(self): GLU.gluLookAt(-self.schematic.Width * 2.8, self.schematic.Height * 2.5 + 1, -self.schematic.Length * 1.5, self.schematic.Width, 0, self.schematic.Length, 0, 1, 0) fbo = None def gl_draw_tex(self): self.clear() self.renderer.draw() def clear(self): if self.drawBackground: GL.glClearColor(0.25, 0.27, 0.77, 1.0) else: GL.glClearColor(0.0, 0.0, 0.0, 0.0) GL.glClear(GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT) def gl_draw(self): if self.schematic.chunkCount > len(self.renderer.chunkRenderers): self.gl_draw_thumb() else: if self.fbo is None: w, h = self.fboSize self.fbo = FramebufferTexture(w, h, self.gl_draw_tex) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() GL.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY) GL.glColor(1.0, 1.0, 1.0, 1.0) GL.glVertexPointer(2, GL.GL_FLOAT, 0, array([-1, -1, - 1, 1, 1, 1, 1, -1, ], dtype='float32')) GL.glTexCoordPointer(2, GL.GL_FLOAT, 0, array([0, 0, 0, 256, 256, 256, 256, 0], dtype='float32')) e = (GL.GL_TEXTURE_2D,) if not self.drawBackground: e += (GL.GL_ALPHA_TEST,) with gl.glEnable(*e): self.fbo.bind() GL.glDrawArrays(GL.GL_QUADS, 0, 4) GL.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY) drawBackground = True def gl_draw_thumb(self): GL.glPushAttrib(GL.GL_SCISSOR_BIT) r = self.rect r = r.move(*self.local_to_global_offset()) GL.glScissor(r.x, self.get_root().height - r.y - r.height, r.width, r.height) with gl.glEnable(GL.GL_SCISSOR_TEST): self.clear() self.renderer.draw() GL.glPopAttrib()
class ThumbView(GLPerspective): def __init__(self, sch, **kw): GLPerspective.__init__( self, **kw ) # self, xmin= -32, xmax=32, ymin= -32, ymax=32, near= -1000, far=1000) self.p_margin = 0 self.p_spacing = 0 self.widget_index = 0 self.set_position_modifiers() self.far = 16000 self.schematic = sch self.renderer = PreviewRenderer(sch) self.fboSize = (128, 128) self.root = self.get_root() # self.renderer.position = (sch.Length / 2, 0, sch.Height / 2) def set_position_modifiers(self): if getattr(self, 'parent', None) is not None: self.p_margin = getattr(self.parent, 'margin', 0) self.p_spacing = getattr(self.parent, 'spacing', 0) if hasattr(self.parent, 'subwidgets') and self in self.parent.subwidgets: self.widget_index = self.parent.subwidgets.index(self) def setup_modelview(self): GLU.gluLookAt(-self.schematic.Width * 2.8, self.schematic.Height * 2.5 + 1, -self.schematic.Length * 1.5, self.schematic.Width, 0, self.schematic.Length, 0, 1, 0) fbo = None def gl_draw_tex(self): self.clear() self.renderer.draw() def clear(self): if self.drawBackground: GL.glClearColor(0.25, 0.27, 0.77, 1.0) else: GL.glClearColor(0.0, 0.0, 0.0, 0.0) GL.glClear(GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT) def gl_draw(self): if self.schematic.chunkCount > len(self.renderer.chunkRenderers): self.gl_draw_thumb() else: if self.fbo is None: w, h = self.fboSize self.fbo = FramebufferTexture(w, h, self.gl_draw_tex) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() GL.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY) GL.glColor(1.0, 1.0, 1.0, 1.0) GL.glVertexPointer( 2, GL.GL_FLOAT, 0, array([ -1, -1, -1, 1, 1, 1, 1, -1, ], dtype='float32')) GL.glTexCoordPointer( 2, GL.GL_FLOAT, 0, array([0, 0, 0, 256, 256, 256, 256, 0], dtype='float32')) e = (GL.GL_TEXTURE_2D, ) if not self.drawBackground: e += (GL.GL_ALPHA_TEST, ) with gl.glEnable(*e): self.fbo.bind() GL.glDrawArrays(GL.GL_QUADS, 0, 4) GL.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY) drawBackground = True def gl_draw_thumb(self): GL.glPushAttrib(GL.GL_SCISSOR_BIT) r = self.rect x, y = self.local_to_global_offset() self.set_position_modifiers() if hasattr(self.parent, 'axis'): s_sz = 0 if self.widget_index > 0: s_sz = getattr(self.parent.subwidgets[self.widget_index - 1], self.parent.longways, 0) #-# Do we have a bad hack or the real solution with `(self.parent.height - self.height) / 2 + 1` stuff? #-# Need extensive tests to confirm... if self.parent.axis == 'h': r = r.move( x + (self.parent.height - self.height) / 2 + 1 + self.p_margin - self.p_spacing - s_sz, y - (self.parent.height - self.height) / 2) else: r = r.move( x - (self.parent.width - self.height) / 2, y - (self.parent.width - self.height) / 2 + 1 + self.p_margin - self.p_spacing - s_sz) else: r = r.move(*self.local_to_global_offset()) GL.glScissor(r.x, self.root.height - r.y - r.height, r.width, r.height) with gl.glEnable(GL.GL_SCISSOR_TEST): self.clear() self.renderer.draw() GL.glPopAttrib()
class ThumbView(GLPerspective): def __init__(self, sch, **kw): GLPerspective.__init__(self, **kw) # self, xmin= -32, xmax=32, ymin= -32, ymax=32, near= -1000, far=1000) self.p_margin = 0 self.p_spacing = 0 self.widget_index = 0 self.set_position_modifiers() self.far = 16000 self.schematic = sch self.renderer = PreviewRenderer(sch) self.fboSize = (128, 128) self.root = self.get_root() # self.renderer.position = (sch.Length / 2, 0, sch.Height / 2) def set_position_modifiers(self): if getattr(self, 'parent', None) is not None: self.p_margin = getattr(self.parent, 'margin', 0) self.p_spacing = getattr(self.parent, 'spacing', 0) if hasattr(self.parent, 'subwidgets') and self in self.parent.subwidgets: self.widget_index = self.parent.subwidgets.index(self) def setup_modelview(self): GLU.gluLookAt(-self.schematic.Width * 2.8, self.schematic.Height * 2.5 + 1, -self.schematic.Length * 1.5, self.schematic.Width, 0, self.schematic.Length, 0, 1, 0) fbo = None def gl_draw_tex(self): self.clear() self.renderer.draw() def clear(self): if self.drawBackground: GL.glClearColor(0.25, 0.27, 0.77, 1.0) else: GL.glClearColor(0.0, 0.0, 0.0, 0.0) GL.glClear(GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT) def gl_draw(self): if self.schematic.chunkCount > len(self.renderer.chunkRenderers): self.gl_draw_thumb() else: if self.fbo is None: w, h = self.fboSize self.fbo = FramebufferTexture(w, h, self.gl_draw_tex) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() GL.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY) GL.glColor(1.0, 1.0, 1.0, 1.0) GL.glVertexPointer(2, GL.GL_FLOAT, 0, array([-1, -1, - 1, 1, 1, 1, 1, -1, ], dtype='float32')) GL.glTexCoordPointer(2, GL.GL_FLOAT, 0, array([0, 0, 0, 256, 256, 256, 256, 0], dtype='float32')) e = (GL.GL_TEXTURE_2D,) if not self.drawBackground: e += (GL.GL_ALPHA_TEST,) with gl.glEnable(*e): self.fbo.bind() GL.glDrawArrays(GL.GL_QUADS, 0, 4) GL.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY) drawBackground = True def gl_draw_thumb(self): GL.glPushAttrib(GL.GL_SCISSOR_BIT) r = self.rect x, y = self.local_to_global_offset() self.set_position_modifiers() if hasattr(self.parent, 'axis'): s_sz = 0 if self.widget_index > 0: s_sz = getattr(self.parent.subwidgets[self.widget_index - 1], self.parent.longways, 0) #-# Do we have a bad hack or the real solution with `(self.parent.height - self.height) / 2 + 1` stuff? #-# Need extensive tests to confirm... if self.parent.axis == 'h': r = r.move(x + (self.parent.height - self.height) / 2 + 1 + self.p_margin - self.p_spacing - s_sz, y - (self.parent.height - self.height) / 2) else: r = r.move(x - (self.parent.width - self.height) / 2, y - (self.parent.width - self.height) / 2 + 1 + self.p_margin - self.p_spacing - s_sz) else: r = r.move(*self.local_to_global_offset()) GL.glScissor(r.x, self.root.height - r.y - r.height, r.width, r.height) with gl.glEnable(GL.GL_SCISSOR_TEST): self.clear() self.renderer.draw() GL.glPopAttrib()