comparison tools/area_editor.py @ 424:a64d894aa1bd

Actually snap to grid.
author Simon Cross <hodgestar@gmail.com>
date Sat, 07 Sep 2013 13:30:06 +0200
parents eb1a4a269d37
children 1a85044f81a8
comparison
equal deleted inserted replaced
423:eb1a4a269d37 424:a64d894aa1bd
71 self.y = y 71 self.y = y
72 # Lookup initiliasition info from the objects 72 # Lookup initiliasition info from the objects
73 self.lookup = {} 73 self.lookup = {}
74 self._move_poly = None 74 self._move_poly = None
75 75
76 def round_point(self, pos):
77 return (10 * (pos[0] // 10), 10 * (pos[1] // 10))
78
79 def load(self, space): 76 def load(self, space):
80 super(EditorLevel, self).load(space) 77 super(EditorLevel, self).load(space)
81 # Needed to fill in the lookup dict 78 # Needed to fill in the lookup dict
82 self.reset_objs() 79 self.reset_objs()
83 80
88 return (pos[0], self.y - pos[1]) 85 return (pos[0], self.y - pos[1])
89 86
90 def add_point(self, poly_index, pos): 87 def add_point(self, poly_index, pos):
91 self.polygons.setdefault(poly_index, []) 88 self.polygons.setdefault(poly_index, [])
92 if not self.polygons[poly_index]: 89 if not self.polygons[poly_index]:
93 point = self.point_to_pymunk(self.round_point(pos)) 90 point = self.point_to_pymunk(pos)
94 self.polygons[poly_index].append(point) 91 self.polygons[poly_index].append(point)
95 else: 92 else:
96 add_pos = self.fix_poly_angle(poly_index, pos) 93 add_pos = self.point_to_pymunk(pos)
97 self.polygons[poly_index].append(add_pos) 94 self.polygons[poly_index].append(add_pos)
98
99 def _fix_angle(self, point1, pos):
100 # We want the line (point1 to pos) to be an angle of
101 # 0, 45, 90, 135, 180, 225, 270, 305
102 # However, we only need to consider half the circle
103 # This is a hack to approximate the right thing
104 pos0 = (pos[0], point1[1])
105 pos90 = (point1[0], pos[1])
106 dist = max(abs(point1[0] - pos[0]), abs(point1[1] - pos[1]))
107 pos45 = (point1[0] + dist, point1[1] + dist)
108 pos135 = (point1[0] + dist, point1[1] - dist)
109 pos225 = (point1[0] - dist, point1[1] - dist)
110 pos305 = (point1[0] - dist, point1[1] + dist)
111 min_dist = 9999999
112 new_pos = point1
113 for cand in [pos0, pos90, pos45, pos135, pos225, pos305]:
114 dist = distance(pos, cand)
115 if dist < min_dist:
116 new_pos = cand
117 min_dist = dist
118 return self.point_to_pymunk(new_pos)
119
120 def fix_line_angle(self, start_pos, pos):
121 start_pos = self.round_point(start_pos)
122 pos = self.round_point(pos)
123 return self._fix_angle(start_pos, pos)
124
125 def fix_poly_angle(self, index, pos):
126 # Last point
127 point1 = self.point_to_pygame(self.polygons[index][-1])
128 pos = self.round_point(pos)
129 return self._fix_angle(point1, pos)
130 95
131 def delete_point(self, index): 96 def delete_point(self, index):
132 if index in self.polygons and len(self.polygons[index]) > 0: 97 if index in self.polygons and len(self.polygons[index]) > 0:
133 self.polygons[index].pop() 98 self.polygons[index].pop()
134 99
139 it's limited as it's a magic point addition""" 104 it's limited as it's a magic point addition"""
140 if len(self.polygons[index]) < 2: 105 if len(self.polygons[index]) < 2:
141 # Too small 106 # Too small
142 return False 107 return False
143 first = self.polygons[index][0] 108 first = self.polygons[index][0]
144 if self.fix_poly_angle(index, self.point_to_pygame(first)) == first: 109 self.add_point(index, self.point_to_pygame(first))
145 self.add_point(index, self.point_to_pygame(first)) 110 return True
146 return True
147 candidates = [(first[0] + 10 * i, first[1]) for
148 i in (-3, -2, -1, 1, 2, 3)]
149 candidates.extend([(first[0], first[1] + 10 * i) for
150 i in (-3, -2, -1, 1, 2, 3)])
151 candidates.extend([(first[0] + 10 * i, first[1] + 10 * i) for
152 i in (-3, -2, -1, 1, 2, 3)])
153 candidates.extend([(first[0] + 10 * i, first[1] - 10 * i) for
154 i in (-3, -2, -1, 1, 2, 3)])
155 min_dist = 99999
156 poss = None
157 for cand in candidates:
158 if self.fix_poly_angle(index, self.point_to_pygame(cand)) == cand:
159 dist = distance(first, cand)
160 if dist < min_dist:
161 poss = cand
162 if poss is not None:
163 self.add_point(index, self.point_to_pygame(poss))
164 self.add_point(index, self.point_to_pygame(first))
165 return True
166 return False
167 111
168 def add_line(self, start_pos, end_pos): 112 def add_line(self, start_pos, end_pos):
169 endpoint = self.fix_line_angle(start_pos, end_pos) 113 startpoint = self.point_to_pymunk(start_pos)
170 startpoint = self.point_to_pymunk(self.round_point(start_pos)) 114 endpoint = self.point_to_pymunk(end_pos)
171 self.lines.append([startpoint, endpoint]) 115 self.lines.append([startpoint, endpoint])
172 116
173 def draw(self, mouse_pos, mouse_poly, filled, draw_cand_line, start_pos, 117 def draw(self, mouse_pos, mouse_poly, filled, draw_cand_line, start_pos,
174 move_point_mode, move_point): 118 move_point_mode, move_point):
175 self._draw_background(True) 119 self._draw_background(True)
186 break 130 break
187 if len(polygon) > 1: 131 if len(polygon) > 1:
188 pointlist = [self.point_to_pygame(p) for p in polygon] 132 pointlist = [self.point_to_pygame(p) for p in polygon]
189 pygame.draw.lines(self._surface, color, False, pointlist, 2) 133 pygame.draw.lines(self._surface, color, False, pointlist, 2)
190 if index == mouse_poly and mouse_pos: 134 if index == mouse_poly and mouse_pos:
191 endpoint = self.fix_poly_angle(index, mouse_pos) 135 endpoint = self.point_to_pymunk(mouse_pos)
192 pygame.draw.line(self._surface, color, 136 pygame.draw.line(self._surface, color,
193 self.point_to_pygame(polygon[-1]), 137 self.point_to_pygame(polygon[-1]),
194 self.point_to_pygame(endpoint)) 138 self.point_to_pygame(endpoint))
195 line_found = False # Hack for sane behaviour if lines overlap 139 line_found = False # Hack for sane behaviour if lines overlap
196 for line in self.lines: 140 for line in self.lines:
200 line_found = True 144 line_found = True
201 pointlist.remove(self.point_to_pygame(move_point)) 145 pointlist.remove(self.point_to_pygame(move_point))
202 pointlist.append(mouse_pos) 146 pointlist.append(mouse_pos)
203 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 2) 147 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 2)
204 if draw_cand_line and start_pos and mouse_pos: 148 if draw_cand_line and start_pos and mouse_pos:
205 endpoint = self.fix_line_angle(start_pos, mouse_pos) 149 endpoint = self.snap_to_grid(mouse_pos)
206 pointlist = [self.round_point(start_pos), 150 pointlist = [start_pos,
207 self.point_to_pygame(endpoint)] 151 self.point_to_pygame(endpoint)]
208 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 1) 152 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 1)
209 return self._surface.copy() 153 return self._surface.copy()
210 154
211 def reset_objs(self): 155 def reset_objs(self):
481 self.pos = tuple(new_pos) 425 self.pos = tuple(new_pos)
482 426
483 def inc_grid_size(self, amount): 427 def inc_grid_size(self, amount):
484 self.grid_size = max(1, self.grid_size + amount) 428 self.grid_size = max(1, self.grid_size + amount)
485 429
430 def snap_to_grid(self, pos):
431 x = pos[0] - (pos[0] % self.grid_size)
432 y = pos[1] - (pos[1] % self.grid_size)
433 return (x, y)
434
486 def set_objects(self, value): 435 def set_objects(self, value):
487 if self._draw_objects != value: 436 if self._draw_objects != value:
488 self._draw_objects = value 437 self._draw_objects = value
489 self.invalidate() 438 self.invalidate()
490 439
506 def draw(self, surface): 455 def draw(self, surface):
507 if (self.cur_poly is not None and self.cur_poly in self.level.polygons 456 if (self.cur_poly is not None and self.cur_poly in self.level.polygons
508 and len(self.level.polygons[self.cur_poly])): 457 and len(self.level.polygons[self.cur_poly])):
509 # We have an active polygon 458 # We have an active polygon
510 mouse_pos = self._level_coordinates(self.mouse_pos) 459 mouse_pos = self._level_coordinates(self.mouse_pos)
460 mouse_pos = self.snap_to_grid(mouse_pos)
511 elif self._draw_lines: 461 elif self._draw_lines:
512 # Interior wall mode 462 # Interior wall mode
513 mouse_pos = self._level_coordinates(self.mouse_pos) 463 mouse_pos = self._level_coordinates(self.mouse_pos)
464 mouse_pos = self.snap_to_grid(mouse_pos)
514 elif self._move_point_mode: 465 elif self._move_point_mode:
515 mouse_pos = self._level_coordinates(self.mouse_pos) 466 mouse_pos = self._level_coordinates(self.mouse_pos)
467 mouse_pos = self.snap_to_grid(mouse_pos)
516 else: 468 else:
517 mouse_pos = None 469 mouse_pos = None
518 level_surface = level.draw(mouse_pos, self.cur_poly, self.filled_mode, 470 level_surface = level.draw(mouse_pos, self.cur_poly, self.filled_mode,
519 self._draw_lines, self._start_pos, 471 self._draw_lines, self._start_pos,
520 self._move_point_mode, self._move_point) 472 self._move_point_mode, self._move_point)
603 self._move_view(diff) 555 self._move_view(diff)
604 self.invalidate() 556 self.invalidate()
605 557
606 def mouse_down(self, ev): 558 def mouse_down(self, ev):
607 corrected_pos = self._level_coordinates(ev.pos) 559 corrected_pos = self._level_coordinates(ev.pos)
560 snapped_pos = self.snap_to_grid(corrected_pos)
608 if self.sel_mode and ev.button == 1: 561 if self.sel_mode and ev.button == 1:
609 obj = self.level.find_obj_at_pos(corrected_pos) 562 obj = self.level.find_obj_at_pos(corrected_pos)
610 if obj is not None: 563 if obj is not None:
611 self._edit_selected(obj) 564 self._edit_selected(obj)
612 elif self._move_point_mode and ev.button == 1: 565 elif self._move_point_mode and ev.button == 1:
613 if self._move_point: 566 if self._move_point:
614 # Place the current point 567 # Place the current point
615 self.level.replace_vertex(self._move_point, corrected_pos) 568 self.level.replace_vertex(self._move_point, snapped_pos)
616 self._move_point = None 569 self._move_point = None
617 self.invalidate() 570 self.invalidate()
618 else: 571 else:
619 # find the current point 572 # find the current point
620 self._move_point = self.level.find_vertex(corrected_pos) 573 self._move_point = self.level.find_vertex(snapped_pos)
621 elif ev.button == 1: 574 elif ev.button == 1:
622 if self._draw_lines: 575 if self._draw_lines:
623 if self._start_pos is None: 576 if self._start_pos is None:
624 self._start_pos = corrected_pos 577 self._start_pos = corrected_pos
625 else: 578 else:
626 self.level.add_line(self._start_pos, corrected_pos) 579 self.level.add_line(self._start_pos, snapped_pos)
627 self._start_pos = None 580 self._start_pos = None
628 else: 581 else:
629 print "Click: %r" % ( 582 print "Click: %r" % (
630 self.level.point_to_pymunk(corrected_pos),) 583 self.level.point_to_pymunk(corrected_pos),)
631 if ev.button == 4: # Scroll up 584 if ev.button == 4: # Scroll up
636 self._move_view((-10, 0)) 589 self._move_view((-10, 0))
637 elif ev.button == 7: # Scroll right 590 elif ev.button == 7: # Scroll right
638 self._move_view((10, 0)) 591 self._move_view((10, 0))
639 elif self.cur_poly and ev.button == 1: 592 elif self.cur_poly and ev.button == 1:
640 # Add a point 593 # Add a point
641 self.level.add_point(self.cur_poly, corrected_pos) 594 self.level.add_point(self.cur_poly, snapped_pos)
642 elif ev.button == 3: 595 elif ev.button == 3:
643 self._mouse_drag = True 596 self._mouse_drag = True
644 597
645 def mouse_up(self, ev): 598 def mouse_up(self, ev):
646 if ev.button == 3: 599 if ev.button == 3: