diff --git a/examples/gui17.py b/examples/gui17.py index 7d12284..1943c14 100644 --- a/examples/gui17.py +++ b/examples/gui17.py @@ -36,7 +36,7 @@ def lkey(_event): try: code = compile(val,'','single') eval(code,globals(),_locals) - except: + except Exception: e_type,e_value,e_traceback = sys.exc_info() print('Traceback (most recent call last):') traceback.print_tb(e_traceback,None,s) diff --git a/pgu/__init__.py b/pgu/__init__.py index 7b4558c..8f80f08 100644 --- a/pgu/__init__.py +++ b/pgu/__init__.py @@ -4,6 +4,6 @@ """ -__version__ = '0.18' +__version__ = '0.21.dev0' diff --git a/pgu/ani.py b/pgu/ani.py index 27d6540..e2b3ca5 100644 --- a/pgu/ani.py +++ b/pgu/ani.py @@ -9,51 +9,45 @@ import math import pygame -# Quick fix for python3 -try: - xrange -except: - xrange = range - def _ani_load(tv,name,parts,frames,shape): l = len(frames) n = parts.pop() if len(parts): s = l/n - for i in xrange(0,n): + for i in range(0,n): _ani_load(tv,name + ".%d"%i,parts[:],frames[s*i:s*(i+1)],shape) return - - for i in xrange(0,n): + + for i in range(0,n): tv.images[name+".%d"%i] = frames[i],shape def ani_load(tv,name,img,size,shape,parts): """Load an animation from an image - Arguments: + Arguments: tv -- vid to load into name -- prefix name to give the images image -- image to load anis from size -- w,h size of image shape -- shape of image (usually a subset of 0,0,w,h) used for collision detection - parts -- list of parts to divide the animation into + parts -- list of parts to divide the animation into for example parts = [4,5] would yield 4 animations 5 frames long, 20 total for example parts = [a,b,c] would yield ... images['name.a.b.c'] ..., a*b*c total - + """ parts = parts[:] parts.reverse() w,h = size frames = [] - for y in xrange(0,img.get_height(),h): - for x in xrange(0,img.get_width(),w): + for y in range(0,img.get_height(),h): + for x in range(0,img.get_width(),w): frames.append(img.subsurface(x,y,w,h)) _ani_load(tv,name,parts,frames,shape) - - + + def image_rotate(tv,name,img,shape,angles,diff=0): """Rotate an image and put it into tv.images - + Arguments: tv -- vid to load into name -- prefix name to give the images @@ -75,7 +69,7 @@ def image_rotate(tv,name,img,shape,angles,diff=0): a2 = math.radians(a+diff) #NOTE: the + and - are switched from the normal formula because of #the weird way that pygame does the angle... - x2 = x*math.cos(a2) + y*math.sin(a2) + x2 = x*math.cos(a2) + y*math.sin(a2) y2 = y*math.cos(a2) - x*math.sin(a2) x2,y2 = x2+w2/2,y2+h2/2 minx = min(minx,x2) @@ -85,5 +79,3 @@ def image_rotate(tv,name,img,shape,angles,diff=0): r = pygame.Rect(minx,miny,maxx-minx,maxy-miny) #((ww-w)/2,(hh-h)/2,w,h) tv.images["%s.%d"%(name,a)] = img2,r - - diff --git a/pgu/fonts.py b/pgu/fonts.py index 36d86b7..ec0477c 100644 --- a/pgu/fonts.py +++ b/pgu/fonts.py @@ -9,20 +9,14 @@ import pygame from pygame.locals import * -# Quick fix for python3 -try: - xrange -except: - xrange = range - -class TileFont: - """Creates an instance of the TileFont class. Interface compatible +class TileFont(object): + """Creates an instance of the TileFont class. Interface compatible with pygame.Font - - TileFonts are fonts that are stored in a tiled image. Where the image - opaque, it assumed that the font is visible. Font color is changed + + TileFonts are fonts that are stored in a tiled image. Where the image + opaque, it assumed that the font is visible. Font color is changed automatically, so it does not work with fonts with stylized coloring. - + Arguments: size -- the dimensions of the characters hints -- a string of hints "abcdefg..." @@ -31,104 +25,101 @@ class TileFont: """ - def __init__(self,fname,size,hints,scale=None,sensitive=False): - + def __init__(self, fname, size, hints, scale=None, sensitive=False): + self.image = pygame.image.load(fname) - - w,h = self.image.get_width(),self.image.get_height() - tw,th = size + + w, h = self.image.get_width(), self.image.get_height() + tw, th = size if not scale: scale = size self._size = size self.scale = scale - + self.chars = {} - x,y = 0,0 + x, y = 0, 0 self.sensitive = sensitive if not self.sensitive: hints = hints.lower() for c in hints: - if c not in ('\r','\n','\t'): - img = self.image.subsurface(x,y,tw,th) + if c not in ('\r', '\n', '\t'): + img = self.image.subsurface(x, y, tw, th) self.chars[c] = img x += tw - if x >= w: x,y = 0,y+th - + if x >= w: x, y = 0, y+th + self.colors = {} - - def size(self,text): - tw,th = self.scale - return len(text)*tw,th - - def render(self,text,antialias=0,color=(255,255,255),background=None): + + def size(self, text): + tw, th = self.scale + return len(text)*tw, th + + def render(self, text, antialias=0, color=(255, 255, 255), background=None): size = self.size(text) scale = self.scale - tw,th = self._size + tw, th = self._size if background == None: s = pygame.Surface(size).convert_alpha() - s.fill((0,0,0,0)) + s.fill((0, 0, 0, 0)) else: s = pygame.Surface(size).convert() s.fill(background) - + if not self.sensitive: text = text.lower() - + if color not in self.colors: self.colors[color] = {} colored = self.colors[color] - - x,y = 0,0 + + x, y = 0, 0 for c in text: if c in self.chars: if c not in colored: img = self.chars[c].convert_alpha() - for yy in xrange(0,th): - for xx in xrange(0,tw): - r,g,b,a = img.get_at((xx,yy)) + for yy in range(0, th): + for xx in range(0, tw): + r, g, b, a = img.get_at((xx, yy)) if a > 128: - img.set_at((xx,yy),color) + img.set_at((xx, yy), color) colored[c] = img img = colored[c] - if scale != (tw,th): img = pygame.transform.scale(img,scale) - s.blit(img,(x,y)) + if scale != (tw, th): img = pygame.transform.scale(img, scale) + s.blit(img, (x, y)) x += scale[0] return s - - -class BorderFont: + + +class BorderFont(object): """A decorator for normal fonts, adds a border. Interface compatible with pygame.Font. - + Arguments: size -- width of border; defaults 0 - color -- color of border; default (0,0,0) + color -- color of border; default (0, 0, 0) """ - def __init__(self,font,size=1,color=(0,0,0)): - + def __init__(self, font, size=1, color=(0, 0, 0)): self.font = font self._size = size self.color = color - - def size(self,text): - w,h = self.font.size(text) + + def size(self, text): + w, h = self.font.size(text) s = self._size - return w+s*2,h+s*2 - - def render(self,text,antialias=0,color=(255,255,255),background=None): + return w+s*2, h+s*2 + + def render(self, text, antialias=0, color=(255, 255, 255), background=None): size = self.size(text) - + if background == None: s = pygame.Surface(size).convert_alpha() - s.fill((0,0,0,0)) + s.fill((0, 0, 0, 0)) else: s = pygame.Surface(size).convert() s.fill(background) - - bg = self.font.render(text,antialias,self.color) - fg = self.font.render(text,antialias,color) - - si = self._size - dirs = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] - for dx,dy in dirs: s.blit(bg,(si+dx*si,si+dy*si)) - s.blit(fg,(si,si)) - return s + bg = self.font.render(text, antialias, self.color) + fg = self.font.render(text, antialias, color) + si = self._size + dirs = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)] + for dx, dy in dirs: s.blit(bg, (si+dx*si, si+dy*si)) + s.blit(fg, (si, si)) + return s diff --git a/pgu/gui/__init__.py b/pgu/gui/__init__.py index 0b142d3..1e8cf87 100644 --- a/pgu/gui/__init__.py +++ b/pgu/gui/__init__.py @@ -1,9 +1,9 @@ -"""Modules for creating a widget-based user interface. See the examples folder +"""Modules for creating a widget-based user interface. See the examples folder for sample scripts that use this module.""" import pygame -# The basestring class was removed in Python 3, but we want to keep it to maintain +# The basestring class was removed in Python 3, but we want to keep it to maintain # compatibility with previous versions of python. try: __builtins__["basestring"] @@ -23,7 +23,7 @@ from .table import Table from .document import Document #html -from .area import SlideBox, ScrollArea, List +from .area import SlideBox, ScrollArea, List from .form import Form from .group import Group @@ -41,4 +41,3 @@ from .textarea import TextArea from .deprecated import Toolbox, action_open, action_setvalue, action_quit, action_exec - diff --git a/pgu/gui/basic.py b/pgu/gui/basic.py index 1e4b33a..d0cbe45 100644 --- a/pgu/gui/basic.py +++ b/pgu/gui/basic.py @@ -21,20 +21,10 @@ def parse_color(desc): # Already a color return desc elif (desc and desc[0] == "#"): - # Because of a bug in pygame 1.8.1 we need to explicitly define the + # Because of a bug in pygame 1.8.1 we need to explicitly define the # alpha value otherwise it will default to transparent. if (len(desc) == 7): desc += "FF" - # pygame.Color in python2 doesn't want a unicode string as an argument, - # so we need to check that here and convert to a regular string first. - try: - if (type(desc) == unicode): - desc = str(desc) - except: - # Throws an exception in python3 since it doesn't the 'unicode' - # function. - pass - return pygame.Color(desc) # Determines if the given object is a pygame-compatible color or not @@ -59,13 +49,13 @@ class Spacer(widget.Widget): def __init__(self,width,height,**params): params.setdefault('focusable',False) - widget.Widget.__init__(self,width=width,height=height,**params) - + super(Spacer, self).__init__(width=width,height=height,**params) + class Color(widget.Widget): """A widget that renders as a solid block of color. - - Note the color can be changed by setting the 'value' field, and the + + Note the color can be changed by setting the 'value' field, and the widget will automatically be repainted, eg: c = Color() @@ -76,14 +66,14 @@ class Color(widget.Widget): # The pygame Color instance _value = None - + def __init__(self,value=None,**params): params.setdefault('focusable',False) if value != None: params['value']=value - widget.Widget.__init__(self,**params) - + super(Color, self).__init__(**params) + def paint(self,s): - if hasattr(self,'value') and is_color(self.value): + if hasattr(self,'value') and is_color(self.value): s.fill(self.value) @property @@ -92,7 +82,7 @@ def value(self): @value.setter def value(self, val): - if (isinstance(val, basestring)): + if isinstance(val, str): # Parse the string as a color val = parse_color(val) oldval = self._value @@ -101,7 +91,7 @@ def value(self, val): # Emit a change signal self.send(CHANGE) self.repaint() - + class Label(widget.Widget): """A text label widget.""" @@ -109,15 +99,15 @@ class Label(widget.Widget): def __init__(self, value="", **params): params.setdefault('focusable', False) params.setdefault('cls', 'label') - widget.Widget.__init__(self, **params) + super(Label, self).__init__(**params) self.style.check("font") self.value = value + self.font = self.style.font self.style.width, self.style.height = self.font.size(self.value) - + def paint(self,s): """Renders the label onto the given surface in the upper-left corner.""" - #s.blit(self.font.render(self.value, 1, self.style.color),(0,0)) - s.blit(self.style.font.render(self.value, 1, self.style.color),(0,0)) + s.blit(self.font.render(self.value, 1, self.style.color),(0,0)) def set_text(self, txt): """Set the text of this label.""" @@ -126,35 +116,28 @@ def set_text(self, txt): self.chsize() def set_font(self, font): - """Set the font used to render this label. Obsolete: use label.font instead""" + """Set the font used to render this label.""" self.font = font + # Signal to the application that we need a resize + self.chsize() def resize(self,width=None,height=None): # Calculate the size of the rendered text (self.style.width, self.style.height) = self.font.size(self.value) return (self.style.width, self.style.height) - @property - def font(self): - return self.style.font - - @font.setter - def font(self, font): - self.style.font = font - # Signal to the application that we need a resize - self.chsize() class Image(widget.Widget): """An image widget. The constructor takes a file name or a pygame surface.""" def __init__(self,value,**params): params.setdefault('focusable',False) - widget.Widget.__init__(self,**params) + super(Image, self).__init__(**params) if (not value): raise PguError("Image widget takes a path or pygame surface as first argument") - if (isinstance(value, basestring)): + if isinstance(value, str): # Assume the argument is a path value = pygame.image.load(value) if (not value): @@ -162,19 +145,19 @@ def __init__(self,value,**params): ow,oh = iw,ih = value.get_width(),value.get_height() sw,sh = self.style.width,self.style.height - + if sw and not sh: iw,ih = sw,ih*sw/iw elif sh and not sw: iw,ih = iw*sh/ih,sh elif sw and sh: iw,ih = sw,sh - + if (ow,oh) != (iw,ih): value = pygame.transform.scale(value,(iw,ih)) self.style.width,self.style.height = iw,ih self.value = value - + def paint(self,s): s.blit(self.value,(0,0)) diff --git a/pgu/gui/button.py b/pgu/gui/button.py index 88fe536..0c276b2 100644 --- a/pgu/gui/button.py +++ b/pgu/gui/button.py @@ -11,9 +11,9 @@ class _button(widget.Widget): _value = None def __init__(self,**params): - widget.Widget.__init__(self,**params) + super(_button, self).__init__(**params) self.state = 0 - + def event(self,e): if e.type == ENTER: self.repaint() elif e.type == EXIT: self.repaint() @@ -23,7 +23,7 @@ def event(self,e): if e.key == K_SPACE or e.key == K_RETURN: self.state = 1 self.repaint() - elif e.type == MOUSEBUTTONDOWN: + elif e.type == MOUSEBUTTONDOWN: self.state = 1 self.repaint() elif e.type == KEYUP: @@ -33,7 +33,7 @@ def event(self,e): self._event(sub) #self.event(sub) #self.click() - + self.state = 0 self.repaint() elif e.type == MOUSEBUTTONUP: @@ -41,20 +41,20 @@ def event(self,e): self.repaint() elif e.type == CLICK: self.click() - + self.pcls = "" if self.state == 0 and self.is_hovering(): self.pcls = "hover" if self.state == 1 and self.is_hovering(): self.pcls = "down" - - def click(self): + + def click(self): pass class Button(_button): """A button, buttons can be clicked, they are usually used to set up callbacks. - + Example: w = gui.Button("Click Me") w.connect(gui.CLICK, fnc, value) @@ -65,12 +65,12 @@ class Button(_button): def __init__(self, value=None, **params): """Button constructor, which takes either a string label or widget. - + See Widget documentation for additional style parameters. """ params.setdefault('cls', 'button') - _button.__init__(self, **params) + super(Button, self).__init__(**params) self.value = value @property @@ -79,7 +79,7 @@ def value(self): @value.setter def value(self, val): - if (isinstance(val, basestring)): + if isinstance(val, str): # Allow the choice of font to propagate to the button label params = {} if (self.style.font): @@ -116,20 +116,20 @@ class Switch(_button): def __init__(self,value=False,**params): params.setdefault('cls','switch') - _button.__init__(self,**params) + super(Switch, self).__init__(**params) self.value = value - + img = self.style.off self.style.width = img.get_width() self.style.height = img.get_height() - + def paint(self,s): #self.pcls = "" #if self.container.myhover is self: self.pcls = "hover" if self.value: img = self.style.on else: img = self.style.off s.blit(img,(0,0)) - + @property def value(self): return self._value @@ -141,17 +141,17 @@ def value(self, val): if oldval != val: self.send(CHANGE) self.repaint() - + def click(self): self.value = not self.value -class Checkbox(_button): +class Checkbox(_button): """A type of switch that can be grouped with other checkboxes. - + Example: # The 'value' parameter indicates which checkboxes are on by default g = gui.Group(name='colors',value=['r','b']) - + t = gui.Table() t.tr() t.td(gui.Label('Red')) @@ -164,38 +164,38 @@ class Checkbox(_button): t.td(gui.Checkbox(g,'b')) """ - + def __init__(self,group,value=None,**params): """Checkbox constructor. Keyword arguments: group -- the Group that this checkbox belongs to value -- the initial value (True or False) - + See Widget documentation for additional style parameters. """ params.setdefault('cls','checkbox') - _button.__init__(self,**params) + super(Checkbox, self).__init__(**params) self.group = group self.group.add(self) if self.group.value == None: self.group.value = [] self.value = value - + img = self.style.off self.style.width = img.get_width() self.style.height = img.get_height() - + def paint(self,s): #self.pcls = "" #if self.container.myhover is self: self.pcls = "hover" if self.value in self.group.value: img = self.style.on else: img = self.style.off - + s.blit(img,(0,0)) - + def click(self): if self.value in self.group.value: self.group.value.remove(self.value) @@ -206,10 +206,10 @@ def click(self): class Radio(_button): """A type of switch that can be grouped with other radio buttons, except that only one radio button can be active at a time. - + Example: g = gui.Group(name='colors',value='g') - + t = gui.Table() t.tr() t.td(gui.Label('Red')) @@ -221,33 +221,33 @@ class Radio(_button): t.td(gui.Label('Blue')) t.td(gui.Radio(g,'b')) - """ - + """ + def __init__(self,group=None,value=None,**params): """Radio constructor. - Keyword arguments: + Keyword arguments: group -- the Group this radio button belongs to value -- the initial value (True or False) """ params.setdefault('cls','radio') - _button.__init__(self,**params) + super(Radio, self).__init__(**params) self.group = group self.group.add(self) self.value = value - + img = self.style.off self.style.width = img.get_width() self.style.height = img.get_height() - + def paint(self,s): #self.pcls = "" #if self.container.myhover is self: self.pcls = "hover" if self.group.value == self.value: img = self.style.on else: img = self.style.off s.blit(img,(0,0)) - + def click(self): self.group.value = self.value @@ -256,7 +256,7 @@ class Tool(_button): Example: g = gui.Group(name='colors',value='g') - + t = gui.Table() t.tr() t.td(gui.Tool(g,'Red','r')) @@ -270,58 +270,58 @@ class Tool(_button): def __init__(self,group,widget=None,value=None,**params): #TODO widget= could conflict with module widget """Tool constructor. - Keyword arguments: + Keyword arguments: group -- a gui.Group for the Tool to belong to widget -- a widget to appear on the Tool (similar to a Button) value -- the value """ params.setdefault('cls','tool') - _button.__init__(self,**params) + super(Tool, self).__init__(**params) self.group = group self.group.add(self) self.value = value - + if widget: self.setwidget(widget) - + if self.group.value == self.value: self.pcls = "down" - + def setwidget(self,w): self.widget = w - + def resize(self,width=None,height=None): self.widget.rect.w,self.widget.rect.h = self.widget.resize() #self.widget._resize() #self.rect.w,self.rect.h = self.widget.rect_margin.w,self.widget.rect_margin.h - + return self.widget.rect.w,self.widget.rect.h - + def event(self,e): _button.event(self,e) if self.group.value == self.value: self.pcls = "down" - + def paint(self,s): if self.group.value == self.value: self.pcls = "down" self.widget.paint(surface.subsurface(s,self.widget.rect)) - + def click(self): self.group.value = self.value for w in self.group.widgets: if w != self: w.pcls = "" - + class Icon(_button): """TODO - might be deprecated """ def __init__(self,cls,**params): params['cls'] = cls - _button.__init__(self,**params) + super(Icon, self).__init__(**params) s = self.style.image self.style.width = s.get_width() self.style.height = s.get_height() self.state = 0 - + def paint(self,s): #self.pcls = "" #if self.state == 0 and hasattr(self.container,'myhover') and self.container.myhover is self: self.pcls = "hover" @@ -332,7 +332,7 @@ class Link(_button): """A link, links can be clicked, they are usually used to set up callbacks. Basically the same as the button widget, just text only with a different cls. Made for convenience. - + Example: w = gui.Link("Click Me") w.connect(gui.CLICK,fnc,value) @@ -341,11 +341,10 @@ class Link(_button): def __init__(self,value,**params): params.setdefault('focusable',True) params.setdefault('cls','link') - _button.__init__(self,**params) + super(Link, self).__init__(**params) self.value = value self.font = self.style.font self.style.width, self.style.height = self.font.size(self.value) - + def paint(self,s): s.blit(self.font.render(self.value, 1, self.style.color),(0,0)) - diff --git a/pgu/gui/container.py b/pgu/gui/container.py index e009f7c..0686a69 100644 --- a/pgu/gui/container.py +++ b/pgu/gui/container.py @@ -20,17 +20,17 @@ class Container(widget.Widget): mywindow = None def __init__(self,**params): - widget.Widget.__init__(self,**params) + super(Container, self).__init__(**params) self.widgets = [] self.windows = [] self.toupdate = {} self.topaint = {} - + def update(self,s): updates = [] - + if self.myfocus: self.toupdate[self.myfocus] = self.myfocus - + # Paint all child widgets, skipping over the currently open window (if any) for w in self.topaint: if w is self.mywindow: @@ -40,11 +40,11 @@ def update(self,s): # sub.blit(w._container_bkgr,(0,0)) # Check for the theme alpha hack. This is needed (for now) to accomodate rendering - # images with alpha blending (eg alpha value between fully opaque and fully transparent). - # Normally in PGU when a widget changes state (eg normal to highlighted state) the new + # images with alpha blending (eg alpha value between fully opaque and fully transparent). + # Normally in PGU when a widget changes state (eg normal to highlighted state) the new # widget appearance is rendered directly overtop of the old image. This usually works okay. # - # However, if the images have a different shape, then the new image may fail to + # However, if the images have a different shape, then the new image may fail to # completely paint over the old image, leaving bits behind. As well, if the images use # alpha blending you have a similar situation where the old image isn't completely # covered by the new image (since alpha blending preserves some of the pixel data). The @@ -54,7 +54,7 @@ def update(self,s): # This hack isn't perfect and so it's not enabled by default, but only by # themes that explicitly request it. alpha = pguglobals.app.theme.getstyle("pgu", "", "themealpha") - except StyleError: + except StyleError as e: alpha = False if (alpha): @@ -88,7 +88,7 @@ def update(self,s): w.paint(sub) updates.append(pygame.rect.Rect(w.rect)) - + # Update the child widgets, excluding the open window for w in self.toupdate: if w is self.mywindow: @@ -98,7 +98,7 @@ def update(self,s): for u in us: updates.append(pygame.rect.Rect(u.x + w.rect.x,u.y+w.rect.y,u.w,u.h)) - # Now handle the open window (if any) + # Now handle the open window (if any) if self.mywindow: # Render the window self.mywindow.paint(self.top_surface(s,self.mywindow)) @@ -111,10 +111,10 @@ def update(self,s): u.x + self.mywindow.rect.x, u.y + self.mywindow.rect.y, u.w, u.h)) - + self.topaint = {} self.toupdate = {} - + return updates def repaint(self,w=None): @@ -122,45 +122,45 @@ def repaint(self,w=None): return widget.Widget.repaint(self) self.topaint[w] = w self.reupdate() - + def reupdate(self,w=None): if not w: return widget.Widget.reupdate(self) self.toupdate[w] = w self.reupdate() - + def paint(self,s): self.toupdate = {} self.topaint = {} for w in self.widgets: try: sub = surface.subsurface(s, w.rect) - except: - print('container.paint(): %s not inside %s' % ( - w.__class__.__name__,self.__class__.__name__)) - print(s.get_width(), s.get_height(), w.rect) + except Exception: + print(('container.paint(): %s not inside %s' % ( + w.__class__.__name__,self.__class__.__name__))) + print((s.get_width(), s.get_height(), w.rect)) print("") else: w.paint(sub) for w in self.windows: w.paint(self.top_surface(s,w)) - + def top_surface(self,s,w): x,y = s.get_abs_offset() s = s.get_abs_parent() return surface.subsurface(s,(x+w.rect.x,y+w.rect.y,w.rect.w,w.rect.h)) - + def event(self,e): used = False - + if self.mywindow and e.type == MOUSEBUTTONDOWN: w = self.mywindow if self.myfocus is w: if not w.collidepoint(e.pos): self.blur(w) if not self.myfocus: if w.collidepoint(e.pos): self.focus(w) - + if not self.mywindow: #### by Gal Koren ## @@ -175,7 +175,7 @@ def event(self,e): elif e.type == MOUSEBUTTONDOWN: h = None for w in self.widgets: - if not w.disabled: + if not w.disabled: # Focusable not considered, since that is only for tabs if w.collidepoint(e.pos): h = w @@ -187,25 +187,25 @@ def event(self,e): if self.myfocus: ws = [self.myfocus] else: ws = [] else: ws = self.widgets - + h = None for w in ws: if w.collidepoint(e.pos): h = w - if self.myhover is not w: + if self.myhover is not w: self.enter(w) break if not h and self.myhover: self.exit(self.myhover) w = self.myhover - + if w and w is not self.myfocus: sub = pygame.event.Event(e.type,{ 'buttons':e.buttons, 'pos':(e.pos[0]-w.rect.x,e.pos[1]-w.rect.y), 'rel':e.rel}) used = w._event(sub) - + w = self.myfocus if w: if e.type == MOUSEBUTTONUP or e.type == MOUSEBUTTONDOWN: @@ -234,12 +234,12 @@ def event(self,e): if not used and e.type is KEYDOWN: if e.key is K_TAB and self.myfocus: - if (e.mod&KMOD_SHIFT) == 0: - self.myfocus.next() + if not (e.mod & KMOD_SHIFT): + next(self.myfocus) else: self.myfocus.previous() return True - elif e.key == K_UP: + elif e.key == K_UP: self._move_focus(0,-1) return True elif e.key == K_RIGHT: @@ -256,7 +256,7 @@ def event(self,e): def _move_focus(self,dx_,dy_): myfocus = self.myfocus if not self.myfocus: return - + widgets = self._get_widgets(pguglobals.app) #if myfocus not in widgets: return #widgets.remove(myfocus) @@ -264,12 +264,12 @@ def _move_focus(self,dx_,dy_): widgets.remove(myfocus) rect = myfocus.get_abs_rect() fx,fy = rect.centerx,rect.centery - + def sign(v): if v < 0: return -1 if v > 0: return 1 return 0 - + dist = [] for w in widgets: wrect = w.get_abs_rect() @@ -284,7 +284,7 @@ def sign(v): dist.sort() d,w = dist.pop(0) w.focus() - + def _get_widgets(self,c): widgets = [] if c.mywindow: @@ -303,11 +303,11 @@ def remove(self,w): self.widgets.remove(w) #self.repaint() self.chsize() - + def add(self,w,x,y): """Add a widget to the container given the position.""" w.style.x = x - w.style.y = y + w.style.y = y w.container = self #NOTE: this might fix it, sort of... #but the thing is, we don't really want to resize @@ -317,7 +317,7 @@ def add(self,w,x,y): #w.rect.w, w.rect.h = w.resize() self.widgets.append(w) self.chsize() - + def open(self,w=None,x=None,y=None): if (not w): w = self @@ -330,7 +330,7 @@ def open(self,w=None,x=None,y=None): pos = None # Have the application open the window pguglobals.app.open(w, pos) - + def focus(self,w=None): widget.Widget.focus(self) ### by Gal koren # if not w: @@ -340,9 +340,9 @@ def focus(self,w=None): if self.myhover is not w: self.enter(w) self.myfocus = w w._event(pygame.event.Event(FOCUS)) - + #print self.myfocus,self.myfocus.__class__.__name__ - + def blur(self,w=None): if not w: return widget.Widget.blur(self) @@ -350,35 +350,35 @@ def blur(self,w=None): if self.myhover is w: self.exit(w) self.myfocus = None w._event(pygame.event.Event(BLUR)) - + def enter(self,w): if self.myhover: self.exit(self.myhover) self.myhover = w w._event(pygame.event.Event(ENTER)) - + def exit(self,w): if self.myhover and self.myhover is w: self.myhover = None - w._event(pygame.event.Event(EXIT)) - - + w._event(pygame.event.Event(EXIT)) + + # def first(self): # for w in self.widgets: # if w.focusable: # self.focus(w) # return # if self.container: self.container.next(self) - + # def next(self,w): # if w not in self.widgets: return #HACK: maybe. this happens in windows for some reason... -# +# # for w in self.widgets[self.widgets.index(w)+1:]: # if w.focusable: # self.focus(w) # return # if self.container: return self.container.next(self) - - + + def _next(self,orig=None): start = 0 if orig in self.widgets: start = self.widgets.index(orig)+1 @@ -391,7 +391,7 @@ def _next(self,orig=None): self.focus(w) return True return False - + def _previous(self,orig=None): end = len(self.widgets) if orig in self.widgets: end = self.widgets.index(orig) @@ -406,33 +406,33 @@ def _previous(self,orig=None): self.focus(w) return True return False - + def next(self,w=None): if w != None and w not in self.widgets: return #HACK: maybe. this happens in windows for some reason... - + if self._next(w): return True if self.container: return self.container.next(self) - - + + def previous(self,w=None): if w != None and w not in self.widgets: return #HACK: maybe. this happens in windows for some reason... - + if self._previous(w): return True if self.container: return self.container.previous(self) - + def resize(self,width=None,height=None): #r = self.rect #r.w,r.h = 0,0 ww,hh = 0,0 if self.style.width: ww = self.style.width if self.style.height: hh = self.style.height - + for w in self.widgets: #w.rect.w,w.rect.h = 0,0 w.rect.x,w.rect.y = w.style.x,w.style.y w.rect.w, w.rect.h = w.resize() #w._resize() - + ww = max(ww,w.rect.right) hh = max(hh,w.rect.bottom) return ww,hh diff --git a/pgu/gui/deprecated.py b/pgu/gui/deprecated.py index 7ae03f1..61c65f5 100644 --- a/pgu/gui/deprecated.py +++ b/pgu/gui/deprecated.py @@ -7,56 +7,56 @@ from . import pguglobals def action_open(value): - print('gui.action_open',"Scheduled to be deprecated.") + print(('gui.action_open',"Scheduled to be deprecated.")) value.setdefault('x',None) value.setdefault('y',None) value['container'].open(value['window'],value['x'],value['y']) def action_setvalue(value): - print('gui.action_setvalue',"Scheduled to be deprecated.") + print(('gui.action_setvalue',"Scheduled to be deprecated.")) a,b = value b.value = a.value def action_quit(value): - print('gui.action_quit',"Scheduled to be deprecated.") + print(('gui.action_quit',"Scheduled to be deprecated.")) value.quit() def action_exec(value): - print('gui.action_exec',"Scheduled to be deprecated.") + print(('gui.action_exec',"Scheduled to be deprecated.")) exec(value['script'],globals(),value['dict']) class Toolbox(table.Table): def __setattr__(self,k,v): _v = self.__dict__.get(k,NOATTR) self.__dict__[k]=v - if k == 'value' and _v != NOATTR and _v != v: + if k == 'value' and _v != NOATTR and _v != v: self.group.value = v for w in self.group.widgets: if w.value != v: w.pcls = "" else: w.pcls = "down" self.repaint() - + def _change(self,value): self.value = self.group.value self.send(CHANGE) - + def __init__(self,data,cols=0,rows=0,tool_cls='tool',value=None,**params): - print('gui.Toolbox','Scheduled to be deprecated.') + print(('gui.Toolbox','Scheduled to be deprecated.')) params.setdefault('cls','toolbox') table.Table.__init__(self,**params) - + if cols == 0 and rows == 0: cols = len(data) if cols != 0 and rows != 0: rows = 0 - + self.tools = {} - + _value = value - + g = group.Group() self.group = g g.connect(CHANGE,self._change,None) self.group.value = _value - + x,y,p,s = 0,0,None,1 for ico,value in data: #from __init__ import theme diff --git a/pgu/gui/form.py b/pgu/gui/form.py index c60759b..309c2ed 100644 --- a/pgu/gui/form.py +++ b/pgu/gui/form.py @@ -4,17 +4,17 @@ class Form(widget.Widget): """A form that automatically will contain all named widgets. - - After a form is created, all named widget that are subsequently created are + + After a form is created, all named widget that are subsequently created are added to that form. You may use dict style access to access named widgets. - + Example: f = gui.Form() - + w = gui.Input("Phil",name="firstname") w = gui.Input("Hassey",name="lastname") - + print(f.results()) print('') print(f.items()) @@ -32,22 +32,22 @@ class Form(widget.Widget): _emap = None # The dirty flag is set when a new widget is added to the form _dirty = 0 - + def __init__(self): - widget.Widget.__init__(self,decorate=False) + super(Form, self).__init__(decorate=False) self._elist = [] self._emap = {} self._dirty = 0 # Register this form as the one used by new widgets Form.form = self - + def add(self,e,name=None,value=None): """Adds a PGU widget to this form""" if name != None: e.name = name if value != None: e.value = value self._elist.append(e) self._dirty = 1 - + def _clean(self): # Remove elements from our list if they no longer have an assigned name for e in self._elist[:]: @@ -58,18 +58,18 @@ def _clean(self): for e in self._elist: self._emap[e.name] = e self._dirty = 0 - + def __getitem__(self,k): """Returns the widget instance given the name of the widget""" if self._dirty: self._clean() return self._emap[k] - + def __contains__(self,k): """Returns true if this form contains the named widget""" if self._dirty: self._clean() if k in self._emap: return True return False - + def results(self): """Return a dict of name, widget-value pairs.""" if self._dirty: self._clean() @@ -81,9 +81,7 @@ def results(self): else: r[e.name] = None return r - + def items(self): """Return a list of name, widget pairs.""" - return self.results().items() - - + return list(self.results().items()) diff --git a/pgu/gui/input.py b/pgu/gui/input.py index f43fd2e..b949aff 100644 --- a/pgu/gui/input.py +++ b/pgu/gui/input.py @@ -8,11 +8,11 @@ class Input(widget.Widget): """A single line text input. - + Example: w = Input(value="Cuzco the Goat",size=20) w = Input("Marbles") - + """ _value = None @@ -26,7 +26,7 @@ def __init__(self,value="",size=20,**params): """ params.setdefault('cls','input') - widget.Widget.__init__(self,**params) + super(Input, self).__init__(**params) self.value = value self.pos = len(str(value)) self.vpos = 0 @@ -38,31 +38,31 @@ def __init__(self,value="",size=20,**params): #self.style.width = max(self.style.width,w) #self.rect.w=w+self.style.padding_left+self.style.padding_right; #self.rect.h=h+self.style.padding_top+self.style.padding_bottom; - + def paint(self,s): r = pygame.Rect(0,0,self.rect.w,self.rect.h) - + cs = 2 #NOTE: should be in a style - + w,h = self.font.size(self.value[0:self.pos]) x = w-self.vpos if x < 0: self.vpos -= -x if x+cs > s.get_width(): self.vpos += x+cs-s.get_width() - + s.blit(self.font.render(self.value, 1, self.style.color),(-self.vpos,0)) - + if self.container.myfocus is self: w,h = self.font.size(self.value[0:self.pos]) r.x = w-self.vpos r.w = cs r.h = h s.fill(self.style.color,r) - + def _setvalue(self,v): #self.__dict__['value'] = v self._value = v self.send(CHANGE) - + def event(self,e): used = None if e.type == KEYDOWN: @@ -73,7 +73,7 @@ def event(self,e): elif e.key == K_DELETE: if len(self.value) > self.pos: self._setvalue(self.value[:self.pos] + self.value[self.pos+1:]) - elif e.key == K_HOME: + elif e.key == K_HOME: self.pos = 0 elif e.key == K_END: self.pos = len(self.value) @@ -88,7 +88,6 @@ def event(self,e): elif e.key == K_TAB: pass else: - #c = str(e.unicode) if (type(e.unicode) == str): c = e.unicode else: @@ -98,26 +97,26 @@ def event(self,e): if c: self._setvalue(self.value[:self.pos] + c + self.value[self.pos:]) self.pos += 1 - except: #ignore weird characters + except (TypeError, ValueError): #ignore weird characters pass self.repaint() elif e.type == FOCUS: self.repaint() elif e.type == BLUR: self.repaint() - + self.pcls = "" if self.container.myfocus is self: self.pcls = "focus" - + return used - + @property def value(self): return self._value @value.setter def value(self, val): - if (val == None): + if (val == None): val = "" val = str(val) self.pos = len(val) @@ -131,30 +130,29 @@ def value(self, val): class Password(Input): """A password input, in which text is rendered with '*' characters.""" - def paint(self,s): + def paint(self, s): hidden="*" show=len(self.value)*hidden - + #print "self.value:",self.value if self.pos == None: self.pos = len(self.value) - + r = pygame.Rect(0,0,self.rect.w,self.rect.h) - + cs = 2 #NOTE: should be in a style - + w,h = self.font.size(show) x = w-self.vpos if x < 0: self.vpos -= -x if x+cs > s.get_width(): self.vpos += x+cs-s.get_width() - + s.blit(self.font.render(show, 1, self.style.color),(-self.vpos,0)) - + if self.container.myfocus is self: - #w,h = self.font.size(self.value[0:self.pos]) + #w,h = self.font.size(self.value[0:self.pos]) w,h = self.font.size(show[0:self.pos]) r.x = w-self.vpos r.w = cs r.h = h s.fill(self.style.color,r) - diff --git a/pgu/gui/keysym.py b/pgu/gui/keysym.py index 8589799..d6d74b2 100644 --- a/pgu/gui/keysym.py +++ b/pgu/gui/keysym.py @@ -11,18 +11,18 @@ class Keysym(widget.Widget): _value = None - def __init__(self,value=None,**params): - params.setdefault('cls','keysym') - widget.Widget.__init__(self,**params) + def __init__(self, value=None, **params): + params.setdefault('cls', 'keysym') + super(Keysym, self).__init__(**params) self.value = value - + self.font = self.style.font - w,h = self.font.size("Right Super") #"Right Shift") - self.style.width,self.style.height = w,h + w, h = self.font.size("Right Super") #"Right Shift") + self.style.width, self.style.height = w, h #self.rect.w=w+self.style.padding_left+self.style.padding_right #self.rect.h=h+self.style.padding_top+self.style.padding_bottom - - def event(self,e): + + def event(self, e): used = None if e.type == FOCUS or e.type == BLUR: self.repaint() elif e.type == KEYDOWN: @@ -35,10 +35,10 @@ def event(self,e): self.pcls = "" if self.container.myfocus is self: self.pcls = "focus" return used - - def paint(self,s): - r = pygame.rect.Rect(0,0,self.rect.w,self.rect.h) - #render_box(s,self.style.background,r) + + def paint(self, s): + r = pygame.rect.Rect(0, 0, self.rect.w, self.rect.h) + #render_box(s, self.style.background, r) if self.value == None: return name = "" for p in pygame.key.name(self.value).split(): name += p.capitalize()+" " diff --git a/pgu/gui/menus.py b/pgu/gui/menus.py index 2dfa78d..c538ecb 100644 --- a/pgu/gui/menus.py +++ b/pgu/gui/menus.py @@ -5,17 +5,17 @@ from . import basic, button class _Menu_Options(table.Table): - def __init__(self,menu,**params): - table.Table.__init__(self,**params) - + def __init__(self, menu, **params): + super(_Menu_Options, self).__init__(**params) + self.menu = menu - - def event(self,e): + + def event(self, e): handled = False arect = self.get_abs_rect() - + if e.type == MOUSEMOTION: - abspos = e.pos[0]+arect.x,e.pos[1]+arect.y + abspos = e.pos[0]+arect.x, e.pos[1]+arect.y for w in self.menu.container.widgets: if not w is self.menu: mrect = w.get_abs_rect() @@ -23,61 +23,61 @@ def event(self,e): self.menu._close(None) w._open(None) handled = True - - if not handled: table.Table.event(self,e) + + if not handled: table.Table.event(self, e) class _Menu(button.Button): - def __init__(self,parent,widget=None,**params): #TODO widget= could conflict with module widget - params.setdefault('cls','menu') - button.Button.__init__(self,widget,**params) - + def __init__(self, parent, widget=None, **params): #TODO widget= could conflict with module widget + params.setdefault('cls', 'menu') + super(_Menu, self).__init__(widget, **params) + self.parent = parent - + self._cls = self.cls self.options = _Menu_Options(self, cls=self.cls+".options") - - self.connect(CLICK,self._open,None) - + + self.connect(CLICK, self._open, None) + self.pos = 0 - - def _open(self,value): + + def _open(self, value): self.parent.value = self self.pcls = 'down' - + self.repaint() - self.container.open(self.options,self.rect.x,self.rect.bottom) - self.options.connect(BLUR,self._close,None) + self.container.open(self.options, self.rect.x, self.rect.bottom) + self.options.connect(BLUR, self._close, None) self.options.focus() self.repaint() - - def _pass(self,value): + + def _pass(self, value): pass - - def _close(self,value): + + def _close(self, value): self.pcls = '' self.parent.value = None self.repaint() self.options.close() - - def _valuefunc(self,value): + + def _valuefunc(self, value): self._close(None) if value['fnc'] != None: value['fnc'](value['value']) - - def event(self,e): - button.Button.event(self,e) - + + def event(self, e): + button.Button.event(self, e) + if self.parent.value == self: self.pcls = 'down' - - def add(self,w,fnc=None,value=None): + + def add(self, w, fnc=None, value=None): w.style.align = -1 - b = button.Button(w,cls=self.cls+".option") - b.connect(CLICK,self._valuefunc,{'fnc':fnc,'value':value}) - + b = button.Button(w, cls=self.cls+".option") + b.connect(CLICK, self._valuefunc, {'fnc':fnc, 'value':value}) + self.options.tr() self.options.add(b) - + return b class Menus(table.Table): @@ -95,21 +95,20 @@ class Menus(table.Table): w = Menus(data) """ - - def __init__(self,data,menu_cls='menu',**params): - params.setdefault('cls','menus') - table.Table.__init__(self,**params) - + + def __init__(self, data, menu_cls='menu', **params): + params.setdefault('cls', 'menus') + super().__init__(**params) + self.value = None - - n,m,mt = 0,None,None - for path,cmd,value in data: + + n, m, mt = 0, None, None + for path, cmd, value in data: parts = path.split("/") if parts[0] != mt: mt = parts[0] - m = _Menu(self,basic.Label(mt,cls=menu_cls+".label"),cls=menu_cls) - self.add(m,n,0) + m = _Menu(self, basic.Label(mt, cls=menu_cls+".label"), cls=menu_cls) + self.add(m, n, 0) n += 1 - #print ("add", parts[1], cmd, value) - m.add(basic.Label(parts[1],cls=m.cls+".option.label"),cmd,value) - + print ("add", parts[1], cmd, value) + m.add(basic.Label(parts[1], cls=m.cls+".option.label"), cmd, value) diff --git a/pgu/gui/style.py b/pgu/gui/style.py index cf38b44..6285c1e 100644 --- a/pgu/gui/style.py +++ b/pgu/gui/style.py @@ -5,79 +5,49 @@ from .errors import StyleError class Style(object): - """Widget style information. If the style attribute is not explicitly defined in the - style, the fallback is to use the default defined by the global theme. Example: + """The class used by widget for the widget.style - Arguments: - widget -- The widget this style applies to - values -- A dictionary of style information to use instead of the theme defaults - - Example: - # Create a button - w = Button("Testing") - - # Print out the default value for 'padding_left' - print w.style.padding_left - - # Change the default style for all buttons - app.theme.putstyle("button", "", "padding_left", 10) - print w.style.padding_left - - # Define 'padding_left' only for this widget - w.style.padding_left = 1 - # Alternate syntax - w.style["padding_left"] = 2 + This object is used mainly as a dictionary, accessed via widget.style.attr, + as opposed to widget.style['attr']. It automatically grabs information + from the theme via value = theme.get(widget.cls,widget.pcls,attr) """ - def __init__(self, widget, values): - self.widget = widget - for (key, value) in values.items(): - setattr(self, key, value) + def __init__(self, obj, dict): + self.obj = obj + for k,v in dict.items(): + self.__dict__[k]=v # Verify that the given style is defined, otherwise raises an StyleError exception. This # is used by various widgets to check that they have all required style information. def check(self, attr): if (not self.exists(attr)): - desc = self.widget.cls - if (self.widget.pcls): desc += "."+self.widget.pcls + desc = self.obj.cls + if (self.obj.pcls): desc += "."+self.obj.pcls raise StyleError("Cannot find the style attribute '%s' for '%s'" % (attr, desc)) # Checks if the given style attribute exists def exists(self, attr): try: - self.getstyle(attr) + value = pguglobals.app.theme.getstyle(self.obj.cls, self.obj.pcls, attr) return True except StyleError: return False - def getstyle(self, attr): -# if (attr == "font"): -# print "getstyle", self.widget, self.widget.name - - if (hasattr(self.widget, "name") and self.widget.name): - try: - return pguglobals.app.theme.getstyle(self.widget.cls+"#"+self.widget.name, self.widget.pcls, attr) - except StyleError: - pass - #print "fallback", self.widget.cls, self.widget.pcls, attr - return pguglobals.app.theme.getstyle(self.widget.cls, self.widget.pcls, attr) - def __getattr__(self, attr): # Lookup the attribute try: - value = self.getstyle(attr) + value = pguglobals.app.theme.getstyle(self.obj.cls, self.obj.pcls, attr) except StyleError: value = 0 -# if attr in ( -# 'border_top','border_right','border_bottom','border_left', -# 'padding_top','padding_right','padding_bottom','padding_left', -# 'margin_top','margin_right','margin_bottom','margin_left', -# 'align','valign','width','height', -# ): self.__dict__[attr] = value + if attr in ( + 'border_top','border_right','border_bottom','border_left', + 'padding_top','padding_right','padding_bottom','padding_left', + 'margin_top','margin_right','margin_bottom','margin_left', + 'align','valign','width','height', + ): self.__dict__[attr] = value return value -# def __setattr__(self, attr, value): -# self.__dict__[attr] = value - + def __setattr__(self, attr, value): + self.__dict__[attr] = value diff --git a/pgu/gui/table.py b/pgu/gui/table.py index c47efe7..2ac751d 100644 --- a/pgu/gui/table.py +++ b/pgu/gui/table.py @@ -5,14 +5,13 @@ from .const import * from . import container -from .style import StyleError class Table(container.Container): """A table style container widget. - + Example: t = gui.Table() - + # This starts a new row of the table t.tr() # The 'td' call creates a new table cell @@ -25,131 +24,131 @@ class Table(container.Container): t.tr() t.td(gui.Input(), colspan=2) - + """ - - + + def __init__(self, **params): - params.setdefault('cls','table') - container.Container.__init__(self, **params) + params.setdefault('cls', 'table') + super(Table, self).__init__(**params) self._rows = [] self._curRow = 0 self._trok = False -# self._hpadding = params.get("hpadding", 0) -# self._vpadding = params.get("vpadding", 0) - + self._hpadding = params.get("hpadding", 0) + self._vpadding = params.get("vpadding", 0) + def getRows(self): return len(self._rows) - + def getColumns(self): if self._rows: return len(self._rows[0]) else: return 0 - + def remove_row(self, n): #NOTE: won't work in all cases. if n >= self.getRows(): print("Trying to remove a nonexistant row:", n, "there are only", self.getRows(), "rows") return - + for cell in self._rows[n]: if isinstance(cell, dict) and cell["widget"] in self.widgets: #print 'removing widget' self.widgets.remove(cell["widget"]) del self._rows[n] #print "got here" - + for w in self.widgets: if w.style.row > n: w.style.row -= 1 - + if self._curRow >= n: self._curRow -= 1 - + #self.rect.w, self.rect.h = self.resize() #self.repaint() - + self.chsize() - + def clear(self): self._rows = [] self._curRow = 0 self._trok = False self.widgets = [] - + self.chsize() - - #print 'clear',self,self._rows - + + #print 'clear', self, self._rows + def _addRow(self): self._rows.append([None for x in range(self.getColumns())]) - + def tr(self): """Start on the next row.""" if not self._trok: self._trok = True - return + return self._curRow += 1 if self.getRows() <= self._curRow: self._addRow() - + def _addColumn(self): if not self._rows: self._addRow() for row in self._rows: row.append(None) - + def _setCell(self, w, col, row, colspan=1, rowspan=1): #make room for the widget by adding columns and rows while self.getColumns() < col + colspan: self._addColumn() while self.getRows() < row + rowspan: self._addRow() - - #print w.__class__.__name__,col,row,colspan,rowspan - + + #print w.__class__.__name__, col, row, colspan, rowspan + #actual widget setting and modification stuff w.container = self w.style.row = row #HACK - to work with gal's list w.style.col = col #HACK - to work with gal's list self._rows[row][col] = {"widget":w, "colspan":colspan, "rowspan":rowspan} self.widgets.append(self._rows[row][col]["widget"]) - + #set the spanned columns #for acell in range(col + 1, col + colspan): # self._rows[row][acell] = True - + #set the spanned rows and the columns on them #for arow in range(row + 1, row + rowspan): # for acell in range(col, col + colspan): #incorrect? # self._rows[arow][acell] = True - + for arow in range(row, row + rowspan): for acell in range(col, col + colspan): #incorrect? if row != arow or col != acell: self._rows[arow][acell] = True - - + + def td(self, w, col=None, row=None, colspan=1, rowspan=1, **params): """Add a widget to a table after wrapping it in a TD container. - Keyword arguments: + Keyword arguments: w -- widget col -- column row -- row colspan -- colspan rowspan -- rowspan - align -- horizontal alignment (-1,0,1) - valign -- vertical alignment (-1,0,1) + align -- horizontal alignment (-1, 0, 1) + valign -- vertical alignment (-1, 0, 1) params -- other params for the TD container, style information, etc """ - - Table.add(self,_Table_td(w, **params), col=col, row=row, colspan=colspan, rowspan=rowspan) - + + Table.add(self, _Table_td(w, **params), col=col, row=row, colspan=colspan, rowspan=rowspan) + def add(self, w, col=None, row=None, colspan=1, rowspan=1): """Add a widget directly into the table, without wrapping it in a TD container. - + See Table.td for an explanation of the parameters. """ @@ -158,54 +157,54 @@ def add(self, w, col=None, row=None, colspan=1, rowspan=1): if row is None: row = self._curRow #print row - + #if its going to be a new row, have it be on the first column if row >= self.getRows(): col = 0 - + #try to find an open cell for the widget if col is None: for cell in range(self.getColumns()): if col is None and not self._rows[row][cell]: col = cell break - + #otherwise put the widget in a new column if col is None: col = self.getColumns() - + self._setCell(w, col, row, colspan=colspan, rowspan=rowspan) - + self.chsize() return - - def remove(self,w): - if hasattr(w,'_table_td'): w = w._table_td - row,col = w.style.row,w.style.col + + def remove(self, w): + if hasattr(w, '_table_td'): w = w._table_td + row, col = w.style.row, w.style.col cell = self._rows[row][col] - colspan,rowspan = cell['colspan'],cell['rowspan'] - + colspan, rowspan = cell['colspan'], cell['rowspan'] + for arow in range(row , row + rowspan): for acell in range(col, col + colspan): #incorrect? self._rows[arow][acell] = False self.widgets.remove(w) self.chsize() - - - + + + def resize(self, width=None, height=None): #if 1 or self.getRows() == 82: #print '' - #print 'resize',self.getRows(),self.getColumns(),width,height + #print 'resize', self.getRows(), self.getColumns(), width, height #import inspect - #for obj,fname,line,fnc,code,n in inspect.stack()[9:20]: - # print fname,line,':',fnc,code[0].strip() + #for obj, fname, line, fnc, code, n in inspect.stack()[9:20]: + # print fname, line, ':', fnc, code[0].strip() + - #resize the widgets to their smallest size for w in self.widgets: w.rect.w, w.rect.h = w.resize() - + #calculate row heights and column widths rowsizes = [0 for y in range(self.getRows())] columnsizes = [0 for x in range(self.getColumns())] @@ -216,10 +215,10 @@ def resize(self, width=None, height=None): columnsizes[cell] = max(columnsizes[cell], self._rows[row][cell]["widget"].rect.w) if not self._rows[row][cell]["rowspan"] > 1: rowsizes[row] = max(rowsizes[row], self._rows[row][cell]["widget"].rect.h) - + #distribute extra space if necessary for wide colspanning/rowspanning - def _table_div(a,b,c): - v,r = a/b, a%b + def _table_div(a, b, c): + v, r = a/b, a%b if r != 0 and (c%b) 1: rows = range(row, row + self._rows[row][cell]["rowspan"]) totalheight = 0 @@ -241,21 +240,11 @@ def _table_div(a,b,c): totalheight += rowsizes[arow] if totalheight < self._rows[row][cell]["widget"].rect.h: for arow in rows: - rowsizes[arow] += _table_div(self._rows[row][cell]["widget"].rect.h - totalheight, self._rows[row][cell]["rowspan"],arow) - - # Lookup the style definition for horizontal and vertical cell padding - try: - hpadding = self.style.getstyle("hpadding") - except StyleError: - hpadding = 0 - try: - vpadding = self.style.getstyle("vpadding") - except StyleError: - vpadding = 0 + rowsizes[arow] += _table_div(self._rows[row][cell]["widget"].rect.h - totalheight, self._rows[row][cell]["rowspan"], arow) # Now calculate the total width and height occupied by the rows and columns - rowsizes = [sz+2*vpadding for sz in rowsizes] - columnsizes = [sz+2*hpadding for sz in columnsizes] + rowsizes = [sz+2*self._vpadding for sz in rowsizes] + columnsizes = [sz+2*self._hpadding for sz in columnsizes] # Now possibly expand the table cells to fill out the specified width w = sum(columnsizes) @@ -270,7 +259,7 @@ def _table_div(a,b,c): amount = (self.style.height - h) / float(h) for n in range(0, len(rowsizes)): rowsizes[n] += rowsizes[n] * amount - + #set the widget's position by calculating their row/column x/y offset cellpositions = [[[sum(columnsizes[0:cell]), sum(rowsizes[0:row])] for cell in range(self.getColumns())] for row in range(self.getRows())] for row in range(self.getRows()): @@ -279,59 +268,59 @@ def _table_div(a,b,c): x, y = cellpositions[row][cell] w = sum(columnsizes[cell:cell+self._rows[row][cell]["colspan"]]) h = sum(rowsizes[row:row+self._rows[row][cell]["rowspan"]]) - + widget = self._rows[row][cell]["widget"] widget.rect.x = x widget.rect.y = y - if 1 and (w,h) != (widget.rect.w,widget.rect.h): + if 1 and (w, h) != (widget.rect.w, widget.rect.h): # if h > 20: -# print widget.widget.__class__.__name__, (widget.rect.w,widget.rect.h),'=>',(w,h) +# print widget.widget.__class__.__name__, (widget.rect.w, widget.rect.h), '=>', (w, h) widget.rect.w, widget.rect.h = widget.resize(w, h) - + #print self._rows[row][cell]["widget"].rect - + #print columnsizes #print sum(columnsizes) #size = sum(columnsizes), sum(rowsizes); print size - + #return the tables final size - return sum(columnsizes),sum(rowsizes) + return sum(columnsizes), sum(rowsizes) class _Table_td(container.Container): - def __init__(self,widget,**params):#hexpand=0,vexpand=0, - container.Container.__init__(self,**params) + def __init__(self, widget, **params): #hexpand=0, vexpand=0, + super(_Table_td, self).__init__(**params) self.widget = widget #self.hexpand=hexpand #self.vexpand=vexpand widget._table_td = self - self.add(widget,0,0) - - def resize(self,width=None,height=None): + self.add(widget, 0, 0) + + def resize(self, width=None, height=None): w = self.widget - + #expansion code, but i didn't like the idea that much.. #a bit obscure, fairly useless when a user can just #add a widget to a table instead of td it in. - #ww,hh=None,None + #ww, hh=None, None #if self.hexpand: ww = self.style.width #if self.vexpand: hh = self.style.height - #if self.hexpand and width != None: ww = max(ww,width) - #if self.vexpand and height != None: hh = max(hh,height) - #w.rect.w,w.rect.h = w.resize(ww,hh) - + #if self.hexpand and width != None: ww = max(ww, width) + #if self.vexpand and height != None: hh = max(hh, height) + #w.rect.w, w.rect.h = w.resize(ww, hh) + #why bother, just do the lower mentioned item... - w.rect.w,w.rect.h = w.resize() - + w.rect.w, w.rect.h = w.resize() + #this should not be needed, widgets should obey their sizing on their own. - + # if (self.style.width!=0 and w.rect.w > self.style.width) or (self.style.height!=0 and w.rect.h > self.style.height): -# ww,hh = None,None +# ww, hh = None, None # if self.style.width: ww = self.style.width # if self.style.height: hh = self.style.height -# w.rect.w,w.rect.h = w.resize(ww,hh) - - +# w.rect.w, w.rect.h = w.resize(ww, hh) + + #in the case that the widget is too big, we try to resize it if (width != None and width < w.rect.w) or (height != None and height < w.rect.h): (w.rect.w, w.rect.h) = w.resize(width, height) @@ -339,14 +328,13 @@ def resize(self,width=None,height=None): # In python3 max and min no longer accept None as an argument if (width == None): width = -sys.maxsize if (height == None): height = -sys.maxsize - - width = max(width, w.rect.w, self.style.width) #,self.style.cell_width) - height = max(height, w.rect.h, self.style.height) #,self.style.cell_height) - + + width = max(width, w.rect.w, self.style.width) #, self.style.cell_width) + height = max(height, w.rect.h, self.style.height) #, self.style.cell_height) + dx = width-w.rect.w dy = height-w.rect.h w.rect.x = (self.style.align+1)*dx/2 w.rect.y = (self.style.valign+1)*dy/2 - - return width,height + return width, height diff --git a/pgu/gui/theme.py b/pgu/gui/theme.py index 4710a5d..dd21aaf 100644 --- a/pgu/gui/theme.py +++ b/pgu/gui/theme.py @@ -2,19 +2,10 @@ """ """ - -try: - from StringIO import StringIO -except: - from io import StringIO - import os, re import pygame -try: - from configparser import ConfigParser -except: - from ConfigParser import ConfigParser +from configparser import ConfigParser from .const import * from . import widget @@ -26,41 +17,27 @@ class Theme(object): """Theme interface. - - If you wish to create your own theme, create a class with this interface, and - pass it to gui.App via gui.App(theme=MyTheme()). - - """ - # The cache of style information hashed by the tuple (cls, pcls, attr) where - # cls = the class name (eg button) - # pcls = the psuedo-class name (eg hover) - # attr = the attribute name (eg font) - config = None - - # A cache of previously created font instances hashed by name and size. This is - # maintained in addition to the 'config' cache, since the same font (and size) - # can be used by multiple widgets. - fontCache = None + If you wish to create your own theme, create a class with this interface, and + pass it to gui.App via gui.App(theme=MyTheme()). - # The directory where the loaded theme is located - baseThemePath = None + """ # Image extensions automatically recognized by the theme class image_extensions = (".gif", ".jpg", ".bmp", ".png", ".tga") - def __init__(self,dirs='default'): + def __init__(self, dirs='default'): """Theme constructor. Keyword arguments: - dirs -- Name of the theme dir to load a theme from. May be an - absolute path to a theme, if pgu is not installed, or if you - created your own theme. May include several dirs in a list if + dirs -- Name of the theme dir to load a theme from. May be an + absolute path to a theme, if pgu is not installed, or if you + created your own theme. May include several dirs in a list if data is spread across several themes. - + Example: theme = gui.Theme("default") - theme = gui.Theme(["mytheme","mytheme2"]) + theme = gui.Theme(["mytheme", "mytheme2"]) """ self.config = {} @@ -68,54 +45,44 @@ def __init__(self,dirs='default'): self.cache = {} self._preload(dirs) pygame.font.init() - - def _preload(self,ds): + + def _preload(self, ds): if not isinstance(ds, list): ds = [ds] for d in ds: if d not in self._loaded: self._load(d) self._loaded.append(d) - + def _load(self, name): + #theme_dir = themes[name] + #try to load the local dir, or absolute path dnames = [name] - + #if the package isn't installed and people are just #trying out the scripts or examples - dnames.append(os.path.join(os.path.dirname(__file__),"..","..","data","themes",name)) - + dnames.append(os.path.join(os.path.dirname(__file__), "..", "..", "data", "themes", name)) + #if the package is installed, and the package is installed #in /usr/lib/python2.3/site-packages/pgu/ #or c:\python23\lib\site-packages\pgu\ #the data is in ... lib/../share/ ... - dnames.append(os.path.join(os.path.dirname(__file__),"..","..","..","..","share","pgu","themes",name)) - dnames.append(os.path.join(os.path.dirname(__file__),"..","..","..","..","..","share","pgu","themes",name)) - dnames.append(os.path.join(os.path.dirname(__file__),"..","..","share","pgu","themes",name)) + dnames.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "share", "pgu", "themes", name)) + dnames.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "..", "..", "share", "pgu", "themes", name)) + dnames.append(os.path.join(os.path.dirname(__file__), "..", "..", "share", "pgu", "themes", name)) for dname in dnames: if os.path.isdir(dname): break - if not os.path.isdir(dname): - raise Exception("Could not find theme: %s" % name) + if not os.path.isdir(dname): + raise Exception('could not find theme '+name) # Normalize the path to make it look nicer (gets rid of the ..'s) dname = os.path.normpath(dname) - # Empty the font cache - self.fontCache = {} - - # Try parsing the theme data as an ini file - fname = os.path.join(dname, "style.ini") + # Try parsing the theme in the custom txt file format + fname = os.path.join(dname, "config.txt") if os.path.isfile(fname): - self.baseThemePath = dname - txt = open(fname).read() - self.configure(txt, path=dname) - return - - # Fall back to parsing the theme in the custom txt file format - fname = os.path.join(dname,"config.txt") - if os.path.isfile(fname): - self.baseThemePath = dname try: f = open(fname) for line in f.readlines(): @@ -129,13 +96,29 @@ def _load(self, name): if (":" in cls): (cls, pcls) = cls.split(":") - self.config[cls, pcls, attr] = (dname, " ".join(vals)) + self.config[cls, pcls, attr] = (dname, vals) finally: f.close() return + # Try parsing the theme data as an ini file + fname = os.path.join(dname, "style.ini") + if os.path.isfile(fname): + cfg = ConfigParser() + f = open(fname, 'r') + cfg.readfp(f) + for section in cfg.sections(): + cls = section + pcls = '' + if cls.find(":")>=0: + cls, pcls = cls.split(":") + for attr in cfg.options(section): + vals = cfg.get(section, attr).strip().split() + self.config[cls, pcls, attr] = (dname, vals) + return + # The folder probably doesn't contain a theme - raise IOError("Cannot load theme: missing style.ini") + raise IOError("Cannot load theme: missing style.ini or config.txt") def _get(self, cls, pcls, attr): key = (cls, pcls, attr) @@ -146,146 +129,119 @@ def _get(self, cls, pcls, attr): # This property is already in the cache return self.cache[key] - (dname, value) = self.config[key] + (dname, vals) = self.config[key] - if (os.path.splitext(str(value).lower())[1] in self.image_extensions): + if (os.path.splitext(vals[0].lower())[1] in self.image_extensions): # This is an image attribute - v = pygame.image.load(os.path.join(dname, value)) + v = pygame.image.load(os.path.join(dname, vals[0])) elif (attr == "color" or attr == "background"): # This is a color value - v = parse_color(value) + v = parse_color(vals[0]) elif (attr == "font"): # This is a font value - args = value.split() - name = args[0] - size = int(args[1]) - try: - v = self.fontCache[name, size] - except KeyError: - if (name.lower().endswith(".ttf")): - # Load the font from a file - v = pygame.font.Font(os.path.join(dname, name), size) - else: - # Must be a system font - v = pygame.font.SysFont(name, size) - # Cache the font for later - self.fontCache[name, size] = v + name = vals[0] + size = int(vals[1]) + if (name.endswith(".ttf")): + # Load the font from a file + v = pygame.font.Font(os.path.join(dname, name), size) + else: + # Must be a system font + v = pygame.font.SysFont(name, size) else: try: - v = int(value) - except: - v = value + v = int(vals[0]) + except ValueError: + v = vals[0] self.cache[key] = v return v # TODO - obsolete, use 'getstyle' below instead - def get(self,cls,pcls,attr): + def get(self, cls, pcls, attr): try: return self.getstyle(cls, pcls, attr) except StyleError: return 0 - # Returns the style information, given the class, sub-class and attribute names. + # Returns the style information, given the class, sub-class and attribute names. # This raises a StylError if the style isn't found. def getstyle(self, cls, pcls, attr): """Interface method -- get the value of a style attribute. - + Arguments: cls -- class, for example "checkbox", "button", etc. pcls -- pseudo class, for example "hover", "down", etc. attr -- attribute, for example "image", "background", "font", "color", etc. - + This method is called from gui.style """ - if not self._loaded: + if not self._loaded: # Load the default theme self._preload("default") o = (cls, pcls, attr) - + v = self._get(cls, pcls, attr) - if v: + if v: return v - + v = self._get(cls, "", attr) - if v: + if v: return v - + v = self._get("default", "", attr) - if v: + if v: return v - + # The style doesn't exist - #self.cache[o] = 0 + self.cache[o] = 0 raise StyleError("Style not defined: '%s', '%s', '%s'" % o) - def putstyle(self, cls, pcls, attr, *values): - self.config[cls, pcls, attr] = [".", values] - - def configure(self, txt, path=None): - if (not path): - path = self.baseThemePath - cfg = ConfigParser() - cfg.readfp(StringIO(txt)) - for section in cfg.sections(): - cls = section - pcls = '' - if cls.find(":")>=0: - cls,pcls = cls.split(":") - for attr in cfg.options(section): - value = cfg.get(section,attr).strip() - key = (cls,pcls,attr) - self.config[key] = (path, value) - if (key in self.cache): - # Remove the style from the cache - del self.cache[key] - # Draws a box around the surface in the given style - def box(self, style, surf, rect): - color = style.border_color - if (not color): - color = (0, 0, 0) - (x, y) = rect.topleft - (w, h) = rect.size - - surf.fill(color, (x, y, rect.width, style.border_top)) - surf.fill(color, (x, y+h-style.border_bottom, w, style.border_bottom)) - surf.fill(color, (x, y, style.border_left, h)) - surf.fill(color, (x+w-style.border_right, y, style.border_right, h)) - - def getspacing(self,w): + def box(self, style, surf): + c = (0, 0, 0) + if style.border_color != 0: + c = style.border_color + w, h = surf.get_size() + + surf.fill(c, (0, 0, w, style.border_top)) + surf.fill(c, (0, h-style.border_bottom, w, style.border_bottom)) + surf.fill(c, (0, 0, style.border_left, h)) + surf.fill(c, (w-style.border_right, 0, style.border_right, h)) + + def getspacing(self, w): # return the top, right, bottom, left spacing around the widget - if not hasattr(w,'_spacing'): #HACK: assume spacing doesn't change re pcls + if not hasattr(w, '_spacing'): #HACK: assume spacing doesn't change re pcls s = w.style xt = s.margin_top+s.border_top+s.padding_top xr = s.padding_right+s.border_right+s.margin_right xb = s.padding_bottom+s.border_bottom+s.margin_bottom xl = s.margin_left+s.border_left+s.padding_left - w._spacing = xt,xr,xb,xl + w._spacing = xt, xr, xb, xl return w._spacing - - def resize(self,w,func): + + + def resize(self, w, func): # Returns the rectangle expanded in each direction def expand_rect(rect, left, top, right, bottom): - return pygame.Rect(rect.x - left, - rect.y - top, - rect.w + left + right, + return pygame.Rect(rect.x - left, + rect.y - top, + rect.w + left + right, rect.h + top + bottom) - def theme_resize(width=None,height=None): + def theme_resize(width=None, height=None): s = w.style - - pt,pr,pb,pl = (s.padding_top,s.padding_right, - s.padding_bottom,s.padding_left) - bt,br,bb,bl = (s.border_top,s.border_right, - s.border_bottom,s.border_left) - mt,mr,mb,ml = (s.margin_top,s.margin_right, - s.margin_bottom,s.margin_left) + + pt, pr, pb, pl = (s.padding_top, s.padding_right, + s.padding_bottom, s.padding_left) + bt, br, bb, bl = (s.border_top, s.border_right, + s.border_bottom, s.border_left) + mt, mr, mb, ml = (s.margin_top, s.margin_right, + s.margin_bottom, s.margin_left) # Calculate the total space on each side top = pt+bt+mt right = pr+br+mr @@ -293,30 +249,30 @@ def theme_resize(width=None,height=None): left = pl+bl+ml ttw = left+right tth = top+bottom - - tilew,tileh = None,None + + tilew, tileh = None, None if width != None: tilew = width-ttw if height != None: tileh = height-tth - tilew,tileh = func(tilew,tileh) + tilew, tileh = func(tilew, tileh) if width == None: width = tilew if height == None: height = tileh - + #if the widget hasn't respected the style.width, #style height, we'll add in the space for it... width = max(width-ttw, tilew, w.style.width) height = max(height-tth, tileh, w.style.height) - - #width = max(tilew,w.style.width-tw) - #height = max(tileh,w.style.height-th) - r = pygame.Rect(left,top,width,height) - + #width = max(tilew, w.style.width-tw) + #height = max(tileh, w.style.height-th) + + r = pygame.Rect(left, top, width, height) + w._rect_padding = expand_rect(r, pl, pt, pr, pb) w._rect_border = expand_rect(w._rect_padding, bl, bt, br, bb) w._rect_margin = expand_rect(w._rect_border, ml, mt, mr, mb) - # align it within it's zone of power. + # align it within it's zone of power. rect = pygame.Rect(left, top, tilew, tileh) dx = width-rect.w dy = height-rect.h @@ -329,50 +285,50 @@ def theme_resize(width=None,height=None): return theme_resize - def paint(self,w,func): - # The function that renders the widget according to the theme, then calls the + def paint(self, w, func): + # The function that renders the widget according to the theme, then calls the # widget's own paint function. def theme_paint(s): # if w.disabled: -# if not hasattr(w,'_disabled_bkgr'): +# if not hasattr(w, '_disabled_bkgr'): # w._disabled_bkgr = s.convert() # orig = s # s = w._disabled_bkgr.convert() -# if not hasattr(w,'_theme_paint_bkgr'): +# if not hasattr(w, '_theme_paint_bkgr'): # w._theme_paint_bkgr = s.convert() # else: -# s.blit(w._theme_paint_bkgr,(0,0)) -# +# s.blit(w._theme_paint_bkgr, (0, 0)) +# # if w.disabled: # orig = s # s = w._theme_paint_bkgr.convert() if w.disabled: - if (not (hasattr(w,'_theme_bkgr') and - w._theme_bkgr.get_width() == s.get_width() and + if (not (hasattr(w, '_theme_bkgr') and + w._theme_bkgr.get_width() == s.get_width() and w._theme_bkgr.get_height() == s.get_height())): w._theme_bkgr = s.copy() orig = s s = w._theme_bkgr - s.fill((0,0,0,0)) - s.blit(orig,(0,0)) - + s.fill((0, 0, 0, 0)) + s.blit(orig, (0, 0)) + if w.background: - w.background.paint(surface.subsurface(s,w._rect_border)) + w.background.paint(surface.subsurface(s, w._rect_border)) + + self.box(w.style, surface.subsurface(s, w._rect_border)) + r = func(surface.subsurface(s, w._rect_content)) - self.box(w.style, s, w._rect_border) #surface.subsurface(s,w._rect_border)) - r = func(surface.subsurface(s,w._rect_content)) - if w.disabled: s.set_alpha(128) - orig.blit(s,(0,0)) - + orig.blit(s, (0, 0)) + w._painted = True return r return theme_paint - - def event(self,w,func): + + def event(self, w, func): def theme_event(e): rect = w._rect_content if (not rect): @@ -381,80 +337,80 @@ def theme_event(e): return func(e) if e.type == MOUSEBUTTONUP or e.type == MOUSEBUTTONDOWN: - sub = pygame.event.Event(e.type,{ + sub = pygame.event.Event(e.type, { 'button':e.button, - 'pos':(e.pos[0]-rect.x,e.pos[1]-rect.y)}) + 'pos':(e.pos[0]-rect.x, e.pos[1]-rect.y)}) elif e.type == CLICK: - sub = pygame.event.Event(e.type,{ + sub = pygame.event.Event(e.type, { 'button':e.button, - 'pos':(e.pos[0]-rect.x,e.pos[1]-rect.y)}) + 'pos':(e.pos[0]-rect.x, e.pos[1]-rect.y)}) elif e.type == MOUSEMOTION: - sub = pygame.event.Event(e.type,{ + sub = pygame.event.Event(e.type, { 'buttons':e.buttons, - 'pos':(e.pos[0]-rect.x,e.pos[1]-rect.y), + 'pos':(e.pos[0]-rect.x, e.pos[1]-rect.y), 'rel':e.rel}) else: sub = e return func(sub) return theme_event - - def update(self,w,func): + + def update(self, w, func): def theme_update(s): if w.disabled: return [] - r = func(surface.subsurface(s,w._rect_content)) + r = func(surface.subsurface(s, w._rect_content)) if type(r) == list: - dx,dy = w._rect_content.topleft + dx, dy = w._rect_content.topleft for rr in r: - rr.x,rr.y = rr.x+dx,rr.y+dy + rr.x, rr.y = rr.x+dx, rr.y+dy return r return theme_update - - def open(self,w,func): - def theme_open(widget=None,x=None,y=None): - if not hasattr(w,'_rect_content'): + + def open(self, w, func): + def theme_open(widget=None, x=None, y=None): + if not hasattr(w, '_rect_content'): # HACK: so that container.open won't resize again! - w.rect.w,w.rect.h = w.resize() + w.rect.w, w.rect.h = w.resize() rect = w._rect_content ##print w.__class__.__name__, rect if x != None: x += rect.x if y != None: y += rect.y - return func(widget,x,y) + return func(widget, x, y) return theme_open - def decorate(self,widget,level): + def decorate(self, widget, level): """Interface method -- decorate a widget. - - The theme system is given the opportunity to decorate a widget + + The theme system is given the opportunity to decorate a widget methods at the end of the Widget initializer. Arguments: widget -- the widget to be decorated - level -- the amount of decoration to do, False for none, True for + level -- the amount of decoration to do, False for none, True for normal amount, 'app' for special treatment of App objects. - - """ + + """ w = widget if level == False: return - + if type(w.style.background) != int: - w.background = Background(w,self) - + w.background = Background(w, self) + if level == 'app': return - - for k,v in list(w.style.__dict__.items()): - if k in ('border','margin','padding'): - for kk in ('top','bottom','left','right'): - setattr(w.style,'%s_%s'%(k,kk),v) - - w.paint = self.paint(w,w.paint) - w.event = self.event(w,w.event) - w.update = self.update(w,w.update) - w.resize = self.resize(w,w.resize) - w.open = self.open(w,w.open) - - def render(self,surf,box,r,size=None,offset=None): + + for k, v in list(w.style.__dict__.items()): + if k in ('border', 'margin', 'padding'): + for kk in ('top', 'bottom', 'left', 'right'): + setattr(w.style, '%s_%s'%(k, kk), v) + + w.paint = self.paint(w, w.paint) + w.event = self.event(w, w.event) + w.update = self.update(w, w.update) + w.resize = self.resize(w, w.resize) + w.open = self.open(w, w.open) + + def render(self, surf, box, r, size=None, offset=None): """Renders a box using an image. Arguments: @@ -462,19 +418,19 @@ def render(self,surf,box,r,size=None,offset=None): box -- pygame surface or color r -- pygame rect describing the size of the image to render - If 'box' is a surface, it is interpreted as a 3x3 grid of tiles. The - corner tiles are rendered in the corners of the box. The side tiles - are used to fill the top, bottom and sides of the box. The centre tile + If 'box' is a surface, it is interpreted as a 3x3 grid of tiles. The + corner tiles are rendered in the corners of the box. The side tiles + are used to fill the top, bottom and sides of the box. The centre tile is used to fill the interior of the box. """ if box == 0: return if is_color(box): - surf.fill(box,r) + surf.fill(box, r) return - - x,y,w,h=r.x,r.y,r.w,r.h + + x, y, w, h=r.x, r.y, r.w, r.h if (size and offset): pass @@ -489,62 +445,61 @@ def render(self,surf,box,r,size=None,offset=None): # Render the interior of the box surf.set_clip(pygame.Rect(x+tilew, y+tileh, w-tilew*2, h-tileh*2)) - src.x,src.y = tilew,tileh - for dest.y in range(y+tileh,yy-tileh,tileh): - for dest.x in range(x+tilew,xx-tilew,tilew): - surf.blit(box,dest,src) + src.x, src.y = tilew, tileh + for dest.y in range(y+tileh, yy-tileh, tileh): + for dest.x in range(x+tilew, xx-tilew, tilew): + surf.blit(box, dest, src) # Render the top side of the box - surf.set_clip(pygame.Rect(x+tilew,y,w-tilew*2,tileh)) - src.x,src.y,dest.y = tilew,0,y - for dest.x in range(x+tilew, xx-tilew*2+tilew, tilew): - surf.blit(box,dest,src) - + surf.set_clip(pygame.Rect(x+tilew, y, w-tilew*2, tileh)) + src.x, src.y, dest.y = tilew, 0, y + for dest.x in range(x+tilew, xx-tilew*2+tilew, tilew): + surf.blit(box, dest, src) + # Render the bottom side - surf.set_clip(pygame.Rect(x+tilew,yy-tileh,w-tilew*2,tileh)) - src.x,src.y,dest.y = tilew,tileh*2,yy-tileh - for dest.x in range(x+tilew,xx-tilew*2+tilew,tilew): - surf.blit(box,dest,src) + surf.set_clip(pygame.Rect(x+tilew, yy-tileh, w-tilew*2, tileh)) + src.x, src.y, dest.y = tilew, tileh*2, yy-tileh + for dest.x in range(x+tilew, xx-tilew*2+tilew, tilew): + surf.blit(box, dest, src) # Render the left side - surf.set_clip(pygame.Rect(x,y+tileh,xx,h-tileh*2)) - src.y,src.x,dest.x = tileh,0,x - for dest.y in range(y+tileh,yy-tileh*2+tileh,tileh): - surf.blit(box,dest,src) + surf.set_clip(pygame.Rect(x, y+tileh, xx, h-tileh*2)) + src.y, src.x, dest.x = tileh, 0, x + for dest.y in range(y+tileh, yy-tileh*2+tileh, tileh): + surf.blit(box, dest, src) # Render the right side - surf.set_clip(pygame.Rect(xx-tilew,y+tileh,xx,h-tileh*2)) - src.y,src.x,dest.x=tileh,tilew*2,xx-tilew - for dest.y in range(y+tileh,yy-tileh*2+tileh,tileh): - surf.blit(box,dest,src) + surf.set_clip(pygame.Rect(xx-tilew, y+tileh, xx, h-tileh*2)) + src.y, src.x, dest.x=tileh, tilew*2, xx-tilew + for dest.y in range(y+tileh, yy-tileh*2+tileh, tileh): + surf.blit(box, dest, src) # Render the upper-left corner surf.set_clip() - src.x,src.y,dest.x,dest.y = 0,0,x,y - surf.blit(box,dest,src) - + src.x, src.y, dest.x, dest.y = 0, 0, x, y + surf.blit(box, dest, src) + # Render the upper-right corner - src.x,src.y,dest.x,dest.y = tilew*2,0,xx-tilew,y - surf.blit(box,dest,src) - + src.x, src.y, dest.x, dest.y = tilew*2, 0, xx-tilew, y + surf.blit(box, dest, src) + # Render the lower-left corner - src.x,src.y,dest.x,dest.y = 0,tileh*2,x,yy-tileh - surf.blit(box,dest,src) - + src.x, src.y, dest.x, dest.y = 0, tileh*2, x, yy-tileh + surf.blit(box, dest, src) + # Render the lower-right corner - src.x,src.y,dest.x,dest.y = tilew*2,tileh*2,xx-tilew,yy-tileh - surf.blit(box,dest,src) + src.x, src.y, dest.x, dest.y = tilew*2, tileh*2, xx-tilew, yy-tileh + surf.blit(box, dest, src) class Background(widget.Widget): - def __init__(self,value,theme,**params): + def __init__(self, value, theme, **params): params['decorate'] = False - widget.Widget.__init__(self,**params) + super(Background, self).__init__(**params) self.value = value self.theme = theme - + def paint(self, s, size=None, offset=None): - r = pygame.Rect(0,0,s.get_width(),s.get_height()) + r = pygame.Rect(0, 0, s.get_width(), s.get_height()) v = self.value.style.background - self.theme.render(s,v,r, size=size, offset=offset) - + self.theme.render(s, v, r, size=size, offset=offset) diff --git a/pgu/gui/widget.py b/pgu/gui/widget.py index 4b6c5a7..8deeced 100644 --- a/pgu/gui/widget.py +++ b/pgu/gui/widget.py @@ -7,7 +7,7 @@ from . import style from .errors import PguError -class SignalCallback: +class SignalCallback(object): # The function to call func = None # The parameters to pass to the function (as a list) @@ -22,15 +22,15 @@ class Draw(gui.Widget): def paint(self,s): # Paint the pygame.Surface return - + def update(self,s): # Update the pygame.Surface and return the update rects return [pygame.Rect(0,0,self.rect.w,self.rect.h)] - + def event(self,e): # Handle the pygame.Event return - + def resize(self,width=None,height=None): # Return the width and height of this widget return 256,256 @@ -53,12 +53,12 @@ def resize(self,width=None,height=None): connects = None # The area covered by the widget, relative to the parent widget rect = None - - def __init__(self, **params): + + def __init__(self, **params): """Create a new Widget instance given the style parameters. Keyword arguments: - decorate -- whether to call theme.decorate(self) to allow the + decorate -- whether to call theme.decorate(self) to allow the theme a chance to decorate the widget. (default is true) style -- a dict of style parameters. x, y -- position parameters @@ -68,8 +68,8 @@ def __init__(self, **params): color -- the color property, if applicable background -- the widget used to paint the background cls -- class name as used by Theme - name -- name of widget as used by Form. If set, will call - form.add(self,name) to add the widget to the most recently + name -- name of widget as used by Form. If set, will call + form.add(self,name) to add the widget to the most recently created Form. focusable -- True if this widget can receive focus via Tab, etc. (default is True) @@ -77,31 +77,31 @@ def __init__(self, **params): value -- initial value """ - #object.Object.__init__(self) + #object.Object.__init__(self) self.connects = {} params.setdefault('decorate',True) params.setdefault('style',{}) params.setdefault('focusable',True) params.setdefault('disabled',False) - + self.focusable = params['focusable'] self.disabled = params['disabled'] - + self.rect = pygame.Rect(params.get('x',0), params.get('y',0), params.get('width',0), params.get('height',0)) - + s = params['style'] #some of this is a bit "theme-ish" but it is very handy, so these #things don't have to be put directly into the style. for att in ('align','valign','x','y','width','height','color','font','background'): if att in params: s[att] = params[att] self.style = style.Style(self,s) - + self.cls = 'default' if 'cls' in params: self.cls = params['cls'] - if 'name' in params: + if 'name' in params: from . import form self.name = params['name'] if form.Form.form: @@ -109,7 +109,7 @@ def __init__(self, **params): self.form = form.Form.form if 'value' in params: self.value = params['value'] self.pcls = "" - + if params['decorate'] != False: if (not pguglobals.app): # TODO - fix this somehow @@ -119,11 +119,11 @@ def __init__(self, **params): def focus(self): """Focus this Widget.""" - if self.container: + if self.container: if self.container.myfocus != self: ## by Gal Koren self.container.focus(self) - def blur(self): + def blur(self): """Blur this Widget.""" if self.container: self.container.blur(self) @@ -158,13 +158,13 @@ def resize(self,width=None,height=None): def chsize(self): """Signal that this widget has changed its size.""" - - if (not self._painted): + + if (not self._painted): return - - if (not self.container): + + if (not self.container): return - + if (pguglobals.app): pguglobals.app.chsize() @@ -175,7 +175,7 @@ def update(self,s): """ return - + def paint(self,s): """Render this widget onto the given surface @@ -184,7 +184,7 @@ def paint(self,s): """ return - def repaint(self): + def repaint(self): """Request a repaint of this Widget.""" if self.container: self.container.repaint(self) #pguglobals.app.repaint_widget(self) @@ -193,27 +193,28 @@ def repaintall(self): """Request a repaint of all Widgets.""" if self.container: self.container.repaintall() - def reupdate(self): + def reupdate(self): """Request a reupdate of this Widget.""" if self.container: self.container.reupdate(self) - def next(self): + def next(self): """Pass focus to next Widget. - + Widget order determined by the order they were added to their container. """ - if self.container: self.container.next(self) + if self.container: + self.container.next(self) - def previous(self): + def previous(self): """Pass focus to previous Widget. - + Widget order determined by the order they were added to their container. """ - + if self.container: self.container.previous(self) - + def get_abs_rect(self): """Returns the absolute rect of this widget on the App screen.""" x, y = self.rect.x, self.rect.y @@ -229,25 +230,25 @@ def get_abs_rect(self): def connect(self,code,func,*params): """Connect an event code to a callback function. - + Note that there may be multiple callbacks per event code. Arguments: code -- event type fnc -- callback function - *values -- values to pass to callback. + *values -- values to pass to callback. - Please note that callbacks may also have "magicaly" parameters. + Please note that callbacks may also have "magicaly" parameters. Such as: _event -- receive the event _code -- receive the event code _widget -- receive the sending widget - + Example: def onclick(value): print ('click', value) - + w = Button("PGU!") w.connect(gui.CLICK,onclick,'PGU Button Clicked') @@ -293,26 +294,17 @@ def send(self,code,event=None): func = cb.func values = list(cb.params) - # Attempt to be compatible with previous versions of python - try: - code = func.__code__ - except: - try: - code = func.func_code - except: - # Nothing to inspect, so just call the object and hope for the best - func(*cb.params) - continue + code = func.__code__ nargs = code.co_argcount names = list(code.co_varnames)[:nargs] # If the function is bound to an instance, remove the first argument name. Again # we keep compatibility with older versions of python. - if (hasattr(func, "__self__") and hasattr(func.__self__, "__class__") or - hasattr(func,'im_class')): + if (hasattr(func, "__self__") and hasattr(func.__self__, "__class__") or + hasattr(func,'im_class')): names.pop(0) - + args = [] magic = {'_event':event,'_code':code,'_widget':self} for name in names: @@ -324,18 +316,18 @@ def send(self,code,event=None): break args.extend(values) func(*args) - + def _event(self,e): if self.disabled: return self.send(e.type,e) return self.event(e) - + def event(self,e): """Called when an event is passed to this object. - + Please note that if you use an event, returning the value True will stop parent containers from also using the event. (For example, if - your widget handles TABs or arrow keys, and you don't want those to + your widget handles TABs or arrow keys, and you don't want those to also alter the focus.) This should be implemented by a subclass. @@ -355,4 +347,3 @@ def collidepoint(self, pos): """Test if the given point hits this widget. Over-ride this function for more advanced collision testing.""" return self.rect.collidepoint(pos) - diff --git a/pgu/hexvid.py b/pgu/hexvid.py index a8c7c54..f0b3d3d 100644 --- a/pgu/hexvid.py +++ b/pgu/hexvid.py @@ -15,113 +15,106 @@ import pygame -class Hexvid(Vid): +class Hexvid(VidPaintUpdateMixin, Vid): """Create an hex vid engine. See [[vid]]""" - def update(self,screen): - return self.paint(screen) - - def paint(self,screen): - sw,sh = screen.get_width(),screen.get_height() - self.view.w,self.view.h = sw,sh - + def paint(self, screen): + sw, sh = screen.get_width(), screen.get_height() + self.view.w, self.view.h = sw, sh + tlayer = self.tlayer blayer = self.blayer - #zlayer = self.zlayer - w,h = len(tlayer[0]),len(tlayer) - - #iso_w,iso_h,iso_z,tile_w,tile_h,base_w,base_h = self.iso_w,self.iso_h,self.iso_z,self.tile_w,self.tile_h,self.base_w,self.base_h - - tile_w,tile_h = self.tile_w,self.tile_h - tile_w2,tile_h2 = tile_w/2,tile_h/2 - + w, h = self.size + + tile_w, tile_h = self.tile_w, self.tile_h + tile_w2, tile_h2 = tile_w // 2, tile_h // 2 + view = self.view - adj = self.adj = pygame.Rect(-self.view.x,-self.view.y,0,0) - - w,h = len(tlayer[0]),len(tlayer) + adj = self.adj = pygame.Rect(-self.view.x, -self.view.y, 0, 0) + + w, h = len(tlayer[0]), len(tlayer) tiles = self.tiles - - #"" - if self.bounds is None: - tmp,y1 = self.tile_to_view((0,0)) - x1,tmp = self.tile_to_view((0,h+1)) - tmp,y2 = self.tile_to_view((w+1,h+1)) - x2,tmp = self.tile_to_view((w+1,0)) - self.bounds = pygame.Rect(x1,y1,x2-x1,y2-y1) + + if self.bounds == None: + tmp, y1 = self.tile_to_view((0, 0)) + x1, tmp = self.tile_to_view((0, h+1)) + tmp, y2 = self.tile_to_view((w+1, h+1)) + x2, tmp = self.tile_to_view((w+1, 0)) + self.bounds = pygame.Rect(x1, y1, x2-x1, y2-y1) print(self.bounds) - #"" - - if self.bounds != None: self.view.clamp_ip(self.bounds) - - ox,oy = self.screen_to_tile((0,0)) - sx,sy = self.tile_to_view((ox,oy)) - dx,dy = sx - self.view.x,sy - self.view.y - + + if self.bounds != None: + self.view.clamp_ip(self.bounds) + + ox, oy = self.screen_to_tile((0, 0)) + sx, sy = self.tile_to_view((ox, oy)) + dx, dy = sx - self.view.x, sy - self.view.y + bot = 1 - - tile_wi = tile_w + tile_w/2 - tile_wi2 = tile_wi/2 - + + tile_wi = tile_w + tile_w // 2 + tile_wi2 = tile_wi // 2 + #dx += tile_w/2 - - for i2 in xrange(-bot,self.view.h//tile_h2+bot*3): #NOTE: 3 seems a bit much, but it works. - tx,ty = ox + i2/2 + i2%2,oy + i2/2 - x,y = (i2%2)*tile_wi2 + dx,i2*tile_h2 + dy - + + for i2 in range(-bot, int(self.view.h // tile_h2 + bot * 3)): #NOTE: 3 seems a bit much, but it works. + tx, ty = ox + i2 // 2 + i2 % 2, oy + i2 // 2 + x, y = (i2%2)*tile_wi2 + dx, i2*tile_h2 + dy + #to adjust for the -1 in i1 - x,tx,ty = x-tile_wi,tx-1,ty+1 - - x -= tile_w/2 - for i1 in xrange(-1,self.view.w//tile_wi+1): + x, tx, ty = x-tile_wi, tx-1, ty+1 + + x -= tile_w // 2 + for i1 in range(-1, int(self.view.w // tile_wi+1)): if ty >= 0 and ty < h and tx >= 0 and tx < w: if blayer != None: n = blayer[ty][tx] if n != 0: t = tiles[n] if t != None and t.image != None: - screen.blit(t.image,(x,y)) + screen.blit(t.image, (x, y)) n = tlayer[ty][tx] if n != 0: t = tiles[n] if t != None and t.image != None: - screen.blit(t.image,(x,y)) - - + screen.blit(t.image, (x, y)) + + tx += 1 ty -= 1 - x += tile_wi + x += tile_wi - return [pygame.Rect(0,0,screen.get_width(),screen.get_height())] - - def view_to_tile(self,pos): - x,y = pos + return [pygame.Rect(0, 0, screen.get_width(), screen.get_height())] + + def view_to_tile(self, pos): + x, y = pos #x = x + (self.tile_w*1/2) - - x,y = int(x*4/(self.tile_w*3)), y*2/self.tile_h - nx = (x + y) / 2 - ny = (y - x) / 2 - return nx,ny - - def tile_to_view(self,pos): - x,y = pos + + x, y = int(x*4/(self.tile_w*3)), y*2 // self.tile_h + nx = (x + y) // 2 + ny = (y - x) // 2 + return nx, ny + + def tile_to_view(self, pos): + x, y = pos nx = x - y ny = x + y - nx,ny = int(nx*(self.tile_w*3)/4), ny*self.tile_h/2 - + nx, ny = int(nx*(self.tile_w*3) // 4), ny*self.tile_h // 2 + #nx = nx - (self.tile_w*1/2) - return nx,ny - - def screen_to_tile(self,pos): #NOTE HACK : not sure if the 3/8 is right or not, but it is pretty close... - pos = pos[0]+self.view.x + self.tile_w*3/8,pos[1]+self.view.y + return nx, ny + + def screen_to_tile(self, pos): #NOTE HACK : not sure if the 3/8 is right or not, but it is pretty close... + pos = int(pos[0]+self.view.x + self.tile_w*3/8), pos[1]+self.view.y pos = self.view_to_tile(pos) return pos - - def tile_to_screen(self,pos): + + def tile_to_screen(self, pos): pos = self.tile_to_view(pos) - pos = pos[0]-self.view.x,pos[1]-self.view.y + pos = pos[0]-self.view.x, pos[1]-self.view.y return pos - - - def tga_load_tiles(self,fname,size,tdata={}): - Vid.tga_load_tiles(self,fname,size,tdata) - - self.tile_w,self.tile_h = size + + + def tga_load_tiles(self, fname, size, tdata={}): + Vid.tga_load_tiles(self, fname, size, tdata) + + self.tile_w, self.tile_h = size diff --git a/pgu/html.py b/pgu/html.py index 4f67176..00177d3 100644 --- a/pgu/html.py +++ b/pgu/html.py @@ -4,14 +4,8 @@ import sys # Import the html parser code, maintaing compatibility with older versions of python -if (sys.version_info[0] < 3): - # Import the old style htmllib parser - import htmllib - from htmllib import HTMLParser -else: - # Import the new html.parser module - from html.parser import HTMLParser - htmllib = None + +from html.parser import HTMLParser import re import pygame @@ -19,53 +13,55 @@ from pgu import gui -_amap = {'left':-1,'right':1,'center':0,None:None,'':None,} -_vamap = {'top':-1,'bottom':1,'center':0,'middle':0,None:None,'':None,} +_amap = {'left':-1, 'right':1, 'center':0, None:None, '':None, } +_vamap = {'top':-1, 'bottom':1, 'center':0, 'middle':0, None:None, '':None, } -# Used by the HTML parser to load external resources (like images). This -# class loads content from the local file system. But you can pass your own +# Used by the HTML parser to load external resources (like images). This +# class loads content from the local file system. But you can pass your own # resource loader to the HTML parser to find images by other means. class ResourceLoader(object): # Loads an image and returns it as a pygame image def load_image(this, path): return pygame.image.load(path) -class _dummy: +class _dummy(object): pass -class _flush: +class _flush(object): def __init__(self): self.style = _dummy() self.style.font = None self.style.color = None self.cls = None - def add(self,w): pass - def space(self,v): pass - + def add(self, w): pass + + def space(self, v): pass + class _hr(gui.Color): - def __init__(self,**params): - gui.Color.__init__(self,(0,0,0),**params) - def resize(self,width=None,height=None): - w,h = self.style.width,self.style.height + def __init__(self, **params): + super(_hr, self).__init__((0, 0, 0), **params) + + def resize(self, width=None, height=None): + w, h = self.style.width, self.style.height #if width != None: self.rect.w = width #else: self.rect.w = 1 - - #xt,xr,xb,xl = self.getspacing() - - if width != None: w = max(w,width) - if height != None: h = max(h,height) - w = max(w,1) - h = max(h,1) - - return w,h #self.container.rect.w,h - - #self.rect.w = max(1,width,self.container.rect.w-(xl+xr)) - + + #xt, xr, xb, xl = self.getspacing() + + if width != None: w = max(w, width) + if height != None: h = max(h, height) + w = max(w, 1) + h = max(h, 1) + + return w, h #self.container.rect.w, h + + #self.rect.w = max(1, width, self.container.rect.w-(xl+xr)) + #print self.rect #self.rect.w = 1 class _html(HTMLParser): - def init(self,doc,font,color,_globals,_locals,loader=None): + def init(self, doc, font, color, _globals, _locals, loader=None): self.mystack = [] self.document = doc if (loader): @@ -73,27 +69,27 @@ def init(self,doc,font,color,_globals,_locals,loader=None): else: # Use the default resource loader self.loader = ResourceLoader() - self.myopen('document',self.document) - + self.myopen('document', self.document) + self.myfont = self.font = font self.mycolor = self.color = color - + self.form = None - + self._globals = _globals self._locals = _locals - - def myopen(self,type_,w): - - self.mystack.append((type_,w)) - self.type,self.item = type_,w - + + def myopen(self, type_, w): + + self.mystack.append((type_, w)) + self.type, self.item = type_, w + self.font = self.item.style.font self.color = self.item.style.color - + if not self.font: self.font = self.myfont if not self.color: self.color = self.mycolor - + def myclose(self, tag): self.mydone() n = len(self.mystack)-1 @@ -106,8 +102,8 @@ def myclose(self, tag): # Pop off the parent element, then add it back on to set the # font, color, etc. # TODO - tacky - t,w = self.mystack.pop() - self.myopen(t,w) + t, w = self.mystack.pop() + self.myopen(t, w) break n -= 1 @@ -116,64 +112,64 @@ def myclose(self, tag): # if len(self.mystack)==0: # # Closing a tag that was never opened # break -# t,w = self.mystack.pop() -# t,w = self.mystack.pop() -# self.myopen(t,w) - - def myback(self,type_): - if type(type_) == str: type_ = [type_,] +# t, w = self.mystack.pop() +# t, w = self.mystack.pop() +# self.myopen(t, w) + + def myback(self, type_): + if type(type_) == str: type_ = [type_, ] self.mydone() - #print 'myback',type_ + #print 'myback', type_ t = None while t not in type_: #if len(self.mystack)==0: return - t,w = self.mystack.pop() - self.myopen(t,w) - + t, w = self.mystack.pop() + self.myopen(t, w) + def mydone(self): #clearing out the last

