summaryrefslogtreecommitdiff
path: root/slippy.py
blob: afd12716cb7a9bdce1efa180a732e76ad0919ff8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import sys, pygame
pygame.init()

SIZE = WIDTH, HEIGHT = 480, 320
BLACK = 0,0,0
WHITE = 255,255,255

screen = pygame.display.set_mode(SIZE)

offset = 100,100
origin = [0,0]
size = 300
level = 1

if len(sys.argv) >= 2: tilepath = sys.argv[1]
else: tilepath = 0

def sub2(a, b):
	return [a[0] - b[0], a[1] - b[1]]

def coord2zone(x, y):
	assert level > 0
	childIds = ["012", "345", "678"]
	ret = ""
	for i in xrange(level):
		ret = childIds[y%3][x%3] + ret
		y = y // 3
		x = x // 3

	INVERT = "678345012"
	REVERSE = "876543210"
	CCW = "258147036"
	CW = "630741852"
	def rot(table): return "".join(table[int(c)] for c in ret) if table else ret
	if y % 4 == 0: return "N" + rot([CCW, None, CW, REVERSE][x%4])
	elif y % 4 == 2: return "S" + rot([REVERSE, CW, None, CCW][x%4])
	elif y % 4 == 3: return "QROP"[x%4] + rot(INVERT)
	else: return "OPQR"[x%4] + ret

def render():
	screen.fill(WHITE)

	font = pygame.font.Font(pygame.font.get_default_font(), 10)
	for X, x in enumerate(xrange(-offset[0], WIDTH+size, size)):
		for Y, y in enumerate(xrange(-offset[1], HEIGHT+size, size)):
			rect = pygame.Rect((x, y), (0,0)).inflate(size,size)
			pygame.draw.rect(screen, BLACK, rect, 1)
			zone = coord2zone(origin[0]+X,origin[1]+Y)

			tile = None
			if tilepath:
				try:
					tile = pygame.image.load(tilepath.replace("?", zone))
					tile = pygame.transform.scale(tile, (size, size))
				except:
					pass
			if tile == None:
				tile = font.render(zone, True, BLACK, WHITE)
			screen.blit(tile, (x - size/2 + 2, y - size/2 + 2))
	pygame.display.flip()
render()

dragging = False
while True:
	changed = False
	for event in pygame.event.get():
		if event.type == pygame.QUIT: sys.exit()
		elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: dragging = True
		elif event.type == pygame.MOUSEBUTTONUP and event.button == 1: dragging = False
		elif dragging and event.type == pygame.MOUSEMOTION:
			offset = sub2(offset, event.rel)
			if offset[0] < 0:
				offset[0] += size
				origin[0] -= 1
			elif offset[0] > size:
				offset[0] -= size
				origin[0] += 1
			if offset[1] < 0:
				offset[1] += size
				origin[1] -= 1
			elif offset[1] > size:
				offset[1] -= size
				origin[1] += 1
			changed = True
		# Scroll wheel API is a bit weird...
		elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 5:
			size += 1
			if size > WIDTH or size > HEIGHT:
				size = size / 3
				level += 1
				origin[0] += 1; origin[1] += 1
			changed = True
		elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 4:
			size -= 1
			if size*3 < WIDTH or size*3 < HEIGHT:
				if level == 1: size += 1
				else:
					size *= 3
					level -= 1
					origin[0] -= 1; origin[1] -= 1
			changed = True

	if changed:
		render()
	pygame.time.wait(100)

# FIXME: panning left or right on polar faces are incorrect.
# Fix by determining a main face (via origin variable) and special case left/right.
# Or better yet, by panning directly via zone IDs rather than screen cells.