#!C:\Python32\python.exe """a simple tile editor for pygame

usage: tileedit tiles.tga [tile_w] [tile_h]
windows: python tileedit tiles.tga [tile_w] [tile_h]

options:
  -h, --help            show this help message and exit
  --sw=SCREEN_W         screen width (app)
  --sh=SCREEN_H         screen height (app)
  --tw=TILE_W           tile width (image)
  --th=TILE_H           tile height (image)
  --width=WIDTH         new width (image)
  --height=HEIGHT       new height (image)
  -pPALETTE, --pal=PALETTE
                        filename of palette (image)
  -d, --defaults        set default settings (image)

example:
tileedit tiles.tga 16 16

note:
the editor can only edit tga files.

you may edit default options in tileedit.ini

interface:
- menus for common commands
- toolbox
- tile edit area
    left click to use current tool
    right click to select color
- tile select area
    left click to select a tile
    right click to select any region
- color select area
    click to select a color

keys:
s - save
d - reload

z - undo
x - cut selection
c - copy selection
v - paste clipboard
delete - delete selection
f - fill selection
e - draw ellipse in selection
a - select all

[ - rotate -90
] - rotate +90
, - flip horizontal
. - flip vertical

arrows - change tile
F10 - toggle fullscreen
""" import os,sys from optparse import OptionParser from ConfigParser import ConfigParser import pygame from pygame.locals import * # try: # import Image # have_pil=True # except: # print "import Image failure; PIL not found." # have_pil=False have_pil = False # the following line is not needed if pgl is installed import sys; sys.path.insert(0, "..") import shutil from pgu import gui, html #whatever... ini_fname = "tileedit.ini" ini = ConfigParser() cfg = {} class _app(gui.Container): def __init__(self): gui.Container.__init__(self) #self.cls = "desktop" #self.background = gui.Box(self.style.background) self.screen_w = cfg['screen_w'] self.screen_h = cfg['screen_h'] self.screen = pygame.display.set_mode((self.screen_w,self.screen_h),SWSURFACE) self.fname = cfg['fname'] if self.fname != None: if have_pil==True: im = Image.open(self.fname) mode = im.mode size = im.size data = im.tostring() assert mode in ("RGB", "RGBA") self.tiles = pygame.image.fromstring(data, size, mode) else: self.tiles = pygame.image.load(self.fname) # old tga-only method else: w,h = cfg['width'],cfg['height'] s = pygame.Surface((w,h),SWSURFACE|SRCALPHA,32) s.fill((0,0,0,0)) self.tiles = s self.tiles_w, self.tiles_h = self.tiles.get_width(),self.tiles.get_height() self.tile_w, self.tile_h = cfg['tile_w'],cfg['tile_h'] self.tile = self.tiles.subsurface((0,0,self.tile_w,self.tile_h)) self.color = (255,255,255,255) self.mode = 'draw' self.clipboard = None self.select = Rect(0,0,self.tile_w,self.tile_h) self.history = [] self.dirty = 0 def archive(self): h = self.history if len(h) >= 32: del h[0] c = pygame.Surface((self.tile_w,self.tile_h),SWSURFACE,self.tile) c.fill((0,0,0,0)) c.blit(self.tile,(0,0)) h.append((c,self.tile.get_offset())) self.dirty = 1 def undo(self): if len(self.history) == 0: return c,off = self.history.pop() self.tiles.fill((0,0,0,0),(off[0],off[1],self.tile_w,self.tile_h)) self.tiles.blit(c,off) self.tdraw.repaint() self.tpicker.repaint() self.dirty = 1 def __setattr__(self,k,v): self.__dict__[k] = v if k == 'color': if hasattr(self,'cpreview'): self.cpreview.repaint() if k == 'tile': if hasattr(self,'tdraw'): self.tdraw.repaint() if hasattr(self,'tpicker'): self.tpicker.repaint() if hasattr(self,'tpreview'): self.tpreview.repaint() def event(self,e): if e.type is KEYDOWN: for key,cmd,value in keys: if e.key == key: cmd(value) return return gui.Container.event(self,e) class cpreview(gui.Widget): def __init__(self,w,h): gui.Widget.__init__(self) self.style.width = w self.style.height = h def paint(self,s): s.fill((128,128,128)) s.fill(app.color) class cpicker(gui.Widget): def __init__(self,w,h,pal): gui.Widget.__init__(self) self.style.width = w self.style.height = h self.palette = pal self.palette_w = pal.get_width() self.palette_h = pal.get_height() def paint(self,s): s.blit(pygame.transform.scale(self.palette,(self.rect.w,self.rect.h)),(0,0)) def event(self,e): if (e.type is MOUSEBUTTONDOWN) or (e.type is MOUSEMOTION and e.buttons[0] == 1 and self.container.myfocus == self): x,y = e.pos[0]*self.palette_w/self.rect.w,e.pos[1]*self.palette_h/self.rect.h x,y = max(0,x),max(0,y) x,y = min(self.palette_w-1,x),min(self.palette_h-1,y) app.color = self.palette.get_at((x,y)) class tpicker(gui.Widget): def __init__(self): gui.Widget.__init__(self) self.style.width = app.tiles_w self.style.height = app.tiles_h def paint(self,s): s.fill((128,128,128)) s.blit(app.tiles,(0,0)) off = app.tile.get_offset() pygame.draw.rect(s,(255,255,255),(off[0],off[1],app.tile_w,app.tile_h),2) def pick(self,pos): x,y = pos while x < 0: x += self.rect.w while y < 0: y += self.rect.h while x >= self.rect.w: x -= self.rect.w while y >= self.rect.h: y -= self.rect.h app.tile = app.tiles.subsurface((x,y,app.tile_w,app.tile_h)) def event(self,e): if (e.type is MOUSEBUTTONDOWN and e.button == 1) or (e.type is MOUSEMOTION and e.buttons[0] == 1 and self.container.myfocus == self): x,y = e.pos[0]/app.tile_w*app.tile_w,e.pos[1]/app.tile_h*app.tile_h self.pick((x,y)) if (e.type is MOUSEBUTTONDOWN and e.button == 3) or (e.type is MOUSEMOTION and e.buttons[2] == 1 and self.container.myfocus == self): x,y = e.pos[0]-app.tile_w/2,e.pos[1]-app.tile_h/2 x = min(self.rect.w-app.tile_w-1,max(0,x)) y = min(self.rect.h-app.tile_h-1,max(0,y)) self.pick((x,y)) class tpreview(gui.Widget): def __init__(self): gui.Widget.__init__(self) self.style.width = app.tile_w*3 self.style.height = app.tile_h*3 def paint(self, s): atw = app.tile_w ath = app.tile_h s.fill((100,100,100)) s.blit(app.tile,(0,0)) s.blit(app.tile,(1*atw,0)) s.blit(app.tile,(2*atw,0)) s.blit(app.tile,(0,1*ath)) s.blit(app.tile,(1*atw,1*ath)) s.blit(app.tile,(2*atw,1*ath)) s.blit(app.tile,(0,2*ath)) s.blit(app.tile,(1*atw,2*ath)) s.blit(app.tile,(2*atw,2*ath)) class tdraw(gui.Widget): def __init__(self,w,h): gui.Widget.__init__(self) self.rect.w = self.style.width = w self.rect.h = self.style.height = h self.overlay = pygame.Surface((app.tile_w,app.tile_h)).convert_alpha() self.overlay.fill((0,0,0,0)) s = pygame.Surface((self.rect.w,self.rect.h)) clrs = [(148,148,148),(108,108,108)] for y in range(0,app.tile_h*2): for x in range(0,app.tile_w*2): s.fill(clrs[(x+y)%2],( self.rect.w*x/(app.tile_w*2), self.rect.h*y/(app.tile_h*2), self.rect.w/(app.tile_w*2)+1, self.rect.h/(app.tile_h*2)+2)) self.bg = s s = pygame.Surface((self.rect.w,self.rect.h)).convert_alpha() s.fill((0,0,0,0)) for x in range(0,app.tile_w): 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)) for y in range(0,app.tile_h): 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)) self.grid = s def paint(self,s): s.blit(self.bg,(0,0)) s.blit(pygame.transform.scale(app.tile,(self.rect.w,self.rect.h)),(0,0)) s.blit(pygame.transform.scale(self.overlay,(self.rect.w,self.rect.h)),(0,0)) #if app.mode == 'select': s.blit(self.grid,(0,0)) r = app.select 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) def event(self,e): if (e.type is MOUSEBUTTONDOWN and e.button == 3) or (e.type is MOUSEMOTION and e.buttons[2]==1 and self.container.myfocus == self): self.picker_down(e) if e.type is MOUSEBUTTONDOWN and e.button == 1: a = '%s_down'%app.mode if hasattr(self,a): getattr(self,a)(e) if e.type is MOUSEMOTION and e.buttons[0] and self.container.myfocus == self: a = '%s_drag'%app.mode if hasattr(self,a): getattr(self,a)(e) if e.type is MOUSEBUTTONUP and e.button == 1: a = '%s_up'%app.mode if hasattr(self,a): getattr(self,a)(e) #picker def picker_down(self,e): pos = self.getpos(e) c = app.tile.get_at(pos) app.color = c #fill def fill_down(self,e): app.archive() pos = self.getpos(e) bg = app.tile.get_at(pos) if bg == app.color: return self.fill_pixel(pos,bg) self.repaint() def fill_pixel(self,pos,bg): #worst algorithm c = app.tile.get_at(pos) if c != bg: return app.tile.set_at(pos,app.color) x,y = pos if x > 0: self.fill_pixel((x-1,y),bg) if x < app.tile_w-1: self.fill_pixel((x+1,y),bg) if y > 0: self.fill_pixel((x,y-1),bg) if y < app.tile_h-1: self.fill_pixel((x,y+1),bg) #pixel def pixel_down(self,e): app.archive() pos = self.getpos(e) app.tile.set_at(pos,app.color) self.repaint() #line def line_down(self,e): pos = self.getpos(e) self.pos = pos def line_drag(self,e): self.overlay.fill((0,0,0,0)) pos = self.getpos(e) pygame.draw.line(self.overlay,app.color,self.pos,pos) self.repaint() def line_up(self,e): app.archive() self.overlay.fill((0,0,0,0)) pos = self.getpos(e) pygame.draw.line(app.tile,app.color,self.pos,pos) self.repaint() #ellipse def ellipse_down(self,e): pos = self.getpos(e) self.pos = pos def ellipse_drag(self,e): self.overlay.fill((0,0,0,0)) pos = self.getpos(e) r = pygame.Rect(self.pos[0],self.pos[1],pos[0]-self.pos[0],pos[1]-self.pos[1]) r.normalize() r.width += 1 r.height += 1 r.width,r.height = max(2,r.width),max(2,r.height) pygame.draw.ellipse(self.overlay,app.color,r,1) self.repaint() def ellipse_up(self,e): app.archive() self.overlay.fill((0,0,0,0)) pos = self.getpos(e) r = pygame.Rect(self.pos[0],self.pos[1],pos[0]-self.pos[0],pos[1]-self.pos[1]) r.normalize() r.width += 1 r.height += 1 r.width,r.height = max(2,r.width),max(2,r.height) pygame.draw.ellipse(app.tile,app.color,r,1) self.repaint() #draw def draw_down(self,e): app.archive() pos = self.getpos(e) app.tile.set_at(pos,app.color) self.pos = pos self.repaint() def draw_drag(self,e): pos = self.getpos(e) pygame.draw.line(app.tile,app.color,self.pos,pos) self.pos = pos self.repaint() def getpos(self,e): x,y = (e.pos[0])*app.tile_w/self.rect.w,(e.pos[1])*app.tile_h/self.rect.h x = min(max(0,x),app.tile_w-1) y = min(max(0,y),app.tile_h-1) return x,y def getpos2(self,e): w = self.rect.w/app.tile_w h = self.rect.h/app.tile_h x,y = (e.pos[0]+w/2)*app.tile_w/self.rect.w,(e.pos[1]+h/2)*app.tile_h/self.rect.h x = min(max(0,x),app.tile_w) y = min(max(0,y),app.tile_h) return x,y #select def select_down(self,e): pos = self.getpos2(e) app.select = Rect(pos[0],pos[1],0,0) self.repaint() def select_drag(self,e): pos = self.getpos2(e) #pos = (e.pos[0]+app.tile_w/2)/app.tile_w,(e.pos[1]+app.tile_h/2)/app.tile_h app.select = Rect(app.select.x,app.select.y,pos[0]-app.select.x,pos[1]-app.select.y) app.select.w = max(0,app.select.w) app.select.h = max(0,app.select.h) #print app.select self.repaint() #eraser def eraser_down(self,e): app.archive() pos = self.getpos(e) app.tile.set_at(pos,(0,0,0,0)) self.pos = pos self.repaint() def eraser_drag(self,e): pos = self.getpos(e) pygame.draw.line(app.tile,(0,0,0,0),self.pos,pos) self.pos = pos self.repaint() def cmd_quit(value): if app.dirty: _dirty(_cmd_quit,value) else: _cmd_quit(value) def _cmd_quit(value): app.top.quit() def cmd_all(value): app.select = Rect(0,0,app.tile_w,app.tile_h) app.tdraw.repaint() def cmd_undo(value): app.undo() def cmd_redo(value): pass def cmd_copy(value): #next version of pygame? #app.clipboard = app.tile.subsurface(app.select).copy() s = app.tile.subsurface(app.select) app.clipboard = pygame.Surface((app.select.w,app.select.h),SWSURFACE,s) app.clipboard.fill((0,0,0,0)) app.clipboard.blit(s,(0,0)) def cmd_paste(value): if app.clipboard != None: app.archive() app.tile.fill((0,0,0,0),(app.select.x,app.select.y,app.clipboard.get_width(),app.clipboard.get_height())) app.tile.blit(app.clipboard,app.select) app.tdraw.repaint() def cmd_cut(value): cmd_copy(value) cmd_delete(value) def cmd_fullscreen(value): pygame.display.toggle_fullscreen() def cmd_delete(value): app.archive() app.tile.fill((0,0,0,0),app.select) app.tdraw.repaint() def cmd_fill(value): app.archive() app.tile.fill(app.color,app.select) app.tdraw.repaint() #NOTE: this feature is a temporary HACK, to be replaced by #an ellipse tool in the future def cmd_ellipse(value): app.archive() pygame.draw.ellipse(app.tile,app.color,app.select,1) app.tdraw.repaint() def cmd_rotate(value): a = value app.archive() s = pygame.transform.rotate(app.tile,a) app.tile.fill((0,0,0,0)) app.tile.blit(s,(0,0)) app.tdraw.repaint() def cmd_flip(value): fh,fv = value app.archive() s = pygame.transform.flip(app.tile,fh,fv) app.tile.fill((0,0,0,0)) app.tile.blit(s,(0,0)) app.tdraw.repaint() def cmd_tpick(value): dx,dy = value off = app.tile.get_offset() app.tpicker.pick((off[0]+dx*app.tile_w,off[1]+dy*app.tile_h)) def cmd_mode(value): mode = value app.mode = mode def cmd_load(value): if app.dirty: _dirty(_cmd_load,value) else: _cmd_load(value) def _cmd_load(value): if app.fname == None: ErrorDialog("Load failed","Image is untitled.").open() return raise Restart() def cmd_active_save(value): """ we check if we want to save on screen focus... """ if app.save_activeevent_switch.value: if app.dirty: #"is dirty... saving" return cmd_save(value) else: pass #"is not dirty, not saving" def cmd_save(value): if app.fname == None: return cmd_saveas(value) try: # make a temp file... save it there, and then move it in. # so as to avoid race with anything reading it. temp_file_name = "tmp_" + app.fname print temp_file_name if have_pil==True: stim = pygame.image.tostring(app.tiles, "RGB") im=Image.fromstring("RGB", (app.tiles.get_width(),app.tiles.get_height()), stim) im.save(temp_file_name) else: pygame.image.save(app.tiles,temp_file_name) #move temp file into place. shutil.move(temp_file_name, app.fname) cfg_to_ini(['tile_w','tile_h','palette'],app.fname) ini_save() app.dirty = 0 except Exception, v: ErrorDialog("Save failed.",v).open() return def cmd_saveas(value): dialog = SaveAsDialog() def onchange(value): value.close() vv = value.value fname = vv['fname'].value if len(fname) == 0: ErrorDialog("Save As failed.","File Name too short!").open() return global cfg app.fname = cfg['fname'] = fname return cmd_save(None) dialog.connect(gui.CHANGE,onchange,dialog) dialog.open() def cmd_open(value): if app.dirty: _dirty(_cmd_open,value) else: _cmd_open(value) def _cmd_open(value): dialog = OpenDialog() def onchange(value): value.close() vv = value.value ok = 0 try: fname,tile_w,tile_h = vv['fname'].value,int(vv['tile_w'].value),int(vv['tile_h'].value) global cfg cfg['fname'] = fname cfg['tile_w'] = tile_w cfg['tile_h'] = tile_h ok = 1 except Exception,v: ErrorDialog("Open failed.",v).open() if ok: raise Restart() dialog.connect(gui.CHANGE,onchange,dialog) dialog.open() class Restart(Exception): pass def _dirty(fnc,v): dialog = DirtyDialog() def onchange(value): value.close() return fnc(v) dialog.connect(gui.CHANGE,onchange,dialog) dialog.open() def cmd_new(value): if app.dirty: _dirty(_cmd_new,value) else: _cmd_new(value) def _cmd_new(value): dialog = NewDialog() def onchange(value): value.close() vv = value.value ok = 0 try: width,height,tile_w,tile_h = int(vv['width'].value),int(vv['height'].value),int(vv['tile_w'].value),int(vv['tile_h'].value) global cfg cfg['fname'] = None cfg['width'] = width cfg['height'] = height cfg['tile_w'] = tile_w cfg['tile_h'] = tile_h ok = 1 except Exception, v: ErrorDialog("New failed.",v).open() if ok: raise Restart() dialog.connect(gui.CHANGE,onchange,dialog) dialog.open() menus = [ ('File/New',cmd_new,None), ('File/Open',cmd_open,None), ('File/Save',cmd_save,None), ('File/Save As',cmd_saveas,None), ('File/Reload',cmd_load,None), ('File/Quit',cmd_quit,None), ('Edit/Undo',cmd_undo,None), #('Edit/Redo',None,None,None), ('Edit/Cut',cmd_cut,None), ('Edit/Copy',cmd_copy,None), ('Edit/Paste',cmd_paste,None), ('Edit/Delete',cmd_delete,None), ('Edit/Fill',cmd_fill,None), ('Edit/Ellipse',cmd_ellipse,None), ('Edit/Select All',cmd_all,None), ('Transform/Rotate 90 CCW',cmd_rotate,90), ('Transform/Rotate 90 CW',cmd_rotate,-90), ('Transform/Flip Horizontal',cmd_flip,(1,0)), ('Transform/Flip Vertical',cmd_flip,(0,1)), ] keys = [ (K_s,cmd_save,None), (K_d,cmd_load,None), (K_a,cmd_all,None), (K_z,cmd_undo,None), #('Edit/Redo',None,None,None), (K_c,cmd_copy,None), (K_v,cmd_paste,None), (K_x,cmd_cut,None), (K_DELETE,cmd_delete,None), (K_f,cmd_fill,None), (K_e,cmd_ellipse,None), (K_LEFTBRACKET,cmd_rotate,90), (K_RIGHTBRACKET,cmd_rotate,-90), (K_COMMA,cmd_flip,(1,0)), (K_PERIOD,cmd_flip,(0,1)), (K_UP,cmd_tpick,(0,-1)), (K_DOWN,cmd_tpick,(0,1)), (K_LEFT,cmd_tpick,(-1,0)), (K_RIGHT,cmd_tpick,(1,0)), (K_F10,cmd_fullscreen,None), ] tools = [ ('draw','draw'), ('pixel','pixel'), ('line','line'), #('ellipse','ellipse'), ('fill','fill'), ('select','select'), ('eraser','eraser'), ] def init_ini(): ini.read([ini_fname]) def ini_save(): f = open(ini_fname,"wb") ini.write(f) f.close() def init_opts(): usage = "%prog [tiles.tga] [tile_w] [tile_h]" parser = OptionParser(usage) parser.add_option("--sw",dest="screen_w",help="screen width (app)",type='int') parser.add_option("--sh",dest="screen_h",help="screen height (app)",type='int') parser.add_option("--tw",dest="tile_w",help="tile width (image)",type='int') parser.add_option("--th",dest="tile_h",help="tile height (image)",type='int') parser.add_option("--width",dest="width",help="new width (image)",type='int') parser.add_option("--height",dest="height",help="new height (image)",type='int') parser.add_option("-p","--pal",dest="palette",help="filename of palette (image)") parser.add_option("-d","--defaults",dest="defaults",help="set default settings (image)",action="store_true") #parser.add_option("-a","--app",dest="app",help="set application level defaults",action="store_true") (opts,args) = parser.parse_args() if len(args) > 3: parser.error("incorrect number of arguments") #parse arguments if len(args) == 0: opts.fname = "None" elif len(args) == 1: opts.fname = args[0] elif len(args) == 2: opts.fname = "None" try: opts.tile_w,opts.tile_h = int(args[0]),int(args[1]) except: parser.error("tile width and height must be integers") if opts.tile_w < 1 or opts.tile_h < 1: parser.error("width and height must be greater than 0") else: try: opts.fname,opts.tile_w,opts.tile_h = args[0],int(args[1]),int(args[2]) except: parser.error("tile width and height must be integers") if opts.tile_w < 1 or opts.tile_h < 1: parser.error("width and height must be greater than 0") fname = opts.fname #create all sections for k in [fname,"None","app"]: if not ini.has_section(k): ini.add_section(k) #set app level defaults for k,v in [('screen_w',800),('screen_h',600)]: if not ini.has_option('app',k): ini.set('app',k,str(v)) #set app level values for k in ['screen_w','screen_h']: if hasattr(opts,k): v = getattr(opts,k) if v != None: ini.set('app',k,str(v)) #set default defaults for k,v in [('width',256),('height',256),('tile_w',32),('tile_h',32),('palette','palette.tga')]: if not ini.has_option('None',k): ini.set('None',k,str(v)) #name of keys for normal stuff file_ks = ['width','height','tile_w','tile_h','palette'] #set default values if opts.defaults: for k in file_ks: if hasattr(opts,k): v = getattr(opts,k) if v != None: ini.set('None',k,str(v)) #set fname values for k in file_ks: if hasattr(opts,k): v = getattr(opts,k) if v != None: ini.set(fname,k,str(v)) #save the ini ini_save() #convert ini to cfg stuff... ini_to_cfg(['app','None',fname]) if fname == 'None': fname = None cfg['fname'] = fname def ini_to_cfg(sections): global cfg ik = ['screen_w','screen_h','tile_w','tile_h','width','height'] for s in sections: for k,v in ini.items(s): if k in ik: v = int(v) cfg[k] = v def ini_to_dict(section): cfg = {} ik = ['screen_w','screen_h','tile_w','tile_h','width','height'] for s in [section]: for k,v in ini.items(s): if k in ik: v = int(v) cfg[k] = v return cfg def cfg_to_ini(ks,section): if not ini.has_section(section): ini.add_section(section) for k in ks: v = cfg[k] ini.set(section,k,str(v)) def init_gui(): #themes = cfg['theme'].split(",") #gui.theme.load(themes) #gui.theme.load(['default','tools']) global top top = gui.Desktop(theme=gui.Theme(['default','tools'])) #top = gui.Desktop() #top.theme.load(['default','tools']) #pass def init_app(): global app app = _app() # colors_height = 64 ss = 8 #--- top x,y,h = 0,0,0 #menus e = gui.Menus(menus) e.rect.w,e.rect.h = e.resize() app.add(e,x,y) x,h = x+e.rect.w,max(h,e.rect.h) menus_height = e.rect.h #--- row x,y,h = 0,y+h,0 #--- vspace y += ss #--- hspace x += ss #tools e = gui.Toolbox(tools,1,0,value='draw') #,"icons48") e.rect.w,e.rect.h = e.resize() def _set_mode(value): cmd_mode(value.value) e.connect(gui.CHANGE,_set_mode,e) app.add(e,x,y) #--- vspace y += ss #--- switchbox for saving. sx, sy = x,y+(max(h,e.rect.h)) savelabel = gui.Label("Save on") app.add(savelabel, sx,sy) savelabel2 = gui.Label("focus:") app.add(savelabel2, sx,sy+(ss*2)) #--- vspace y += (ss *5) sy += (ss *5) save_activeevent_switch = gui.Switch(False) app.add(save_activeevent_switch, sx,sy) app.save_activeevent_switch = save_activeevent_switch x,h = x+e.rect.w,max(h,e.rect.h) toolbox_width = e.rect.w #--- hspace x += ss y -= ss*6 #undo what was done above to the y val #tdraw #tdraw-calcs dw = app.screen_w - (toolbox_width+app.tiles.get_width()+ss*4) dh = app.screen_h - (menus_height+colors_height+ss*2) if dw/float(app.tile_w) > dh/float(app.tile_h): dw = dh/float(app.tile_h)*app.tile_w else: dh = dw/float(app.tile_w)*app.tile_h e = app.tdraw = tdraw(dw,dh) app.add(e,x,y) x,h = x+e.rect.w,max(h,e.rect.h) #--- hspace x += ss #tpicker e = app.tpicker = tpicker() e.rect.w,e.rect.h = e.resize() #--- right x = app.screen_w-e.rect.w-ss app.add(e,x,y) h = max(h,e.rect.h) #tpreview y = y+e.rect.h e = app.tpreview = tpreview() e.rect.w,e.rect.h = e.resize() app.add(e,x,y) #--- bottom x,y,h = 0,app.screen_h - colors_height,0 #cpreview colors_width = toolbox_width + ss * 2 e = app.cpreview = cpreview(colors_width,colors_height) e.rect.w,e.rect.h = e.resize() app.add(e,x,y) x,h = x+e.rect.w,max(h,e.rect.h) #cpicker if os.path.isfile(cfg['palette']): pal = pygame.image.load(cfg['palette']) else: #default to EGA / NES palette pw,ph = 16,6 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)] pal = pygame.Surface((pw,ph),SWSURFACE,32) n=0 for py in range(0,ph): for px in range(0,pw): pal.set_at((px,py),pdata[n]) n+=1 e = app.cpicker = cpicker(app.screen_w-colors_width,colors_height,pal) e.rect.w,e.rect.h = e.resize() app.add(e,x,y) x,h = x+e.rect.w,max(h,e.rect.h) pygame.key.set_repeat(500,30) app.screen.fill((255,255,255,255)) class NewDialog(gui.Dialog): def __init__(self,**params): title = gui.Label("New...") doc = html.HTML(globals={'gui':gui,'dialog':self},data="""
Image Size Tile Size
Width:
Height:
Width:
Height:
Palette:
 
