source: tools/area_editor.py@ 486:04908862a0b2

Last change on this file since 486:04908862a0b2 was 486:04908862a0b2, checked in by Simon Cross <hodgestar@…>, 9 years ago

Sort object editor list.

  • Property exe set to *
File size: 46.4 KB
RevLine 
[71]1#!/usr/bin/env python
2
[51]3# The basic area editor
4#
5# To edit an existing level, use
6# editor levelname
7#
8# To create a new level:
9#
[315]10# editor levelname <xsize> <ysize>
[51]11# (size specified in pixels
12#
13
[71]14import os
15import sys
16
[51]17import pygame
18import pygame.locals as pgl
19
[152]20sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
21
[153]22import pymunk
23
[108]24from albow.root import RootWidget
25from albow.widget import Widget
[198]26from albow.controls import Button, Label, CheckBox
[225]27from albow.dialogs import alert, Dialog
28from albow.layout import Row
[251]29from albow.fields import TextField
[225]30from albow.table_view import TableView, TableColumn
[108]31
[199]32from nagslang.options import parse_args
[109]33from nagslang.constants import SCREEN
[204]34from nagslang.level import Level, POLY_COLORS, LINE_COLOR
[255]35from nagslang.yamlish import load_s
[251]36import nagslang.enemies as ne
37import nagslang.game_object as ngo
38import nagslang.puzzle as np
[51]39
[108]40# layout constants
41MENU_BUTTON_HEIGHT = 35
[423]42MENU_PAD = 4
[115]43MENU_HALF_PAD = MENU_PAD // 2
44MENU_LEFT = SCREEN[0] + MENU_HALF_PAD
45MENU_WIDTH = 200 - MENU_PAD
[419]46MENU_HALF_WIDTH = MENU_WIDTH // 2 - MENU_HALF_PAD
[108]47
[220]48BUTTON_RECT = pygame.rect.Rect(0, 0, MENU_WIDTH, MENU_BUTTON_HEIGHT)
[419]49HALF_BUTTON_RECT = pygame.rect.Rect(0, 0, MENU_HALF_WIDTH, MENU_BUTTON_HEIGHT)
[220]50CHECK_RECT = pygame.rect.Rect(0, 0, MENU_BUTTON_HEIGHT // 2,
51 MENU_BUTTON_HEIGHT // 2)
52
[108]53
[355]54class TestWorld(object):
55
56 def __init__(self):
57 self.level_state = {}
[407]58 self.inventory = {}
59
60
61def distance(tup1, tup2):
62 return (tup1[0] - tup2[0]) ** 2 + (tup1[1] - tup2[1]) ** 2
[355]63
64
[51]65class EditorLevel(Level):
66
67 def __init__(self, name, x=800, y=600):
[355]68 world = TestWorld()
69 super(EditorLevel, self).__init__(name, world)
[51]70 self.x = x
71 self.y = y
[275]72 # Lookup initiliasition info from the objects
73 self.lookup = {}
[407]74 self._move_poly = None
[51]75
[439]76 def _in_bounds(self, pos):
77 if pos[0] < 0 or pos[0] >= self.x:
78 return False
79 if pos[1] < 0 or pos[1] >= self.y:
80 return False
81 return True
82
[275]83 def load(self, space):
84 super(EditorLevel, self).load(space)
85 # Needed to fill in the lookup dict
86 self.reset_objs()
87
[51]88 def point_to_pymunk(self, pos):
89 # inverse of point_to_pygame
90 # (this is also the same as point_to_pygame, but a additional
91 # function for sanity later in pyweek).
92 return (pos[0], self.y - pos[1])
93
94 def add_point(self, poly_index, pos):
95 self.polygons.setdefault(poly_index, [])
[439]96 if not self._in_bounds(pos):
97 return False
[51]98 if not self.polygons[poly_index]:
[424]99 point = self.point_to_pymunk(pos)
[99]100 self.polygons[poly_index].append(point)
[51]101 else:
[424]102 add_pos = self.point_to_pymunk(pos)
[51]103 self.polygons[poly_index].append(add_pos)
[439]104 return True
[51]105
106 def delete_point(self, index):
107 if index in self.polygons and len(self.polygons[index]) > 0:
108 self.polygons[index].pop()
109
[135]110 def close_poly(self, index):
111 """Attempts to close the current polygon.
112
113 We allow a small additional step to close the polygon, but
114 it's limited as it's a magic point addition"""
115 if len(self.polygons[index]) < 2:
116 # Too small
117 return False
118 first = self.polygons[index][0]
[439]119 if self.add_point(index, self.point_to_pygame(first)):
120 return True
121 return False
[135]122
[205]123 def add_line(self, start_pos, end_pos):
[424]124 startpoint = self.point_to_pymunk(start_pos)
125 endpoint = self.point_to_pymunk(end_pos)
[205]126 self.lines.append([startpoint, endpoint])
127
[407]128 def draw(self, mouse_pos, mouse_poly, filled, draw_cand_line, start_pos,
[459]129 move_point_mode, move_poly_mode, move_point, zoom_factor,
130 level_widget):
[51]131 self._draw_background(True)
132 # Draw polygons as needed for the editor
[436]133 line_width = int(2 * zoom_factor)
[96]134 if filled:
135 self._draw_exterior(True)
[51]136 for index, polygon in self.polygons.items():
[425]137 color = POLY_COLORS.get(index, pygame.color.THECOLORS['black'])
[458]138 if move_point_mode and index == self._move_poly and move_point:
[407]139 pointlist = [p for p in polygon]
140 pointlist = [self.point_to_pygame(p) if p != move_point else
141 mouse_pos for p in pointlist]
[436]142 pygame.draw.lines(self._surface, color, False, pointlist,
143 line_width)
[411]144 break
[458]145 if move_poly_mode and index == self._move_poly and move_point:
[463]146 new_point = self.point_to_pymunk(mouse_pos)
147 pointlist = [self.point_to_pygame(p)
148 for p in self.translate_poly(
149 polygon, move_point, new_point)]
[458]150 pygame.draw.lines(self._surface, color, False, pointlist,
151 line_width)
[463]152 #break
[411]153 if len(polygon) > 1:
[51]154 pointlist = [self.point_to_pygame(p) for p in polygon]
[436]155 pygame.draw.lines(self._surface, color, False, pointlist,
156 line_width)
[461]157 if index == mouse_poly and mouse_pos and len(polygon) > 0:
[424]158 endpoint = self.point_to_pymunk(mouse_pos)
[51]159 pygame.draw.line(self._surface, color,
[99]160 self.point_to_pygame(polygon[-1]),
[441]161 self.point_to_pygame(endpoint),
162 line_width // 2)
[407]163 line_found = False # Hack for sane behaviour if lines overlap
[204]164 for line in self.lines:
165 pointlist = [self.point_to_pygame(p) for p in line]
[407]166 if move_point_mode and not self._move_poly and not line_found:
167 if move_point in line:
168 line_found = True
169 pointlist.remove(self.point_to_pygame(move_point))
170 pointlist.append(mouse_pos)
[436]171 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist,
172 line_width)
[205]173 if draw_cand_line and start_pos and mouse_pos:
[452]174 endpoint = level_widget.snap_to_grid(mouse_pos)
[457]175 endpoint = self.point_to_pymunk(endpoint)
[424]176 pointlist = [start_pos,
[206]177 self.point_to_pygame(endpoint)]
[205]178 pygame.draw.lines(self._surface, LINE_COLOR, False, pointlist, 1)
[432]179 return self._surface
[51]180
[239]181 def reset_objs(self):
182 # Reset the object state - needed when changing stuff
183 self.drawables = []
184 self.overlay_drawables = []
[251]185 self._glue = np.PuzzleGlue()
[239]186 for game_object_dict in self._game_objects:
[275]187 obj = self._create_game_object(pymunk.Space(), **game_object_dict)
188 self.lookup[obj] = game_object_dict
[239]189 for enemy_dict in self._enemies:
[275]190 obj = self._create_enemy(pymunk.Space(), **enemy_dict)
191 self.lookup[obj] = enemy_dict
[239]192
[251]193 def get_class(self, classname, mod=None):
194 # Get the class given the classname
195 modules = {
196 'game_object': ngo,
197 'enemies': ne,
198 'puzzle': np,
199 }
200 if '.' in classname:
201 modname, classname = classname.split('.')
202 mod = modules[modname]
203 if mod is None:
204 mod = ngo
205 return getattr(mod, classname)
206
[262]207 def try_new_object(self, classname, target, new, old=None):
[251]208 if old in target:
209 target.remove(old)
210 try:
211 target.append(new)
212 self.reset_objs()
[467]213 test_surface = pygame.surface.Surface((self.x, self.y))
214 # Check for initialisation stuff that happens in render
215 for thing in self.drawables:
216 if not isinstance(thing, ne.Enemy):
217 thing.render(test_surface)
[251]218 return True
[262]219 except Exception as e:
[251]220 target.remove(new)
221 if old is not None:
222 target.append(old)
223 self.reset_objs()
[262]224 alert("Failed to update object %s: %s" % (classname, e))
[251]225 return False
226
[275]227 def find_obj_at_pos(self, mouse_pos):
228 pymunk_pos = self.point_to_pymunk(mouse_pos)
229 # Search visible objects
230 for obj in self.drawables:
231 if obj.get_shape().point_query(pymunk_pos):
232 return obj
233 return None
234
[407]235 def find_vertex(self, mouse_pos):
236 # search for vertexes closest to where we've killed
[463]237 mindist = 1000
[407]238 move_point = None
239 search_point = self.point_to_pymunk(mouse_pos)
240 for index, polygon in self.polygons.items():
241 for point in polygon:
242 dist = distance(point, search_point)
243 if dist < mindist:
244 mindist = dist
245 move_point = point
246 self._move_poly = index
247 # Also check lines
248 for line in self.lines:
249 for point in line:
250 dist = distance(point, search_point)
251 if dist < mindist:
252 mindist = dist
253 move_point = point
254 self._move_poly = None
255 return move_point
256
[463]257 def translate_poly(self, poly, move_point, new_point):
258 dx = new_point[0] - move_point[0]
259 dy = new_point[1] - move_point[1]
[458]260 new_poly = [(p[0] + dx, p[1] + dy) for p in poly]
261 return new_poly
262
[463]263 def replace_poly(self, move_point, new_point):
[458]264 new_point = self.point_to_pymunk(new_point)
265 if self._move_poly:
266 self.polygons[self._move_poly] = self.translate_poly(
[463]267 self.polygons[self._move_poly], move_point, new_point)
[458]268
[407]269 def replace_vertex(self, old_point, new_point):
270 new_point = self.point_to_pymunk(new_point)
271 if self._move_poly:
272 new_polygon = [p if p != old_point else new_point for p in
273 self.polygons[self._move_poly]]
274 self.polygons[self._move_poly] = new_polygon
275 else:
276 for line in self.lines:
277 if old_point in line:
278 line.remove(old_point)
279 line.append(new_point)
280 break
281
[109]282
[225]283class ObjectTable(TableView):
284
285 columns = [TableColumn("Object", 690, 'l', '%r')]
286
287 def __init__(self, data):
288 super(ObjectTable, self).__init__(height=450)
[486]289 self.data = sorted(data,
290 key=lambda d: (d.get('classname'), d.get('name')))
[225]291 self.selected_row = -1
292
293 def num_rows(self):
294 return len(self.data)
295
296 def row_data(self, i):
297 data = self.data[i]
298 if 'name' in data:
299 return ('%s (%s)' % (data['classname'], data['name']), )
300 return (data['classname'], )
301
302 def row_is_selected(self, i):
303 return self.selected_row == i
304
305 def click_row(self, i, ev):
306 self.selected_row = i
307
308 def get_selection(self):
309 if self.selected_row >= 0:
310 return self.data[self.selected_row]
311 return None
312
313
[251]314class EditClassDialog(Dialog):
315
[355]316 def __init__(self, classname, cls, data, level_widget,
317 delete=False):
[251]318 super(EditClassDialog, self).__init__()
[355]319 self.level_widget = level_widget
[255]320 self.classname = classname
[355]321 self.rect = pygame.rect.Rect(0, 0, 900, 550)
[251]322 title = Label("Editing %s" % classname)
323 title.rect = pygame.rect.Rect(100, 10, 600, 25)
324 self.add(title)
[262]325 self.requires = cls.requires()
[251]326 y = 40
327 self.fields = {}
328 index = 0
[355]329 self.poly_field = None
330 self.needs_cleanup = False
[262]331 for requirement, hint in self.requires:
[251]332 label = Label(requirement)
333 label.rect = pygame.rect.Rect(40, y, 200, 25)
334 self.add(label)
335 field = TextField()
336 field.rect = pygame.rect.Rect(220, y, 400, 25)
337 self.add(field)
338 if data is not None:
339 if requirement in data:
340 field.set_text('%s' % data[requirement])
[255]341 elif 'args' in data and requirement != 'name':
[251]342 # NB: The ordering assumptions in requires should make
343 # this safe, but it's really, really, really fragile
[255]344 try:
345 field.set_text('%s' % data['args'][index])
346 index += 1
347 except IndexError:
348 # Assumed to be arguments with the default value
349 pass
[355]350 if hint.startswith('polygon'):
351 self.poly_field = field
[251]352 self.fields[requirement] = field
353 hintlabel = Label(hint)
[355]354 hintlabel.rect = pygame.rect.Rect(640, y, 250, 25)
[251]355 self.add(hintlabel)
356 y += 30
[355]357 if self.poly_field:
358 y += 20
359 button = Button('Use Polygon 6', action=self.get_poly)
360 button.rect = pygame.rect.Rect(350, y, 250, 30)
361 self.add(button)
[251]362 buttons = []
[275]363 if delete:
364 labels = ['OK', 'Delete', 'Cancel']
365 else:
366 labels = ['OK', 'Cancel']
367 for text in labels:
[251]368 but = Button(text, action=lambda x=text: self.dismiss(x))
369 buttons.append(but)
370 row = Row(buttons)
371 row.rect = pygame.rect.Rect(250, 500, 700, 50)
372 self.add(row)
373
[355]374 def get_poly(self):
375 try:
376 data = self.level_widget.level.polygons[6][:]
377 except KeyError:
378 data = []
379 if data:
380 # We unclose the polygon, because that's what pymunk
381 # wants
382 if data[0] == data[-1] and len(data) > 1:
383 data.pop()
384 data = [list(x) for x in data]
385 self.needs_cleanup = True
386 self.poly_field.set_text('%s' % data)
387
388 def cleanup(self):
389 if self.needs_cleanup:
390 self.level_widget.level.polygons[6] = []
391 self.level_widget.invalidate()
392
[251]393 def get_data(self):
[255]394 result = {}
395 result['classname'] = self.classname
396 args = []
397 # We arrange to bounce this through yaml'ish to convert
398 # stuff to the expected type
[262]399 for val, _ in self.requires:
[255]400 text = self.fields[val].get_text()
401 if not text:
402 # skip empty fields
403 continue
404 if val == 'name':
405 result['name'] = text
[355]406 elif self.fields[val] == self.poly_field and text:
407 # Evil, but faster than good
408 try:
409 l = eval(text)
410 except Exception:
411 alert("Invalid polygon %s" % text)
412 self.needs_cleanup = False
413 return None
414 # Check for convexity
[449]415 if not pymunk.util.is_convex(l):
[355]416 alert("Invalid polygon %s - not convex" % text)
417 return None
[449]418 if not pymunk.util.is_clockwise(l):
419 l.reverse()
420 if not pymunk.util.is_clockwise(l):
421 alert("Invalid polygon %s - unable to make clockwise"
422 % text)
423 return None
424 args.append(' - - %s' % l[0])
425 for coord in l[1:]:
426 args.append(' - %s' % coord)
[255]427 else:
428 args.append(' - ' + text)
429 data = "args:\n" + '\n'.join(args)
430 result['args'] = load_s(data)['args']
431 return result
[251]432
433
[108]434class LevelWidget(Widget):
[51]435
[280]436 def __init__(self, level, parent):
[108]437 super(LevelWidget, self).__init__(pygame.rect.Rect(0, 0,
[109]438 SCREEN[0], SCREEN[1]))
[51]439 self.level = level
440 self.pos = (0, 0)
[108]441 self.filled_mode = False
[51]442 self.mouse_pos = None
[108]443 self.cur_poly = None
[167]444 self._mouse_drag = False
[199]445 self._draw_objects = False
446 self._draw_enemies = False
[204]447 self._draw_lines = False
[419]448 self.grid_size = 1
[275]449 self.sel_mode = False
[478]450 self.move_obj_mode = False
451 self.move_obj = None
[205]452 self._start_pos = None
[280]453 self._parent = parent
[407]454 self._move_point_mode = False
[458]455 self._move_poly_mode = False
[407]456 self._move_point = False
[413]457 self._zoom_factor = 1.0
[51]458
[108]459 def _level_coordinates(self, pos):
460 # Move positions to level values
461 if not pos:
462 return (0, 0)
[413]463 # Apply zoom_factor
[450]464 pos = pos[0] + self.pos[0], pos[1] + self.pos[1]
[413]465 zoomed = (pos[0] * self._zoom_factor, pos[1] * self._zoom_factor)
[450]466 return int(zoomed[0]), int(zoomed[1])
[108]467
468 def _move_view(self, offset):
[51]469 new_pos = [self.pos[0] + offset[0], self.pos[1] + offset[1]]
470 if new_pos[0] < 0:
471 new_pos[0] = self.pos[0]
472 elif new_pos[0] > self.level.x - SCREEN[0]:
473 new_pos[0] = self.pos[0]
474 if new_pos[1] < 0:
475 new_pos[1] = self.pos[1]
476 elif new_pos[1] > self.level.y - SCREEN[1]:
477 new_pos[1] = self.pos[1]
478 self.pos = tuple(new_pos)
479
[419]480 def inc_grid_size(self, amount):
481 self.grid_size = max(1, self.grid_size + amount)
[426]482 if self.grid_size > 1:
483 self.grid_size = self.grid_size - (self.grid_size % 5)
[419]484
[424]485 def snap_to_grid(self, pos):
486 x = pos[0] - (pos[0] % self.grid_size)
487 y = pos[1] - (pos[1] % self.grid_size)
488 return (x, y)
489
[199]490 def set_objects(self, value):
491 if self._draw_objects != value:
492 self._draw_objects = value
493 self.invalidate()
494
495 def set_enemies(self, value):
496 if self._draw_enemies != value:
497 self._draw_enemies = value
498 self.invalidate()
499
[413]500 def zoom_out(self):
501 self._zoom_factor = self._zoom_factor * 2.0
502 if self._zoom_factor > 8:
503 self._zoom_factor = 8
504
505 def zoom_in(self):
506 self._zoom_factor = self._zoom_factor // 2.0
507 if self._zoom_factor < 1:
508 self._zoom_factor = 1
509
[108]510 def draw(self, surface):
[51]511 if (self.cur_poly is not None and self.cur_poly in self.level.polygons
512 and len(self.level.polygons[self.cur_poly])):
513 # We have an active polygon
514 mouse_pos = self._level_coordinates(self.mouse_pos)
[424]515 mouse_pos = self.snap_to_grid(mouse_pos)
[205]516 elif self._draw_lines:
517 # Interior wall mode
518 mouse_pos = self._level_coordinates(self.mouse_pos)
[424]519 mouse_pos = self.snap_to_grid(mouse_pos)
[458]520 elif self._move_point_mode or self._move_poly_mode:
[407]521 mouse_pos = self._level_coordinates(self.mouse_pos)
[424]522 mouse_pos = self.snap_to_grid(mouse_pos)
[51]523 else:
524 mouse_pos = None
[205]525 level_surface = level.draw(mouse_pos, self.cur_poly, self.filled_mode,
[407]526 self._draw_lines, self._start_pos,
[458]527 self._move_point_mode, self._move_poly_mode,
[459]528 self._move_point, self._zoom_factor, self)
[199]529 if self._draw_objects:
530 for thing in self.level.drawables:
[251]531 if not isinstance(thing, ne.Enemy):
[199]532 thing.render(level_surface)
533 if self._draw_enemies:
534 for thing in self.level.drawables:
[251]535 if isinstance(thing, ne.Enemy):
[199]536 thing.render(level_surface)
537 surface_area = pygame.rect.Rect(self.pos, SCREEN)
[413]538 zoomed_surface = level_surface.copy()
[432]539 if self._zoom_factor != 1:
540 zoomed_surface = pygame.transform.scale(
541 level_surface,
[433]542 (int(level_surface.get_width() / self._zoom_factor),
543 int(level_surface.get_height() / self._zoom_factor)))
[413]544 surface.blit(zoomed_surface, (0, 0), surface_area)
[51]545
[115]546 def change_poly(self, new_poly):
547 self.cur_poly = new_poly
[204]548 self._draw_lines = False
[462]549 self._move_point_mode = False
[115]550 if self.cur_poly is not None:
[280]551 self._parent.reset_lit_buttons()
[115]552 self.filled_mode = False
553
[204]554 def line_mode(self):
555 self.cur_poly = None
[280]556 self._parent.reset_lit_buttons()
[204]557 self._draw_lines = True
558 self.filled_mode = False
[205]559 self._start_pos = None
[407]560 self._move_point_mode = False
[458]561 self._move_poly_mode = False
[204]562
[108]563 def key_down(self, ev):
564 if ev.key == pgl.K_LEFT:
565 self._move_view((-10, 0))
566 elif ev.key == pgl.K_RIGHT:
567 self._move_view((10, 0))
568 elif ev.key == pgl.K_UP:
569 self._move_view((0, -10))
570 elif ev.key == pgl.K_DOWN:
571 self._move_view((0, 10))
[115]572 elif ev.key in (pgl.K_1, pgl.K_2, pgl.K_3, pgl.K_4, pgl.K_5, pgl.K_6):
573 self.change_poly(ev.key - pgl.K_0)
[108]574 elif ev.key == pgl.K_0:
[115]575 self.change_poly(None)
[108]576 elif ev.key == pgl.K_d and self.cur_poly:
577 self.level.delete_point(self.cur_poly)
578 elif ev.key == pgl.K_f:
[117]579 self.set_filled()
[135]580 elif ev.key == pgl.K_c:
581 self.close_poly()
[117]582
[458]583 def set_move_poly_mode(self):
584 self._draw_lines = False
585 self._move_point_mode = False
586 self._move_poly_mode = True
587 self.filled_mode = False
588 self._parent.reset_lit_buttons()
589 self._move_point = None
590
[407]591 def set_move_mode(self):
592 self._draw_lines = False
593 self._move_point_mode = True
[458]594 self._move_poly_mode = False
[407]595 self.filled_mode = False
596 self._parent.reset_lit_buttons()
597 self._move_point = None
598
[117]599 def set_filled(self):
[165]600 closed, _ = self.level.all_closed()
601 if closed:
[117]602 self.cur_poly = None
[280]603 self._parent.reset_lit_buttons()
[117]604 self.filled_mode = True
[204]605 self._draw_lines = False
[407]606 self._move_point_mode = False
[458]607 self._move_poly_mode = False
[117]608 else:
[165]609 alert('Not all polygons closed, so not filling')
[108]610
[109]611 def mouse_move(self, ev):
612 old_pos = self.mouse_pos
613 self.mouse_pos = ev.pos
[481]614 if self.move_obj:
615 corrected_pos = self._level_coordinates(ev.pos)
616 snapped_pos = self.snap_to_grid(corrected_pos)
617 self._update_pos(self.move_obj, snapped_pos)
[407]618 if old_pos != self.mouse_pos and (self.cur_poly or self._draw_lines
[458]619 or self._move_point_mode
620 or self._move_poly_mode):
[109]621 self.invalidate()
622
[167]623 def mouse_drag(self, ev):
624 if self._mouse_drag:
625 old_pos = self.mouse_pos
626 self.mouse_pos = ev.pos
627 diff = (-self.mouse_pos[0] + old_pos[0],
628 -self.mouse_pos[1] + old_pos[1])
629 self._move_view(diff)
630 self.invalidate()
631
[109]632 def mouse_down(self, ev):
[414]633 corrected_pos = self._level_coordinates(ev.pos)
[424]634 snapped_pos = self.snap_to_grid(corrected_pos)
[275]635 if self.sel_mode and ev.button == 1:
636 obj = self.level.find_obj_at_pos(corrected_pos)
637 if obj is not None:
638 self._edit_selected(obj)
[478]639 elif self.move_obj_mode and ev.button == 1 and not self.move_obj:
640 obj = self.level.find_obj_at_pos(corrected_pos)
641 if obj is not None:
642 if obj.movable():
643 self.move_obj = obj
[483]644 data = self.level.lookup[obj]
645 print data
[478]646 elif self.move_obj_mode and ev.button == 1 and self.move_obj:
647 self._update_pos(self.move_obj, snapped_pos)
648 self.move_obj = None
[458]649 elif self._move_poly_mode and ev.button == 1:
650 if self._move_point:
651 # Place the current point
652 self.level.replace_poly(self._move_point, snapped_pos)
653 self._move_point = None
654 self.invalidate()
655 else:
656 # find the current point
[465]657 self._move_point = self.level.find_vertex(corrected_pos)
[407]658 elif self._move_point_mode and ev.button == 1:
659 if self._move_point:
660 # Place the current point
[424]661 self.level.replace_vertex(self._move_point, snapped_pos)
[407]662 self._move_point = None
663 self.invalidate()
664 else:
665 # find the current point
[465]666 self._move_point = self.level.find_vertex(corrected_pos)
[275]667 elif ev.button == 1:
[204]668 if self._draw_lines:
[205]669 if self._start_pos is None:
[414]670 self._start_pos = corrected_pos
[205]671 else:
[424]672 self.level.add_line(self._start_pos, snapped_pos)
[205]673 self._start_pos = None
[204]674 else:
675 print "Click: %r" % (
[414]676 self.level.point_to_pymunk(corrected_pos),)
[157]677 if ev.button == 4: # Scroll up
678 self._move_view((0, -10))
679 elif ev.button == 5: # Scroll down
680 self._move_view((0, 10))
681 elif ev.button == 6: # Scroll left
682 self._move_view((-10, 0))
683 elif ev.button == 7: # Scroll right
684 self._move_view((10, 0))
[413]685 elif self.cur_poly and ev.button == 1:
686 # Add a point
[439]687 if not self.level.add_point(self.cur_poly, snapped_pos):
688 alert("Failed to place point")
[167]689 elif ev.button == 3:
690 self._mouse_drag = True
691
692 def mouse_up(self, ev):
693 if ev.button == 3:
694 self._mouse_drag = False
[108]695
[135]696 def close_poly(self):
697 if self.cur_poly is None:
698 return
699 if self.level.close_poly(self.cur_poly):
700 alert("Successfully closed the polygon")
701 self.change_poly(None)
702 else:
703 alert("Failed to close the polygon")
704
[251]705 def _edit_class(self, classname, cls, data):
706 # Dialog for class properties
[355]707 dialog = EditClassDialog(classname, cls, data, self)
[251]708 if dialog.present() == 'OK':
[355]709 return dialog
[251]710 return None
711
[275]712 def _edit_selected(self, obj):
713 data = self.level.lookup[obj]
714 cls = obj.__class__
715 classname = obj.__class__.__name__
[355]716 dialog = EditClassDialog(classname, cls, data, self, True)
[275]717 res = dialog.present()
718 if res == 'OK':
719 edited = dialog.get_data()
720 if edited is not None:
721 for target in [self.level._game_objects, self.level._enemies]:
722 if data in target:
[355]723 if self.level.try_new_object(classname, target,
724 edited, data):
725 dialog.cleanup()
[275]726 break
727 elif res == 'Delete':
728 for target in [self.level._game_objects, self.level._enemies]:
729 if data in target:
730 target.remove(data)
731 self.level.reset_objs()
732 break
733
[225]734 def _make_edit_dialog(self, entries):
735 # Dialog to hold the editor
736 edit_box = Dialog()
737 edit_box.rect = pygame.rect.Rect(0, 0, 700, 500)
738 table = ObjectTable(entries)
739 edit_box.add(table)
740 buttons = []
741 for text in ['OK', 'Delete', 'Cancel']:
742 but = Button(text, action=lambda x=text: edit_box.dismiss(x))
743 buttons.append(but)
744 row = Row(buttons)
[251]745 row.rect = pygame.rect.Rect(250, 450, 700, 50)
[225]746 edit_box.add(row)
[236]747 edit_box.get_selection = lambda: table.get_selection()
[225]748 return edit_box
749
750 def edit_objects(self):
751 edit_box = self._make_edit_dialog(self.level._game_objects)
752 res = edit_box.present()
[236]753 choice = edit_box.get_selection()
754 if choice is None:
755 return
[225]756 if res == 'OK':
[251]757 cls = self.level.get_class(choice['classname'])
[355]758 edit_dlg = self._edit_class(choice['classname'], cls, choice)
759 if edit_dlg is not None:
760 edited = edit_dlg.get_data()
761 if self.level.try_new_object(choice["classname"],
762 self.level._game_objects,
763 edited, choice):
764 edit_dlg.cleanup()
[225]765 elif res == 'Delete':
[239]766 self.level._game_objects.remove(choice)
767 self.level.reset_objs()
[225]768
769 def edit_enemies(self):
770 edit_box = self._make_edit_dialog(self.level._enemies)
771 res = edit_box.present()
[236]772 choice = edit_box.get_selection()
773 if choice is None:
774 return
[225]775 if res == 'OK':
[251]776 cls = self.level.get_class(choice['classname'], ne)
[355]777 edit_dlg = self._edit_class(choice['classname'], cls, choice)
778 if edit_dlg is not None:
779 edited = edit_dlg.get_data()
780 if self.level.try_new_object(choice["classname"],
781 self.level._enemies,
782 edited, choice):
783 edit_dlg.cleanup()
[225]784 elif res == 'Delete':
[239]785 self.level._enemies.remove(choice)
786 self.level.reset_objs()
[225]787
[236]788 def _make_choice_dialog(self, classes):
789 # Dialog to hold the editor
790 data = []
791 for cls_name, cls in classes:
792 data.append({"classname": cls_name, "class": cls})
[239]793 choice_box = Dialog()
794 choice_box.rect = pygame.rect.Rect(0, 0, 700, 500)
[236]795 table = ObjectTable(data)
[239]796 choice_box.add(table)
[236]797 buttons = []
798 for text in ['OK', 'Cancel']:
[239]799 but = Button(text, action=lambda x=text: choice_box.dismiss(x))
[236]800 buttons.append(but)
801 row = Row(buttons)
[251]802 row.rect = pygame.rect.Rect(250, 450, 700, 50)
[239]803 choice_box.add(row)
804 choice_box.get_selection = lambda: table.get_selection()
805 return choice_box
[236]806
807 def add_game_object(self):
[251]808 classes = ngo.get_editable_game_objects()
809 choose = self._make_choice_dialog(classes)
810 res = choose.present()
811 choice = choose.get_selection()
812 if res == 'OK' and choice is not None:
813 classname = choice['classname']
814 cls = choice['class']
[355]815 edit_dlg = self._edit_class(classname, cls, None)
816 if edit_dlg is not None:
817 new_cls = edit_dlg.get_data()
818 if self.level.try_new_object(classname,
819 self.level._game_objects,
820 new_cls, None):
821 edit_dlg.cleanup()
[251]822
823 def add_enemy(self):
824 classes = ne.get_editable_enemies()
[236]825 choose = self._make_choice_dialog(classes)
826 res = choose.present()
827 choice = choose.get_selection()
828 if res == 'OK' and choice is not None:
[251]829 classname = choice['classname']
830 cls = choice['class']
[355]831 edit_dlg = self._edit_class(classname, cls, None)
832 if edit_dlg is not None:
833 new_cls = edit_dlg.get_data()
834 if self.level.try_new_object(classname, self.level._enemies,
835 new_cls, None):
836 edit_dlg.cleanup()
[236]837
[251]838 def add_puzzler(self):
839 classes = np.get_editable_puzzlers()
[236]840 choose = self._make_choice_dialog(classes)
841 res = choose.present()
842 choice = choose.get_selection()
843 if res == 'OK' and choice is not None:
[251]844 classname = choice['classname']
845 cls = choice['class']
[355]846 edit_dlg = self._edit_class(classname, cls, None)
847 if edit_dlg is not None:
848 new_cls = edit_dlg.get_data()
849 if self.level.try_new_object(classname,
850 self.level._game_objects,
851 new_cls, None):
852 edit_dlg.cleanup()
[236]853
[478]854 def _update_pos(self, obj, new_pos):
855 data = self.level.lookup[obj]
856 new_coords = self.level.point_to_pymunk(new_pos)
857 data['args'][0][0] = new_coords[0]
858 data['args'][0][1] = new_coords[1]
859 self.level.reset_objs()
860 self.invalidate()
861
[108]862
[280]863class HighLightButton(Button):
864 """Button with highlight support"""
865 def __init__(self, text, parent, **kwds):
866 super(HighLightButton, self).__init__(text, **kwds)
867 self._parent = parent
868
869 def highlight(self):
870 self.border_color = pygame.color.Color('red')
871
872 def reset(self):
873 self.border_color = self.fg_color
874
875
876class PolyButton(HighLightButton):
[115]877 """Button for coosing the correct polygon"""
878
[280]879 def __init__(self, index, level_widget, parent):
[115]880 if index is not None:
881 text = "Draw: %s" % index
882 else:
883 text = 'Exit Draw Mode'
[280]884 super(PolyButton, self).__init__(text, parent)
[115]885 self.index = index
886 self.level_widget = level_widget
887
888 def action(self):
889 self.level_widget.change_poly(self.index)
[280]890 self._parent.reset_lit_buttons()
891 if self.index is not None:
892 self.highlight()
[115]893
894
[419]895class GridSizeLabel(Label):
896 """Label and setter for grid size."""
897
898 def __init__(self, level_widget, **kwds):
899 self.level_widget = level_widget
900 super(GridSizeLabel, self).__init__(self.grid_text(), **kwds)
901
902 def grid_text(self):
903 return "Grid size: %d" % self.level_widget.grid_size
904
905 def inc_grid_size(self, amount):
906 self.level_widget.inc_grid_size(amount)
907 self.set_text(self.grid_text())
908
909
910class SnapButton(Button):
911 """Button for increasing or decreasing snap-to-grid size."""
912
913 def __init__(self, grid_size_label, parent, inc_amount):
914 self.grid_size_label = grid_size_label
915 self.inc_amount = inc_amount
916 text = "Grid %s%d" % (
917 '-' if inc_amount < 0 else '+',
918 abs(inc_amount))
919 self._parent = parent
920 super(SnapButton, self).__init__(text)
921
922 def action(self):
923 self.grid_size_label.inc_grid_size(self.inc_amount)
924
925
[108]926class EditorApp(RootWidget):
927
928 def __init__(self, level, surface):
929 super(EditorApp, self).__init__(surface)
930 self.level = level
[280]931 self.level_widget = LevelWidget(self.level, self)
[108]932 self.add(self.level_widget)
933
[220]934 self._dMenus = {}
935
[280]936 self._light_buttons = []
937
[220]938 self._make_draw_menu()
939 self._make_objects_menu()
940
941 self._menu_mode = 'drawing'
942 self._populate_menu()
943
[413]944 self._zoom = 1
945
[220]946 def _make_draw_menu(self):
947 widgets = []
948
[419]949 white = pygame.color.Color("white")
950
[115]951 # Add poly buttons
[423]952 y = 5
[115]953 for poly in range(1, 7):
[280]954 but = PolyButton(poly, self.level_widget, self)
[115]955 but.rect = pygame.rect.Rect(0, 0, MENU_WIDTH // 2 - MENU_PAD,
956 MENU_BUTTON_HEIGHT)
957 if poly % 2:
958 but.rect.move_ip(MENU_LEFT, y)
959 else:
960 but.rect.move_ip(MENU_LEFT + MENU_WIDTH // 2 - MENU_HALF_PAD,
961 y)
962 y += MENU_BUTTON_HEIGHT + MENU_PAD
[280]963 self._light_buttons.append(but)
[220]964 widgets.append(but)
[198]965
[280]966 end_poly_but = PolyButton(None, self.level_widget, self)
[220]967 end_poly_but.rect = BUTTON_RECT.copy()
[115]968 end_poly_but.rect.move_ip(MENU_LEFT, y)
[220]969 widgets.append(end_poly_but)
[115]970 y += MENU_BUTTON_HEIGHT + MENU_PAD
971
[458]972 self.move_point_but = HighLightButton("Mv Point", self,
[407]973 action=self.move_point)
[458]974 self.move_point_but.rect = HALF_BUTTON_RECT.copy()
[407]975 self.move_point_but.rect.move_ip(MENU_LEFT, y)
976 widgets.append(self.move_point_but)
977 self._light_buttons.append(self.move_point_but)
[458]978
979 self.move_poly_but = HighLightButton("Mv Poly", self,
980 action=self.move_poly)
981 self.move_poly_but.rect = HALF_BUTTON_RECT.copy()
982 self.move_poly_but.rect.move_ip(MENU_LEFT + MENU_HALF_WIDTH, y)
983 widgets.append(self.move_poly_but)
984 self._light_buttons.append(self.move_poly_but)
985
[423]986 y += MENU_BUTTON_HEIGHT + MENU_PAD
[419]987
988 # grid size widgets
989 grid_size_label = GridSizeLabel(
990 self.level_widget, width=BUTTON_RECT.width,
991 align="c", fg_color=white)
992 grid_size_label.rect.move_ip(MENU_LEFT, y)
993 widgets.append(grid_size_label)
994 y += grid_size_label.rect.height + MENU_PAD
[426]995 inc_snap_but = SnapButton(grid_size_label, self, 5)
[419]996 inc_snap_but.rect = HALF_BUTTON_RECT.copy()
997 inc_snap_but.rect.move_ip(MENU_LEFT, y)
998 widgets.append(inc_snap_but)
[426]999 dec_snap_but = SnapButton(grid_size_label, self, -5)
[419]1000 dec_snap_but.rect = HALF_BUTTON_RECT.copy()
1001 dec_snap_but.rect.move_ip(
1002 MENU_LEFT + MENU_HALF_WIDTH, y)
1003 widgets.append(dec_snap_but)
[407]1004 y += MENU_BUTTON_HEIGHT + MENU_PAD
1005
[280]1006 self.draw_line_but = HighLightButton("Draw interior wall", self,
1007 action=self.set_line_mode)
1008 self.draw_line_but.rect = BUTTON_RECT.copy()
1009 self.draw_line_but.rect.move_ip(MENU_LEFT, y)
1010 widgets.append(self.draw_line_but)
1011 self._light_buttons.append(self.draw_line_but)
[204]1012 y += MENU_BUTTON_HEIGHT + MENU_PAD
1013
[117]1014 fill_but = Button('Fill exterior', action=self.level_widget.set_filled)
[220]1015 fill_but.rect = BUTTON_RECT.copy()
[117]1016 fill_but.rect.move_ip(MENU_LEFT, y)
[220]1017 widgets.append(fill_but)
[117]1018 y += MENU_BUTTON_HEIGHT + MENU_PAD
1019
[135]1020 close_poly_but = Button('Close Polygon',
1021 action=self.level_widget.close_poly)
[220]1022 close_poly_but.rect = BUTTON_RECT.copy()
[135]1023 close_poly_but.rect.move_ip(MENU_LEFT, y)
[220]1024 widgets.append(close_poly_but)
[135]1025 y += MENU_BUTTON_HEIGHT + MENU_PAD
1026
[198]1027 self.show_objs = CheckBox(fg_color=white)
[220]1028 self.show_objs.rect = CHECK_RECT.copy()
[198]1029 self.show_objs.rect.move_ip(MENU_LEFT, y)
1030 label = Label("Show Objects", fg_color=white)
1031 label.rect.move_ip(MENU_LEFT + MENU_BUTTON_HEIGHT // 2 + MENU_PAD, y)
[220]1032 widgets.append(self.show_objs)
1033 widgets.append(label)
[198]1034 y += label.rect.height + MENU_PAD
1035
1036 self.show_enemies = CheckBox(fg_color=white)
[220]1037 self.show_enemies.rect = CHECK_RECT.copy()
[198]1038 self.show_enemies.rect.move_ip(MENU_LEFT, y)
1039 label = Label("Show enemy start pos", fg_color=white)
1040 label.rect.move_ip(MENU_LEFT + MENU_BUTTON_HEIGHT // 2 + MENU_PAD, y)
[220]1041 widgets.append(self.show_enemies)
1042 widgets.append(label)
[198]1043 y += label.rect.height + MENU_PAD
1044
[236]1045 y += MENU_PAD
[220]1046 switch_but = Button('Switch to Objects', action=self.switch_to_objects)
1047 switch_but.rect = BUTTON_RECT.copy()
1048 switch_but.rect.move_ip(MENU_LEFT, y)
1049 widgets.append(switch_but)
1050 y += switch_but.rect.height + MENU_PAD
1051
[236]1052 save_but = Button('Save Level', action=self.save)
1053 save_but.rect = BUTTON_RECT.copy()
1054 save_but.rect.move_ip(MENU_LEFT, y)
1055 widgets.append(save_but)
1056 y += MENU_BUTTON_HEIGHT + MENU_PAD
1057
[413]1058 zoom_out = Button('Zoom out', action=self.level_widget.zoom_out)
1059 zoom_out.rect = BUTTON_RECT.copy()
[422]1060 zoom_out.rect.width = zoom_out.rect.width // 2
[413]1061 zoom_out.rect.move_ip(MENU_LEFT, y)
1062 widgets.append(zoom_out)
1063
1064 zoom_in = Button('Zoom in', action=self.level_widget.zoom_in)
1065 zoom_in.rect = BUTTON_RECT.copy()
[422]1066 zoom_in.width = zoom_in.width // 2
1067 zoom_in.rect.move_ip(MENU_LEFT + zoom_out.width, y)
[413]1068 widgets.append(zoom_in)
1069
[330]1070 y = SCREEN[1] - MENU_BUTTON_HEIGHT - MENU_PAD
[108]1071 quit_but = Button('Quit', action=self.quit)
[220]1072 quit_but.rect = BUTTON_RECT.copy()
[115]1073 quit_but.rect.move_ip(MENU_LEFT, y)
[220]1074 widgets.append(quit_but)
1075
1076 self._dMenus['drawing'] = widgets
1077
1078 def _make_objects_menu(self):
1079 widgets = []
1080
1081 # Add poly buttons
1082 y = 15
1083
[225]1084 edit_objs_but = Button('Edit Objects',
1085 action=self.level_widget.edit_objects)
1086 edit_objs_but.rect = BUTTON_RECT.copy()
1087 edit_objs_but.rect.move_ip(MENU_LEFT, y)
1088 widgets.append(edit_objs_but)
1089 y += MENU_BUTTON_HEIGHT + MENU_PAD
1090
1091 edir_enemies_but = Button('Edit Enemies',
1092 action=self.level_widget.edit_enemies)
1093 edir_enemies_but.rect = BUTTON_RECT.copy()
1094 edir_enemies_but.rect.move_ip(MENU_LEFT, y)
1095 widgets.append(edir_enemies_but)
1096 y += MENU_BUTTON_HEIGHT + MENU_PAD
1097
[236]1098 add_obj_but = Button('Add Game Object',
1099 action=self.level_widget.add_game_object)
1100 add_obj_but.rect = BUTTON_RECT.copy()
1101 add_obj_but.rect.move_ip(MENU_LEFT, y)
1102 widgets.append(add_obj_but)
1103 y += MENU_BUTTON_HEIGHT + MENU_PAD
1104
1105 add_puzzle_but = Button('Add Puzzler',
1106 action=self.level_widget.add_puzzler)
1107 add_puzzle_but.rect = BUTTON_RECT.copy()
1108 add_puzzle_but.rect.move_ip(MENU_LEFT, y)
1109 widgets.append(add_puzzle_but)
1110 y += MENU_BUTTON_HEIGHT + MENU_PAD
1111
1112 add_enemy_but = Button('Add Enemy',
1113 action=self.level_widget.add_enemy)
1114 add_enemy_but.rect = BUTTON_RECT.copy()
1115 add_enemy_but.rect.move_ip(MENU_LEFT, y)
1116 widgets.append(add_enemy_but)
1117 y += MENU_BUTTON_HEIGHT + MENU_PAD
1118
1119 y += MENU_PAD
[280]1120 self.sel_mode_but = HighLightButton('Select Object', self,
1121 action=self.sel_mode)
1122 self.sel_mode_but.rect = BUTTON_RECT.copy()
1123 self.sel_mode_but.rect.move_ip(MENU_LEFT, y)
1124 widgets.append(self.sel_mode_but)
1125 self._light_buttons.append(self.sel_mode_but)
[275]1126 y += MENU_BUTTON_HEIGHT + MENU_PAD
1127
1128 y += MENU_PAD
[478]1129 self.move_obj_mode_but = HighLightButton('Move Object', self,
1130 action=self.move_obj_mode)
1131 self.move_obj_mode_but.rect = BUTTON_RECT.copy()
1132 self.move_obj_mode_but.rect.move_ip(MENU_LEFT, y)
1133 widgets.append(self.move_obj_mode_but)
1134 self._light_buttons.append(self.move_obj_mode_but)
1135 y += MENU_BUTTON_HEIGHT + MENU_PAD
1136
1137 y += MENU_PAD
[236]1138 switch_but = Button('Switch to Drawing', action=self.switch_to_draw)
1139 switch_but.rect = BUTTON_RECT.copy()
1140 switch_but.rect.move_ip(MENU_LEFT, y)
1141 widgets.append(switch_but)
1142 y += switch_but.rect.height + MENU_PAD
1143
[220]1144 save_but = Button('Save Level', action=self.save)
1145 save_but.rect = BUTTON_RECT.copy()
1146 save_but.rect.move_ip(MENU_LEFT, y)
1147 widgets.append(save_but)
1148 y += MENU_BUTTON_HEIGHT + MENU_PAD
1149
[414]1150 zoom_out = Button('Zoom out', action=self.level_widget.zoom_out)
1151 zoom_out.rect = BUTTON_RECT.copy()
[422]1152 zoom_out.rect.width = zoom_out.rect.width // 2
[414]1153 zoom_out.rect.move_ip(MENU_LEFT, y)
1154 widgets.append(zoom_out)
1155
1156 zoom_in = Button('Zoom in', action=self.level_widget.zoom_in)
1157 zoom_in.rect = BUTTON_RECT.copy()
[422]1158 zoom_in.width = zoom_in.width // 2
1159 zoom_in.rect.move_ip(MENU_LEFT + zoom_out.width, y)
[414]1160 widgets.append(zoom_in)
[422]1161 y += MENU_BUTTON_HEIGHT + MENU_PAD
[414]1162
[330]1163 y = SCREEN[1] - MENU_BUTTON_HEIGHT - MENU_PAD
[220]1164 quit_but = Button('Quit', action=self.quit)
1165 quit_but.rect = BUTTON_RECT.copy()
1166 quit_but.rect.move_ip(MENU_LEFT, y)
1167 widgets.append(quit_but)
1168
1169 self._dMenus['objects'] = widgets
[108]1170
1171 def key_down(self, ev):
1172 if ev.key == pgl.K_ESCAPE:
1173 self.quit()
[116]1174 elif ev.key == pgl.K_s:
1175 self.save()
[108]1176 else:
1177 self.level_widget.key_down(ev)
[51]1178
[116]1179 def save(self):
[122]1180 closed, messages = self.level.all_closed()
1181 if closed:
1182 self.level.save()
1183 # display success
1184 alert("Level %s saved successfully." % self.level.name)
1185 else:
1186 # display errors
1187 alert("Failed to save level.\n\n%s" % '\n'.join(messages))
[116]1188
[220]1189 def switch_to_draw(self):
1190 if self._menu_mode != 'drawing':
1191 self._clear_menu()
1192 self._menu_mode = 'drawing'
1193 self._populate_menu()
1194
1195 def switch_to_objects(self):
1196 if self._menu_mode != 'objects':
1197 self._clear_menu()
1198 self._menu_mode = 'objects'
1199 self._populate_menu()
1200
1201 def _clear_menu(self):
1202 for widget in self._dMenus[self._menu_mode]:
1203 self.remove(widget)
1204
[280]1205 def reset_lit_buttons(self):
1206 for but in self._light_buttons:
1207 but.reset()
1208
[220]1209 def _populate_menu(self):
1210 self.level_widget.change_poly(None)
[275]1211 self.level_widget.sel_mode = False
[478]1212 self.level_widget.move_obj_mode = False
1213 self.level_widget.move_obj = None
[220]1214 for widget in self._dMenus[self._menu_mode]:
1215 self.add(widget)
1216 self.invalidate()
1217
[280]1218 def set_line_mode(self):
1219 self.level_widget.line_mode()
1220 self.draw_line_but.highlight()
1221
[275]1222 def sel_mode(self):
1223 self.level_widget.sel_mode = not self.level_widget.sel_mode
[280]1224 if self.level_widget.sel_mode:
[478]1225 self.move_obj_mode_but.reset()
[280]1226 self.sel_mode_but.highlight()
[478]1227 self.level_widget.move_obj_mode = False
1228 self.level_widget.move_obj = None
[280]1229 else:
1230 self.sel_mode_but.reset()
[275]1231
[478]1232 def move_obj_mode(self):
1233 self.level_widget.move_obj_mode = not self.level_widget.move_obj_mode
1234 if self.level_widget.move_obj_mode:
1235 self.sel_mode_but.reset()
1236 self.move_obj_mode_but.highlight()
1237 self.level_widget.sel_mode = False
1238 else:
1239 self.move_obj_mode_but.reset()
1240
[109]1241 def mouse_move(self, ev):
1242 self.level_widget.mouse_move(ev)
1243
[407]1244 def move_point(self):
1245 self.level_widget.set_move_mode()
1246 self.move_point_but.highlight()
1247
[458]1248 def move_poly(self):
1249 self.level_widget.set_move_poly_mode()
1250 self.move_poly_but.highlight()
1251
[199]1252 def draw(self, surface):
1253 # Update checkbox state
[223]1254 if self._menu_mode == 'drawing':
1255 self.level_widget.set_objects(self.show_objs.value)
1256 self.level_widget.set_enemies(self.show_enemies.value)
1257 else:
1258 self.level_widget.set_objects(True)
1259 self.level_widget.set_enemies(True)
[199]1260 super(EditorApp, self).draw(surface)
1261
[51]1262
1263if __name__ == "__main__":
[195]1264 if len(sys.argv) not in [2, 4]:
[51]1265 print 'Please supply a levelname or levelname and level size'
1266 sys.exit()
[199]1267 # Need to ensure we have defaults for rendering
1268 parse_args([])
[51]1269 pygame.display.init()
1270 pygame.font.init()
[108]1271 pygame.display.set_mode((SCREEN[0] + MENU_WIDTH, SCREEN[1]),
[109]1272 pgl.SWSURFACE)
[195]1273 if len(sys.argv) == 2:
1274 level = EditorLevel(sys.argv[1])
1275 level.load(pymunk.Space())
1276 elif len(sys.argv) == 4:
1277 level = EditorLevel(sys.argv[1], int(sys.argv[2]), int(sys.argv[3]))
[51]1278 pygame.display.set_caption('Nagslang Area Editor')
[108]1279 pygame.key.set_repeat(200, 100)
1280 app = EditorApp(level, pygame.display.get_surface())
1281 app.run()
Note: See TracBrowser for help on using the repository browser.