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