- if not hasattr(self.item,'layout'): return - if len(self.item.layout._widgets) == 0: return + if not hasattr(self.item, 'layout'): return + if len(self.item.layout._widgets) == 0: return w = self.item.layout._widgets[-1] if type(w) == tuple: del self.item.layout._widgets[-1] - - def start_b(self,attrs): self.font.set_bold(1) + + def start_b(self, attrs): self.font.set_bold(1) def end_b(self): self.font.set_bold(0) - def start_i(self,attrs): self.font.set_italic(1) + def start_i(self, attrs): self.font.set_italic(1) def end_i(self): self.font.set_italic(0) - def start_u(self,attrs): self.font.set_underline(1) + def start_u(self, attrs): self.font.set_underline(1) def end_u(self): self.font.set_underline(0) - def start_br(self,attrs): self.do_br(attrs) - def do_br(self,attrs): self.item.br(self.font.size(" ")[1]) - def attrs_to_map(self,attrs): + def start_br(self, attrs): self.do_br(attrs) + def do_br(self, attrs): self.item.br(self.font.size(" ")[1]) + def attrs_to_map(self, attrs): k = None r = {} - for k,v in attrs: r[k] = v + for k, v in attrs: r[k] = v return r - - def map_to_params(self,r): + + def map_to_params(self, r): anum = re.compile("\D") - + params = {'style':{}} style = params['style'] - if 'bgcolor' in r: + if 'bgcolor' in r: style['background'] = gui.parse_color(r['bgcolor']) - if 'background' in r: + if 'background' in r: style['background'] = self.loader.load_image(r['background']) if 'border' in r: style['border'] = int(r['border']) - - for k in ['width','height','colspan','rowspan','size','min','max']: - if k in r: params[k] = int(anum.sub("",r[k])) - - for k in ['name','value']: + + for k in ['width', 'height', 'colspan', 'rowspan', 'size', 'min', 'max']: + if k in r: params[k] = int(anum.sub("", r[k])) + + for k in ['name', 'value']: if k in r: params[k] = r[k] - + if 'class' in r: params['cls'] = r['class'] - - if 'align' in r: + + if 'align' in r: params['align'] = _amap[r['align']] if 'valign' in r: params['valign'] = _vamap[r['valign']] @@ -183,44 +179,44 @@ def map_to_params(self,r): #print st if ":" in st: #print st.split(":") - k,v = st.split(":") - k = k.replace("-","_") - k = k.replace(" ","") - v = v.replace(" ","") + k, v = st.split(":") + k = k.replace("-", "_") + k = k.replace(" ", "") + v = v.replace(" ", "") if k == 'color' or k == 'border_color' or k == 'background': v = gui.parse_color(v) else: - v = int(anum.sub("",v)) + v = int(anum.sub("", v)) style[k] = v return params - - def map_to_connects(self,e,r): - for k,evt in [('onclick',gui.CLICK),('onchange',gui.CHANGE)]: #blah blah blah - + + def map_to_connects(self, e, r): + for k, evt in [('onclick', gui.CLICK), ('onchange', gui.CHANGE)]: #blah blah blah + if k in r: - #print k,r[k] - e.connect(evt,self.myexec,(e,r[k])) + #print k, r[k] + e.connect(evt, self.myexec, (e, r[k])) - def start_p(self,attrs): + def start_p(self, attrs): r = self.attrs_to_map(attrs) - align = r.get("align","left") - + align = r.get("align", "left") + self.check_p() self.item.block(_amap[align]) - + def check_p(self): if len(self.item.layout._widgets) == 0: return if type(self.item.layout._widgets[-1]) == tuple: - w,h = self.item.layout._widgets[-1] + w, h = self.item.layout._widgets[-1] if w == 0: return self.do_br(None) - + def end_p(self): #print 'end p' self.check_p() - - - def start_block(self,t,attrs,align=-1): + + + def start_block(self, t, attrs, align=-1): r = self.attrs_to_map(attrs) params = self.map_to_params(r) if 'cls' in params: params['cls'] = t+"."+params['cls'] @@ -231,119 +227,119 @@ def start_block(self,t,attrs,align=-1): align = params['align'] self.item.block(align) self.item.add(b) - self.myopen(t,b) + self.myopen(t, b) + - - - def end_block(self,t): + + def end_block(self, t): self.myclose(t) self.item.block(-1) - - def start_div(self,attrs): self.start_block('div',attrs) + + def start_div(self, attrs): self.start_block('div', attrs) def end_div(self): self.end_block('div') - def start_center(self,attrs): self.start_block('div',attrs,0) + def start_center(self, attrs): self.start_block('div', attrs, 0) def end_center(self): self.end_block('div') - - def start_h1(self,attrs): self.start_block('h1',attrs) + + def start_h1(self, attrs): self.start_block('h1', attrs) def end_h1(self): self.end_block('h1') - def start_h2(self,attrs): self.start_block('h2',attrs) + def start_h2(self, attrs): self.start_block('h2', attrs) def end_h2(self): self.end_block('h2') - def start_h3(self,attrs): self.start_block('h3',attrs) + def start_h3(self, attrs): self.start_block('h3', attrs) def end_h3(self): self.end_block('h3') - def start_h4(self,attrs): self.start_block('h4',attrs) + def start_h4(self, attrs): self.start_block('h4', attrs) def end_h4(self): self.end_block('h4') - def start_h5(self,attrs): self.start_block('h5',attrs) + def start_h5(self, attrs): self.start_block('h5', attrs) def end_h5(self): self.end_block('h5') - def start_h6(self,attrs): self.start_block('h6',attrs) + def start_h6(self, attrs): self.start_block('h6', attrs) def end_h6(self): self.end_block('h6') - def start_ul(self,attrs): self.start_block('ul',attrs) + def start_ul(self, attrs): self.start_block('ul', attrs) def end_ul(self): self.end_block('ul') - def start_ol(self,attrs): - self.start_block('ol',attrs) + def start_ol(self, attrs): + self.start_block('ol', attrs) self.item.counter = 0 def end_ol(self): self.end_block('ol') - def start_li(self,attrs): - self.myback(['ul','ol']) + def start_li(self, attrs): + self.myback(['ul', 'ol']) cur = self.item - self.start_block('li',attrs) - if hasattr(cur,'counter'): + self.start_block('li', attrs) + if hasattr(cur, 'counter'): cur.counter += 1 self.handle_data("%d. "%cur.counter) else: self.handle_data("- ") #def end_li(self): self.end_block('li') #this isn't needed because of how the parser works - def start_pre(self,attrs): self.start_block('pre',attrs) + def start_pre(self, attrs): self.start_block('pre', attrs) def end_pre(self): self.end_block('pre') - def start_code(self,attrs): self.start_block('code',attrs) + def start_code(self, attrs): self.start_block('code', attrs) def end_code(self): self.end_block('code') - - def start_table(self,attrs): + + def start_table(self, attrs): r = self.attrs_to_map(attrs) params = self.map_to_params(r) - - align = r.get("align","left") + + align = r.get("align", "left") self.item.block(_amap[align]) t = gui.Table(**params) self.item.add(t) - - self.myopen('table',t) - - def start_tr(self,attrs): + + self.myopen('table', t) + + def start_tr(self, attrs): self.myback('table') self.item.tr() - - def _start_td(self,t,attrs): + + def _start_td(self, t, attrs): r = self.attrs_to_map(attrs) params = self.map_to_params(r) if 'cls' in params: params['cls'] = t+"."+params['cls'] else: params['cls'] = t b = gui.Document(cls=t) - + self.myback('table') - self.item.td(b,**params) - self.myopen(t,b) - + self.item.td(b, **params) + self.myopen(t, b) + self.font = self.item.style.font self.color = self.item.style.color - - def start_td(self,attrs): - self._start_td('td',attrs) - - def start_th(self,attrs): - self._start_td('th',attrs) - + + def start_td(self, attrs): + self._start_td('td', attrs) + + def start_th(self, attrs): + self._start_td('th', attrs) + def end_table(self): self.myclose('table') self.item.block(-1) - - def start_form(self,attrs): + + def start_form(self, attrs): r = self.attrs_to_map(attrs) e = self.form = gui.Form() e.groups = {} - - self._locals[r.get('id',None)] = e - - def start_input(self,attrs): + + self._locals[r.get('id', None)] = e + + def start_input(self, attrs): r = self.attrs_to_map(attrs) params = self.map_to_params(r) #why bother #params = {} - - type_,name,value = r.get('type','text'),r.get('name',None),r.get('value',None) + + type_, name, value = r.get('type', 'text'), r.get('name', None), r.get('value', None) f = self.form if type_ == 'text': e = gui.Input(**params) - self.map_to_connects(e,r) + self.map_to_connects(e, r) self.item.add(e) elif type_ == 'radio': if name not in f.groups: f.groups[name] = gui.Group(name=name) g = f.groups[name] del params['name'] - e = gui.Radio(group=g,**params) - self.map_to_connects(e,r) + e = gui.Radio(group=g, **params) + self.map_to_connects(e, r) self.item.add(e) if 'checked' in r: g.value = value elif type_ == 'checkbox': @@ -351,71 +347,71 @@ def start_input(self,attrs): f.groups[name] = gui.Group(name=name) g = f.groups[name] del params['name'] - e = gui.Checkbox(group=g,**params) - self.map_to_connects(e,r) + e = gui.Checkbox(group=g, **params) + self.map_to_connects(e, r) self.item.add(e) if 'checked' in r: g.value = value elif type_ == 'button': e = gui.Button(**params) - self.map_to_connects(e,r) + self.map_to_connects(e, r) self.item.add(e) elif type_ == 'submit': e = gui.Button(**params) - self.map_to_connects(e,r) + self.map_to_connects(e, r) self.item.add(e) elif type_ == 'file': e = gui.Input(**params) - self.map_to_connects(e,r) + self.map_to_connects(e, r) self.item.add(e) b = gui.Button(value='Browse...') self.item.add(b) def _browse(value): d = gui.FileDialog(); - d.connect(gui.CHANGE,gui.action_setvalue,(d,e)) + d.connect(gui.CHANGE, gui.action_setvalue, (d, e)) d.open(); - b.connect(gui.CLICK,_browse,None) + b.connect(gui.CLICK, _browse, None) - self._locals[r.get('id',None)] = e + self._locals[r.get('id', None)] = e - def start_object(self,attrs): + def start_object(self, attrs): r = self.attrs_to_map(attrs) params = self.map_to_params(r) # Use eval to automagically get the class being refered cls = eval(r["type"]) e = cls(**params) - self.map_to_connects(e,r) + self.map_to_connects(e, r) self.item.add(e) - self._locals[r.get('id',None)] = e - - def start_select(self,attrs): + self._locals[r.get('id', None)] = e + + def start_select(self, attrs): r = self.attrs_to_map(attrs) params = {} - - name,value = r.get('name',None),r.get('value',None) - e = gui.Select(name=name,value=value,**params) - self.map_to_connects(e,r) + + name, value = r.get('name', None), r.get('value', None) + e = gui.Select(name=name, value=value, **params) + self.map_to_connects(e, r) self.item.add(e) - self.myopen('select',e) - - def start_option(self,attrs): + self.myopen('select', e) + + def start_option(self, attrs): r = self.attrs_to_map(attrs) params = {} #style = self.map_to_style(r) - + self.myback('select') e = gui.Document(**params) - self.item.add(e,value=r.get('value',None)) - self.myopen('option',e) - - + self.item.add(e, value=r.get('value', None)) + self.myopen('option', e) + + def end_select(self): self.myclose('select') - - def start_hr(self,attrs): + + def start_hr(self, attrs): self.do_hr(attrs) - def do_hr(self,attrs): + def do_hr(self, attrs): h = self.font.size(" ")[1]/2 - + r = self.attrs_to_map(attrs) params = self.map_to_params(r) params['style']['padding'] = h @@ -423,69 +419,69 @@ def do_hr(self,attrs): self.item.block(0) self.item.add(_hr(**params)) self.item.block(-1) - - def anchor_begin(self,href,name,type_): + + def anchor_begin(self, href, name, type_): pass def anchor_end(self): pass - - def start_title(self,attrs): self.myopen('title',_flush()) + + def start_title(self, attrs): self.myopen('title', _flush()) def end_title(self): self.myclose('title') - - def myexec(self,value): - w,code = value + + def myexec(self, value): + w, code = value g = self._globals l = self._locals l['self'] = w - exec(code,g,l) - - def handle_image(self,src,alt,ismap,align,width,height): + exec(code, g, l) + + def handle_image(self, src, alt, ismap, align, width, height): try: w = gui.Image(self.loader.load_image(src)) if align != '': - self.item.add(w,_amap[align]) + self.item.add(w, _amap[align]) else: self.item.add(w) - except: + except Exception: print('handle_image: missing %s'%src) - - def handle_data(self,txt): - if self.type == 'table': return - elif self.type in ('pre','code'): - txt = txt.replace("\t"," ") + + def handle_data(self, txt): + if self.type == 'table': return + elif self.type in ('pre', 'code'): + txt = txt.replace("\t", " ") ss = txt.split("\n") if ss[-1] == "": del ss[-1] for sentence in ss: - img = self.font.render(sentence,1,self.color) + img = self.font.render(sentence, 1, self.color) w = gui.Image(img) self.item.add(w) self.item.block(-1) return - txt = re.compile("^[\t\r\n]+").sub("",txt) - txt = re.compile("[\t\r\n]+$").sub("",txt) - - tst = re.compile("[\t\r\n]+").sub("",txt) + txt = re.compile("^[\t\r\n]+").sub("", txt) + txt = re.compile("[\t\r\n]+$").sub("", txt) + + tst = re.compile("[\t\r\n]+").sub("", txt) if tst == "": return - - txt = re.compile("\s+").sub(" ",txt) + + txt = re.compile("\s+").sub(" ", txt) if txt == "": return - + if txt == " ": self.item.space(self.font.size(" ")) return - + for word in txt.split(" "): - word = word.replace(chr(160)," ") #  + word = word.replace(chr(160), " ") #  #print self.item.cls - w = gui.Image(self.font.render(word,1,self.color)) + w = gui.Image(self.font.render(word, 1, self.color)) self.item.add(w) self.item.space(self.font.size(" ")) if (sys.version_info[0] >= 3): - # These functions are for compatibility with python 3, where it seems that HTMLParser - # was rewritten to be more general. There is a problem though, since python pre 3 + # These functions are for compatibility with python 3, where it seems that HTMLParser + # was rewritten to be more general. There is a problem though, since python pre 3 # defines these same functions with an extra argument. So we have to include them # conditionally, depending on whether we're using python 2 or 3. Ugh. def handle_starttag(this, tag, attrs): @@ -524,43 +520,40 @@ class HTML(gui.Document): globals -- global variables (for scripting) locals -- local variables (for scripting) loader -- the resource loader - + You may access html elements that have an id via widget[id] """ - def __init__(self,data,globals=None,locals=None,loader=None,**params): - gui.Document.__init__(self,**params) + def __init__(self, data, globals=None, locals=None, loader=None, **params): + super(HTML, self).__init__(**params) # This ensures that the whole HTML document is left-aligned within # the rendered surface. self.style.align = -1 - - _globals,_locals = globals,locals - + + _globals, _locals = globals, locals + if _globals == None: _globals = {} if _locals == None: _locals = {} self._globals = _globals self._locals = _locals - - #font = gui.theme.get("label","","font") - if (htmllib): - # The constructor is slightly different - p = _html(None, 0) - else: - p = _html() - p.init(self,self.style.font,self.style.color,_globals,_locals, + + #font = gui.theme.get("label", "", "font") + + p = _html() + p.init(self, self.style.font, self.style.color, _globals, _locals, loader=loader) - p.feed(data) - p.close() + p.feed(data) + p.close() p.mydone() - - - def __getitem__(self,k): + + + def __getitem__(self, k): return self._locals[k] # Returns a box (pygame rectangle) surrounding all widgets in this document def get_bounding_box(this): - minx = miny = sys.maxint - maxx = maxy = -sys.maxint + minx = miny = sys.maxsize + maxx = maxy = -sys.maxsize for e in this.layout.widgets: minx = min(minx, e.rect.left) miny = min(miny, e.rect.top) @@ -569,7 +562,7 @@ def get_bounding_box(this): return pygame.Rect(minx, miny, maxx-minx, maxy-miny) -def render_ext(font, rect, text, aa, color, bgcolor=(0,0,0,0), **params): +def render_ext(font, rect, text, aa, color, bgcolor=(0, 0, 0, 0), **params): """Renders some html and returns the rendered surface, plus the HTML instance that produced it. """ @@ -578,7 +571,7 @@ def render_ext(font, rect, text, aa, color, bgcolor=(0,0,0,0), **params): if (rect == -1): # Make the surface large enough to fit the rendered text - htm.resize(width=sys.maxint) + htm.resize(width=10000) (width, height) = htm.get_bounding_box().size # Now set the proper document width (computed from the bounding box) htm.resize(width=width) @@ -597,22 +590,20 @@ def render_ext(font, rect, text, aa, color, bgcolor=(0,0,0,0), **params): htm.paint(surf) return (surf, htm) -def render(font, rect, text, aa, color, bgcolor=(0,0,0,0), **params): +def render(font, rect, text, aa, color, bgcolor=(0, 0, 0, 0), **params): """Renders some html""" return render_ext(font, rect, text, aa, color, bgcolor, **params)[0] -def rendertrim(font,rect,text,aa,color,bgcolor=(0,0,0,0),**params): +def rendertrim(font, rect, text, aa, color, bgcolor=(0, 0, 0, 0), **params): """Render html, and make sure to trim the size.""" # Render the HTML (surf, htm) = render_ext(font, rect, text, aa, color, bgcolor, **params) return surf.subsurface(htm.get_bounding_box()) - -def write(s,font,rect,text,aa=0,color=(0,0,0), **params): + +def write(s, font, rect, text, aa=0, color=(0, 0, 0), **params): """Write html to a surface.""" htm = HTML(text, font=font, color=color, **params) htm.resize(width=rect.w) s = s.subsurface(rect) htm.paint(s) - - diff --git a/pgu/isovid.py b/pgu/isovid.py index 3404b61..b0945a8 100644 --- a/pgu/isovid.py +++ b/pgu/isovid.py @@ -1,7 +1,7 @@ """Isometric tile engine. -Note -- this engine is not finished, any may not work for your -particular needs. If you are able to update it, help would be +Note -- this engine is not finished, any may not work for your +particular needs. If you are able to update it, help would be greatly appreciated! Please note that this file is alpha, and is subject to modification in @@ -13,71 +13,63 @@ from pgu.vid import * import pygame -# Quick fix for python3 -try: - xrange -except: - xrange = range - -class Isovid(Vid): +class Isovid(VidPaintUpdateMixin, Vid): """Create an iso vid engine. See [[vid]]""" - def update(self,screen): - return self.paint(screen) - - def paint(self,screen): - sw,sh = screen.get_width(),screen.get_height() - + def paint(self, screen): + sw, sh = screen.get_width(), screen.get_height() + tlayer = self.tlayer blayer = self.blayer zlayer = self.zlayer - w,h = len(tlayer[0]),len(tlayer) - - iso_w,iso_h,iso_z,tile_w,tile_h,base_w,base_h = self.iso_w,self.iso_h,self.iso_z,self.tile_w,self.tile_h,self.base_w,self.base_h - - base_h2 = base_h/2 - base_w2 = base_w/2 - - bot = tile_h/base_h2 - todo_max = sh/base_h2+bot - todo = [[] for y in xrange(0,todo_max)] - - self.view.w,self.view.h = sw,sh + w, h = self.size + + iso_w, iso_h, iso_z, tile_w, tile_h, base_w, base_h = self.iso_w, self.iso_h, self.iso_z, self.tile_w, self.tile_h, self.base_w, self.base_h + + base_h2 = base_h // 2 + base_w2 = base_w // 2 + + bot = tile_h // base_h2 + todo_max = sh // base_h2+bot + todo = [[] for y in range(0, todo_max)] + + self.view.w, self.view.h = sw, sh view = self.view - adj = self.adj = pygame.Rect(-self.view.x,-self.view.y,0,0) - + adj = self.adj = pygame.Rect(-self.view.x, -self.view.y, 0, 0) + for s in self.sprites: self.sprite_calc_irect(s) - x,y = self.iso_to_view((s.rect.centerx,s.rect.centery)) - v = (y+adj.y)/base_h2 - 1 + x, y = self.iso_to_view((s.rect.centerx, s.rect.centery)) + v = (y+adj.y) // base_h2 - 1 if v >= 0 and v < todo_max: - todo[v].append((s.image,s.irect)) - #else: print 'doesnt fit',v - - w,h = len(tlayer[0]),len(tlayer) + todo[v].append((s.image, s.irect)) + #else: print 'doesnt fit', v + + w, h = len(tlayer[0]), len(tlayer) tiles = self.tiles - + #"" if self.bounds == None: - tmp,y1 = self.tile_to_view((0,0)) - x1,tmp = self.tile_to_view((0,h+1)) - tmp,y2 = self.tile_to_view((w+1,h+1)) - x2,tmp = self.tile_to_view((w+1,0)) - self.bounds = pygame.Rect(x1,y1,x2-x1,y2-y1) + tmp, y1 = self.tile_to_view((0, 0)) + x1, tmp = self.tile_to_view((0, h+1)) + tmp, y2 = self.tile_to_view((w+1, h+1)) + x2, tmp = self.tile_to_view((w+1, 0)) + self.bounds = pygame.Rect(x1, y1, x2-x1, y2-y1) #"" - - if self.bounds != None: self.view.clamp_ip(self.bounds) - - ox,oy = self.screen_to_tile((0,0)) - sx,sy = self.iso_to_view((ox*iso_w,oy*iso_h)) - dx,dy = sx - self.view.x,sy - self.view.y - - for i2 in xrange(-bot,self.view.h//base_h2+bot): - tx,ty = ox + i2/2 + i2%2,oy + i2/2 - x,y = (i2%2)*base_w2 + dx,i2*base_h2 + dy - + + if self.bounds != None: + self.view.clamp_ip(self.bounds) + + ox, oy = self.screen_to_tile((0, 0)) + sx, sy = self.iso_to_view((ox*iso_w, oy*iso_h)) + dx, dy = sx - self.view.x, sy - self.view.y + + for i2 in range(-bot, self.view.h // base_h2+bot): + tx, ty = ox + i2 // 2 + i2 % 2, oy + i2 // 2 + x, y = (i2 % 2) * base_w2 + dx, i2 * base_h2 + dy + #to adjust for the -1 in i1 - x,tx,ty = x-base_w,tx-1,ty+1 - for i1 in xrange(-1,self.view.w//base_w+2): #NOTE: not sure why +2 + x, tx, ty = x-base_w, tx-1, ty+1 + for i1 in range(-1, self.view.w // base_w+2): #NOTE: not sure why +2 if ty >= 0 and ty < h and tx >= 0 and tx < w: z = zlayer[ty][tx]*iso_z if blayer != None: @@ -85,104 +77,103 @@ def paint(self,screen): if n != 0: t = tiles[n] if t != None and t.image != None: - screen.blit(t.image,(x-base_w2,y+z)) + screen.blit(t.image, (x-base_w2, y+z)) n = tlayer[ty][tx] if n != 0: t = tiles[n] if t != None and t.image != None: - screen.blit(t.image,(x-base_w2,y-(t.image_h-base_h)+z)) - + screen.blit(t.image, (x-base_w2, y-(t.image_h-base_h)+z)) + tx += 1 ty -= 1 x += base_w - for img,irect in todo[y/base_h2]: - screen.blit(img,(irect.x+adj.x,irect.y+adj.y)) + for img, irect in todo[y // base_h2]: + screen.blit(img, (irect.x+adj.x, irect.y+adj.y)) - return [pygame.Rect(0,0,screen.get_width(),screen.get_height())] - - def iso_to_view(self,pos): + return [pygame.Rect(0, 0, screen.get_width(), screen.get_height())] + + def iso_to_view(self, pos): tlayer = self.tlayer - w,h = len(tlayer[0]),len(tlayer) - - x,y = pos - - #nx,ny = (h*self.iso_w + x - y)/2, (0 + x + y)/2 - nx,ny = (x - y)/2, (0 + x + y)/2 - - return (nx * self.base_w / self.iso_w), (ny * self.base_h / self.iso_h) - - def view_to_iso(self,pos): + w, h = len(tlayer[0]), len(tlayer) + + x, y = pos + + nx, ny = (x - y) // 2, (0 + x + y) // 2 + + return (nx * self.base_w // self.iso_w), (ny * self.base_h // self.iso_h) + + def view_to_iso(self, pos): tlayer = self.tlayer - w,h = len(tlayer[0]),len(tlayer) - - x,y = pos - - x,y = x*self.iso_w/self.base_w, y*self.iso_h/self.base_h - + w, h = len(tlayer[0]), len(tlayer) + + x, y = pos + + x, y = x*self.iso_w // self.base_w, y*self.iso_h // self.base_h + #x -= (self.iso_w/2) * h #x -= (self.iso_w/2) * h - - nx = (x+y) + + nx = (x+y) ny = y*2-nx - - return nx,ny - - def tile_to_view(self,pos): - return self.iso_to_view((pos[0]*self.iso_w,pos[1]*self.iso_h)) - - def screen_to_tile(self,pos): - x,y = pos + + return nx, ny + + def tile_to_view(self, pos): + return self.iso_to_view((pos[0]*self.iso_w, pos[1]*self.iso_h)) + + def screen_to_tile(self, pos): + x, y = pos x += self.view.x y += self.view.y - x,y = self.view_to_iso((x,y)) - return x/self.iso_w,y/self.iso_h - - def tile_to_screen(self,pos): - x,y = self.iso_to_view((pos[0]*self.iso_w,pos[1]*self.iso_h)) - return x-self.view.x,y-self.view.y - - def tga_load_tiles(self,fname,size,tdata={}): - Vid.tga_load_tiles(self,fname,size,tdata) - - self.tile_w,self.tile_h = size - self.iso_w,self.iso_h,self.iso_z = self.tile_w,self.tile_w,1 - self.base_w,self.base_h = self.tile_w,self.tile_w/2 - - - - def resize(self,size,bg=0): - Vid.resize(self,size,bg) - + x, y = self.view_to_iso((x, y)) + return x // self.iso_w, y // self.iso_h + + def tile_to_screen(self, pos): + x, y = self.iso_to_view((pos[0]*self.iso_w, pos[1]*self.iso_h)) + return x-self.view.x, y-self.view.y + + def tga_load_tiles(self, fname, size, tdata={}): + Vid.tga_load_tiles(self, fname, size, tdata) + + self.tile_w, self.tile_h = size + self.iso_w, self.iso_h, self.iso_z = self.tile_w, self.tile_w, 1 + self.base_w, self.base_h = self.tile_w, self.tile_w // 2 + + + + def resize(self, size, bg=0): + Vid.resize(self, size, bg) + tlayer = self.tlayer - w,h = len(tlayer[0]),len(tlayer) - - self.zlayer = [[0 for x in xrange(0,w)] for y in xrange(0,h)] + w, h = len(tlayer[0]), len(tlayer) + + self.zlayer = [[0 for x in range(0, w)] for y in range(0, h)] - - def sprite_calc_irect(self,s): + + def sprite_calc_irect(self, s): tlayer = self.tlayer - w,h = len(tlayer[0]),len(tlayer) + w, h = len(tlayer[0]), len(tlayer) zlayer = self.zlayer - - x,y = self.iso_to_view((s.rect.centerx,s.rect.centery)) - tx,ty = s.rect.centerx/self.iso_w,s.rect.centery/self.iso_h + + x, y = self.iso_to_view((s.rect.centerx, s.rect.centery)) + tx, ty = s.rect.centerx // self.iso_w, s.rect.centery // self.iso_h z = 0 if ty >= 0 and ty < h and tx >= 0 and tx < w: z = zlayer[ty][tx]*self.iso_z - - nx,ny = x - s.shape.centerx, y - s.shape.centery + z - - s.irect.x,s.irect.y = nx,ny - - def run_codes(self,cdata,rect): + + nx, ny = x - s.shape.centerx, y - s.shape.centery + z + + s.irect.x, s.irect.y = nx, ny + + def run_codes(self, cdata, rect): #HACK to make run_codes work - w,h = self.iso_w,self.iso_h - + w, h = self.iso_w, self.iso_h + img = self.tiles[0].image - - self.tiles[0].image = pygame.Surface((w,h)) - r = Vid.run_codes(self,cdata,rect) + + self.tiles[0].image = pygame.Surface((w, h)) + r = Vid.run_codes(self, cdata, rect) self.tiles[0].image = img return r diff --git a/pgu/tilevid.py b/pgu/tilevid.py index ceab75c..bbb0bae 100644 --- a/pgu/tilevid.py +++ b/pgu/tilevid.py @@ -3,60 +3,54 @@ from pgu.vid import * import pygame -# Quick fix for python3 -try: - xrange -except: - xrange = range - class Tilevid(Vid): """Based on [[vid]] -- see for reference.""" def paint(self,s): sw,sh = s.get_width(),s.get_height() self.view.w,self.view.h = sw,sh - + tiles = self.tiles tw,th = tiles[0].image.get_width(),tiles[0].image.get_height() w,h = self.size - + if self.bounds != None: self.view.clamp_ip(self.bounds) - + ox,oy = self.view.x,self.view.y tlayer = self.tlayer blayer = self.blayer alayer = self.alayer sprites = self.sprites - + blit = s.blit - yy = - (self.view.y%th) - my = (oy+sh)/th + yy = - (self.view.y%th) + my = (oy+sh) // th if (oy+sh)%th: my += 1 - + if blayer != None: - for y in xrange(oy//th,my): + for y in range(oy // th, my): if y >=0 and y < h: trow = tlayer[y] brow = blayer[y] arow = alayer[y] xx= - (self.view.x%tw) - mx = (ox+sw)/tw + mx = (ox+sw) // tw #if (ox+sh)%tw: mx += 1 - for x in xrange(ox//tw,mx+1): - if x >=0and x=0 and x=0 and y=0 and x= 1000: + if (self.ct - self.st) >= 1000: r = self.fps = self.frames #print "%s: %d fps"%(self.__class__.__name__,self.fps) self.frames = 0 self.st += 1000 pygame.time.wait(0) #NOTE: not sure why, but you gotta call this now and again return r - - - - diff --git a/pgu/vid.py b/pgu/vid.py index 7ee24f6..2054d77 100644 --- a/pgu/vid.py +++ b/pgu/vid.py @@ -9,7 +9,7 @@ * Sprites * Sprite-Sprite Collision handling * Sprite-Tile Collision handling -* Scrolling +* Scrolling * Loading from PGU tile and sprite formats (optional) * Set rate FPS (optional) @@ -23,87 +23,81 @@ from pygame.locals import * import math -# Quick fix for python3 -try: - xrange -except: - xrange = range - -class Sprite: +class Sprite(object): """The object used for Sprites. Arguments: ishape -- an image, or an image, rectstyle. The rectstyle will describe the shape of the image, used for collision detection. - pos -- initial (x,y) position of the Sprite. - + pos -- initial (x, y) position of the Sprite. + Attributes: rect -- the current position of the Sprite _rect -- the previous position of the Sprite groups -- the groups the Sprite is in agroups -- the groups the Sprite can hit in a collision - hit -- the handler for hits -- hit(g,s,a) + hit -- the handler for hits -- hit(g, s, a) loop -- the loop handler, called once a frame """ - def __init__(self,ishape,pos): + def __init__(self, ishape, pos): if not isinstance(ishape, tuple): - ishape = ishape,None - image,shape = ishape + ishape = ishape, None + image, shape = ishape if shape == None: - shape = pygame.Rect(0,0,image.get_width(),image.get_height()) + shape = pygame.Rect(0, 0, image.get_width(), image.get_height()) if isinstance(shape, tuple): shape = pygame.Rect(shape) self.image = image self._image = self.image self.shape = shape - self.rect = pygame.Rect(pos[0],pos[1],shape.w,shape.h) + self.rect = pygame.Rect(pos[0], pos[1], shape.w, shape.h) self._rect = pygame.Rect(self.rect) - self.irect = pygame.Rect(pos[0]-self.shape.x,pos[1]-self.shape.y, - image.get_width(),image.get_height()) + self.irect = pygame.Rect(pos[0]-self.shape.x, pos[1]-self.shape.y, + image.get_width(), image.get_height()) self._irect = pygame.Rect(self.irect) self.groups = 0 self.agroups = 0 self.updated = 1 - - def setimage(self,ishape): + + def setimage(self, ishape): """Set the image of the Sprite. - + Arguments: ishape -- an image, or an image, rectstyle. The rectstyle will describe the shape of the image, used for collision detection. - """ + """ if not isinstance(ishape, tuple): - ishape = ishape,None - image,shape = ishape + ishape = ishape, None + image, shape = ishape if shape == None: - shape = pygame.Rect(0,0,image.get_width(),image.get_height()) + shape = pygame.Rect(0, 0, image.get_width(), image.get_height()) if isinstance(shape, tuple): shape = pygame.Rect(shape) self.image = image self.shape = shape - self.rect.w,self.rect.h = shape.w,shape.h - self.irect.w,self.irect.h = image.get_width(),image.get_height() + self.rect.w, self.rect.h = shape.w, shape.h + self.irect.w, self.irect.h = image.get_width(), image.get_height() self.updated = 1 - -class Tile: + +class Tile(object): """Tile Object used by TileCollide. - + Arguments: image -- an image for the Tile. - + Attributes: agroups -- the groups the Tile can hit in a collision - hit -- the handler for hits -- hit(g,t,a) + hit -- the handler for hits -- hit(g, t, a) """ - def __init__(self,image=None): + def __init__(self, image=None): self.image = image self.agroups = 0 - - def __setattr__(self,k,v): + + def __setattr__(self, k, v): if k == 'image' and v != None: self.image_h = v.get_height() self.image_w = v.get_width() @@ -111,25 +105,25 @@ def __setattr__(self,k,v): class _Sprites(list): def __init__(self): - list.__init__(self) + super(_Sprites, self).__init__() self.removed = [] - - def append(self,v): - list.append(self,v) + + def append(self, v): + list.append(self, v) v.updated = 1 - - def remove(self,v): - list.remove(self,v) + + def remove(self, v): + list.remove(self, v) v.updated = 1 self.removed.append(v) - -class Vid: + +class Vid(object): """An engine for rendering Sprites and Tiles. - + Attributes: sprites -- a list of the Sprites to be displayed. You may append and remove Sprites from it. - images -- a dict for images to be put in. + images -- a dict for images to be put in. size -- the width, height in Tiles of the layers. Do not modify. view -- a pygame.Rect of the viewed area. You may change .x, .y, etc to move the viewed area around. @@ -139,58 +133,58 @@ class Vid: tlayer -- the foreground tiles layer clayer -- the code layer (optional) blayer -- the background tiles layer (optional) - groups -- a hash of group names to group values (32 groups max, as a tile/sprites + groups -- a hash of group names to group values (32 groups max, as a tile/sprites membership in a group is determined by the bits in an integer) """ - + def __init__(self): - self.tiles = [None for x in xrange(0,256)] + self.tiles = [None for x in range(0, 256)] self.sprites = _Sprites() self.images = {} #just a store for images. self.layers = None self.size = None - self.view = pygame.Rect(0,0,0,0) + self.view = pygame.Rect(0, 0, 0, 0) self._view = pygame.Rect(self.view) self.bounds = None self.updates = [] self.groups = {} - - - def resize(self,size,bg=0): + + + def resize(self, size, bg=0): """Resize the layers. - + Arguments: - size -- w,h in Tiles of the layers + size -- w, h in Tiles of the layers bg -- set to 1 if you wish to use both a foreground layer and a background layer """ self.size = size - w,h = size - self.layers = [[[0 for x in xrange(0,w)] for y in xrange(0,h)] - for z in xrange(0,4)] + w, h = size + self.layers = [[[0 for x in range(0, w)] for y in range(0, h)] + for z in range(0, 4)] self.tlayer = self.layers[0] self.blayer = self.layers[1] if not bg: self.blayer = None self.clayer = self.layers[2] self.alayer = self.layers[3] - - self.view.x, self.view.y = 0,0 - self._view.x, self.view.y = 0,0 + + self.view.x, self.view.y = 0, 0 + self._view.x, self.view.y = 0, 0 self.bounds = None - + self.updates = [] - - def set(self,pos,v): + + def set(self, pos, v): """Set a tile in the foreground to a value. - + Use this method to set tiles in the foreground, as it will make sure the screen is updated with the change. Directly changing the tlayer will not guarantee updates unless you are using .paint() - + Arguments: - pos -- (x,y) of tile + pos -- (x, y) of tile v -- value """ @@ -198,19 +192,19 @@ def set(self,pos,v): self.tlayer[pos[1]][pos[0]] = v self.alayer[pos[1]][pos[0]] = 1 self.updates.append(pos) - - def get(self,pos): + + def get(self, pos): """Get the tlayer at pos. - + Arguments: - pos -- (x,y) of tile + pos -- (x, y) of tile """ return self.tlayer[pos[1]][pos[0]] - - def paint(self,s): + + def paint(self, s): """Paint the screen. - + Arguments: screen -- a pygame.Surface to paint to @@ -218,22 +212,22 @@ def paint(self,s): """ return [] - - def update(self,s): + + def update(self, s): """Update the screen. - + Arguments: screen -- a pygame.Rect to update - + Returns a list of updated rectangles. """ self.updates = [] return [] - def tga_load_level(self,fname,bg=0): - """Load a TGA level. - + def tga_load_level(self, fname, bg=0): + """Load a TGA level. + Arguments: g -- a Tilevid instance fname -- tga image to load @@ -242,132 +236,132 @@ def tga_load_level(self,fname,bg=0): """ if type(fname) == str: img = pygame.image.load(fname) else: img = fname - w,h = img.get_width(),img.get_height() - self.resize((w,h),bg) - for y in range(0,h): - for x in range(0,w): - t,b,c,_a = img.get_at((x,y)) + w, h = img.get_width(), img.get_height() + self.resize((w, h), bg) + for y in range(0, h): + for x in range(0, w): + t, b, c, _a = img.get_at((x, y)) self.tlayer[y][x] = t if bg: self.blayer[y][x] = b self.clayer[y][x] = c - - def tga_save_level(self,fname): + + def tga_save_level(self, fname): """Save a TGA level. Arguments: fname -- tga image to save to """ - w,h = self.size - img = pygame.Surface((w,h),SWSURFACE,32) - img.fill((0,0,0,0)) - for y in range(0,h): - for x in range(0,w): + w, h = self.size + img = pygame.Surface((w, h), SWSURFACE, 32) + img.fill((0, 0, 0, 0)) + for y in range(0, h): + for x in range(0, w): t = self.tlayer[y][x] b = 0 if self.blayer: b = self.blayer[y][x] c = self.clayer[y][x] _a = 0 - img.set_at((x,y),(t,b,c,_a)) - pygame.image.save(img,fname) - - + img.set_at((x, y), (t, b, c, _a)) + pygame.image.save(img, fname) - def tga_load_tiles(self,fname,size,tdata={}): + + + def tga_load_tiles(self, fname, size, tdata={}): """Load a TGA tileset. - + Arguments: g -- a Tilevid instance fname -- tga image to load - size -- (w,h) size of tiles in pixels + size -- (w, h) size of tiles in pixels tdata -- tile data, a dict of tile:(agroups, hit handler, config) """ - TW,TH = size + TW, TH = size if type(fname) == str: img = pygame.image.load(fname).convert_alpha() else: img = fname - w,h = img.get_width(),img.get_height() - + w, h = img.get_width(), img.get_height() + n = 0 - for y in range(0,h,TH): - for x in range(0,w,TW): - i = img.subsurface((x,y,TW,TH)) + for y in range(0, h, TH): + for x in range(0, w, TW): + i = img.subsurface((x, y, TW, TH)) tile = Tile(i) self.tiles[n] = tile if n in tdata: - agroups,hit,config = tdata[n] + agroups, hit, config = tdata[n] tile.agroups = self.string2groups(agroups) tile.hit = hit tile.config = config n += 1 - def load_images(self,idata): + def load_images(self, idata): """Load images. - + Arguments: idata -- a list of (name, fname, shape) """ - for name,fname,shape in idata: - self.images[name] = pygame.image.load(fname).convert_alpha(),shape + for name, fname, shape in idata: + self.images[name] = pygame.image.load(fname).convert_alpha(), shape - def run_codes(self,cdata,rect): + def run_codes(self, cdata, rect): """Run codes. - + Arguments: cdata -- a dict of code:(handler function, value) rect -- a tile rect of the parts of the layer that should have their codes run """ - tw,th = self.tiles[0].image.get_width(),self.tiles[0].image.get_height() + tw, th = self.tiles[0].image.get_width(), self.tiles[0].image.get_height() - x1,y1,w,h = rect + x1, y1, w, h = rect clayer = self.clayer t = Tile() - for y in range(y1,y1+h): - for x in range(x1,x1+w): + for y in range(y1, y1 + h): + for x in range(int(x1), int(x1 + w)): n = clayer[y][x] if n in cdata: - fnc,value = cdata[n] - t.tx,t.ty = x,y - t.rect = pygame.Rect(x*tw,y*th,tw,th) - fnc(self,t,value) + fnc, value = cdata[n] + t.tx, t.ty = x, y + t.rect = pygame.Rect(x*tw, y*th, tw, th) + fnc(self, t, value) - - def string2groups(self,str): + + def string2groups(self, str): """Convert a string to groups.""" if str == None: return 0 - return self.list2groups(str.split(",")) + return self.list2groups(str.split(", ")) - def list2groups(self,igroups): + def list2groups(self, igroups): """Convert a list to groups.""" for s in igroups: if not s in self.groups: self.groups[s] = 2**len(self.groups) v = 0 - for s,n in self.groups.items(): + for s, n in self.groups.items(): if s in igroups: v|=n return v - def groups2list(self,groups): + def groups2list(self, groups): """Convert a groups to a list.""" v = [] - for s,n in self.groups.items(): + for s, n in self.groups.items(): if (n&groups)!=0: v.append(s) return v - def hit(self,x,y,t,s): + def hit(self, x, y, t, s): tiles = self.tiles - tw,th = tiles[0].image.get_width(),tiles[0].image.get_height() + tw, th = tiles[0].image.get_width(), tiles[0].image.get_height() t.tx = x t.ty = y - t.rect = Rect(x*tw,y*th,tw,th) + t.rect = Rect(x*tw, y*th, tw, th) t._rect = t.rect - if hasattr(t,'hit'): - t.hit(self,t,s) + if hasattr(t, 'hit'): + t.hit(self, t, s) def loop(self): """Update and hit testing loop. Run this once per frame.""" @@ -376,29 +370,29 @@ def loop(self): self.loop_spritehits() #no sprites should move for s in self.sprites: s._rect = pygame.Rect(s.rect) - + def loop_sprites(self): as_ = self.sprites[:] for s in as_: - if hasattr(s,'loop'): - s.loop(self,s) + if hasattr(s, 'loop'): + s.loop(self, s) def loop_tilehits(self): tiles = self.tiles - tw,th = tiles[0].image.get_width(),tiles[0].image.get_height() + tw, th = tiles[0].image.get_width(), tiles[0].image.get_height() layer = self.layers[0] as_ = self.sprites[:] for s in as_: self._tilehits(s) - - def _tilehits(self,s): + + def _tilehits(self, s): tiles = self.tiles - tw,th = tiles[0].image.get_width(),tiles[0].image.get_height() + tw, th = tiles[0].image.get_width(), tiles[0].image.get_height() layer = self.layers[0] - - for _z in (0,): + + for _z in (0, ): if s.groups != 0: _rect = s._rect @@ -418,29 +412,29 @@ def _tilehits(self,s): rect.h = _rect.h hits = [] - ct,cb,cl,cr = rect.top,rect.bottom,rect.left,rect.right + ct, cb, cl, cr = rect.top, rect.bottom, rect.left, rect.right #nasty ol loops - y = ct/th*th + y = ct // th * th while y < cb: - x = cl/tw*tw - yy = y/th + x = cl // tw * tw + yy = y // th while x < cr: - xx = x/tw + xx = x // tw t = tiles[layer[yy][xx]] if (s.groups & t.agroups)!=0: - #self.hit(xx,yy,t,s) - d = math.hypot(rect.centerx-(xx*tw+tw/2), - rect.centery-(yy*th+th/2)) - hits.append((d,t,xx,yy)) + #self.hit(xx, yy, t, s) + d = math.hypot(rect.centerx-(xx*tw+tw // 2), + rect.centery-(yy*th+th // 2)) + hits.append((d, t, xx, yy)) x += tw y += th - + hits.sort() - #if len(hits) > 0: print self.frame,hits - for d,t,xx,yy in hits: - self.hit(xx,yy,t,s) - + #if len(hits) > 0: print self.frame, hits + for d, t, xx, yy in hits: + self.hit(xx, yy, t, s) + #switching directions... _rect.x = rect.x _rect.w = rect.w @@ -448,27 +442,27 @@ def _tilehits(self,s): rect.h = recth hits = [] - ct,cb,cl,cr = rect.top,rect.bottom,rect.left,rect.right + ct, cb, cl, cr = rect.top, rect.bottom, rect.left, rect.right #nasty ol loops - y = ct/th*th + y = ct // th * th while y < cb: - x = cl/tw*tw - yy = y/th + x = cl // tw * tw + yy = y // th while x < cr: - xx = x/tw + xx = x // tw t = tiles[layer[yy][xx]] if (s.groups & t.agroups)!=0: - d = math.hypot(rect.centerx-(xx*tw+tw/2), - rect.centery-(yy*th+th/2)) - hits.append((d,t,xx,yy)) - #self.hit(xx,yy,t,s) + d = math.hypot(rect.centerx-(xx*tw+tw // 2), + rect.centery - (yy * th + th // 2)) + hits.append((d, t, xx, yy)) + #self.hit(xx, yy, t, s) x += tw y += th - - hits.sort() - #if len(hits) > 0: print self.frame,hits - for d,t,xx,yy in hits: - self.hit(xx,yy,t,s) + + hits.sort() + #if len(hits) > 0: print self.frame, hits + for d, t, xx, yy in hits: + self.hit(xx, yy, t, s) #done with loops _rect.x = _rectx @@ -477,9 +471,9 @@ def _tilehits(self,s): def loop_spritehits(self): as_ = self.sprites[:] - + groups = {} - for n in range(0,31): + for n in range(0, 31): groups[1<>= 1 n <<= 1 - + for s in as_: if s.agroups!=0: - rect1,rect2 = s.rect,Rect(s.rect) + rect1, rect2 = s.rect, Rect(s.rect) #if rect1.centerx < 320: rect2.x += 640 #else: rect2.x -= 640 g = s.agroups n = 1 while g: if (g&1)!=0: - for b in groups[n]: + for b in groups[n]: if (s != b and (s.agroups & b.groups)!=0 and s.rect.colliderect(b.rect)): - s.hit(self,s,b) + s.hit(self, s, b) g >>= 1 n <<= 1 - def screen_to_tile(self,pos): + def screen_to_tile(self, pos): """Convert a screen position to a tile position.""" return pos - - def tile_to_screen(self,pos): + + def tile_to_screen(self, pos): """Convert a tile position to a screen position.""" return pos - + +class VidPaintUpdateMixin: + pass diff --git a/scripts/leveledit b/scripts/leveledit index 17f760c..d5a9c4e 100755 --- a/scripts/leveledit +++ b/scripts/leveledit @@ -67,7 +67,7 @@ return - toggle fullscreen import os,sys from optparse import OptionParser -from ConfigParser import ConfigParser +from configparser import ConfigParser import pygame from pygame.locals import * @@ -206,8 +206,6 @@ class _app(gui.Container): #self.view_w = min(self.level.size[0],self.view_w) #self.view_h = min(self.level.size[1],self.view_h) - #print self.view_w,self.view_h - #self.view = self.level.subsurface((0,0,self.view_w,self.view_h)) self.select = Rect(0,0,self.level.size[0],self.level.size[1]) #self.view_w,self.view_h) @@ -262,7 +260,6 @@ class _app(gui.Container): #bx,by = lvl.screen_to_tile((self.vdraw.rect.w,self.vdraw.rect.h)) #rect = pygame.Rect(ox,oy,bx-ox,by-oy) - #print self.modrect h.append(self.changes) self.changes = [] @@ -454,8 +451,8 @@ class vdraw(gui.Widget): s = pygame.Surface((self.rect.w,self.rect.h)) clrs = [(148,148,148),(108,108,108)] inc = 7 - for y in range(0,self.rect.w//inc): - for x in range(0,self.rect.h//inc): + for y in range(0,self.rect.w/inc): + for x in range(0,self.rect.h/inc): s.fill(clrs[(x+y)%2],(x*inc,y*inc,inc,inc)) self.bg = s @@ -471,8 +468,8 @@ class vdraw(gui.Widget): def paint(self,s): - #print s - #print s.get_width(),s.get_height(),s.get_clip() + #print (s) + #print (s.get_width(),s.get_height(),s.get_clip()) #s.blit(self.bg,(0,0)) s.fill((128,128,128)) @@ -683,7 +680,7 @@ def cmd_all(value): app.select = Rect(0,0,app.level.size[0],app.level.size[1]) app.vdraw.repaint() - #print 'deprecated in v0.5' + #print('deprecated in v0.5') def cmd_shrink(value): if app.select.w <= 2 or app.select.h <= 2: return @@ -711,7 +708,7 @@ def cmd_copy(value): #app.clipboard.fill((0,0,0,0)) #app.clipboard.blit(s,(0,0)) - print app.clipboard.get_at((0,0)) + print(app.clipboard.get_at((0,0))) def cmd_paste(value): if app.clipboard != None: @@ -761,7 +758,7 @@ def _cmd_new(value): cfg['tiles'] = tiles cfg['class'] = klass ok = 1 - except Exception, v: + except Exception as v: ErrorDialog("New failed.",v).open() if ok: raise Restart() @@ -795,7 +792,7 @@ def _cmd_open(value): ok = 1 - except Exception,v: + except Exception as v: ErrorDialog("Open failed.",v).open() if ok: raise Restart() @@ -912,7 +909,7 @@ def cmd_save(value): cfg_to_ini(['class','codes','tiles','tile_w','tile_h'],app.fname) ini_save() app.dirty = 0 - except Exception, v: + except Exception as v: ErrorDialog("Save failed.",v).open() return @@ -921,7 +918,7 @@ import os def cmd_preview(value): app.level.tga_save_level("_preview.tga") cmd = "python preview.py _preview.tga" - print cmd + print(cmd) os.system(cmd) def cmd_quit(value): @@ -1140,7 +1137,7 @@ def init_ini(): ini.read([ini_fname]) def ini_save(): - f = open(ini_fname,"wb") + f = open(ini_fname,"wt") ini.write(f) f.close() @@ -1194,8 +1191,10 @@ def init_opts(): opts.codes = args[2] if len(args) in (4,5): n = len(args)-2 - try: opts.tile_w,opts.tile_h = int(args[n]),int(args[n+1]) - except: parser.error("width and height must be integers") + try: + opts.tile_w,opts.tile_h = int(args[n]),int(args[n+1]) + except ValueError: + parser.error("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 @@ -1382,7 +1381,8 @@ def main(): try: init_app() run() - except Restart: restart = 1 + except Restart: + restart = 1 main() # vim: set filetype=python sts=4 sw=4 noet si : diff --git a/scripts/levelfancy b/scripts/levelfancy index 3f44b63..6f7eadf 100755 --- a/scripts/levelfancy +++ b/scripts/levelfancy @@ -42,13 +42,6 @@ but those base tiles look better when rendered using lots of fancier tiles. import os,sys from optparse import OptionParser -try: - import psyco - psyco.full() - print 'psyco installed' -except: - print 'psyco not installed' - from pgu.tilevid import Tilevid scoring = [ @@ -139,7 +132,6 @@ for y in range(0,height): width,height = i_level.size for y in range(0,height): - print y for x in range(0,width): v = get(it,x,y) if v in used: diff --git a/scripts/tganew b/scripts/tganew index 2d6071b..c2b672e 100755 --- a/scripts/tganew +++ b/scripts/tganew @@ -18,9 +18,13 @@ parser = OptionParser(usage) if len(args) != 3: parser.error("incorrect number of arguments") -try: fname,w,h = args[0],int(args[1]),int(args[2]) -except: parser.error("width and height must be integers") -if w < 1 or h < 1: parser.error("width and height must be greater than 0") +try: + fname,w,h = args[0],int(args[1]),int(args[2]) +except ValueError: + parser.error("width and height must be integers") + +if w < 1 or h < 1: + parser.error("width and height must be greater than 0") import pygame from pygame.locals import * diff --git a/scripts/tileedit b/scripts/tileedit index 6d3e367..5cea762 100755 --- a/scripts/tileedit +++ b/scripts/tileedit @@ -62,15 +62,15 @@ F10 - toggle fullscreen import os,sys from optparse import OptionParser -from ConfigParser import ConfigParser +from configparser import ConfigParser import pygame from pygame.locals import * # try: # import Image # have_pil=True -# except: -# print "import Image failure; PIL not found." +# except ImportError: +# print ("import Image failure; PIL not found.") # have_pil=False have_pil = False @@ -422,8 +422,6 @@ class tdraw(gui.Widget): app.select.w = max(0,app.select.w) app.select.h = max(0,app.select.h) - #print app.select - self.repaint() @@ -559,7 +557,7 @@ def cmd_save(value): # so as to avoid race with anything reading it. temp_file_name = "tmp_" + app.fname - print temp_file_name + 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) @@ -571,7 +569,7 @@ def cmd_save(value): cfg_to_ini(['tile_w','tile_h','palette'],app.fname) ini_save() app.dirty = 0 - except Exception, v: + except Exception as v: ErrorDialog("Save failed.",v).open() return @@ -612,7 +610,7 @@ def _cmd_open(value): cfg['tile_w'] = tile_w cfg['tile_h'] = tile_h ok = 1 - except Exception,v: + except Exception as v: ErrorDialog("Open failed.",v).open() if ok: raise Restart() @@ -653,7 +651,7 @@ def _cmd_new(value): cfg['tile_w'] = tile_w cfg['tile_h'] = tile_h ok = 1 - except Exception, v: + except Exception as v: ErrorDialog("New failed.",v).open() if ok: raise Restart() @@ -759,13 +757,18 @@ def init_opts(): 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") + try: + opts.tile_w,opts.tile_h = int(args[0]),int(args[1]) + except ValueError: + 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") + try: + opts.fname,opts.tile_w,opts.tile_h = args[0],int(args[1]),int(args[2]) + except ValueError: + 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 @@ -1112,7 +1115,8 @@ def main(): try: init_app() run() - except Restart: restart = 1 + except Restart: + restart = 1