def setMouseOffset(myCanvas, tiles, selectedTiles, mouseLoc, isDrag, selectedTile, grid, gridRes): # Only areas near the clicked tile are checked to see if they were # clicked on areasToCheck = getAreasToCheck(mouseLoc, grid, gridRes) for area in areasToCheck: for tile in area: # Part of this next block insures that only the tile on top # of other tiles is selected if (not isDrag and common.isInSquare(mouseLoc, tile.position, tile.radius) and common.getDistance(mouseLoc, tile.position) < tile.radius and (selectedTile is None or tiles.index(tile) > tiles.index(selectedTile))): selectedTile = tile # If there has been a left click, a single tile is selected. If # there has been a right click, a group of snapped tiles is # selected. if selectedTile is not None: if myCanvas.isLDown: selectedTiles = [selectedTile] else: selectedTiles = [] for tile in selectedTile.tileGroup: selectedTiles.append(tile) isDrag = True for tile in selectedTile.tileGroup: tile.mouseOffset = common.mySub(mouseLoc, tile.position) # The next two lines move all the tiles in a seleted group # of tiles to the top layer of the tiles tiles.remove(tile) tiles.append(tile) return selectedTiles, isDrag, selectedTile
def moveAll(myCanvas, mouseLoc, tiles, grid, gridRes, dirtyRects, isDrawAll, windowSurface): for tile in tiles: misc.toGrid(myCanvas, tile, grid, gridRes) pygame.draw.rect(windowSurface, objects.Canvas.BACK_COLOR, tile.getRect()) dirtyRects.append(tile.getRect()) tile.setPosition(common.mySub(mouseLoc, tile.mouseOffset)) tile.scalePosition(objects.Canvas.scale) isDrawAll = True return isDrawAll
def checkPallet(myCanvas, tiles, mouseLoc, isDrag, selectedTile): for tile in myCanvas.tilePallet: if (not isDrag and common.isInSquare(mouseLoc, tile.position, tile.radius) and common.getDistance(mouseLoc, tile.position) < tile.radius): newTile = objects.Tile(myCanvas, tile.image) newTile.setPosition(tile.position) tiles.append(newTile) newTile.mouseOffset = common.mySub(mouseLoc, tile.position) selectedTile = newTile isDrag = True return isDrag, selectedTile
def snapTiles(selectedTile, snapdSide, adjSide): snapdTile = snapdSide.tile for tile in selectedTile.tileGroup: tile.groupOffset = common.mySub(tile.absPosition, snapdTile.absPosition) for tile in selectedTile.tileGroup: tile.matchCorner(snapdSide.corner, common.myAdd(adjSide.corner.getAbsPosition(), tile.groupOffset)) snapdTile.adjTile = adjSide.tile snapdTile.adjTile.adjTile = snapdTile isSnapped = True return isSnapped, snapdTile, snapdSide
def moveUnSnappable(myCanvas, mouseLoc, selectedTiles, selectedTile, isSnapped, sidesToSnap, snapdTile, tiles): # Checks each side of one of the tiles which is snapped but can # potentially still be unsnapped. If the distance between this # tile and another tile is enough, the tiles unsnap for side in snapdTile.sides: if (side.adjSide is not None and common.getDistance(common.myAdd( common.mySub(mouseLoc, snapdTile.mouseOffset), side.corner.getOffset()), side.adjSide.corner.getPosition()) > objects.Canvas.SNAP_DISTANCE * objects.Canvas.scale + 1): isSnapped, sidesToSnap, snapdTile = moveUnSnap(myCanvas, mouseLoc, selectedTiles, selectedTile, sidesToSnap, tiles) break return (isSnapped, sidesToSnap, snapdTile)
def moveUnSnap(myCanvas, mouseLoc, selectedTiles, selectedTile, sidesToSnap, tiles): # Moves the tiles back to the position they would be if not snapped for tile in selectedTiles: tile.setPosition(common.mySub(mouseLoc, tile.mouseOffset)) # The next block only runs if the left mouse button is down, meaning # only one tile is being selected if myCanvas.isLDown: gapCount = 0 for i in range(-1, len(selectedTile.sides) - 1): if (selectedTile.sides[i].isSnapped and not selectedTile.sides[i + 1].isSnapped): gapCount += 1 # This block only runs if the tile being unsapped is holding two # groups of tiles together. If this happens, the tile group # needs to be and is split into two or more new tile groups. if gapCount >= 2: # Ungroups all tiles for side in selectedTile.sides: if side.isSnapped: side.adjSide.tile.tileGroup = [] # Regroups tiles into new seperate groups. For each side of # the single tile that is being unsnapped, this checks # whether there is another tile snapped to the unsnapping # tile which should be part of a seperate group from that # other tile. If so, that seperate tile is recursively # grouped with other tiles extensionally connected to it for side in selectedTile.sides: if side.isSnapped: for sideB in selectedTile.sides: if (sideB.isSnapped and sideB.adjSide.tile not in side.adjSide.tile.tileGroup): side.adjSide.tile.tileGroup = [side.adjSide.tile] misc.addNeighbors(side.adjSide.tile, selectedTile) selectedTile.unSnap() for side in sidesToSnap: side.adjSide = None sidesToSnap = [] snapdTile = None isSnapped = False return (isSnapped, sidesToSnap, snapdTile)
def update(myCanvas, tiles, selectedTiles, mouseLoc, button, isUnClick, isClick, isScrollDown, isScrollUp, grid, gridRes, isDrag, selectedTile, palletBack, isSnapped, sidesToSnap, snapdTile, snapdSide, adjSide, clock, FPS, oldMouseLoc, windowSurface): # oldPositions keeps track of where tiles were before they were moved oldPositions = [] # dirtyRects keeps track of parts of the screen that need to be # updated after drawing to the screen dirtyRects = [] # determines whether either tiles which have been moved should be # re-drawn, or if all of the tiles should be re-drawn isDrawClicked = isDrawAll = False # isDrag keeps track of whether or not a tile is being dragged # around by the mouse if isUnClick: myCanvas.isMouseDown = myCanvas.isLDown = myCanvas.isRDown = \ isClick = isDrag = False else: if button == myCanvas.RIGHT: myCanvas.isRDown = True myCanvas.isMouseDown = True elif button == myCanvas.LEFT: myCanvas.isLDown = True myCanvas.isMouseDown = True clock.tick(FPS) # isDeleted is set to true when one or more tiles has been deleted # on the current step isDeleted = False # This function resizes the display if the user is scrolling grid, gridRes, palletBack, isDrawAll = scrollSize(myCanvas, tiles, grid, gridRes, palletBack, isScrollDown, isScrollUp, dirtyRects, isDrawAll, windowSurface) # This function checks if the user has clicked on the tile pallet. # If so, a tile is chosen from the pallet. It also checks if the # user has clicked on a tile already on the canvas. Either way it # sets the mouseOffset attribute for all of the selected tiles, which # hold the distance between the center of the tile and the mouse # location. Right mouse clicks chose tile groups, left clicks # choose individual tiles. Generally this gets the tiles ready to be # moved. selectedTiles, isDrawClicked, isDrag, selectedTile, = \ checkers.checkClick(myCanvas, mouseLoc, tiles, selectedTiles, isClick, isDrawClicked, isDrag, selectedTile, grid, gridRes) # Checks if the mouse has unclicked, and if so, sets up tile groups # such that any snapped tiles are now in the same group. # Also changes which part of the tile grid they are now a part of. isDrawClicked, selectedTile, isSnapped, sidesToSnap, \ snapdTile, snapdSide = checkers.checkUnclick(myCanvas, isUnClick, isClick, tiles, selectedTiles, isDrawClicked, oldPositions, dirtyRects, selectedTile, isSnapped, sidesToSnap, snapdTile, grid, gridRes, snapdSide) # Checks if tiles are currently over the tile pallet, and sets them # to turn red if and only if they are over it. If there has been an # unclick and the tiles are over the pallet, they are deleted isDeleted = checkers.checkTrash(myCanvas, tiles, selectedTiles, oldPositions, isUnClick, dirtyRects, selectedTile, grid, gridRes, palletBack, isDeleted, windowSurface) #Sets the mouse offset on all the tiles if the background is dragged if not isDrag and isClick: for tile in tiles: tile.mouseOffset = common.mySub(mouseLoc, tile.position) # Things in this block only evaluate if there is both a mouse click, # and mouse movement since the last update if myCanvas.isMouseDown and mouseLoc != oldMouseLoc: # If a tile or tiles is being dragged, this determines where # they should be moved and also snaps or unsnaps them from other # tiles if isDrag: isDrawClicked, isSnapped, sidesToSnap, snapdTile, snapdSide, \ adjSide = movers.moveSome(myCanvas, mouseLoc, tiles, selectedTiles, oldPositions, isUnClick, dirtyRects, selectedTile, isSnapped, sidesToSnap, snapdTile, palletBack, snapdSide, adjSide, grid, gridRes, windowSurface) # This only evaluates if the background is being dragged and there # are one or more tiles. It moves all of the movable tiles. elif len(tiles) > 0: isDrawAll = movers.moveAll(myCanvas, mouseLoc, tiles, grid, gridRes, dirtyRects, isDrawAll, windowSurface) if isDeleted: selectedTile = None # Draws tiles which need to be drawn if isDrawClicked or isDrawAll: drawers.draw(myCanvas, tiles, oldPositions, isUnClick, dirtyRects, isDrawClicked, isDrawAll, selectedTile, palletBack, grid, gridRes, windowSurface) if isUnClick: selectedTile = None oldMouseLoc = mouseLoc return (selectedTiles, grid, gridRes, isDrag, selectedTile, palletBack, isSnapped, sidesToSnap, snapdTile, snapdSide, adjSide, oldMouseLoc)
def getRect(self): return pygame.Rect(map(int, map(round, common.mySub(self.position, (self.adjWRad, self.adjHRad)))), (self.adjWidth, self.adjHeight))
def matchCorner(self, corner, adjPoint): self.absPosition = map(int, map(round, common.mySub(adjPoint, corner.offset))) self.scalePosition(Canvas.scale)
def setPosition(self, position): self.position = position self.absPosition = map(int, map(round, common.myDiv(common.mySub( position, (self.myCanvas.WIDTH / 2, self.myCanvas.HEIGHT / 2)), Canvas.scale))) self.scalePosition(Canvas.scale)
def noSnapMove(mouseLoc, selectedTiles): for tile in selectedTiles: tile.setPosition(common.mySub(mouseLoc, tile.mouseOffset))