add material option for wLabel3D
[pyworlds.git] / src / pyworlds / basics / wbody.py
blob9ff23b452492b8b086c200328a920c69a4c70bda
1 import soya
2 import pyworlds.worlds
3 from pyworlds.utils import *
6 SIM_TYPE= {
7 # none - No simulation at all.
8 # (The body gets paused)
9 'none': 0,
11 # Simulation done on each frame render
12 # (Good for fast-action games, live is good for games with low cpu use)
13 'live': 1,
15 # Simulation done in each round, and the render is interpolated
16 # (Good for simulation games than need to execute thins more often than once per frame)
17 # (Interpolation has a penalty: the object is rendered with a lag of one round)
18 'round': 2,
19 'interpolated': 2,
21 # Simulation done in both, on rounds and on each frame.
22 # (Increases CPU cost to create a simulation that doesn't need to interpolate)
23 'both': 3,
28 class wBody(soya.World):
29 def __init__(self, parent = None, model = None):
30 soya.World.__init__(self,parent)
32 self.body = soya.Body(self,model)
33 self.set_timefactor(1)
34 self.elapsed_render_time = 0
35 self.elapsed_round_time = 0
36 self.elapsed_real_time = 0
37 self.set_timesimulation(SIM_TYPE['live'])
38 self.time_factor = 1
39 self.min_elapse_time = 1 / 80.0
40 self.max_elapse_time = 1 / 20.0
41 self.state1 = soya.CoordSystState(self)
42 self.state2 = soya.CoordSystState(self)
43 self.state1_time = 0
44 self.state2_time = 0
45 self.round_duration = 0.04
46 self.list_elapsecalls=[self.elapsed_time]
48 def set_timesimulation(self,sim_type):
49 self.sim_type=sim_type
51 def set_timefactor(self,factor):
52 self.time_factor = factor
54 def elapse_to_time(self,new_time):
55 seconds = new_time - self.elapsed_real_time
56 total_elapsed=0
57 while seconds > self.min_elapse_time:
58 if seconds > self.max_elapse_time:
59 seconds = self.max_elapse_time
61 for elapsedcall in self.list_elapsecalls:
62 elapsedcall(seconds)
63 # if elapsed_seconds : seconds = elapsed_seconds
64 assert seconds > self.min_elapse_time / 2.0
66 self.elapsed_real_time += seconds
67 total_elapsed += seconds
68 seconds = new_time - self.elapsed_real_time
69 return total_elapsed
71 def addloopcall(self, funccall):
72 try:
73 self.list_elapsecalls.append(funccall)
74 except:
75 raise
77 def elapsed_time(self,seconds):
78 return seconds
80 def get_absoluteangleXZ(self,vector=None):
81 parent = self.get_root()
82 if vector == None:
83 vector = soya.Vector(self,0,0,-1)
85 q=vector % parent
87 return xy_toangle(q.x,q.z)
89 def begin_round(self):
90 soya.World.begin_round(self)
94 self.round_duration = self.parent.round_duration * self.time_factor
96 seconds = 1 * self.round_duration
97 self.elapsed_round_time += seconds
98 elapsed = 0
99 if (self.sim_type == SIM_TYPE['round'] or
100 self.sim_type == SIM_TYPE['both']):
101 elapsed = self.elapse_to_time(self.elapsed_round_time)
103 if elapsed > 0:
104 self.state1 = soya.CoordSystState(self.state2)
105 self.state2 = soya.CoordSystState(self)
106 self.state1_time = self.state2_time
107 self.state2_time = self.elapsed_round_time
110 def advance_time(self, proportion):
111 soya.World.advance_time(self, proportion)
112 seconds = proportion * self.round_duration
113 self.elapsed_render_time += seconds
115 if (self.sim_type == SIM_TYPE['live'] or
116 self.sim_type == SIM_TYPE['both']):
117 self.elapse_to_time(self.elapsed_render_time)
118 else:
119 time1 = self.state2_time - self.state1_time
120 time2 = self.elapsed_render_time - self.state1_time
121 if time1>0:
122 factor = time2 / time1
123 self.interpolate(self.state1, self.state2, factor)
125 def end_round(self):
126 soya.World.end_round(self)
127 if (self.sim_type == SIM_TYPE['live'] or
128 self.sim_type == SIM_TYPE['both']):
129 pass
130 else:
131 self.interpolate(self.state1, self.state2, 1)
135 class wPhysicsBody(wBody):
136 def __init__(self, parent = 'scene', mesh = None, mesh_file = None, animatedmesh_file = None):
137 if parent == 'scene':
139 parent = pyworlds.worlds.scene
141 if mesh_file:
142 mesh = soya.Model.get(mesh_file)
144 if animatedmesh_file:
145 mesh = soya.AnimatedModel.get(animatedmesh_file)
147 self.mesh = mesh
149 wBody.__init__(self,parent,mesh)
150 self.initialize_vars()
152 def initialize_vars(self):
153 self.speed = soya.Vector(self,0,0,0)
154 self.rotation = [0,0,0]
156 def elapsed_time(self,seconds):
157 self.add_mul_vector(seconds, self.speed)
158 #self.rotate_x(seconds * self.rotation[0])
159 #self.rotate_y(seconds * self.rotation[1])
160 #self.rotate_z(seconds * self.rotation[2])
162 self.turn_x(seconds * self.rotation[0])
163 self.turn_y(seconds * self.rotation[1])
164 self.turn_z(seconds * self.rotation[2])
169 m_black = soya.Material()
170 m_black.shininess = 0.1
171 m_black.diffuse = (0.0, 0.0, 0.0, 0.2)
172 m_black.specular = (0.0, 0.0, 0.0, 0.2)
174 m_red = soya.Material()
175 m_red.shininess = 0.1
176 m_red.diffuse = (1.0, 0.0, 0.0, 0.5)
177 m_red.specular = (1.0, 0.0, 0.0, 0.5)
180 class wLabel3DFlat(soya.World):
181 def __init__(self, size = 0.01, compensation = 0.02, follows = None, material = m_black, offset = (0.0,1.0,1.0), *args, **kwargs):
182 if 'parent' not in kwargs:
183 kwargs['parent']=pyworlds.worlds.scene
184 soya.World.__init__(self, kwargs['parent'])
185 kwargs['parent'] = self
186 text = ""
187 if 'text' in kwargs:
188 text = kwargs['text']
190 self.label = soya.label3d.Label3D(**kwargs)
191 self.label.size = size
192 self.label.lit = 0
193 self.label.render()
195 self.box = soya.World(None)
196 self.text_width, self.text_height = self.label._font.get_print_size(self.label._text)
197 self.text_width+=10
198 self.text_height+=10
199 pyworlds.utils.Box(self.text_width*size,size*self.text_height,0,insert_into=self.box, material=material, origin = (0,1*size,-0.01) , lit = False)
200 self.box_normal = self.box.to_model()
202 self.box = soya.World(None)
203 pyworlds.utils.Box(self.text_width*size,size*self.text_height,0,insert_into=self.box, material=m_red, origin = (0,1*size,-0.01), lit = False )
204 self.box_selected = self.box.to_model()
205 self.model = self.box_normal
207 self.flat_follows = follows
208 self.flat_offset = offset
209 self.flat_size = size
210 self.flat_compensation = compensation
213 def advance_time(self,proportion):
215 if self.flat_follows:
216 self.move(self.flat_follows)
217 maxparent = pyworlds.worlds.scene
219 visible= self.flat_follows.visible
220 objparent = self.flat_follows
221 while objparent.is_inside(maxparent) and visible:
222 if hasattr(objparent.parent,"parent") and hasattr(objparent.parent,"visible"):
223 objparent = objparent.parent
225 if objparent.visible == False:
226 visible=False
227 break
228 else:
229 break
231 self.visible=visible
232 self.solid=visible
234 matrix = list(self.matrix)
235 for x in range(3):
236 for y in range(3):
237 matrix[x+y*4] = pyworlds.worlds.camera.matrix[x+y*4]
238 self.matrix = tuple(matrix)
239 self.add_vector(soya.Vector(self,self.flat_offset[0],self.flat_offset[1],self.flat_offset[2]))
240 vect = self.vector_to(pyworlds.worlds.camera)
241 lenvect = vect.length()
242 flat_compensation = self.flat_compensation
243 if self.flat_compensation<0:
244 len2 = lenvect + self.flat_compensation * 180.0 / pyworlds.worlds.camera.fov
245 flat_compensation = len2 / float(lenvect)
248 self.add_mul_vector( flat_compensation,self.vector_to(pyworlds.worlds.camera))