comparison tools/area_editor.py @ 407:314ddad2d6d2

Move points button
author Neil Muller <drnlmuller@gmail.com>
date Sat, 07 Sep 2013 12:10:42 +0200
parents 9589e1db4433
children ddff1f8668d5
comparison
equal deleted inserted replaced
406:7fcde01ea50e 407:314ddad2d6d2
51 51
52 class TestWorld(object): 52 class TestWorld(object):
53 53
54 def __init__(self): 54 def __init__(self):
55 self.level_state = {} 55 self.level_state = {}
56 self.inventory = {}
57
58
59 def distance(tup1, tup2):
60 return (tup1[0] - tup2[0]) ** 2 + (tup1[1] - tup2[1]) ** 2
56 61
57 62
58 class EditorLevel(Level): 63 class EditorLevel(Level):
59 64
60 def __init__(self, name, x=800, y=600): 65 def __init__(self, name, x=800, y=600):
62 super(EditorLevel, self).__init__(name, world) 67 super(EditorLevel, self).__init__(name, world)
63 self.x = x 68 self.x = x
64 self.y = y 69 self.y = y
65 # Lookup initiliasition info from the objects 70 # Lookup initiliasition info from the objects
66 self.lookup = {} 71 self.lookup = {}
72 self._move_poly = None
67 73
68 def round_point(self, pos): 74 def round_point(self, pos):
69 return (10 * (pos[0] // 10), 10 * (pos[1] // 10)) 75 return (10 * (pos[0] // 10), 10 * (pos[1] // 10))
70 76
71 def load(self, space): 77 def load(self, space):
101 pos225 = (point1[0] - dist, point1[1] - dist) 107 pos225 = (point1[0] - dist, point1[1] - dist)
102 pos305 = (point1[0] - dist, point1[1] + dist) 108 pos305 = (point1[0] - dist, point1[1] + dist)
103 min_dist = 9999999 109 min_dist = 9999999
104 new_pos = point1 110 new_pos = point1
105 for cand in [pos0, pos90, pos45, pos135, pos225, pos305]: 111 for cand in [pos0, pos90, pos45, pos135, pos225, pos305]:
106 dist = (pos[0] - cand[0]) ** 2 + (pos[1] - cand[1]) ** 2 112 dist = distance(pos, cand)
107 if dist < min_dist: 113 if dist < min_dist:
108 new_pos = cand 114 new_pos = cand
109 min_dist = dist 115 min_dist = dist
110 return self.point_to_pymunk(new_pos) 116 return self.point_to_pymunk(new_pos)
111 117
146 i in (-3, -2, -1, 1, 2, 3)]) 152 i in (-3, -2, -1, 1, 2, 3)])
147 min_dist = 99999 153 min_dist = 99999
148 poss = None 154 poss = None
149 for cand in candidates: 155 for cand in candidates:
150 if self.fix_poly_angle(index, self.point_to_pygame(cand)) == cand: 156 if self.fix_poly_angle(index, self.point_to_pygame(cand)) == cand:
151 dist = (first[0] - cand[0]) ** 2 + (first[1] - cand[1]) ** 2 157 dist = distance(first, cand)
152 if dist < min_dist: 158 if dist < min_dist:
153 poss = cand 159 poss = cand
154 if poss is not None: 160 if poss is not None:
155 self.add_point(index, self.point_to_pygame(poss)) 161 self.add_point(index, self.point_to_pygame(poss))
156 self.add_point(index, self.point_to_pygame(first)) 162 self.add_point(index, self.point_to_pygame(first))
160 def add_line(self, start_pos, end_pos): 166 def add_line(self, start_pos, end_pos):
161 endpoint = self.fix_line_angle(start_pos, end_pos) 167 endpoint = self.fix_line_angle(start_pos, end_pos)
162 startpoint = self.point_to_pymunk(self.round_point(start_pos)) 168 startpoint = self.point_to_pymunk(self.round_point(start_pos))
163 self.lines.append([startpoint, endpoint]) 169 self.lines.append([startpoint, endpoint])
164 170
165 def draw(self, mouse_pos, mouse_poly, filled, draw_cand_line, start_pos): 171 def draw(self, mouse_pos, mouse_poly, filled, draw_cand_line, start_pos,
172 move_point_mode, move_point):
166 self._draw_background(True) 173 self._draw_background(True)
167 # Draw polygons as needed for the editor 174 # Draw polygons as needed for the editor
168 if filled: 175 if filled:
169 self._draw_exterior(True) 176 self._draw_exterior(True)
170 for index, polygon in self.polygons.items(): 177 for index, polygon in self.polygons.items():
171 color = POLY_COLORS[index] 178 color = POLY_COLORS[index]
172 if len(polygon) > 1: 179 if move_point_mode and index == self._move_poly:
180 pointlist = [p for p in polygon]
181 pointlist = [self.point_to_pygame(p) if p != move_point else
182 mouse_pos for p in pointlist]
183 pygame.draw.lines(self._surface, color, False, pointlist, 2)
184 elif len(polygon) > 1:
173 pointlist = [self.point_to_pygame(p) for p in polygon] 185 pointlist = [self.point_to_pygame(p) for p in polygon]
174 pygame.draw.lines(self._surface, color, False, pointlist, 2) 186 pygame.draw.lines(self._surface, color, False, pointlist, 2)
175 if index == mouse_poly and mouse_pos: 187 elif index == mouse_poly and mouse_pos:
176 endpoint = self.fix_poly_angle(index, mouse_pos) 188 endpoint = self.fix_poly_angle(index, mouse_pos)
177 pygame.draw.line(self._surface, color, 189 pygame.draw.line(self._surface, color,
178 self.point_to_pygame(polygon[-1]), 190 self.point_to_pygame(polygon[-1]),
179 self.point_to_pygame(endpoint)) 191 self.point_to_pygame(endpoint))
192 line_found = False # Hack for sane behaviour if lines overlap
180 for line in self.lines: 193 for line in self.lines:
181 pointlist = [self.point_to_pygame(p) for p in line] 194 pointlist = [self.point_to_pygame(p) for p in line]
195 if move_point_mode and not self._move_poly and not line_found:
196 if move_point in line:
197 line_found = True
198 pointlist.remove(self.point_to_pygame(move_point))
199 pointlist.append(mouse_pos)
182 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 2) 200 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 2)
183 if draw_cand_line and start_pos and mouse_pos: 201 if draw_cand_line and start_pos and mouse_pos:
184 endpoint = self.fix_line_angle(start_pos, mouse_pos) 202 endpoint = self.fix_line_angle(start_pos, mouse_pos)
185 pointlist = [self.round_point(start_pos), 203 pointlist = [self.round_point(start_pos),
186 self.point_to_pygame(endpoint)] 204 self.point_to_pygame(endpoint)]
233 # Search visible objects 251 # Search visible objects
234 for obj in self.drawables: 252 for obj in self.drawables:
235 if obj.get_shape().point_query(pymunk_pos): 253 if obj.get_shape().point_query(pymunk_pos):
236 return obj 254 return obj
237 return None 255 return None
256
257 def find_vertex(self, mouse_pos):
258 # search for vertexes closest to where we've killed
259 mindist = 400
260 move_point = None
261 search_point = self.point_to_pymunk(mouse_pos)
262 for index, polygon in self.polygons.items():
263 for point in polygon:
264 dist = distance(point, search_point)
265 if dist < mindist:
266 mindist = dist
267 move_point = point
268 self._move_poly = index
269 # Also check lines
270 for line in self.lines:
271 for point in line:
272 dist = distance(point, search_point)
273 if dist < mindist:
274 mindist = dist
275 move_point = point
276 self._move_poly = None
277 return move_point
278
279 def replace_vertex(self, old_point, new_point):
280 new_point = self.point_to_pymunk(new_point)
281 if self._move_poly:
282 new_polygon = [p if p != old_point else new_point for p in
283 self.polygons[self._move_poly]]
284 self.polygons[self._move_poly] = new_polygon
285 else:
286 for line in self.lines:
287 if old_point in line:
288 line.remove(old_point)
289 line.append(new_point)
290 break
238 291
239 292
240 class ObjectTable(TableView): 293 class ObjectTable(TableView):
241 294
242 columns = [TableColumn("Object", 690, 'l', '%r')] 295 columns = [TableColumn("Object", 690, 'l', '%r')]
397 self._draw_enemies = False 450 self._draw_enemies = False
398 self._draw_lines = False 451 self._draw_lines = False
399 self.sel_mode = False 452 self.sel_mode = False
400 self._start_pos = None 453 self._start_pos = None
401 self._parent = parent 454 self._parent = parent
455 self._move_point_mode = False
456 self._move_point = False
402 457
403 def _level_coordinates(self, pos): 458 def _level_coordinates(self, pos):
404 # Move positions to level values 459 # Move positions to level values
405 if not pos: 460 if not pos:
406 return (0, 0) 461 return (0, 0)
434 # We have an active polygon 489 # We have an active polygon
435 mouse_pos = self._level_coordinates(self.mouse_pos) 490 mouse_pos = self._level_coordinates(self.mouse_pos)
436 elif self._draw_lines: 491 elif self._draw_lines:
437 # Interior wall mode 492 # Interior wall mode
438 mouse_pos = self._level_coordinates(self.mouse_pos) 493 mouse_pos = self._level_coordinates(self.mouse_pos)
494 elif self._move_point_mode:
495 mouse_pos = self._level_coordinates(self.mouse_pos)
439 else: 496 else:
440 mouse_pos = None 497 mouse_pos = None
441 level_surface = level.draw(mouse_pos, self.cur_poly, self.filled_mode, 498 level_surface = level.draw(mouse_pos, self.cur_poly, self.filled_mode,
442 self._draw_lines, self._start_pos) 499 self._draw_lines, self._start_pos,
500 self._move_point_mode, self._move_point)
443 if self._draw_objects: 501 if self._draw_objects:
444 for thing in self.level.drawables: 502 for thing in self.level.drawables:
445 if not isinstance(thing, ne.Enemy): 503 if not isinstance(thing, ne.Enemy):
446 thing.render(level_surface) 504 thing.render(level_surface)
447 if self._draw_enemies: 505 if self._draw_enemies:
462 self.cur_poly = None 520 self.cur_poly = None
463 self._parent.reset_lit_buttons() 521 self._parent.reset_lit_buttons()
464 self._draw_lines = True 522 self._draw_lines = True
465 self.filled_mode = False 523 self.filled_mode = False
466 self._start_pos = None 524 self._start_pos = None
525 self._move_point_mode = False
467 526
468 def key_down(self, ev): 527 def key_down(self, ev):
469 if ev.key == pgl.K_LEFT: 528 if ev.key == pgl.K_LEFT:
470 self._move_view((-10, 0)) 529 self._move_view((-10, 0))
471 elif ev.key == pgl.K_RIGHT: 530 elif ev.key == pgl.K_RIGHT:
483 elif ev.key == pgl.K_f: 542 elif ev.key == pgl.K_f:
484 self.set_filled() 543 self.set_filled()
485 elif ev.key == pgl.K_c: 544 elif ev.key == pgl.K_c:
486 self.close_poly() 545 self.close_poly()
487 546
547 def set_move_mode(self):
548 self._draw_lines = False
549 self._move_point_mode = True
550 self.filled_mode = False
551 self._parent.reset_lit_buttons()
552 self._move_point = None
553
488 def set_filled(self): 554 def set_filled(self):
489 closed, _ = self.level.all_closed() 555 closed, _ = self.level.all_closed()
490 if closed: 556 if closed:
491 self.cur_poly = None 557 self.cur_poly = None
492 self._parent.reset_lit_buttons() 558 self._parent.reset_lit_buttons()
493 self.filled_mode = True 559 self.filled_mode = True
494 self._draw_lines = False 560 self._draw_lines = False
561 self._move_point_mode = False
495 else: 562 else:
496 alert('Not all polygons closed, so not filling') 563 alert('Not all polygons closed, so not filling')
497 564
498 def mouse_move(self, ev): 565 def mouse_move(self, ev):
499 old_pos = self.mouse_pos 566 old_pos = self.mouse_pos
500 self.mouse_pos = ev.pos 567 self.mouse_pos = ev.pos
501 if old_pos != self.mouse_pos and (self.cur_poly or self._draw_lines): 568 if old_pos != self.mouse_pos and (self.cur_poly or self._draw_lines
569 or self._move_point_mode):
502 self.invalidate() 570 self.invalidate()
503 571
504 def mouse_drag(self, ev): 572 def mouse_drag(self, ev):
505 if self._mouse_drag: 573 if self._mouse_drag:
506 old_pos = self.mouse_pos 574 old_pos = self.mouse_pos
509 -self.mouse_pos[1] + old_pos[1]) 577 -self.mouse_pos[1] + old_pos[1])
510 self._move_view(diff) 578 self._move_view(diff)
511 self.invalidate() 579 self.invalidate()
512 580
513 def mouse_down(self, ev): 581 def mouse_down(self, ev):
582 corrected_pos = ev.pos[0] + self.pos[0], ev.pos[1] + self.pos[1]
514 if self.sel_mode and ev.button == 1: 583 if self.sel_mode and ev.button == 1:
515 corrected_pos = ev.pos[0] + self.pos[0], ev.pos[1] + self.pos[1]
516 obj = self.level.find_obj_at_pos(corrected_pos) 584 obj = self.level.find_obj_at_pos(corrected_pos)
517 if obj is not None: 585 if obj is not None:
518 self._edit_selected(obj) 586 self._edit_selected(obj)
587 elif self._move_point_mode and ev.button == 1:
588 if self._move_point:
589 # Place the current point
590 self.level.replace_vertex(self._move_point, corrected_pos)
591 self._move_point = None
592 self.invalidate()
593 else:
594 # find the current point
595 self._move_point = self.level.find_vertex(corrected_pos)
519 elif ev.button == 1: 596 elif ev.button == 1:
520 if self._draw_lines: 597 if self._draw_lines:
521 if self._start_pos is None: 598 if self._start_pos is None:
522 self._start_pos = ev.pos 599 self._start_pos = ev.pos
523 else: 600 else:
777 end_poly_but.rect = BUTTON_RECT.copy() 854 end_poly_but.rect = BUTTON_RECT.copy()
778 end_poly_but.rect.move_ip(MENU_LEFT, y) 855 end_poly_but.rect.move_ip(MENU_LEFT, y)
779 widgets.append(end_poly_but) 856 widgets.append(end_poly_but)
780 y += MENU_BUTTON_HEIGHT + MENU_PAD 857 y += MENU_BUTTON_HEIGHT + MENU_PAD
781 858
859 self.move_point_but = HighLightButton("Move Point", self,
860 action=self.move_point)
861 self.move_point_but.rect = BUTTON_RECT.copy()
862 self.move_point_but.rect.move_ip(MENU_LEFT, y)
863 widgets.append(self.move_point_but)
864 self._light_buttons.append(self.move_point_but)
865 y += MENU_BUTTON_HEIGHT + MENU_PAD
866
782 self.draw_line_but = HighLightButton("Draw interior wall", self, 867 self.draw_line_but = HighLightButton("Draw interior wall", self,
783 action=self.set_line_mode) 868 action=self.set_line_mode)
784 self.draw_line_but.rect = BUTTON_RECT.copy() 869 self.draw_line_but.rect = BUTTON_RECT.copy()
785 self.draw_line_but.rect.move_ip(MENU_LEFT, y) 870 self.draw_line_but.rect.move_ip(MENU_LEFT, y)
786 widgets.append(self.draw_line_but) 871 widgets.append(self.draw_line_but)
967 else: 1052 else:
968 self.sel_mode_but.reset() 1053 self.sel_mode_but.reset()
969 1054
970 def mouse_move(self, ev): 1055 def mouse_move(self, ev):
971 self.level_widget.mouse_move(ev) 1056 self.level_widget.mouse_move(ev)
1057
1058 def move_point(self):
1059 self.level_widget.set_move_mode()
1060 self.move_point_but.highlight()
972 1061
973 def draw(self, surface): 1062 def draw(self, surface):
974 # Update checkbox state 1063 # Update checkbox state
975 if self._menu_mode == 'drawing': 1064 if self._menu_mode == 'drawing':
976 self.level_widget.set_objects(self.show_objs.value) 1065 self.level_widget.set_objects(self.show_objs.value)