Sharedwww / talks / 2006-05-09-sage-digipen / tutorial / widget-1.pyOpen in CoCalc
Author: William A. Stein
1
# Soya 3D tutorial
2
# Copyright (C) 2005 Javier Correa Villanueva ([email protected])
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19
# widget-1: Widget system : a game presentation
20
21
# WARNING :
22
# soya.widget is now deprecated, you should rather consider using soya.pudding instead.
23
24
25
#!/usr/bin/env python -O
26
27
import sys, os, os.path
28
import soya
29
import soya.sdlconst
30
import soya.widget as widget
31
32
33
soya.init()
34
soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
35
# Some fonts
36
big_font = soya.Font(os.path.join(soya.DATADIR, "FreeSans.ttf"), 40, 60)
37
medium_font=widget.default_font
38
small_font = soya.Font(os.path.join(soya.DATADIR, "FreeSans.ttf"), 10, 15)
39
40
# This class is to get an input widget
41
# When you press RETURN key, it will call action with the text introduced as parameter
42
class Input(widget.Label):
43
def __init__(self, master = None, text = "", action=None,align = 0, color = (1.0, 1.0, 1.0, 1.0), font = None, resize_style = None):
44
self.action=action
45
widget.Label.__init__(self,master,text,align,color,font,resize_style)
46
47
def widget_begin_round(self):
48
for event in soya.process_event():
49
self.process_event(event)
50
51
def process_event(self,event):
52
if event[0]==soya.sdlconst.KEYDOWN :
53
if event[1]==soya.sdlconst.K_RETURN or event[1]==soya.sdlconst.K_KP_ENTER:
54
if self.action:
55
self.action(self.text)
56
else:
57
pass
58
elif event[1]==soya.sdlconst.K_DELETE or event[1]==soya.sdlconst.K_BACKSPACE:
59
if len(self.text)>0:
60
length=len(self.text)
61
temp_text=self.text[0:length-1]
62
self.text=temp_text
63
elif event[1]<256 and chr(event[1]).isalnum():
64
last_character=event[1]
65
# Now check is shift is pressed, i had to use numbers instead of
66
# macros, my soya isntalation didn't have macros for shift modification
67
if event[2]==1 or event[2]==2:
68
last_character-=32
69
temp_text=self.text
70
temp_text=temp_text+chr(last_character)
71
self.text=temp_text
72
73
# Password input, same as normal input, but display only * when character are introduced
74
class PasswordInput(widget.Label):
75
def __init__(self, master = None, text = "", action=None,align = 0, color = (1.0, 1.0, 1.0, 1.0), font = None, resize_style = None):
76
self.action=action
77
self.real_text=""
78
widget.Label.__init__(self,master,text,align,color,font,resize_style)
79
80
def widget_begin_round(self):
81
for event in soya.process_event():
82
self.process_event(event)
83
84
def process_event(self,event):
85
if event[0]==soya.sdlconst.KEYDOWN :
86
if event[1]==soya.sdlconst.K_RETURN or event[1]==soya.sdlconst.K_KP_ENTER:
87
if self.action:
88
self.action(self.real_text)
89
else:
90
pass
91
elif event[1]==soya.sdlconst.K_DELETE or event[1]==soya.sdlconst.K_BACKSPACE:
92
if len(self.text)>0:
93
length=len(self.text)
94
temp_text=self.text[0:length-1]
95
self.text=temp_text
96
temp_text=self.real_text[0:length-1]
97
self.real_text=temp_text
98
99
elif event[1]<256 and chr(event[1]).isalnum():
100
last_character=event[1]
101
if event[2]==1 or event[2]==2:
102
last_character-=32
103
self.text+='*'
104
self.real_text=self.real_text+chr(last_character)
105
106
# Widget with a few effects, fade and move
107
# It may be very ineficient
108
class EffectWidget:
109
# Change the init so if read a hash with the information to change
110
def __init__(self,fade_speed=0.05,up_speed=1.5,down_speed=1.5,left_speed=1.5,right_speed=1.5):
111
# Variables for fading effect
112
self.fadein=None
113
self.fadeout=None
114
self.faded=1
115
self.fade_speed=fade_speed
116
# Variable for moving
117
self.move_up=None
118
self.move_down=None
119
self.move_right=None
120
self.move_left=None
121
self.up_speed=up_speed
122
self.down_speed=down_speed
123
self.right_speed=right_speed
124
self.left_speed=left_speed
125
# The distance to move
126
self.up_distance=50
127
self.down_distance=50
128
self.left_distance=50
129
self.right_distance=50
130
# The traveled so far
131
self.up_travel=0
132
self.down_travel=0
133
self.left_travel=0
134
self.right_travel=0
135
136
def fadeIn(self):
137
self.fadein=1
138
self.fadeout=None
139
140
def fadeOut(self):
141
self.fadeout=1
142
self.fadein=None
143
144
def startUp(self):
145
self.move_up=1
146
self.move_down=None
147
def stopUp(self):
148
self.move_up=None
149
150
def startDown(self):
151
self.move_down=1
152
self.move_up=None
153
def stopDown(self):
154
self.move_down=None
155
156
def startLeft(self):
157
self.move_left=1
158
self.move_right=None
159
def stopLeft(self):
160
self.move_left=None
161
162
def startRight(self):
163
self.move_right=1
164
self.move_left=None
165
def stopRight(self):
166
self.move_right=None
167
168
def resetMove(self):
169
# Variable for moving
170
self.move_up=None
171
self.move_down=None
172
self.move_right=None
173
self.move_left=None
174
# The traveled so far
175
self.up_travel=0
176
self.down_travel=0
177
self.left_travel=0
178
self.right_travel=0
179
180
def doMove(self,proportion):
181
# Implementation of moving animation
182
if self.move_up:
183
if self.up_travel>self.up_distance:
184
self.move_up=None
185
self.up_travel=0
186
else:
187
self.top-=self.up_speed*proportion
188
self.up_travel+=self.up_speed*proportion
189
if self.move_down:
190
if self.down_travel>self.down_distance:
191
self.move_down=None
192
self.down_travel=0
193
else:
194
self.top+=self.down_speed*proportion
195
self.down_travel+=self.down_speed*proportion
196
197
if self.move_left:
198
if self.left_travel>self.left_distance:
199
self.move_left=None
200
self.left_travel=0
201
else:
202
self.top-=self.left_speed*proportion
203
self.left_travel+=self.left_speed*proportion
204
if self.move_right:
205
if self.right_travel>self.right_distance:
206
self.move_right=None
207
self.right_travel=0
208
else:
209
self.top+=self.right_speed*proportion
210
self.right_travel+=self.right_speed*proportion
211
212
# A choice wich is fadable also
213
class EffectChoice(EffectWidget,widget.ChoiceList):
214
def __init__(self, master = None, choices = [], font = None, color = (1.0, 0.5, 0.5,0.0),highlight = (1.0, 1.0, 0.0, 0.0), cancel = None,align=1,fade_speed=0.05):
215
widget.ChoiceList.__init__(self,master,choices,font,color,highlight,cancel,align)
216
EffectWidget.__init__(self,fade_speed)
217
218
def widget_begin_round(self):
219
if not self.faded:
220
widget.ChoiceList.widget_begin_round(self)
221
for event in soya.process_event():
222
self.process_event(event)
223
224
def widget_advance_time(self,proportion):
225
# Implementation of fadinf animation
226
if self.fadeout:
227
r1,g1,b1,a=self.color
228
r2,g2,b2,a2=self.highlight
229
a-=self.fade_speed*proportion
230
if a<0:
231
self.master.remove(self)
232
self.fadeout=None
233
self.faded=1
234
self.color=(r1,g1,b1,a)
235
self.highlight=(r2,g2,b2,a)
236
elif self.fadein:
237
if self.faded:
238
self.faded=None
239
r1,g1,b1,a=self.color
240
r2,g2,b2,a2=self.highlight
241
a+=self.fade_speed*proportion
242
if a<1:
243
self.color=(r1,g1,b1,a)
244
self.highlight=(r2,g2,b2,a)
245
else:
246
self.fadein=None
247
self.faded=None
248
self.doMove(proportion)
249
250
# A fadable label
251
class EffectLabel(EffectWidget,widget.Label):
252
def __init__(self, master = None, text = "", align = 0, color = (1.0, 1.0, 1.0, 0.0), font = None,resize_style = None,fade_speed=0.05):
253
widget.Label.__init__(self,master,text,align,color,font,resize_style)
254
EffectWidget.__init__(self,fade_speed)
255
256
def widget_advance_time(self,proportion):
257
if self.fadeout:
258
r,g,b,a=self.get_color()
259
a-=self.fade_speed*proportion
260
if a<0:
261
self.master.remove(self)
262
self.faded=1
263
self.fadeout=None
264
self.set_color((r,g,b,a))
265
elif self.fadein:
266
r,g,b,a=self.get_color()
267
a+=self.fade_speed*proportion
268
if a<1:
269
self.set_color((r,g,b,a))
270
else:
271
self.faded=None
272
self.fadein=None
273
self.doMove(proportion)
274
275
# The configuration screen
276
class ConfigureScreen(widget.Group):
277
def __init__(self,caller,background):
278
widget.Group.__init__(self)
279
self.caller=caller
280
self.state=0
281
if not background:
282
material=soya.Material()
283
#material.texture=soya.Image.get('back.png')
284
background=widget.Image(None,material)
285
background.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
286
self.add(background)
287
self.configureLabel=EffectLabel(self,'Configuration',1)
288
self.configureLabel.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
289
self.configureLabel.resize(0,-50,640,480)
290
self.configureLabel.resize_style=None
291
# The initial options of the game
292
optionResolution=widget.Choice('Change Resolution',self.changeResolution)
293
optionFullscreen=widget.Choice('Togle Fullscreen',self.goFullscreen)
294
optionServer=widget.Choice('Change Server',self.changeServer)
295
optionBack=widget.Choice('Back',self.goBack)
296
# The menu itself
297
self.optionsMenu=EffectChoice(self,[optionResolution,optionFullscreen,optionServer,optionBack])
298
self.optionsMenu.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
299
300
# Show the menu
301
self.configureLabel.fadeIn()
302
self.configureLabel.startDown()
303
self.optionsMenu.fadeIn()
304
305
def widget_begin_round(self):
306
widget.Group.widget_begin_round(self)
307
if self.state==10:
308
if self.configureLabel.faded:
309
self.master.add(self.caller)
310
self.master.remove(self)
311
self.add(self.configureLabel)
312
self.add(self.optionsMenu)
313
self.configureLabel.fadeIn()
314
self.configureLabel.startDown()
315
self.optionsMenu.fadeIn()
316
self.state=0
317
318
def changeResolution(self):
319
pass
320
def goFullscreen(self):
321
pass
322
def changeServer(self):
323
pass
324
def goBack(self):
325
self.state=10
326
self.configureLabel.fadeOut()
327
self.configureLabel.startUp()
328
self.optionsMenu.fadeOut()
329
330
class LoginScreen(widget.Group):
331
def __init__(self,background=None):
332
widget.Group.__init__(self)
333
if not background:
334
material=soya.Material()
335
#material.texture=soya.Image.get('back.png')
336
background=widget.Image(None,material)
337
background.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
338
self.add(background)
339
# The state on the login process
340
self.state=0
341
self.configScreen=ConfigureScreen(self,background)
342
# This will be the title of the game, always present
343
self.gameName=EffectLabel(self,"The Name of the Game",1,(.3,.3,1.0,0.0),big_font)
344
self.gameName.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
345
346
# The initial options of the game
347
optionLogin=widget.Choice('Login',self.startLogin)
348
optionConfig=widget.Choice('Configure',self.doConfiguration)
349
optionQuit=widget.Choice('Quit',self.quitGame)
350
# The menu itself
351
self.optionsMenu=EffectChoice(self,[optionLogin,optionConfig,optionQuit])
352
self.optionsMenu.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
353
354
# A label saying "Enter username" and user input
355
self.userLabel=EffectLabel(None,'Username:',1)
356
self.userLabel.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
357
self.userLabel.resize(0,100,640,100)
358
self.userLabel.resize_style=None
359
self.userInput=Input(None,"",self.setUser,1)
360
self.userInput.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
361
self.userInput.resize(0,200,640,100)
362
self.userInput.resize_style=None
363
364
# The password label and input
365
self.passLabel=EffectLabel(None,'Password:',1)
366
self.passLabel.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
367
self.passLabel.resize(0,100,640,100)
368
self.passLabel.resize_style=None
369
self.passInput=PasswordInput(None,"",self.doLogin,1)
370
self.passInput.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
371
self.passInput.resize(0,200,640,100)
372
self.passInput.resize_style=None
373
374
# Everything set, let's show the menu
375
self.optionsMenu.fadeIn()
376
self.gameName.fadeIn()
377
378
def widget_begin_round(self):
379
widget.Group.widget_begin_round(self)
380
if self.state==1:
381
if self.optionsMenu.faded:
382
self.optionsMenu.resetMove()
383
self.gameName.resetMove()
384
self.state=2
385
elif self.state==2:
386
self.add(self.userLabel)
387
self.add(self.userInput)
388
self.userLabel.fadeIn()
389
self.state=3
390
elif self.state==4:
391
if self.userLabel.faded:
392
self.state=5
393
elif self.state==5:
394
self.add(self.passLabel)
395
self.add(self.passInput)
396
self.passLabel.fadeIn()
397
self.state=6
398
elif self.state==10:
399
if self.optionsMenu.faded:
400
self.optionsMenu.resetMove()
401
self.gameName.resetMove()
402
self.master.add(self.configScreen)
403
self.master.remove(self)
404
# Set fadeIn, so the next time we add this widget to the root, it will fade in
405
self.add(self.optionsMenu)
406
self.add(self.gameName)
407
self.optionsMenu.fadeIn()
408
self.gameName.fadeIn()
409
self.state=0
410
411
def startLogin(self):
412
self.optionsMenu.fadeOut()
413
self.optionsMenu.startDown()
414
self.state=1
415
416
def mainMenu(self):
417
self.add(self.optionsMenu)
418
self.optionsMenu.fadeIn()
419
self.state=0
420
421
def setUser(self,text):
422
self.userLabel.fadeOut()
423
self.remove(self.userInput)
424
self.state=4
425
426
def doLogin(self,text):
427
self.passLabel.fadeOut()
428
self.remove(self.passInput)
429
print 'The End'
430
self.mainMenu()
431
432
def doConfiguration(self):
433
self.optionsMenu.fadeOut()
434
self.optionsMenu.startUp()
435
self.gameName.fadeOut()
436
self.gameName.startDown()
437
self.state=10
438
439
def quitGame(self):
440
sys.exit()
441
442
443
scene = soya.World()
444
root=soya.widget.Group()
445
soya.set_root_widget(root)
446
root.add(LoginScreen())
447
soya.Idler(scene).idle()
448