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