Enable pudding suport for pyworlds
[pyworlds.git] / src / pyworlds / worlds.py
blobbd83a08b8b8fe211053a93f7ac407ba9e216cae7
1 import sys, os, os.path, soya
2 import soya.widget as widget
3 from soya import sdlconst
4 import soya.widget
5 import math
7 from utils import *
8 import basics.scene
10 global scene,camera,light
12 scene = None
13 camera = None
14 light = None
16 # TODO: Create a full-camera class to handle several kinds of performance for cameras
18 animated_meshes = {}
19 meshes = {}
20 KEY = {}
21 MOUSE_X = 0
22 MOUSE_Y = 0
23 MOUSE_BUTTON = {}
25 # TODO: Place functions to access KEY, and return float or bool values. x>0.5 => True
26 callback_round = None
27 callback_advance = None
28 # TODO: Add the user-callback
29 scene_body = None
30 # TODO: Delete scene_body and use main Soya callbacks
32 enable_fps = False
34 # Import Psyco if available
35 try:
36 import psyco
37 psyco.full()
38 print "Psyco found and started -- Python code accelerated."
39 except ImportError:
40 print "I can't find PsyCo -- install it to get more speed"
41 pass
45 def is_pyWorlds_installed():
46 print "pyWorlds seem to be installed and working."
47 return True
50 def init(create_basic=True):
51 global scene,mainloop
52 soya.init()
53 soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
54 scene = basics.scene.scene
55 mainloop=soya.MainLoop(scene)
56 scene.mainloop=mainloop
57 scene.round_duration=.04
58 mainloop.round_duration=.04
59 if create_basic:
60 init_basicscene()
62 def init_basicscene():
63 global scene, light, camera
64 light = soya.Light(scene)
65 light.directional = 1
66 light.rotate_x(-90)
68 camera = soya.Camera(scene)
69 #camera.set_xyz(0,2,5)
70 #camera.rotate_x(-15)
71 camera.back = 200
72 #camera = soya.TravelingCamera(scene)
75 def begin_loop(callbackround=None, callbackadvance=None, engine="soya" ):
76 global scene, callback_round, callback_advance, camera,mainloop
77 import soya.pudding as pudding
78 callback_round = callbackround
79 callback_advance = callbackadvance
80 if engine=="soya":
81 soya.set_root_widget(camera)
82 elif engine=="pudding":
83 pass
84 else:
85 print "error engine %s unknown" % engine
86 #soya.set_root_widget(soya.widget.Group())
87 #soya.root_widget.add(camera)
88 #if enable_fps: soya.root_widget.add(soya.widget.FPSLabel())
89 scene_body = SceneBody(scene,None)
90 mainloop.main_loop()
92 def init_gui():
93 global root,viewport
94 import soya.gui
96 root = soya.gui.RootLayer(None)
97 viewport = soya.gui.CameraViewport(root, camera)
100 def init_pudding():
101 global root,viewport,camera,scene,mainloop
102 soya.path.append(os.path.join(os.path.dirname(sys.argv[0]), "data"))
104 import soya.pudding as pudding
105 soya.init()
106 pudding.init()
107 scene = basics.scene.scene
108 mainloop=pudding.main_loop.MainLoop(scene)
109 scene.mainloop=mainloop
110 scene.round_duration=.04
111 mainloop.round_duration=.04
114 init_basicscene()
115 soya.set_root_widget(pudding.core.RootWidget())
116 soya.root_widget.add_child(camera)
120 def begin_guiloop(callbackround=None, callbackadvance=None ):
121 global root, mainloop
122 global scene, callback_round, callback_advance, camera
123 callback_round = callbackround
124 callback_advance = callbackadvance
127 soya.set_root_widget(root)
128 scene_body = SceneBody(scene,None)
129 mainloop.main_loop()
133 class SceneBody(soya.Body):
134 def advance_time(self, proportion):
135 global callback_advance
136 soya.Body.advance_time(self, proportion)
137 if callback_advance: callback_advance(proportion)
139 def begin_round(self):
140 global KEY,callback_round, MOUSE_X, MOUSE_Y, MOUSE_BUTTON
141 soya.Body.begin_round(self)
142 for event in soya.process_event():
144 if event[0] == soya.sdlconst.KEYDOWN:
145 if event[1] == soya.sdlconst.K_ESCAPE: soya.MAIN_LOOP.stop()
146 else:
147 KEY[event[1]]=event[:]
149 elif event[0] == sdlconst.KEYUP:
150 if event[1] in KEY: del KEY[event[1]]
152 elif event[0] == sdlconst.QUIT:
153 soya.MAIN_LOOP.stop()
155 elif event[0] == soya.sdlconst.MOUSEBUTTONDOWN:
156 MOUSE_BUTTON[event[1]]=event[:]
157 MOUSE_X = event[2]
158 MOUSE_Y = event[3]
160 elif event[0] == soya.sdlconst.MOUSEBUTTONUP:
161 del MOUSE_BUTTON[event[1]]
162 MOUSE_X = event[2]
163 MOUSE_Y = event[3]
165 elif event[0] == soya.sdlconst.MOUSEMOTION:
166 MOUSE_X = event[1]
167 MOUSE_Y = event[2]
171 if callback_round: callback_round()
174 class Body(soya.Body):
175 def __init__(self,filename):
176 global scene
177 if type(filename) == type(''):
178 if filename in meshes:
179 mesh = meshes[filename]
180 else:
181 mesh = soya.Model.get(filename)
182 meshes[filename] = mesh
183 else:
184 # if it's not a text it is a mesh.
185 mesh = filename
187 self.mesh = mesh
188 soya.Body.__init__(self,scene,mesh)
189 self.velocity = soya.Vector(self,0,0,0)
190 self.rotation = [0,0,0]
192 def advance_time(self, proportion):
193 global mainloop
194 soya.Body.advance_time(self, proportion)
195 elapsed = mainloop.round_duration * proportion
196 if elapsed==0: elapsed=0.001
198 self.add_mul_vector(elapsed, self.velocity)
199 self.rotate_x(elapsed * self.rotation[0])
200 self.rotate_y(elapsed * self.rotation[1])
201 self.rotate_z(elapsed * self.rotation[2])
206 #class Character(soya.Body):
207 #def __init__(self,filename):
208 #global scene
209 #if type(filename) == type(''):
210 #if filename in animated_meshes:
211 #mesh = animated_meshes[filename]
212 #else:
213 #mesh = soya.AnimatedModel.get(filename)
214 #animated_meshes[filename] = mesh
215 #else:
216 ## if it's not a text it is a animated-mesh.
217 #mesh = filename
218 #self.mesh = mesh
219 ## print "Available meshes :", sorcerer_model.meshes .keys()
220 ## print "Available animations:", mesh.animations.keys()
221 ## -> Available animations: ['marche', 'tourneD', 'chute', 'tourneG', 'attente', 'recule']
223 #soya.Body.__init__(self,scene,mesh)
224 #self.states = {
225 #"stop" : ["garde","attente"],
226 #"walk" : ["marche"],
228 #self.state = None
229 #self.statecycle = None
230 #self.character_setstate("stop")
231 #self.velocity = soya.Vector(self,0,0,0)
232 #self.rotation = [0,0,0]
233 #self.desiredangle = 0
234 #self.look_at_speed = 10
236 #def advance_time(self, proportion):
237 #soya.Body.advance_time(self, proportion)
238 #elapsed = mainloop.round_duration * proportion
239 #if elapsed==0: elapsed=0.001
240 #self.angle = self.get_absoluteangleXZ()
241 #if self.desiredangle >= 360: self.desiredangle-=360
242 #if self.desiredangle < 0: self.desiredangle+=360
244 #anglediff = self.desiredangle - self.angle
245 #if anglediff > 180: anglediff-=360
246 #if anglediff < -180: anglediff+=360
247 #factor = self.look_at_speed
248 #if factor > 1/elapsed : factor = 1/elapsed
249 #anglemov = anglediff * factor
251 #if abs(self.rotation[1])>abs(anglemov):
252 #self.rotation[1]=(self.rotation[1]-anglemov)/2.0
253 #else:
254 #self.rotation[1]=(self.rotation[1]*5-anglemov)/6.0
255 #if abs(anglediff)<1:
256 #self.rotation[1]=-anglediff
258 #self.add_mul_vector(elapsed , self.velocity)
259 #self.rotate_x(elapsed * self.rotation[0])
260 #self.rotate_y(elapsed * self.rotation[1])
261 #self.rotate_z(elapsed * self.rotation[2])
263 #def get_absoluteangleXZ(self,vector=None):
264 #if vector == None:
265 #vector = soya.Vector(self,0,0,-1)
267 #q=vector % scene # I mean an upper container.
269 #return xy_toangle(q.x,q.z)
271 #def character_setstate(self,newstate):
272 #if newstate==self.state: return False
273 #if not hasattr(self.mesh,"animations"): return False
274 #if len(self.states[newstate])<1: raise
275 #newstatecycle=None
276 #try:
277 #for statecycle in self.states[newstate]:
278 #if statecycle in self.mesh.animations:
279 #newstatecycle=statecycle
280 #break;
281 #except:
282 #raise
283 #if not newstatecycle:
284 #print "Not found any animation for %s: " % newstate, self.states[newstate]
285 #print "Available animations:", self.mesh.animations.keys()
286 #raise
288 #if self.statecycle:
289 #self.animate_clear_cycle(self.statecycle)
290 #self.statecycle = None
291 #self.animate_blend_cycle(newstatecycle)
292 #self.statecycle = newstatecycle
293 #self.state=newstate
294 #return True
301 class FollowBody(Body):
302 def __init__(self,filename,target):
303 Body.__init__(self,filename)
304 self.x=target.x
305 self.y=target.y
306 self.z=target.z
307 self.target = target
308 self.target_distance = [0.5,1.0,2]
309 self.set_springfactor(16)
310 self.target_velocity = 1
312 for i in range(25):
313 self.begin_round()
314 self.advance_time(0.5)
316 def set_springfactor(self,factor):
317 self.target_springfactor = factor / 100.0
319 def begin_round(self):
320 Body.begin_round(self)
322 distance = self.distance_to(self.target)
323 _min = self.target_distance[0]
324 _med = self.target_distance[1]
325 _max = self.target_distance[2]
326 factor = 1
327 Q = 1
328 if distance <= _min: factor = 0.0
329 elif distance >= _max: factor = 0.0
330 else:
331 Q = (_med - distance)
332 if distance < _med:
333 Q /= math.sqrt(_med - _min)
334 factor = (distance - _min) / (_med - _min)
335 else:
336 Q /= math.sqrt(_max - _med)
337 factor = (_max - distance) / (_max - _med)
341 factor2 = (_med - distance) / (_max - _min)
342 if factor2 < 1: factor2 = 1
343 if self.velocity.z>1:
344 factor/=self.velocity.z
346 vel = self.target_velocity
347 # self.velocity.z = (self.velocity.z * self.target_springfactor * factor + Q * vel ) / (self.target_springfactor * factor + 1 )
348 self.velocity.z = (self.velocity.z * self.target_springfactor * factor + (_med - distance) * vel ) / (self.target_springfactor * factor + 1 )
349 #self.velocity.z *= factor2
350 if distance<_max:
351 look_at_elastic(self,self.target, sqrt_from=360, factor=(1-factor)+.3)
352 else:
353 self.look_at(self.target)
355 def advance_time(self, proportion):
356 Body.advance_time(self, proportion)
357 distance = self.distance_to(self.target)
358 _min = self.target_distance[0]
359 _med = self.target_distance[1]
360 _max = self.target_distance[2]
361 f3 = (distance - _med) / (_max - _med)
362 f1 = self.target_springfactor * 100 + 1
363 if f3>1:
364 f3=1
366 f3*=proportion
367 self.x = (self.x * f1 + self.target.x * f3) / (f1+f3)
368 self.y = (self.y * f1 + self.target.y * f3) / (f1+f3)
369 self.z = (self.z * f1 + self.target.z * f3) / (f1+f3)