Attachment 'sqe.py'

Download

   1 #!/usr/bin/env python
   2 # -*- coding: utf8 -*-
   3 # vim: ts=4:expandtab:sw=4
   4 '''
   5 Веторный редактор, версия 4:
   6     * Простые фигуры
   7     * Фокус
   8     * Изменение тикпа, заливки, цвета (без выбора)
   9     * Перемещение и изменение размера
  10     * Запись и чтение из файла (без выбора)
  11 '''
  12 import pygame, random, sys
  13 pygame.init()
  14 
  15 color, back, width = (255,25,255), (0,0,0), 2
  16 W,H=800,600
  17 screen = pygame.display.set_mode((W,H))
  18 # Типы фигур
  19 shapes = ['rect','line','circle','ellipse']
  20 
  21 def draw_figure(scr, fig):
  22     '''Нарисовать фигуру fig на поверхности scr'''
  23     width,rect,color=fig['width'],fig['rect'],fig['color']
  24     if not fig['shape']:
  25         return
  26     elif fig['shape'] == 'rect':
  27         pygame.draw.rect(scr,color,rect,fig['empty'] and width or 0)
  28     elif fig['shape'] == 'line':
  29         pygame.draw.line(scr,color,rect.topleft,rect.bottomright,width)
  30     elif fig['shape'] == 'circle':
  31         r = max(min(rect.size)/2,width)
  32         pygame.draw.circle(scr,color,rect.center,r,fig['empty'] and width or 0)
  33     elif fig['shape'] == 'ellipse':
  34         r = rect.union(pygame.Rect(0,0,width*2,width*2).clamp(rect))
  35         pygame.draw.ellipse(scr,color,r,fig['empty'] and width or 0)
  36     else:
  37         print >> sys.stderr, "'%s' unimplemented"%fig['shape']
  38 
  39 def draw_all(scr, figs):
  40     '''Нарисовать все фигуры figs на поверхности scr'''
  41     scr.fill(back)
  42     for f in figs:
  43         draw_figure(scr,f)
  44 
  45 def draw_2circle(scr, pos):
  46     '''Нарисовать чёрно-белую окружность'''
  47     pygame.draw.circle(scr, (255,255,255), pos, 2)
  48     pygame.draw.circle(scr, (0,0,0), pos, 3, 1)
  49 
  50 def draw_focus(scr, f):
  51     '''Нарисовать на фигуре f пометку о том, что она получила фокус'''
  52     draw_2circle(scr, f['rect'].topleft)
  53     draw_2circle(scr, f['rect'].topright)
  54     draw_2circle(scr, f['rect'].bottomleft)
  55     draw_2circle(scr, f['rect'].bottomright)
  56 
  57 def get_focus(figs, pos):
  58     'Какой из фигур в figs принадлежат координаты pos'
  59     for i in xrange(len(figs)-1, -1, -1):
  60         if figs[i]['rect'].collidepoint(pos):
  61             return i
  62     return 0
  63 
  64 def upfocus(f, figs):
  65     'Поднять фигуру f в figs на 1 слой'
  66     if f < len(figs)-1 and f>0:
  67         figs[f:f+2]=[figs[f+1],figs[f]]
  68         return f+1
  69     return len(figs) - 1
  70 
  71 def downfocus(f, figs):
  72     'Опустить фигуру f в figs на 1 слой (не ниже подложки)'
  73     if f > 1:
  74         figs[f-1:f+1]=[figs[f],figs[f-1]]
  75         return f-1
  76     return 0
  77 
  78 def random_color(grad=16,channel=255,grey=25):
  79     'Случайный цвет в диапазоне grey..channel (grad градаций каждого канала)'
  80     return [random.randint(0,grad-1)*(channel-grey)/(grad-1)+grey for i in xrange(3)]
  81 
  82 def gen_random(shape=shapes[0], size=[], pos=[], color=[], width=width, empty=True):
  83     '''Сгенерировать фигуру (если параметр не задан, выбирается случайно)
  84     shape -- тип фигуры (по умолчанию 'rect')
  85     size -- размер
  86     pos -- координаты
  87     color -- цвет
  88     width -- ширина пера
  89     empty -- вид заливки (по умолчанию -- пустая)
  90     '''
  91     col = color or random_color()
  92     x, y = pos or (random.randint(10,W-50), random.randint(10,H-50))
  93     w, h = size or (random.randint(50, W-x), random.randint(50, H-y))
  94     return { 'rect':pygame.Rect(x,y,w,h),
  95              'color':col,
  96              'width':width,
  97              'shape':shape,
  98              'empty':empty,
  99            }
 100 
 101 def read_figure(name):
 102     'Прочитать фигуры из файла name'
 103     f = file(name,"r")
 104     W,H=[int(i) for i in f.readline().split()]
 105     fg=[]
 106     for s in f.readlines():
 107         l=s.split()
 108         if l[0] == 'color':
 109             color=[int(i) for i in l[1:]]
 110         elif l[0] == 'width':
 111             width = int(l[1])
 112         else:
 113             shape, rct, args  = l[0], [int(i) for i in l[1:5]], l[5:]
 114             fg.append(gen_random(shape, rct[2:4], rct[:2], color, empty='fill' not in args))
 115     f.close()
 116     return fg
 117 
 118 def select_filename():
 119     'TODO: выбор имени файла'
 120     return "figure"
 121 
 122 def write_figure(name):
 123     'Зпаисать фигуру в файл'
 124     f = file(name,"w")
 125     col = (-1,-1,-1)
 126     print >> f, W, H    # размер
 127     print >> f, "width %d"%width
 128     for fig in figs[1:]:
 129         rect=fig['rect']
 130         if fig['color']!=col:
 131             print >> f, "color %d %d %d"%tuple(fig['color'])
 132             col=fig['color']
 133         if fig['width']!=width:
 134             print >> f, "width %d"%fig['width']
 135         s="%d %d %d %d"%(rect.left,rect.top,rect.w,rect.h)
 136         print >> f, fig['shape'],s + (not fig['empty'] and ' fill' or '')
 137     f.close()
 138 
 139 backing = gen_random('rect',(W,H),(0,0),back)   # подложка
 140 figs = [backing.copy()]
 141 focus = 0
 142 debug= False
 143 while True:
 144     event = pygame.event.wait()
 145     if debug: print event
 146     if event.type == pygame.QUIT:
 147         sys.exit()
 148     elif event.type == pygame.MOUSEBUTTONDOWN:
 149         nfocus = get_focus(figs, event.pos)
 150         if event.button == 1:   # смена фокуса
 151             focus = nfocus
 152         elif event.button == 4: # поднять фигуру
 153             focus = upfocus(focus,figs)
 154         elif event.button == 5: # опустить фигуру
 155             focus = downfocus(focus,figs)
 156     elif event.type == pygame.MOUSEMOTION:
 157         if event.buttons[0]:    # переместить
 158             figs[focus]['rect'].move_ip(event.rel)
 159         elif event.buttons[2]:  # изменить размер
 160             figs[focus]['rect'].inflate_ip(event.rel)
 161     elif event.type == pygame.KEYDOWN:
 162         if event.key == 8:      # BackSpace - отладочная выдача
 163             debug = not debug
 164         elif event.key == 32:  # Space - случайный цвет
 165             figs[focus]['color']=random_color()
 166         elif event.key == 275:  # Right - увеличить ширину пера
 167             figs[focus]['width']+=1
 168         elif event.key == 276:  # Left - уменьшить ширину пера (>0)
 169             figs[focus]['width']=max(1,figs[focus]['width']-1)
 170         elif event.key == 274:  # Down - смениь тип заливки
 171             figs[focus]['empty']=not figs[focus]['empty']
 172         elif event.key == 273:  # Up - сменить тип фигуры
 173             if focus>=0:
 174                 newt=(shapes.index(figs[focus]['shape'])+1)%len(shapes)
 175                 figs[focus]['shape']=shapes[newt]
 176         elif event.key == 277:  # Ins - доавить ещё одну фигуру
 177             figs.append(gen_random(figs[focus]['shape'],empty=figs[focus]['empty']))
 178         elif event.key == 127:  # Del - удалить фигуру (кроме подложки)
 179             if len(figs)>1: figs.pop(focus)
 180             if focus>=len(figs):
 181                 focus=len(figs)-1
 182         elif event.key == 270:  # grey + - поднять фигуру
 183             focus = upfocus(focus,figs)
 184         elif event.key == 269:  # grey - - опустить фигуру
 185             focus = downfocus(focus,figs)
 186         elif event.key == 9:    # tab - сменить фокус
 187             focus = (focus + 1)%len(figs)
 188         elif event.key == 279:  # End - записать файл
 189             write_figure(select_filename())
 190         elif event.key == 278:  # Home - прочитать из файла
 191             figs=[backing.copy()]+read_figure(select_filename())
 192             focus=0
 193         elif event.key in range(48,56): # выбрать один из 8 цветов
 194             figs[focus]['color']=(
 195                                     ( event.key-48)   %2*220+30,
 196                                     ((event.key-48)/2)%2*220+30,
 197                                     ( event.key-48)/4   *220+30,
 198                                  )
 199     figs[0]=backing.copy()
 200     draw_all(screen, figs)
 201     if focus > 0:
 202         draw_focus(screen, figs[focus])
 203     pygame.display.flip()

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.