"""%ini_to_dict('None')) gui.Dialog.__init__(self,title,doc) self.value = doc['form'] class SaveAsDialog(gui.Dialog): def __init__(self,**params): title = gui.Label("Save As...") doc = html.HTML(globals={'gui':gui,'dialog':self},data="""
File Name:
 
""") gui.Dialog.__init__(self,title,doc) self.value = doc['form'] class OpenDialog(gui.Dialog): def __init__(self,**params): title = gui.Label("Open...") def load_vals(fname,form): if not ini.has_section(fname): return for k,v in ini.items(fname): if k in form: form[k].value = v doc = html.HTML(globals={'load_vals':load_vals,'ini':ini,'gui':gui,'dialog':self},data="""
File Name: 
Tile Width: 
Tile Height: 
Palette: 
 
"""%ini_to_dict('None')) gui.Dialog.__init__(self,title,doc) self.value = doc['form'] class ErrorDialog(gui.Dialog): def __init__(self,tt,data,**params): title = gui.Label("Error: "+tt) data = str(data) doc = html.HTML(globals={'gui':gui,'dialog':self},data="""

<!> 

"""+data+"""
 
""") gui.Dialog.__init__(self,title,doc) self.value = doc['form'] class DirtyDialog(gui.Dialog): def __init__(self,**params): title = gui.Label("File not yet saved...") data = "Your file is not yet saved.
Are you sure you want to continue?" doc = html.HTML(globals={'gui':gui,'dialog':self},data="""

<!> 

"""+data+"""
 
""") gui.Dialog.__init__(self,title,doc) self.value = doc['form'] def run(): #top.connect(gui.QUIT,top.quit,None) top.connect(gui.QUIT,cmd_quit,None) top.connect(pygame.ACTIVEEVENT, cmd_active_save,None) top.init(app,app.screen) app.top = top top.run() def main(): init_ini() init_opts() init_gui() restart = 1 while restart: restart = 0 try: init_app() run() except Restart: restart = 1 main() # vim: set filetype=python sts=4 sw=4 noet si :