Mercurial > nagslang
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: |