6d3225553bac82f9073a03e01ba297bc7759bb56
[blender.git] / release / scripts / ui / properties_game.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21
22
23 class PhysicsButtonsPanel():
24     bl_space_type = 'PROPERTIES'
25     bl_region_type = 'WINDOW'
26     bl_context = "physics"
27
28
29 class PHYSICS_PT_game_physics(PhysicsButtonsPanel, bpy.types.Panel):
30     bl_label = "Physics"
31     COMPAT_ENGINES = {'BLENDER_GAME'}
32
33     @staticmethod
34     def poll(context):
35         ob = context.active_object
36         rd = context.scene.render
37         return ob and ob.game and (rd.engine in __class__.COMPAT_ENGINES)
38
39     def draw(self, context):
40         layout = self.layout
41
42         ob = context.active_object
43         game = ob.game
44         soft = ob.game.soft_body
45
46         layout.prop(game, "physics_type")
47         layout.separator()
48
49         #if game.physics_type == 'DYNAMIC':
50         if game.physics_type in ('DYNAMIC', 'RIGID_BODY'):
51             split = layout.split()
52
53             col = split.column()
54             col.prop(game, "actor")
55             col.prop(game, "ghost")
56             col.prop(ob, "hide_render", text="Invisible") # out of place but useful
57
58             col = split.column()
59             col.prop(game, "material_physics")
60             col.prop(game, "rotate_from_normal")
61             col.prop(game, "no_sleeping")
62
63             layout.separator()
64
65             split = layout.split()
66
67             col = split.column()
68             col.label(text="Attributes:")
69             col.prop(game, "mass")
70             col.prop(game, "radius")
71             col.prop(game, "form_factor")
72
73             col = split.column()
74             sub = col.column()
75             sub.active = (game.physics_type == 'RIGID_BODY')
76             sub.prop(game, "anisotropic_friction")
77             subsub = sub.column()
78             subsub.active = game.anisotropic_friction
79             subsub.prop(game, "friction_coefficients", text="", slider=True)
80
81             split = layout.split()
82
83             col = split.column()
84             col.label(text="Velocity:")
85             sub = col.column(align=True)
86             sub.prop(game, "minimum_velocity", text="Minimum")
87             sub.prop(game, "maximum_velocity", text="Maximum")
88
89             col = split.column()
90             col.label(text="Damping:")
91             sub = col.column(align=True)
92             sub.prop(game, "damping", text="Translation", slider=True)
93             sub.prop(game, "rotation_damping", text="Rotation", slider=True)
94
95             layout.separator()
96
97             split = layout.split()
98
99             col = split.column()
100             col.label(text="Lock Translation:")
101             col.prop(game, "lock_x_axis", text="X")
102             col.prop(game, "lock_y_axis", text="Y")
103             col.prop(game, "lock_z_axis", text="Z")
104
105             col = split.column()
106             col.label(text="Lock Rotation:")
107             col.prop(game, "lock_x_rot_axis", text="X")
108             col.prop(game, "lock_y_rot_axis", text="Y")
109             col.prop(game, "lock_z_rot_axis", text="Z")
110
111         elif game.physics_type == 'SOFT_BODY':
112             col = layout.column()
113             col.prop(game, "actor")
114             col.prop(game, "ghost")
115             col.prop(ob, "hide_render", text="Invisible")
116
117             layout.separator()
118
119             split = layout.split()
120
121             col = split.column()
122             col.label(text="Attributes:")
123             col.prop(game, "mass")
124             col.prop(soft, "welding")
125             col.prop(soft, "position_iterations")
126             col.prop(soft, "linstiff", slider=True)
127             col.prop(soft, "dynamic_friction", slider=True)
128             col.prop(soft, "margin", slider=True)
129             col.prop(soft, "bending_const", text="Bending Constraints")
130
131             col = split.column()
132             col.prop(soft, "shape_match")
133             sub = col.column()
134             sub.active = soft.shape_match
135             sub.prop(soft, "threshold", slider=True)
136
137             col.separator()
138
139             col.label(text="Cluster Collision:")
140             col.prop(soft, "cluster_rigid_to_softbody")
141             col.prop(soft, "cluster_soft_to_softbody")
142             sub = col.column()
143             sub.active = (soft.cluster_rigid_to_softbody or soft.cluster_soft_to_softbody)
144             sub.prop(soft, "cluster_iterations", text="Iterations")
145
146         elif game.physics_type == 'STATIC':
147             col = layout.column()
148             col.prop(game, "actor")
149             col.prop(game, "ghost")
150             col.prop(ob, "hide_render", text="Invisible")
151
152         elif game.physics_type in ('SENSOR', 'INVISIBLE', 'NO_COLLISION', 'OCCLUDE'):
153             layout.prop(ob, "hide_render", text="Invisible")
154
155
156 class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, bpy.types.Panel):
157     bl_label = "Collision Bounds"
158     COMPAT_ENGINES = {'BLENDER_GAME'}
159
160     @staticmethod
161     def poll(context):
162         game = context.object.game
163         rd = context.scene.render
164         return (game.physics_type in ('DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC')) and (rd.engine in __class__.COMPAT_ENGINES)
165
166     def draw_header(self, context):
167         game = context.active_object.game
168
169         self.layout.prop(game, "use_collision_bounds", text="")
170
171     def draw(self, context):
172         layout = self.layout
173
174         game = context.active_object.game
175
176         layout.active = game.use_collision_bounds
177         layout.prop(game, "collision_bounds", text="Bounds")
178
179         split = layout.split()
180
181         col = split.column()
182         col.prop(game, "collision_margin", text="Margin", slider=True)
183
184         col = split.column()
185         col.prop(game, "collision_compound", text="Compound")
186
187
188 class RenderButtonsPanel():
189     bl_space_type = 'PROPERTIES'
190     bl_region_type = 'WINDOW'
191     bl_context = "render"
192
193
194 class RENDER_PT_game(RenderButtonsPanel, bpy.types.Panel):
195     bl_label = "Game"
196     COMPAT_ENGINES = {'BLENDER_GAME'}
197
198     @staticmethod
199     def poll(context):
200         rd = context.scene.render
201         return (rd.engine in __class__.COMPAT_ENGINES)
202
203     def draw(self, context):
204         layout = self.layout
205
206         row = layout.row()
207         row.operator("view3d.game_start", text="Start")
208         row.label()
209
210
211 class RENDER_PT_game_player(RenderButtonsPanel, bpy.types.Panel):
212     bl_label = "Standalone Player"
213     COMPAT_ENGINES = {'BLENDER_GAME'}
214
215     @staticmethod
216     def poll(context):
217         rd = context.scene.render
218         return (rd.engine in __class__.COMPAT_ENGINES)
219
220     def draw(self, context):
221         layout = self.layout
222
223         gs = context.scene.game_data
224
225         layout.prop(gs, "fullscreen")
226
227         split = layout.split()
228
229         col = split.column()
230         col.label(text="Resolution:")
231         sub = col.column(align=True)
232         sub.prop(gs, "resolution_x", slider=False, text="X")
233         sub.prop(gs, "resolution_y", slider=False, text="Y")
234
235         col = split.column()
236         col.label(text="Quality:")
237         sub = col.column(align=True)
238         sub.prop(gs, "depth", text="Bit Depth", slider=False)
239         sub.prop(gs, "frequency", text="FPS", slider=False)
240
241         # framing:
242         col = layout.column()
243         col.label(text="Framing:")
244         col.row().prop(gs, "framing_type", expand=True)
245         if gs.framing_type == 'LETTERBOX':
246             col.prop(gs, "framing_color", text="")
247
248
249 class RENDER_PT_game_stereo(RenderButtonsPanel, bpy.types.Panel):
250     bl_label = "Stereo"
251     COMPAT_ENGINES = {'BLENDER_GAME'}
252
253     @staticmethod
254     def poll(context):
255         rd = context.scene.render
256         return (rd.engine in __class__.COMPAT_ENGINES)
257
258     def draw(self, context):
259         layout = self.layout
260
261         gs = context.scene.game_data
262         stereo_mode = gs.stereo
263
264         # stereo options:
265         layout.prop(gs, "stereo", expand=True)
266
267         # stereo:
268         if stereo_mode == 'STEREO':
269             layout.prop(gs, "stereo_mode")
270             layout.prop(gs, "eye_separation")
271
272         # dome:
273         elif stereo_mode == 'DOME':
274             layout.prop(gs, "dome_mode", text="Dome Type")
275
276             dome_type = gs.dome_mode
277
278             split = layout.split()
279
280             if dome_type == 'FISHEYE' or \
281                dome_type == 'TRUNCATED_REAR' or \
282                dome_type == 'TRUNCATED_FRONT':
283
284                 col = split.column()
285                 col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
286                 col.prop(gs, "dome_angle", slider=True)
287
288                 col = split.column()
289                 col.prop(gs, "dome_tesselation", text="Tesselation")
290                 col.prop(gs, "dome_tilt")
291
292             elif dome_type == 'PANORAM_SPH':
293                 col = split.column()
294
295                 col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
296                 col = split.column()
297                 col.prop(gs, "dome_tesselation", text="Tesselation")
298
299             else: # cube map
300                 col = split.column()
301                 col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
302
303                 col = split.column()
304
305             layout.prop(gs, "dome_text")
306
307
308 class RENDER_PT_game_shading(RenderButtonsPanel, bpy.types.Panel):
309     bl_label = "Shading"
310     COMPAT_ENGINES = {'BLENDER_GAME'}
311
312     @staticmethod
313     def poll(context):
314         rd = context.scene.render
315         return (rd.engine in __class__.COMPAT_ENGINES)
316
317     def draw(self, context):
318         layout = self.layout
319
320         gs = context.scene.game_data
321
322         layout.prop(gs, "material_mode", expand=True)
323
324         if gs.material_mode == 'GLSL':
325             split = layout.split()
326
327             col = split.column()
328             col.prop(gs, "glsl_lights", text="Lights")
329             col.prop(gs, "glsl_shaders", text="Shaders")
330             col.prop(gs, "glsl_shadows", text="Shadows")
331
332             col = split.column()
333             col.prop(gs, "glsl_ramps", text="Ramps")
334             col.prop(gs, "glsl_nodes", text="Nodes")
335             col.prop(gs, "glsl_extra_textures", text="Extra Textures")
336
337
338 class RENDER_PT_game_performance(RenderButtonsPanel, bpy.types.Panel):
339     bl_label = "Performance"
340     COMPAT_ENGINES = {'BLENDER_GAME'}
341
342     @staticmethod
343     def poll(context):
344         rd = context.scene.render
345         return (rd.engine in __class__.COMPAT_ENGINES)
346
347     def draw(self, context):
348         layout = self.layout
349
350         gs = context.scene.game_data
351
352         split = layout.split()
353
354         col = split.column()
355         col.label(text="Show:")
356         col.prop(gs, "show_debug_properties", text="Debug Properties")
357         col.prop(gs, "show_framerate_profile", text="Framerate and Profile")
358         col.prop(gs, "show_physics_visualization", text="Physics Visualization")
359         col.prop(gs, "use_deprecation_warnings")
360
361         col = split.column()
362
363         col.label(text="Render:")
364         col.prop(gs, "use_frame_rate")
365         col.prop(gs, "use_display_lists")
366
367
368 class RENDER_PT_game_sound(RenderButtonsPanel, bpy.types.Panel):
369     bl_label = "Sound"
370     COMPAT_ENGINES = {'BLENDER_GAME'}
371
372     @staticmethod
373     def poll(context):
374         rd = context.scene.render
375         return (rd.engine in __class__.COMPAT_ENGINES)
376
377     def draw(self, context):
378         layout = self.layout
379
380         scene = context.scene
381
382         layout.prop(scene, "distance_model")
383
384         layout.prop(scene, "speed_of_sound", text="Speed")
385         layout.prop(scene, "doppler_factor")
386
387
388 class WorldButtonsPanel():
389     bl_space_type = 'PROPERTIES'
390     bl_region_type = 'WINDOW'
391     bl_context = "world"
392
393
394 class WORLD_PT_game_context_world(WorldButtonsPanel, bpy.types.Panel):
395     bl_label = ""
396     bl_show_header = False
397     COMPAT_ENGINES = {'BLENDER_GAME'}
398
399     @staticmethod
400     def poll(context):
401         rd = context.scene.render
402         return (context.scene) and (rd.use_game_engine)
403
404     def draw(self, context):
405         layout = self.layout
406
407         scene = context.scene
408         world = context.world
409         space = context.space_data
410
411         split = layout.split(percentage=0.65)
412         if scene:
413             split.template_ID(scene, "world", new="world.new")
414         elif world:
415             split.template_ID(space, "pin_id")
416
417
418 class WORLD_PT_game_world(WorldButtonsPanel, bpy.types.Panel):
419     bl_label = "World"
420     COMPAT_ENGINES = {'BLENDER_GAME'}
421
422     @staticmethod
423     def poll(context):
424         scene = context.scene
425         return (scene.world and scene.render.engine in __class__.COMPAT_ENGINES)
426
427     def draw(self, context):
428         layout = self.layout
429
430         world = context.world
431
432         split = layout.split()
433
434         col = split.column()
435         col.prop(world, "horizon_color")
436
437         col = split.column()
438         col.prop(world, "ambient_color")
439
440
441 class WORLD_PT_game_mist(WorldButtonsPanel, bpy.types.Panel):
442     bl_label = "Mist"
443     COMPAT_ENGINES = {'BLENDER_GAME'}
444
445     @staticmethod
446     def poll(context):
447         scene = context.scene
448         return (scene.world and scene.render.engine in __class__.COMPAT_ENGINES)
449
450     def draw_header(self, context):
451         world = context.world
452
453         self.layout.prop(world.mist, "use_mist", text="")
454
455     def draw(self, context):
456         layout = self.layout
457
458         world = context.world
459
460         layout.active = world.mist.use_mist
461         split = layout.split()
462
463         col = split.column()
464         col.prop(world.mist, "start")
465
466         col = split.column()
467         col.prop(world.mist, "depth")
468
469
470 class WORLD_PT_game_physics(WorldButtonsPanel, bpy.types.Panel):
471     bl_label = "Physics"
472     COMPAT_ENGINES = {'BLENDER_GAME'}
473
474     @staticmethod
475     def poll(context):
476         scene = context.scene
477         return (scene.world and scene.render.engine in __class__.COMPAT_ENGINES)
478
479     def draw(self, context):
480         layout = self.layout
481
482         gs = context.scene.game_data
483
484         layout.prop(gs, "physics_engine")
485         if gs.physics_engine != 'NONE':
486             layout.prop(gs, "physics_gravity", text="Gravity")
487
488             split = layout.split()
489
490             col = split.column()
491             col.label(text="Physics Steps:")
492             sub = col.column(align=True)
493             sub.prop(gs, "physics_step_max", text="Max")
494             sub.prop(gs, "physics_step_sub", text="Substeps")
495             col.prop(gs, "fps", text="FPS")
496
497             col = split.column()
498             col.label(text="Logic Steps:")
499             col.prop(gs, "logic_step_max", text="Max")
500
501             col = layout.column()
502             col.prop(gs, "use_occlusion_culling", text="Occlusion Culling")
503             sub = col.column()
504             sub.active = gs.use_occlusion_culling
505             sub.prop(gs, "occlusion_culling_resolution", text="Resolution")
506
507         else:
508             split = layout.split()
509
510             col = split.column()
511             col.label(text="Physics Steps:")
512             col.prop(gs, "fps", text="FPS")
513
514             col = split.column()
515             col.label(text="Logic Steps:")
516             col.prop(gs, "logic_step_max", text="Max")
517
518
519 def register():
520     pass
521
522
523 def unregister():
524     pass
525
526 if __name__ == "__main__":
527     register()