# -*- indent-tabs-mode: t -*-

# Soya 3D tutorial
# Copyright (C) 2005 Javier Correa Villanueva (jbcorrea@puc.cl)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


# widget-1: Widget system : a game presentation

# WARNING :
# soya.widget is now deprecated, you should rather consider using soya.pudding instead.


#!/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.05,up_speed=1.5,down_speed=1.5,left_speed=1.5,right_speed=1.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.05):
	 widget.ChoiceList.__init__(self,master,choices,font,color,highlight,cancel,align)
	 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.05):
	 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,optionServer,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.MainLoop(scene).main_loop() 
