Playing a little with widgets, i made this, maybe it could be used as
tutorial??
CODE:
#!/usr/bin/env python -O
import sys, os, os.path
import soya
import soya.sdlconst
import soya.widget as widget
soya.init()
soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
# Some fonts
big_font = soya.Font(os.path.join(soya.DATADIR, "FreeSans.ttf"), 40, 60)
medium_font=widget.default_font
small_font = soya.Font(os.path.join(soya.DATADIR, "FreeSans.ttf"), 10, 15)
# This class is to get an input widget
# When you press RETURN key, it will call action with the text introduced as
parameter
class Input(widget.Label):
def __init__(self, master = None, text = "", action=None,align = 0, color =
(1.0, 1.0, 1.0, 1.0), font = None, resize_style = None):
self.action=action
widget.Label.__init__(self,master,text,align,color,font,resize_style)
def widget_begin_round(self):
for event in soya.process_event():
self.process_event(event)
def process_event(self,event):
if event[0]==soya.sdlconst.KEYDOWN :
if event[1]==soya.sdlconst.K_RETURN or
event[1]==soya.sdlconst.K_KP_ENTER:
if self.action:
self.action(self.text)
else:
pass
elif event[1]==soya.sdlconst.K_DELETE or
event[1]==soya.sdlconst.K_BACKSPACE:
if len(self.text)>0:
length=len(self.text)
temp_text=self.text[0:length-1]
self.text=temp_text
elif event[1]<256 and chr(event[1]).isalnum():
last_character=event[1]
# Now check is shift is pressed, i had to use numbers instead of
# macros, my soya isntalation didn't have macros for shift
modification
if event[2]==1 or event[2]==2:
last_character-=32
temp_text=self.text
temp_text=temp_text+chr(last_character)
self.text=temp_text
# Password input, same as normal input, but display only * when character
are introduced
class PasswordInput(widget.Label):
def __init__(self, master = None, text = "", action=None,align = 0, color =
(1.0, 1.0, 1.0, 1.0), font = None, resize_style = None):
self.action=action
self.real_text=""
widget.Label.__init__(self,master,text,align,color,font,resize_style)
def widget_begin_round(self):
for event in soya.process_event():
self.process_event(event)
def process_event(self,event):
if event[0]==soya.sdlconst.KEYDOWN :
if event[1]==soya.sdlconst.K_RETURN or
event[1]==soya.sdlconst.K_KP_ENTER:
if self.action:
self.action(self.real_text)
else:
pass
elif event[1]==soya.sdlconst.K_DELETE or
event[1]==soya.sdlconst.K_BACKSPACE:
if len(self.text)>0:
length=len(self.text)
temp_text=self.text[0:length-1]
self.text=temp_text
temp_text=self.real_text[0:length-1]
self.real_text=temp_text
elif event[1]<256 and chr(event[1]).isalnum():
last_character=event[1]
if event[2]==1 or event[2]==2:
last_character-=32
self.text+='*'
self.real_text=self.real_text+chr(last_character)
# Widget with a few effects, fade and move
# It may be very ineficient
class EffectWidget:
# Change the init so if read a hash with the information to change
def
__init__(self,fade_speed=0.01,up_speed=.5,down_speed=.5,left_speed=.5,right_
speed=.5):
# Variables for fading effect
self.fadein=None
self.fadeout=None
self.faded=1
self.fade_speed=fade_speed
# Variable for moving
self.move_up=None
self.move_down=None
self.move_right=None
self.move_left=None
self.up_speed=up_speed
self.down_speed=down_speed
self.right_speed=right_speed
self.left_speed=left_speed
# The distance to move
self.up_distance=50
self.down_distance=50
self.left_distance=50
self.right_distance=50
# The traveled so far
self.up_travel=0
self.down_travel=0
self.left_travel=0
self.right_travel=0
def fadeIn(self):
self.fadein=1
self.fadeout=None
def fadeOut(self):
self.fadeout=1
self.fadein=None
def startUp(self):
self.move_up=1
self.move_down=None
def stopUp(self):
self.move_up=None
def startDown(self):
self.move_down=1
self.move_up=None
def stopDown(self):
self.move_down=None
def startLeft(self):
self.move_left=1
self.move_right=None
def stopLeft(self):
self.move_left=None
def startRight(self):
self.move_right=1
self.move_left=None
def stopRight(self):
self.move_right=None
def resetMove(self):
# Variable for moving
self.move_up=None
self.move_down=None
self.move_right=None
self.move_left=None
# The traveled so far
self.up_travel=0
self.down_travel=0
self.left_travel=0
self.right_travel=0
def doMove(self,proportion):
# Implementation of moving animation
if self.move_up:
if self.up_travel>self.up_distance:
self.move_up=None
self.up_travel=0
else:
self.top-=self.up_speed*proportion
self.up_travel+=self.up_speed*proportion
if self.move_down:
if self.down_travel>self.down_distance:
self.move_down=None
self.down_travel=0
else:
self.top+=self.down_speed*proportion
self.down_travel+=self.down_speed*proportion
if self.move_left:
if self.left_travel>self.left_distance:
self.move_left=None
self.left_travel=0
else:
self.top-=self.left_speed*proportion
self.left_travel+=self.left_speed*proportion
if self.move_right:
if self.right_travel>self.right_distance:
self.move_right=None
self.right_travel=0
else:
self.top+=self.right_speed*proportion
self.right_travel+=self.right_speed*proportion
# A choice wich is fadable also
class EffectChoice(EffectWidget,widget.ChoiceList):
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.01):
widget.ChoiceList.__init__(self,master,choices,font,color,highlight,cancel,a
lign)
EffectWidget.__init__(self,fade_speed)
def widget_begin_round(self):
if not self.faded:
widget.ChoiceList.widget_begin_round(self)
for event in soya.process_event():
self.process_event(event)
def widget_advance_time(self,proportion):
# Implementation of fadinf animation
if self.fadeout:
r1,g1,b1,a=self.color
r2,g2,b2,a2=self.highlight
a-=self.fade_speed*proportion
if a<0:
self.master.remove(self)
self.fadeout=None
self.faded=1
self.color=(r1,g1,b1,a)
self.highlight=(r2,g2,b2,a)
elif self.fadein:
if self.faded:
self.faded=None
r1,g1,b1,a=self.color
r2,g2,b2,a2=self.highlight
a+=self.fade_speed*proportion
if a<1:
self.color=(r1,g1,b1,a)
self.highlight=(r2,g2,b2,a)
else:
self.fadein=None
self.faded=None
self.doMove(proportion)
# A fadable label
class EffectLabel(EffectWidget,widget.Label):
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.01):
widget.Label.__init__(self,master,text,align,color,font,resize_style)
EffectWidget.__init__(self,fade_speed)
def widget_advance_time(self,proportion):
if self.fadeout:
r,g,b,a=self.get_color()
a-=self.fade_speed*proportion
if a<0:
self.master.remove(self)
self.faded=1
self.fadeout=None
self.set_color((r,g,b,a))
elif self.fadein:
r,g,b,a=self.get_color()
a+=self.fade_speed*proportion
if a<1:
self.set_color((r,g,b,a))
else:
self.faded=None
self.fadein=None
self.doMove(proportion)
# The configuration screen
class ConfigureScreen(widget.Group):
def __init__(self,caller,background):
widget.Group.__init__(self)
self.caller=caller
self.state=0
if not background:
material=soya.Material()
material.texture=soya.Image.get('back.png')
background=widget.Image(None,material)
background.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
self.add(background)
self.configureLabel=EffectLabel(self,'Configuration',1)
self.configureLabel.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
self.configureLabel.resize(0,-50,640,480)
self.configureLabel.resize_style=None
# The initial options of the game
optionResolution=widget.Choice('Change Resolution',self.changeResolution)
optionFullscreen=widget.Choice('Togle Fullscreen',self.goFullscreen)
optionServer=widget.Choice('Change Server',self.changeServer)
optionBack=widget.Choice('Back',self.goBack)
# The menu itself
self.optionsMenu=EffectChoice(self,[optionResolution,optionFullscreen,option
Server,optionBack])
self.optionsMenu.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
# Show the menu
self.configureLabel.fadeIn()
self.configureLabel.startDown()
self.optionsMenu.fadeIn()
def widget_begin_round(self):
widget.Group.widget_begin_round(self)
if self.state==10:
if self.configureLabel.faded:
self.master.add(self.caller)
self.master.remove(self)
self.add(self.configureLabel)
self.add(self.optionsMenu)
self.configureLabel.fadeIn()
self.configureLabel.startDown()
self.optionsMenu.fadeIn()
self.state=0
def changeResolution(self):
pass
def goFullscreen(self):
pass
def changeServer(self):
pass
def goBack(self):
self.state=10
self.configureLabel.fadeOut()
self.configureLabel.startUp()
self.optionsMenu.fadeOut()
class LoginScreen(widget.Group):
def __init__(self,background=None):
widget.Group.__init__(self)
if not background:
material=soya.Material()
material.texture=soya.Image.get('back.png')
background=widget.Image(None,material)
background.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
self.add(background)
# The state on the login process
self.state=0
self.configScreen=ConfigureScreen(self,background)
# This will be the title of the game, always present
self.gameName=EffectLabel(self,"The Name of the
Game",1,(.3,.3,1.0,0.0),big_font)
self.gameName.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
# The initial options of the game
optionLogin=widget.Choice('Login',self.startLogin)
optionConfig=widget.Choice('Configure',self.doConfiguration)
optionQuit=widget.Choice('Quit',self.quitGame)
# The menu itself
self.optionsMenu=EffectChoice(self,[optionLogin,optionConfig,optionQuit])
self.optionsMenu.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
# A label saying "Enter username" and user input
self.userLabel=EffectLabel(None,'Username:',1)
self.userLabel.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
self.userLabel.resize(0,100,640,100)
self.userLabel.resize_style=None
self.userInput=Input(None,"",self.setUser,1)
self.userInput.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
self.userInput.resize(0,200,640,100)
self.userInput.resize_style=None
# The password label and input
self.passLabel=EffectLabel(None,'Password:',1)
self.passLabel.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
self.passLabel.resize(0,100,640,100)
self.passLabel.resize_style=None
self.passInput=PasswordInput(None,"",self.doLogin,1)
self.passInput.resize_style=soya.widget.WIDGET_RESIZE_MAXIMIZE
self.passInput.resize(0,200,640,100)
self.passInput.resize_style=None
# Everything set, let's show the menu
self.optionsMenu.fadeIn()
self.gameName.fadeIn()
def widget_begin_round(self):
widget.Group.widget_begin_round(self)
if self.state==1:
if self.optionsMenu.faded:
self.optionsMenu.resetMove()
self.gameName.resetMove()
self.state=2
elif self.state==2:
self.add(self.userLabel)
self.add(self.userInput)
self.userLabel.fadeIn()
self.state=3
elif self.state==4:
if self.userLabel.faded:
self.state=5
elif self.state==5:
self.add(self.passLabel)
self.add(self.passInput)
self.passLabel.fadeIn()
self.state=6
elif self.state==10:
if self.optionsMenu.faded:
self.optionsMenu.resetMove()
self.gameName.resetMove()
self.master.add(self.configScreen)
self.master.remove(self)
# Set fadeIn, so the next time we add this widget to the root, it
will fade in
self.add(self.optionsMenu)
self.add(self.gameName)
self.optionsMenu.fadeIn()
self.gameName.fadeIn()
self.state=0
def startLogin(self):
self.optionsMenu.fadeOut()
self.optionsMenu.startDown()
self.state=1
def mainMenu(self):
self.add(self.optionsMenu)
self.optionsMenu.fadeIn()
self.state=0
def setUser(self,text):
self.userLabel.fadeOut()
self.remove(self.userInput)
self.state=4
def doLogin(self,text):
self.passLabel.fadeOut()
self.remove(self.passInput)
print 'The End'
self.mainMenu()
def doConfiguration(self):
self.optionsMenu.fadeOut()
self.optionsMenu.startUp()
self.gameName.fadeOut()
self.gameName.startDown()
self.state=10
def quitGame(self):
sys.exit()
scene = soya.World()
root=soya.widget.Group()
soya.set_root_widget(root)
root.add(LoginScreen())
soya.Idler(scene).idle()
kabutor writes:
Actually that's not a bug, it's the normal use of ChoiceList... Remind
that Soya's widget system is really limited and hackish.
We should rewrite a better one -- BTW where are PyUI and/or PyGUI for
Soya ?
For gui there is a nice resume in the wiki
http://soya.literati.org/UserInterface
Im doing my own gui elements, but better to say Im trying to do my own gui
elements, but are not much reusable and very ugly hacks.
Id love to see at least a droplist and a textbox.
And for the original email sender, I just init all the clasess I want to
use as menus, and just hide them (.visible=0) and the use this idler
class Idler(soya.Idler):
def begin_round(self):
#Check if show the menu
if (select_test.visible == 1):
for event in soya.process_event():
select_test.process_event(event)
if (harbour_gui.visible == 1):
for event in soya.process_event():
harbour_gui.process_event(event)
soya.Idler.begin_round(self)
Where select_test and harbour_gui are two Choicelists (two different
menus)
However I advice to not pay much attention to me as Im very newbie.
:)
_______________________________________________
Soya-user mailing list
[email protected]
https://mail.gna.org/listinfo/soya-user
Javier Correa