1 import sys
, os
, os
.path
, soya
2 import soya
.widget
as widget
3 from soya
import sdlconst
10 global scene
,camera
,light
18 # TODO: Create a full-camera class to handle several kinds of performance for cameras
28 # TODO: Place functions to access KEY, and return float or bool values. x>0.5 => True
30 callback_advance
= None
31 # TODO: Add the user-callback
33 # TODO: Delete scene_body and use main Soya callbacks
37 # Import Psyco if available
41 print "Psyco found and started -- Python code accelerated."
43 print "I can't find PsyCo -- install it to get more speed"
48 def is_pyWorlds_installed():
49 print "pyWorlds seem to be installed and working."
53 def init(create_basic
=True):
54 global scene
,mainloop
,pyworlds_engine
55 pyworlds_engine
= "soya"
57 soya
.path
.append(os
.path
.join(os
.path
.dirname(sys
.argv
[0]), "data"))
58 scene
= basics
.scene
.scene
59 mainloop
=soya
.MainLoop(scene
)
60 scene
.mainloop
=mainloop
61 scene
.round_duration
=.04
62 mainloop
.round_duration
=.04
66 def init_basicscene():
67 global scene
, light
, camera
, scene_body
68 scene_body
= SceneBody(scene
,None)
70 light
= soya
.Light(scene
)
74 camera
= soya
.Camera(scene
)
75 #camera.set_xyz(0,2,5)
78 #camera = soya.TravelingCamera(scene)
81 def begin_loop(callbackround
=None, callbackadvance
=None, engine
="soya" ):
82 global scene
, callback_round
, callback_advance
, camera
,mainloop
83 import soya
.pudding
as pudding
84 callback_round
= callbackround
85 callback_advance
= callbackadvance
87 soya
.set_root_widget(camera
)
88 elif engine
=="pudding":
91 print "error engine %s unknown" % engine
92 #soya.set_root_widget(soya.widget.Group())
93 #soya.root_widget.add(camera)
94 #if enable_fps: soya.root_widget.add(soya.widget.FPSLabel())
95 return mainloop
.main_loop()
101 root
= soya
.gui
.RootLayer(None)
102 viewport
= soya
.gui
.CameraViewport(root
, camera
)
105 def init_pudding(width
= 500,height
= 500, options
= {}):
106 global root
,viewport
,camera
,scene
,mainloop
, pyworlds_engine
107 soya
.path
.append(os
.path
.join(os
.path
.dirname(sys
.argv
[0]), "data"))
108 pyworlds_engine
= "pudding"
109 import soya
.pudding
as pudding
112 scene
= basics
.scene
.scene
113 mainloop
=pudding
.main_loop
.MainLoop(scene
)
114 scene
.mainloop
=mainloop
115 scene
.round_duration
=.04
116 mainloop
.round_duration
=.04
119 if 'nobasics' not in options
: init_basicscene()
120 soya
.set_root_widget(pudding
.core
.RootWidget(width
= width
,height
= height
))
121 if 'nochild' not in options
: soya
.root_widget
.add_child(camera
)
125 def begin_guiloop(callbackround
=None, callbackadvance
=None ):
126 global root
, mainloop
127 global scene
, callback_round
, callback_advance
, camera
, scene_body
128 callback_round
= callbackround
129 callback_advance
= callbackadvance
132 soya
.set_root_widget(root
)
133 scene_body
= SceneBody(scene
,None)
136 def clearScene(fullClear
= False):
137 global scene
,camera
,light
,scene_body
139 validObj
=[scene_body
,camera
,light
]
140 if fullClear
: validObj
=[]
142 for body
in scene
.children
:
143 if body
not in validObj
: toRemove
.append(body
)
145 for body
in toRemove
:
147 scene
.children
.remove(body
)
151 class SceneBody(soya
.Body
):
152 def advance_time(self
, proportion
):
153 global callback_advance
154 soya
.Body
.advance_time(self
, proportion
)
155 if callback_advance
: callback_advance(proportion
)
157 def begin_round(self
):
159 global KEY
,callback_round
, MOUSE_X
, MOUSE_Y
, MOUSE_BUTTON
, mainloop
160 soya
.Body
.begin_round(self
)
162 if pyworlds_engine
== "soya":
163 array_events
= soya
.process_event()
164 elif pyworlds_engine
== "pudding":
165 import soya
.pudding
as pudding
166 # Use mainloop.events instead of pudding.process_event() :
167 # array_events = pudding.process_event()
168 array_events
= mainloop
.events
170 for event
in array_events
:
172 if event
[0] == soya
.sdlconst
.KEYDOWN
:
173 if event
[1] == soya
.sdlconst
.K_ESCAPE
: soya
.MAIN_LOOP
.stop()
175 KEY
[event
[1]]=event
[:]
177 elif event
[0] == sdlconst
.KEYUP
:
178 if event
[1] in KEY
: del KEY
[event
[1]]
180 elif event
[0] == sdlconst
.QUIT
:
181 soya
.MAIN_LOOP
.stop()
183 elif event
[0] == soya
.sdlconst
.MOUSEBUTTONDOWN
:
184 MOUSE_BUTTON
[event
[1]]=event
[:]
187 a
,b
,c
,d
= MOUSE_BUTTON
[event
[1]]
188 if a
== 5 and (b
==4 or b
==5): MOUSE_WHEEL
= b
190 elif event
[0] == soya
.sdlconst
.MOUSEBUTTONUP
:
191 #print "Up: ",MOUSE_BUTTON[event[1]]
192 if MOUSE_BUTTON
.has_key(event
[1]):
193 del MOUSE_BUTTON
[event
[1]]
197 elif event
[0] == soya
.sdlconst
.MOUSEMOTION
:
202 if callback_round
: callback_round()
205 class Body(soya
.Body
):
206 def __init__(self
,filename
):
208 if type(filename
) == type(''):
209 if filename
in meshes
:
210 mesh
= meshes
[filename
]
212 mesh
= soya
.Model
.get(filename
)
213 meshes
[filename
] = mesh
215 # if it's not a text it is a mesh.
219 soya
.Body
.__init
__(self
,scene
,mesh
)
220 self
.velocity
= soya
.Vector(self
,0,0,0)
221 self
.rotation
= [0,0,0]
223 def advance_time(self
, proportion
):
225 soya
.Body
.advance_time(self
, proportion
)
226 elapsed
= mainloop
.round_duration
* proportion
227 if elapsed
==0: elapsed
=0.001
229 self
.add_mul_vector(elapsed
, self
.velocity
)
230 self
.rotate_x(elapsed
* self
.rotation
[0])
231 self
.rotate_y(elapsed
* self
.rotation
[1])
232 self
.rotate_z(elapsed
* self
.rotation
[2])
237 #class Character(soya.Body):
238 #def __init__(self,filename):
240 #if type(filename) == type(''):
241 #if filename in animated_meshes:
242 #mesh = animated_meshes[filename]
244 #mesh = soya.AnimatedModel.get(filename)
245 #animated_meshes[filename] = mesh
247 ## if it's not a text it is a animated-mesh.
250 ## print "Available meshes :", sorcerer_model.meshes .keys()
251 ## print "Available animations:", mesh.animations.keys()
252 ## -> Available animations: ['marche', 'tourneD', 'chute', 'tourneG', 'attente', 'recule']
254 #soya.Body.__init__(self,scene,mesh)
256 #"stop" : ["garde","attente"],
257 #"walk" : ["marche"],
260 #self.statecycle = None
261 #self.character_setstate("stop")
262 #self.velocity = soya.Vector(self,0,0,0)
263 #self.rotation = [0,0,0]
264 #self.desiredangle = 0
265 #self.look_at_speed = 10
267 #def advance_time(self, proportion):
268 #soya.Body.advance_time(self, proportion)
269 #elapsed = mainloop.round_duration * proportion
270 #if elapsed==0: elapsed=0.001
271 #self.angle = self.get_absoluteangleXZ()
272 #if self.desiredangle >= 360: self.desiredangle-=360
273 #if self.desiredangle < 0: self.desiredangle+=360
275 #anglediff = self.desiredangle - self.angle
276 #if anglediff > 180: anglediff-=360
277 #if anglediff < -180: anglediff+=360
278 #factor = self.look_at_speed
279 #if factor > 1/elapsed : factor = 1/elapsed
280 #anglemov = anglediff * factor
282 #if abs(self.rotation[1])>abs(anglemov):
283 #self.rotation[1]=(self.rotation[1]-anglemov)/2.0
285 #self.rotation[1]=(self.rotation[1]*5-anglemov)/6.0
286 #if abs(anglediff)<1:
287 #self.rotation[1]=-anglediff
289 #self.add_mul_vector(elapsed , self.velocity)
290 #self.rotate_x(elapsed * self.rotation[0])
291 #self.rotate_y(elapsed * self.rotation[1])
292 #self.rotate_z(elapsed * self.rotation[2])
294 #def get_absoluteangleXZ(self,vector=None):
296 #vector = soya.Vector(self,0,0,-1)
298 #q=vector % scene # I mean an upper container.
300 #return xy_toangle(q.x,q.z)
302 #def character_setstate(self,newstate):
303 #if newstate==self.state: return False
304 #if not hasattr(self.mesh,"animations"): return False
305 #if len(self.states[newstate])<1: raise
308 #for statecycle in self.states[newstate]:
309 #if statecycle in self.mesh.animations:
310 #newstatecycle=statecycle
314 #if not newstatecycle:
315 #print "Not found any animation for %s: " % newstate, self.states[newstate]
316 #print "Available animations:", self.mesh.animations.keys()
320 #self.animate_clear_cycle(self.statecycle)
321 #self.statecycle = None
322 #self.animate_blend_cycle(newstatecycle)
323 #self.statecycle = newstatecycle
332 class FollowBody(Body
):
333 def __init__(self
,filename
,target
):
334 Body
.__init
__(self
,filename
)
339 self
.target_distance
= [0.5,1.0,2]
340 self
.set_springfactor(16)
341 self
.target_velocity
= 1
345 self
.advance_time(0.5)
347 def set_springfactor(self
,factor
):
348 self
.target_springfactor
= factor
/ 100.0
350 def begin_round(self
):
351 Body
.begin_round(self
)
353 distance
= self
.distance_to(self
.target
)
354 _min
= self
.target_distance
[0]
355 _med
= self
.target_distance
[1]
356 _max
= self
.target_distance
[2]
359 if distance
<= _min
: factor
= 0.0
360 elif distance
>= _max
: factor
= 0.0
362 Q
= (_med
- distance
)
364 Q
/= math
.sqrt(_med
- _min
)
365 factor
= (distance
- _min
) / (_med
- _min
)
367 Q
/= math
.sqrt(_max
- _med
)
368 factor
= (_max
- distance
) / (_max
- _med
)
372 factor2
= (_med
- distance
) / (_max
- _min
)
373 if factor2
< 1: factor2
= 1
374 if self
.velocity
.z
>1:
375 factor
/=self
.velocity
.z
377 vel
= self
.target_velocity
378 # self.velocity.z = (self.velocity.z * self.target_springfactor * factor + Q * vel ) / (self.target_springfactor * factor + 1 )
379 self
.velocity
.z
= (self
.velocity
.z
* self
.target_springfactor
* factor
+ (_med
- distance
) * vel
) / (self
.target_springfactor
* factor
+ 1 )
380 #self.velocity.z *= factor2
382 look_at_elastic(self
,self
.target
, sqrt_from
=360, factor
=(1-factor
)+.3)
384 self
.look_at(self
.target
)
386 def advance_time(self
, proportion
):
387 Body
.advance_time(self
, proportion
)
388 distance
= self
.distance_to(self
.target
)
389 _min
= self
.target_distance
[0]
390 _med
= self
.target_distance
[1]
391 _max
= self
.target_distance
[2]
392 f3
= (distance
- _med
) / (_max
- _med
)
393 f1
= self
.target_springfactor
* 100 + 1
398 self
.x
= (self
.x
* f1
+ self
.target
.x
* f3
) / (f1
+f3
)
399 self
.y
= (self
.y
* f1
+ self
.target
.y
* f3
) / (f1
+f3
)
400 self
.z
= (self
.z
* f1
+ self
.target
.z
* f3
) / (f1
+f3
)