1 #!C:\Python32\python.exe
2 """<title>a simple tile editor for pygame</title>
5 usage: tileedit tiles.tga [tile_w] [tile_h]
6 windows: python tileedit tiles.tga [tile_w] [tile_h]
9 -h, --help show this help message and exit
10 --sw=SCREEN_W screen width (app)
11 --sh=SCREEN_H screen height (app)
12 --tw=TILE_W tile width (image)
13 --th=TILE_H tile height (image)
14 --width=WIDTH new width (image)
15 --height=HEIGHT new height (image)
16 -pPALETTE, --pal=PALETTE
17 filename of palette (image)
18 -d, --defaults set default settings (image)
21 tileedit tiles.tga 16 16
24 the editor can only edit tga files.
26 you may edit default options in tileedit.ini
29 - menus for common commands
32 left click to use current tool
33 right click to select color
35 left click to select a tile
36 right click to select any region
38 click to select a color
48 delete - delete selection
50 e - draw ellipse in selection
59 F10 - toggle fullscreen
64 from optparse import OptionParser
65 from ConfigParser import ConfigParser
67 from pygame.locals import *
73 # print "import Image failure; PIL not found."
78 # the following line is not needed if pgl is installed
79 import sys; sys.path.insert(0, "..")
82 from pgu import gui, html
86 ini_fname = "tileedit.ini"
91 class _app(gui.Container):
93 gui.Container.__init__(self)
95 #self.background = gui.Box(self.style.background)
97 self.screen_w = cfg['screen_w']
98 self.screen_h = cfg['screen_h']
99 self.screen = pygame.display.set_mode((self.screen_w,self.screen_h),SWSURFACE)
101 self.fname = cfg['fname']
103 if self.fname != None:
106 im = Image.open(self.fname)
111 assert mode in ("RGB", "RGBA")
113 self.tiles = pygame.image.fromstring(data, size, mode)
116 self.tiles = pygame.image.load(self.fname) # old tga-only method
118 w,h = cfg['width'],cfg['height']
119 s = pygame.Surface((w,h),SWSURFACE|SRCALPHA,32)
123 self.tiles_w, self.tiles_h = self.tiles.get_width(),self.tiles.get_height()
126 self.tile_w, self.tile_h = cfg['tile_w'],cfg['tile_h']
127 self.tile = self.tiles.subsurface((0,0,self.tile_w,self.tile_h))
129 self.color = (255,255,255,255)
131 self.clipboard = None
132 self.select = Rect(0,0,self.tile_w,self.tile_h)
140 c = pygame.Surface((self.tile_w,self.tile_h),SWSURFACE,self.tile)
142 c.blit(self.tile,(0,0))
143 h.append((c,self.tile.get_offset()))
147 if len(self.history) == 0: return
148 c,off = self.history.pop()
149 self.tiles.fill((0,0,0,0),(off[0],off[1],self.tile_w,self.tile_h))
150 self.tiles.blit(c,off)
152 self.tpicker.repaint()
155 def __setattr__(self,k,v):
159 if hasattr(self,'cpreview'): self.cpreview.repaint()
161 if hasattr(self,'tdraw'): self.tdraw.repaint()
162 if hasattr(self,'tpicker'): self.tpicker.repaint()
163 if hasattr(self,'tpreview'): self.tpreview.repaint()
165 if e.type is KEYDOWN:
166 for key,cmd,value in keys:
170 return gui.Container.event(self,e)
172 class cpreview(gui.Widget):
173 def __init__(self,w,h):
174 gui.Widget.__init__(self)
176 self.style.height = h
179 s.fill((128,128,128))
183 class cpicker(gui.Widget):
184 def __init__(self,w,h,pal):
185 gui.Widget.__init__(self)
187 self.style.height = h
189 self.palette_w = pal.get_width()
190 self.palette_h = pal.get_height()
193 s.blit(pygame.transform.scale(self.palette,(self.rect.w,self.rect.h)),(0,0))
196 if (e.type is MOUSEBUTTONDOWN) or (e.type is MOUSEMOTION and e.buttons[0] == 1 and self.container.myfocus == self):
197 x,y = e.pos[0]*self.palette_w/self.rect.w,e.pos[1]*self.palette_h/self.rect.h
198 x,y = max(0,x),max(0,y)
199 x,y = min(self.palette_w-1,x),min(self.palette_h-1,y)
201 app.color = self.palette.get_at((x,y))
203 class tpicker(gui.Widget):
205 gui.Widget.__init__(self)
206 self.style.width = app.tiles_w
207 self.style.height = app.tiles_h
210 s.fill((128,128,128))
211 s.blit(app.tiles,(0,0))
212 off = app.tile.get_offset()
213 pygame.draw.rect(s,(255,255,255),(off[0],off[1],app.tile_w,app.tile_h),2)
217 while x < 0: x += self.rect.w
218 while y < 0: y += self.rect.h
219 while x >= self.rect.w: x -= self.rect.w
220 while y >= self.rect.h: y -= self.rect.h
221 app.tile = app.tiles.subsurface((x,y,app.tile_w,app.tile_h))
224 if (e.type is MOUSEBUTTONDOWN and e.button == 1) or (e.type is MOUSEMOTION and e.buttons[0] == 1 and self.container.myfocus == self):
225 x,y = e.pos[0]/app.tile_w*app.tile_w,e.pos[1]/app.tile_h*app.tile_h
228 if (e.type is MOUSEBUTTONDOWN and e.button == 3) or (e.type is MOUSEMOTION and e.buttons[2] == 1 and self.container.myfocus == self):
229 x,y = e.pos[0]-app.tile_w/2,e.pos[1]-app.tile_h/2
230 x = min(self.rect.w-app.tile_w-1,max(0,x))
231 y = min(self.rect.h-app.tile_h-1,max(0,y))
234 class tpreview(gui.Widget):
236 gui.Widget.__init__(self)
237 self.style.width = app.tile_w*3
238 self.style.height = app.tile_h*3
242 s.fill((100,100,100))
243 s.blit(app.tile,(0,0))
244 s.blit(app.tile,(1*atw,0))
245 s.blit(app.tile,(2*atw,0))
246 s.blit(app.tile,(0,1*ath))
247 s.blit(app.tile,(1*atw,1*ath))
248 s.blit(app.tile,(2*atw,1*ath))
249 s.blit(app.tile,(0,2*ath))
250 s.blit(app.tile,(1*atw,2*ath))
251 s.blit(app.tile,(2*atw,2*ath))
253 class tdraw(gui.Widget):
254 def __init__(self,w,h):
255 gui.Widget.__init__(self)
256 self.rect.w = self.style.width = w
257 self.rect.h = self.style.height = h
258 self.overlay = pygame.Surface((app.tile_w,app.tile_h)).convert_alpha()
259 self.overlay.fill((0,0,0,0))
260 s = pygame.Surface((self.rect.w,self.rect.h))
261 clrs = [(148,148,148),(108,108,108)]
262 for y in range(0,app.tile_h*2):
263 for x in range(0,app.tile_w*2):
264 s.fill(clrs[(x+y)%2],(
265 self.rect.w*x/(app.tile_w*2),
266 self.rect.h*y/(app.tile_h*2),
267 self.rect.w/(app.tile_w*2)+1,
268 self.rect.h/(app.tile_h*2)+2))
271 s = pygame.Surface((self.rect.w,self.rect.h)).convert_alpha()
273 for x in range(0,app.tile_w):
274 pygame.draw.line(s,(0,0,0),(self.rect.w*x/app.tile_w,0),(self.rect.w*x/app.tile_w,self.rect.h))
275 for y in range(0,app.tile_h):
276 pygame.draw.line(s,(0,0,0),(0,self.rect.h*y/app.tile_h),(self.rect.w,self.rect.h*y/app.tile_h))
281 s.blit(self.bg,(0,0))
282 s.blit(pygame.transform.scale(app.tile,(self.rect.w,self.rect.h)),(0,0))
283 s.blit(pygame.transform.scale(self.overlay,(self.rect.w,self.rect.h)),(0,0))
284 #if app.mode == 'select':
285 s.blit(self.grid,(0,0))
287 pygame.draw.rect(s,(255,255,255,128),Rect(r.x*self.rect.w/app.tile_w,r.y*self.rect.h/app.tile_h,r.w*self.rect.w/app.tile_w,r.h*self.rect.h/app.tile_h),4)
290 if (e.type is MOUSEBUTTONDOWN and e.button == 3) or (e.type is MOUSEMOTION and e.buttons[2]==1 and self.container.myfocus == self):
292 if e.type is MOUSEBUTTONDOWN and e.button == 1:
293 a = '%s_down'%app.mode
294 if hasattr(self,a): getattr(self,a)(e)
295 if e.type is MOUSEMOTION and e.buttons[0] and self.container.myfocus == self:
296 a = '%s_drag'%app.mode
297 if hasattr(self,a): getattr(self,a)(e)
298 if e.type is MOUSEBUTTONUP and e.button == 1:
300 if hasattr(self,a): getattr(self,a)(e)
303 def picker_down(self,e):
305 c = app.tile.get_at(pos)
309 def fill_down(self,e):
312 bg = app.tile.get_at(pos)
313 if bg == app.color: return
314 self.fill_pixel(pos,bg)
318 def fill_pixel(self,pos,bg): #worst algorithm
319 c = app.tile.get_at(pos)
321 app.tile.set_at(pos,app.color)
323 if x > 0: self.fill_pixel((x-1,y),bg)
324 if x < app.tile_w-1: self.fill_pixel((x+1,y),bg)
325 if y > 0: self.fill_pixel((x,y-1),bg)
326 if y < app.tile_h-1: self.fill_pixel((x,y+1),bg)
329 def pixel_down(self,e):
332 app.tile.set_at(pos,app.color)
336 def line_down(self,e):
340 def line_drag(self,e):
341 self.overlay.fill((0,0,0,0))
343 pygame.draw.line(self.overlay,app.color,self.pos,pos)
348 self.overlay.fill((0,0,0,0))
350 pygame.draw.line(app.tile,app.color,self.pos,pos)
354 def ellipse_down(self,e):
358 def ellipse_drag(self,e):
359 self.overlay.fill((0,0,0,0))
361 r = pygame.Rect(self.pos[0],self.pos[1],pos[0]-self.pos[0],pos[1]-self.pos[1])
365 r.width,r.height = max(2,r.width),max(2,r.height)
366 pygame.draw.ellipse(self.overlay,app.color,r,1)
369 def ellipse_up(self,e):
371 self.overlay.fill((0,0,0,0))
373 r = pygame.Rect(self.pos[0],self.pos[1],pos[0]-self.pos[0],pos[1]-self.pos[1])
377 r.width,r.height = max(2,r.width),max(2,r.height)
378 pygame.draw.ellipse(app.tile,app.color,r,1)
382 def draw_down(self,e):
385 app.tile.set_at(pos,app.color)
389 def draw_drag(self,e):
391 pygame.draw.line(app.tile,app.color,self.pos,pos)
396 x,y = (e.pos[0])*app.tile_w/self.rect.w,(e.pos[1])*app.tile_h/self.rect.h
397 x = min(max(0,x),app.tile_w-1)
398 y = min(max(0,y),app.tile_h-1)
402 w = self.rect.w/app.tile_w
403 h = self.rect.h/app.tile_h
404 x,y = (e.pos[0]+w/2)*app.tile_w/self.rect.w,(e.pos[1]+h/2)*app.tile_h/self.rect.h
405 x = min(max(0,x),app.tile_w)
406 y = min(max(0,y),app.tile_h)
412 def select_down(self,e):
413 pos = self.getpos2(e)
414 app.select = Rect(pos[0],pos[1],0,0)
417 def select_drag(self,e):
418 pos = self.getpos2(e)
419 #pos = (e.pos[0]+app.tile_w/2)/app.tile_w,(e.pos[1]+app.tile_h/2)/app.tile_h
421 app.select = Rect(app.select.x,app.select.y,pos[0]-app.select.x,pos[1]-app.select.y)
422 app.select.w = max(0,app.select.w)
423 app.select.h = max(0,app.select.h)
432 def eraser_down(self,e):
435 app.tile.set_at(pos,(0,0,0,0))
439 def eraser_drag(self,e):
441 pygame.draw.line(app.tile,(0,0,0,0),self.pos,pos)
447 if app.dirty: _dirty(_cmd_quit,value)
448 else: _cmd_quit(value)
450 def _cmd_quit(value):
454 app.select = Rect(0,0,app.tile_w,app.tile_h)
464 #next version of pygame?
465 #app.clipboard = app.tile.subsurface(app.select).copy()
466 s = app.tile.subsurface(app.select)
467 app.clipboard = pygame.Surface((app.select.w,app.select.h),SWSURFACE,s)
468 app.clipboard.fill((0,0,0,0))
469 app.clipboard.blit(s,(0,0))
471 def cmd_paste(value):
472 if app.clipboard != None:
474 app.tile.fill((0,0,0,0),(app.select.x,app.select.y,app.clipboard.get_width(),app.clipboard.get_height()))
475 app.tile.blit(app.clipboard,app.select)
482 def cmd_fullscreen(value):
483 pygame.display.toggle_fullscreen()
485 def cmd_delete(value):
487 app.tile.fill((0,0,0,0),app.select)
492 app.tile.fill(app.color,app.select)
495 #NOTE: this feature is a temporary HACK, to be replaced by
496 #an ellipse tool in the future
497 def cmd_ellipse(value):
499 pygame.draw.ellipse(app.tile,app.color,app.select,1)
502 def cmd_rotate(value):
505 s = pygame.transform.rotate(app.tile,a)
506 app.tile.fill((0,0,0,0))
507 app.tile.blit(s,(0,0))
513 s = pygame.transform.flip(app.tile,fh,fv)
514 app.tile.fill((0,0,0,0))
515 app.tile.blit(s,(0,0))
518 def cmd_tpick(value):
520 off = app.tile.get_offset()
521 app.tpicker.pick((off[0]+dx*app.tile_w,off[1]+dy*app.tile_h))
528 if app.dirty: _dirty(_cmd_load,value)
529 else: _cmd_load(value)
532 def _cmd_load(value):
533 if app.fname == None:
534 ErrorDialog("Load failed","Image is untitled.").open()
539 def cmd_active_save(value):
540 """ we check if we want to save on screen focus...
543 if app.save_activeevent_switch.value:
545 #"is dirty... saving"
546 return cmd_save(value)
549 #"is not dirty, not saving"
555 if app.fname == None:
556 return cmd_saveas(value)
558 # make a temp file... save it there, and then move it in.
559 # so as to avoid race with anything reading it.
561 temp_file_name = "tmp_" + app.fname
564 stim = pygame.image.tostring(app.tiles, "RGB")
565 im=Image.fromstring("RGB", (app.tiles.get_width(),app.tiles.get_height()), stim)
566 im.save(temp_file_name)
568 pygame.image.save(app.tiles,temp_file_name)
569 #move temp file into place.
570 shutil.move(temp_file_name, app.fname)
571 cfg_to_ini(['tile_w','tile_h','palette'],app.fname)
575 ErrorDialog("Save failed.",v).open()
578 def cmd_saveas(value):
579 dialog = SaveAsDialog()
584 fname = vv['fname'].value
586 ErrorDialog("Save As failed.","File Name too short!").open()
589 app.fname = cfg['fname'] = fname
590 return cmd_save(None)
592 dialog.connect(gui.CHANGE,onchange,dialog)
596 if app.dirty: _dirty(_cmd_open,value)
597 else: _cmd_open(value)
600 def _cmd_open(value):
601 dialog = OpenDialog()
609 fname,tile_w,tile_h = vv['fname'].value,int(vv['tile_w'].value),int(vv['tile_h'].value)
612 cfg['tile_w'] = tile_w
613 cfg['tile_h'] = tile_h
616 ErrorDialog("Open failed.",v).open()
618 if ok: raise Restart()
621 dialog.connect(gui.CHANGE,onchange,dialog)
625 class Restart(Exception):
628 dialog = DirtyDialog()
632 dialog.connect(gui.CHANGE,onchange,dialog)
636 if app.dirty: _dirty(_cmd_new,value)
637 else: _cmd_new(value)
648 width,height,tile_w,tile_h = int(vv['width'].value),int(vv['height'].value),int(vv['tile_w'].value),int(vv['tile_h'].value)
652 cfg['height'] = height
653 cfg['tile_w'] = tile_w
654 cfg['tile_h'] = tile_h
657 ErrorDialog("New failed.",v).open()
661 dialog.connect(gui.CHANGE,onchange,dialog)
666 ('File/New',cmd_new,None),
667 ('File/Open',cmd_open,None),
668 ('File/Save',cmd_save,None),
669 ('File/Save As',cmd_saveas,None),
670 ('File/Reload',cmd_load,None),
671 ('File/Quit',cmd_quit,None),
673 ('Edit/Undo',cmd_undo,None),
674 #('Edit/Redo',None,None,None),
675 ('Edit/Cut',cmd_cut,None),
676 ('Edit/Copy',cmd_copy,None),
677 ('Edit/Paste',cmd_paste,None),
678 ('Edit/Delete',cmd_delete,None),
679 ('Edit/Fill',cmd_fill,None),
680 ('Edit/Ellipse',cmd_ellipse,None),
681 ('Edit/Select All',cmd_all,None),
683 ('Transform/Rotate 90 CCW',cmd_rotate,90),
684 ('Transform/Rotate 90 CW',cmd_rotate,-90),
685 ('Transform/Flip Horizontal',cmd_flip,(1,0)),
686 ('Transform/Flip Vertical',cmd_flip,(0,1)),
695 #('Edit/Redo',None,None,None),
697 (K_v,cmd_paste,None),
699 (K_DELETE,cmd_delete,None),
701 (K_e,cmd_ellipse,None),
703 (K_LEFTBRACKET,cmd_rotate,90),
704 (K_RIGHTBRACKET,cmd_rotate,-90),
705 (K_COMMA,cmd_flip,(1,0)),
706 (K_PERIOD,cmd_flip,(0,1)),
708 (K_UP,cmd_tpick,(0,-1)),
709 (K_DOWN,cmd_tpick,(0,1)),
710 (K_LEFT,cmd_tpick,(-1,0)),
711 (K_RIGHT,cmd_tpick,(1,0)),
713 (K_F10,cmd_fullscreen,None),
721 #('ellipse','ellipse'),
729 ini.read([ini_fname])
732 f = open(ini_fname,"wb")
738 usage = "%prog [tiles.tga] [tile_w] [tile_h]"
740 parser = OptionParser(usage)
741 parser.add_option("--sw",dest="screen_w",help="screen width (app)",type='int')
742 parser.add_option("--sh",dest="screen_h",help="screen height (app)",type='int')
743 parser.add_option("--tw",dest="tile_w",help="tile width (image)",type='int')
744 parser.add_option("--th",dest="tile_h",help="tile height (image)",type='int')
745 parser.add_option("--width",dest="width",help="new width (image)",type='int')
746 parser.add_option("--height",dest="height",help="new height (image)",type='int')
747 parser.add_option("-p","--pal",dest="palette",help="filename of palette (image)")
748 parser.add_option("-d","--defaults",dest="defaults",help="set default settings (image)",action="store_true")
749 #parser.add_option("-a","--app",dest="app",help="set application level defaults",action="store_true")
751 (opts,args) = parser.parse_args()
753 if len(args) > 3: parser.error("incorrect number of arguments")
762 try: opts.tile_w,opts.tile_h = int(args[0]),int(args[1])
763 except: parser.error("tile width and height must be integers")
764 if opts.tile_w < 1 or opts.tile_h < 1: parser.error("width and height must be greater than 0")
766 try: opts.fname,opts.tile_w,opts.tile_h = args[0],int(args[1]),int(args[2])
767 except: parser.error("tile width and height must be integers")
768 if opts.tile_w < 1 or opts.tile_h < 1: parser.error("width and height must be greater than 0")
773 for k in [fname,"None","app"]:
774 if not ini.has_section(k):
777 #set app level defaults
778 for k,v in [('screen_w',800),('screen_h',600)]:
779 if not ini.has_option('app',k):
780 ini.set('app',k,str(v))
782 #set app level values
783 for k in ['screen_w','screen_h']:
786 if v != None: ini.set('app',k,str(v))
788 #set default defaults
789 for k,v in [('width',256),('height',256),('tile_w',32),('tile_h',32),('palette','palette.tga')]:
790 if not ini.has_option('None',k):
791 ini.set('None',k,str(v))
793 #name of keys for normal stuff
794 file_ks = ['width','height','tile_w','tile_h','palette']
801 if v != None: ini.set('None',k,str(v))
807 if v != None: ini.set(fname,k,str(v))
812 #convert ini to cfg stuff...
813 ini_to_cfg(['app','None',fname])
814 if fname == 'None': fname = None
818 def ini_to_cfg(sections):
820 ik = ['screen_w','screen_h','tile_w','tile_h','width','height']
822 for k,v in ini.items(s):
823 if k in ik: v = int(v)
825 def ini_to_dict(section):
827 ik = ['screen_w','screen_h','tile_w','tile_h','width','height']
829 for k,v in ini.items(s):
830 if k in ik: v = int(v)
834 def cfg_to_ini(ks,section):
835 if not ini.has_section(section): ini.add_section(section)
838 ini.set(section,k,str(v))
842 #themes = cfg['theme'].split(",")
843 #gui.theme.load(themes)
844 #gui.theme.load(['default','tools'])
846 top = gui.Desktop(theme=gui.Theme(['default','tools']))
849 #top.theme.load(['default','tools'])
867 e.rect.w,e.rect.h = e.resize()
869 x,h = x+e.rect.w,max(h,e.rect.h)
870 menus_height = e.rect.h
882 e = gui.Toolbox(tools,1,0,value='draw') #,"icons48")
883 e.rect.w,e.rect.h = e.resize()
884 def _set_mode(value):
885 cmd_mode(value.value)
886 e.connect(gui.CHANGE,_set_mode,e)
894 #--- switchbox for saving.
895 sx, sy = x,y+(max(h,e.rect.h))
897 savelabel = gui.Label("Save on")
898 app.add(savelabel, sx,sy)
899 savelabel2 = gui.Label("focus:")
900 app.add(savelabel2, sx,sy+(ss*2))
906 save_activeevent_switch = gui.Switch(False)
907 app.add(save_activeevent_switch, sx,sy)
908 app.save_activeevent_switch = save_activeevent_switch
910 x,h = x+e.rect.w,max(h,e.rect.h)
911 toolbox_width = e.rect.w
915 y -= ss*6 #undo what was done above to the y val
919 dw = app.screen_w - (toolbox_width+app.tiles.get_width()+ss*4)
920 dh = app.screen_h - (menus_height+colors_height+ss*2)
921 if dw/float(app.tile_w) > dh/float(app.tile_h): dw = dh/float(app.tile_h)*app.tile_w
922 else: dh = dw/float(app.tile_w)*app.tile_h
923 e = app.tdraw = tdraw(dw,dh)
925 x,h = x+e.rect.w,max(h,e.rect.h)
931 e = app.tpicker = tpicker()
932 e.rect.w,e.rect.h = e.resize()
934 x = app.screen_w-e.rect.w-ss
940 e = app.tpreview = tpreview()
941 e.rect.w,e.rect.h = e.resize()
945 x,y,h = 0,app.screen_h - colors_height,0
948 colors_width = toolbox_width + ss * 2
949 e = app.cpreview = cpreview(colors_width,colors_height)
950 e.rect.w,e.rect.h = e.resize()
952 x,h = x+e.rect.w,max(h,e.rect.h)
955 if os.path.isfile(cfg['palette']):
956 pal = pygame.image.load(cfg['palette'])
958 #default to EGA / NES palette
961 pdata = [(0, 0, 0, 255), (0, 0, 170, 255), (0, 170, 0, 255), (0, 170, 170, 255), (170, 0, 0, 255), (170, 0, 170, 255), (170, 85, 0, 255), (170, 170, 170, 255), (85, 85, 85, 255), (85, 85, 255, 255), (85, 255, 85, 255), (85, 255, 255, 255), (255, 85, 85, 255), (255, 85, 255, 255), (255, 255, 85, 255), (255, 255, 255, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255), (255, 255, 255, 255), (173, 243, 255, 255), (223, 214, 255, 255), (255, 190, 255, 255), (255, 176, 255, 255), (255, 177, 237, 255), (255, 191, 185, 255), (255, 217, 145, 255), (237, 246, 128, 255), (185, 255, 138, 255), (145, 255, 173, 255), (128, 255, 223, 255), (138, 255, 255, 255), (197, 197, 197, 255), (0, 0, 0, 255), (0, 0, 0, 255), (255, 255, 255, 255), (129, 200, 255, 255), (179, 171, 255, 255), (231, 146, 255, 255), (255, 132, 244, 255), (255, 133, 194, 255), (255, 148, 141, 255), (244, 173, 101, 255), (194, 202, 84, 255), (141, 227, 94, 255), (101, 240, 129, 255), (84, 240, 179, 255), (94, 225, 231, 255), (120, 120, 120, 255), (0, 0, 0, 255), (0, 0, 0, 255), (192, 192, 192, 255), (57, 128, 200, 255), (108, 99, 217, 255), (160, 74, 207, 255), (200, 61, 172, 255), (217, 61, 122, 255), (207, 76, 70, 255), (172, 102, 30, 255), (122, 130, 13, 255), (70, 155, 23, 255), (30, 169, 57, 255), (13, 168, 108, 255), (23, 153, 160, 255), (61, 61, 61, 255), (0, 0, 0, 255), (0, 0, 0, 255), (128, 128, 128, 255), (16, 87, 159, 255), (67, 58, 176, 255), (119, 34, 166, 255), (159, 20, 131, 255), (176, 20, 81, 255), (166, 35, 29, 255), (131, 61, 0, 255), (81, 89, 0, 255), (29, 114, 0, 255), (0, 128, 16, 255), (0, 127, 67, 255), (0, 112, 119, 255), (0, 0, 0, 255), (0, 0, 0, 255), (0, 0, 0, 255)]
963 pal = pygame.Surface((pw,ph),SWSURFACE,32)
965 for py in range(0,ph):
966 for px in range(0,pw):
967 pal.set_at((px,py),pdata[n])
971 e = app.cpicker = cpicker(app.screen_w-colors_width,colors_height,pal)
972 e.rect.w,e.rect.h = e.resize()
974 x,h = x+e.rect.w,max(h,e.rect.h)
976 pygame.key.set_repeat(500,30)
978 app.screen.fill((255,255,255,255))
980 class NewDialog(gui.Dialog):
981 def __init__(self,**params):
982 title = gui.Label("New...")
984 doc = html.HTML(globals={'gui':gui,'dialog':self},data="""<form id='form'><table>
986 <td align=center>Image Size
987 <td align=center>Tile Size
989 <tr><td colspan='1' align='center' style='padding-right:8px;'><table>
990 <tr><td align=right>Width: <td><input type='text' size='4' value='%(width)s' name='width'>
991 <tr><td align=right>Height: <td><input type='text' size='4' value='%(height)s' name='height'>
994 <td colspan='1' align='center'><table>
995 <tr><td align=right>Width: <td><input type='text' size='4' value='%(tile_w)s' name='tile_w'>
996 <tr><td align=right>Height: <td><input type='text' size='4' value='%(tile_h)s' name='tile_h'>
999 <tr><td colspan=2>Palette: <input type='text' size=20 name='palette' value='%(palette)s'>
1003 <tr><td colspan=2><input type='button' value='Okay' onclick='dialog.send(gui.CHANGE)'> <input type='button' value='Cancel' onclick='dialog.close()'>
1005 </table>"""%ini_to_dict('None'))
1006 gui.Dialog.__init__(self,title,doc)
1008 self.value = doc['form']
1010 class SaveAsDialog(gui.Dialog):
1011 def __init__(self,**params):
1012 title = gui.Label("Save As...")
1014 doc = html.HTML(globals={'gui':gui,'dialog':self},data="""
1019 <tr><td colspan=2>File Name: <input type='file' size=20 name='fname' value=''>
1023 <tr><td colspan=2><input type='button' value='Okay' onclick='dialog.send(gui.CHANGE)'> <input type='button' value='Cancel' onclick='dialog.close()'>
1026 gui.Dialog.__init__(self,title,doc)
1028 self.value = doc['form']
1030 class OpenDialog(gui.Dialog):
1031 def __init__(self,**params):
1032 title = gui.Label("Open...")
1034 def load_vals(fname,form):
1035 if not ini.has_section(fname): return
1037 for k,v in ini.items(fname):
1040 doc = html.HTML(globals={'load_vals':load_vals,'ini':ini,'gui':gui,'dialog':self},data="""<form id='form'><table>
1042 <tr><td align=right>File Name: <td align=left><input type='file' size=20 name='fname' value='' onchange='load_vals(self.value,form)'>
1043 <tr><td align=right>Tile Width: <td align=left><input type='text' size='4' value='%(tile_w)s' name='tile_w'>
1044 <tr><td align=right>Tile Height: <td align=left><input type='text' size='4' value='%(tile_h)s' name='tile_h'>
1046 <tr><td align=right>Palette: <td align=left><input type='text' size=20 name='palette' value='%(palette)s'>
1050 <tr><td colspan=2><input type='button' value='Okay' onclick='dialog.send(gui.CHANGE)'> <input type='button' value='Cancel' onclick='dialog.close()'>
1052 </table>"""%ini_to_dict('None'))
1053 gui.Dialog.__init__(self,title,doc)
1055 self.value = doc['form']
1057 class ErrorDialog(gui.Dialog):
1058 def __init__(self,tt,data,**params):
1059 title = gui.Label("Error: "+tt)
1062 doc = html.HTML(globals={'gui':gui,'dialog':self},data="""
1066 <tr><td><h1><!> </h1>
1069 <tr><td colspan=2><input type='button' value='Okay' onclick='dialog.send(gui.CHANGE);dialog.close()'>
1071 gui.Dialog.__init__(self,title,doc)
1073 self.value = doc['form']
1075 class DirtyDialog(gui.Dialog):
1076 def __init__(self,**params):
1077 title = gui.Label("File not yet saved...")
1078 data = "Your file is not yet saved.<br>Are you sure you want to continue?"
1080 doc = html.HTML(globals={'gui':gui,'dialog':self},data="""
1084 <tr><td><h1><!> </h1>
1087 <tr><td colspan=2><input type='button' value='Okay' onclick='dialog.send(gui.CHANGE)'> <input type='button' value='Cancel' onclick='dialog.close()'>
1089 gui.Dialog.__init__(self,title,doc)
1091 self.value = doc['form']
1096 #top.connect(gui.QUIT,top.quit,None)
1097 top.connect(gui.QUIT,cmd_quit,None)
1098 top.connect(pygame.ACTIVEEVENT, cmd_active_save,None)
1099 top.init(app,app.screen)
1115 except Restart: restart = 1
1121 # vim: set filetype=python sts=4 sw=4 noet si :