remove use of gettext: _("...") style translation now its handled by rna.
[blender.git] / release / scripts / startup / bl_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 from bpy.types import Panel
22
23
24 class PhysicsButtonsPanel():
25     bl_space_type = 'PROPERTIES'
26     bl_region_type = 'WINDOW'
27     bl_context = "physics"
28
29
30 class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
31     bl_label = "Physics"
32     COMPAT_ENGINES = {'BLENDER_GAME'}
33
34     @classmethod
35     def poll(cls, context):
36         ob = context.active_object
37         rd = context.scene.render
38         return ob and ob.game and (rd.engine in cls.COMPAT_ENGINES)
39
40     def draw(self, context):
41         layout = self.layout
42
43         ob = context.active_object
44         game = ob.game
45         soft = ob.game.soft_body
46
47         layout.prop(game, "physics_type")
48         layout.separator()
49
50         #if game.physics_type == 'DYNAMIC':
51         if game.physics_type in {'DYNAMIC', 'RIGID_BODY'}:
52             split = layout.split()
53
54             col = split.column()
55             col.prop(game, "use_actor")
56             col.prop(game, "use_ghost")
57             col.prop(ob, "hide_render", text="Invisible")  # out of place but useful
58
59             col = split.column()
60             col.prop(game, "use_material_physics_fh")
61             col.prop(game, "use_rotate_from_normal")
62             col.prop(game, "use_sleep")
63
64             layout.separator()
65
66             split = layout.split()
67
68             col = split.column()
69             col.label(text="Attributes:")
70             col.prop(game, "mass")
71             col.prop(game, "radius")
72             col.prop(game, "form_factor")
73
74             col = split.column()
75             sub = col.column()
76             sub.prop(game, "use_anisotropic_friction")
77             subsub = sub.column()
78             subsub.active = game.use_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, "velocity_min", text="Minimum")
87             sub.prop(game, "velocity_max", 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_location_x", text="X")
102             col.prop(game, "lock_location_y", text="Y")
103             col.prop(game, "lock_location_z", text="Z")
104
105             col = split.column()
106             col.label(text="Lock Rotation:")
107             col.prop(game, "lock_rotation_x", text="X")
108             col.prop(game, "lock_rotation_y", text="Y")
109             col.prop(game, "lock_rotation_z", text="Z")
110
111         elif game.physics_type == 'SOFT_BODY':
112             col = layout.column()
113             col.prop(game, "use_actor")
114             col.prop(game, "use_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, "weld_threshold")
125             col.prop(soft, "location_iterations")
126             col.prop(soft, "linear_stiffness", slider=True)
127             col.prop(soft, "dynamic_friction", slider=True)
128             col.prop(soft, "collision_margin", slider=True)
129             col.prop(soft, "use_bending_constraints", text="Bending Constraints")
130
131             col = split.column()
132             col.prop(soft, "use_shape_match")
133             sub = col.column()
134             sub.active = soft.use_shape_match
135             sub.prop(soft, "shape_threshold", slider=True)
136
137             col.separator()
138
139             col.label(text="Cluster Collision:")
140             col.prop(soft, "use_cluster_rigid_to_softbody")
141             col.prop(soft, "use_cluster_soft_to_softbody")
142             sub = col.column()
143             sub.active = (soft.use_cluster_rigid_to_softbody or soft.use_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, "use_actor")
149             col.prop(game, "use_ghost")
150             col.prop(ob, "hide_render", text="Invisible")
151
152             layout.separator()
153
154             split = layout.split()
155
156             col = split.column()
157             col.label(text="Attributes:")
158             col.prop(game, "radius")
159
160             col = split.column()
161             sub = col.column()
162             sub.prop(game, "use_anisotropic_friction")
163             subsub = sub.column()
164             subsub.active = game.use_anisotropic_friction
165             subsub.prop(game, "friction_coefficients", text="", slider=True)
166
167         elif game.physics_type in {'SENSOR', 'INVISIBLE', 'NO_COLLISION', 'OCCLUDE'}:
168             layout.prop(ob, "hide_render", text="Invisible")
169
170
171 class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
172     bl_label = "Collision Bounds"
173     COMPAT_ENGINES = {'BLENDER_GAME'}
174
175     @classmethod
176     def poll(cls, context):
177         game = context.object.game
178         rd = context.scene.render
179         return (game.physics_type in {'DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC'}) and (rd.engine in cls.COMPAT_ENGINES)
180
181     def draw_header(self, context):
182         game = context.active_object.game
183
184         self.layout.prop(game, "use_collision_bounds", text="")
185
186     def draw(self, context):
187         layout = self.layout
188
189         game = context.active_object.game
190
191         layout.active = game.use_collision_bounds
192         layout.prop(game, "collision_bounds_type", text="Bounds")
193
194         row = layout.row()
195         row.prop(game, "collision_margin", text="Margin", slider=True)
196         row.prop(game, "use_collision_compound", text="Compound")
197
198
199 class PHYSICS_PT_game_obstacles(PhysicsButtonsPanel, Panel):
200     bl_label = "Create Obstacle"
201     COMPAT_ENGINES = {'BLENDER_GAME'}
202
203     @classmethod
204     def poll(cls, context):
205         game = context.object.game
206         rd = context.scene.render
207         return (game.physics_type in ('DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC'))  and (rd.engine in cls.COMPAT_ENGINES)
208
209     def draw_header(self, context):
210         game = context.active_object.game
211
212         self.layout.prop(game, "create_obstacle", text="")
213
214     def draw(self, context):
215         layout = self.layout
216
217         game = context.active_object.game
218
219         layout.active = game.create_obstacle
220
221         row = layout.row()
222         row.prop(game, "obstacle_radius", text="Radius")
223         row.label()
224
225
226 class RenderButtonsPanel():
227     bl_space_type = 'PROPERTIES'
228     bl_region_type = 'WINDOW'
229     bl_context = "render"
230
231     @classmethod
232     def poll(cls, context):
233         rd = context.scene.render
234         return (rd.engine in cls.COMPAT_ENGINES)
235
236
237 class RENDER_PT_game(RenderButtonsPanel, Panel):
238     bl_label = "Game"
239     COMPAT_ENGINES = {'BLENDER_GAME'}
240
241     def draw(self, context):
242         layout = self.layout
243
244         row = layout.row()
245         row.operator("view3d.game_start", text="Start")
246         row.label()
247
248
249 class RENDER_PT_game_player(RenderButtonsPanel, Panel):
250     bl_label = "Standalone Player"
251     COMPAT_ENGINES = {'BLENDER_GAME'}
252
253     def draw(self, context):
254         layout = self.layout
255
256         gs = context.scene.game_settings
257
258         layout.prop(gs, "show_fullscreen")
259
260         split = layout.split()
261
262         col = split.column()
263         col.label(text="Resolution:")
264         sub = col.column(align=True)
265         sub.prop(gs, "resolution_x", slider=False, text="X")
266         sub.prop(gs, "resolution_y", slider=False, text="Y")
267
268         col = split.column()
269         col.label(text="Quality:")
270         sub = col.column(align=True)
271         sub.prop(gs, "depth", text="Bit Depth", slider=False)
272         sub.prop(gs, "frequency", text="FPS", slider=False)
273
274         # framing:
275         col = layout.column()
276         col.label(text="Framing:")
277         col.row().prop(gs, "frame_type", expand=True)
278         if gs.frame_type == 'LETTERBOX':
279             col.prop(gs, "frame_color", text="")
280
281
282 class RENDER_PT_game_stereo(RenderButtonsPanel, Panel):
283     bl_label = "Stereo"
284     COMPAT_ENGINES = {'BLENDER_GAME'}
285
286     def draw(self, context):
287         layout = self.layout
288
289         gs = context.scene.game_settings
290         stereo_mode = gs.stereo
291
292         # stereo options:
293         layout.prop(gs, "stereo", expand=True)
294
295         # stereo:
296         if stereo_mode == 'STEREO':
297             layout.prop(gs, "stereo_mode")
298             layout.prop(gs, "stereo_eye_separation")
299
300         # dome:
301         elif stereo_mode == 'DOME':
302             layout.prop(gs, "dome_mode", text="Dome Type")
303
304             dome_type = gs.dome_mode
305
306             split = layout.split()
307
308             if dome_type == 'FISHEYE' or \
309                dome_type == 'TRUNCATED_REAR' or \
310                dome_type == 'TRUNCATED_FRONT':
311
312                 col = split.column()
313                 col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
314                 col.prop(gs, "dome_angle", slider=True)
315
316                 col = split.column()
317                 col.prop(gs, "dome_tesselation", text="Tesselation")
318                 col.prop(gs, "dome_tilt")
319
320             elif dome_type == 'PANORAM_SPH':
321                 col = split.column()
322
323                 col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
324                 col = split.column()
325                 col.prop(gs, "dome_tesselation", text="Tesselation")
326
327             else:  # cube map
328                 col = split.column()
329                 col.prop(gs, "dome_buffer_resolution", text="Resolution", slider=True)
330
331                 col = split.column()
332
333             layout.prop(gs, "dome_text")
334
335
336 class RENDER_PT_game_shading(RenderButtonsPanel, Panel):
337     bl_label = "Shading"
338     COMPAT_ENGINES = {'BLENDER_GAME'}
339
340     def draw(self, context):
341         layout = self.layout
342
343         gs = context.scene.game_settings
344
345         layout.prop(gs, "material_mode", expand=True)
346
347         if gs.material_mode == 'GLSL':
348             split = layout.split()
349
350             col = split.column()
351             col.prop(gs, "use_glsl_lights", text="Lights")
352             col.prop(gs, "use_glsl_shaders", text="Shaders")
353             col.prop(gs, "use_glsl_shadows", text="Shadows")
354             col.prop(gs, "use_glsl_color_management", text="Color Management")
355
356             col = split.column()
357             col.prop(gs, "use_glsl_ramps", text="Ramps")
358             col.prop(gs, "use_glsl_nodes", text="Nodes")
359             col.prop(gs, "use_glsl_extra_textures", text="Extra Textures")
360
361
362 class RENDER_PT_game_performance(RenderButtonsPanel, Panel):
363     bl_label = "Performance"
364     COMPAT_ENGINES = {'BLENDER_GAME'}
365
366     def draw(self, context):
367         layout = self.layout
368
369         gs = context.scene.game_settings
370         col = layout.column()
371         row = col.row()
372         row.prop(gs, "use_frame_rate")
373         row.prop(gs, "use_display_lists")
374
375         col.prop(gs, "restrict_animation_updates")
376
377
378 class RENDER_PT_game_display(RenderButtonsPanel, Panel):
379     bl_label = "Display"
380     COMPAT_ENGINES = {'BLENDER_GAME'}
381
382     def draw(self, context):
383         layout = self.layout
384
385         gs = context.scene.game_settings
386         flow = layout.column_flow()
387         flow.prop(gs, "show_debug_properties", text="Debug Properties")
388         flow.prop(gs, "show_framerate_profile", text="Framerate and Profile")
389         flow.prop(gs, "show_physics_visualization", text="Physics Visualization")
390         flow.prop(gs, "use_deprecation_warnings")
391         flow.prop(gs, "show_mouse", text="Mouse Cursor")
392
393
394 class SceneButtonsPanel():
395     bl_space_type = 'PROPERTIES'
396     bl_region_type = 'WINDOW'
397     bl_context = "scene"
398
399
400 class SCENE_PT_game_navmesh(SceneButtonsPanel, bpy.types.Panel):
401     bl_label = "Navigation mesh"
402     bl_default_closed = True
403     COMPAT_ENGINES = {'BLENDER_GAME'}
404
405     @classmethod
406     def poll(cls, context):
407         scene = context.scene
408         return (scene and scene.render.engine in cls.COMPAT_ENGINES)
409
410     def draw(self, context):
411         layout = self.layout
412
413         rd = context.scene.game_settings.recast_data
414
415         layout.operator("object.create_navmesh", text='Build navigation mesh')
416
417         col = layout.column()
418         col.label(text="Rasterization:")
419         row = col.row()
420         row.prop(rd, "cell_size")
421         row.prop(rd, "cell_height")
422
423         col = layout.column()
424         col.label(text="Agent:")
425         split = col.split()
426
427         col = split.column()
428         col.prop(rd, "agent_height", text="Height")
429         col.prop(rd, "agent_radius", text="Radius")
430
431         col = split.column()
432         col.prop(rd, "max_slope")
433         col.prop(rd, "max_climb")
434
435         col = layout.column()
436         col.label(text="Region:")
437         row = col.row()
438         row.prop(rd, "region_min_size")
439         row.prop(rd, "region_merge_size")
440
441         col = layout.column()
442         col.label(text="Polygonization:")
443         split = col.split()
444
445         col = split.column()
446         col.prop(rd, "edge_max_len")
447         col.prop(rd, "edge_max_error")
448
449         split.prop(rd, "verts_per_poly")
450
451         col = layout.column()
452         col.label(text="Detail Mesh:")
453         row = col.row()
454         row.prop(rd, "sample_dist")
455         row.prop(rd, "sample_max_error")
456
457
458 class WorldButtonsPanel():
459     bl_space_type = 'PROPERTIES'
460     bl_region_type = 'WINDOW'
461     bl_context = "world"
462
463
464 class WORLD_PT_game_context_world(WorldButtonsPanel, Panel):
465     bl_label = ""
466     bl_options = {'HIDE_HEADER'}
467     COMPAT_ENGINES = {'BLENDER_GAME'}
468
469     @classmethod
470     def poll(cls, context):
471         rd = context.scene.render
472         return (context.scene) and (rd.use_game_engine)
473
474     def draw(self, context):
475         layout = self.layout
476
477         scene = context.scene
478         world = context.world
479         space = context.space_data
480
481         split = layout.split(percentage=0.65)
482         if scene:
483             split.template_ID(scene, "world", new="world.new")
484         elif world:
485             split.template_ID(space, "pin_id")
486
487
488 class WORLD_PT_game_world(WorldButtonsPanel, Panel):
489     bl_label = "World"
490     COMPAT_ENGINES = {'BLENDER_GAME'}
491
492     @classmethod
493     def poll(cls, context):
494         scene = context.scene
495         return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
496
497     def draw(self, context):
498         layout = self.layout
499
500         world = context.world
501
502         row = layout.row()
503         row.column().prop(world, "horizon_color")
504         row.column().prop(world, "ambient_color")
505
506
507 class WORLD_PT_game_mist(WorldButtonsPanel, Panel):
508     bl_label = "Mist"
509     COMPAT_ENGINES = {'BLENDER_GAME'}
510
511     @classmethod
512     def poll(cls, context):
513         scene = context.scene
514         return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
515
516     def draw_header(self, context):
517         world = context.world
518
519         self.layout.prop(world.mist_settings, "use_mist", text="")
520
521     def draw(self, context):
522         layout = self.layout
523
524         world = context.world
525
526         layout.active = world.mist_settings.use_mist
527
528         row = layout.row()
529         row.prop(world.mist_settings, "start")
530         row.prop(world.mist_settings, "depth")
531
532
533 class WORLD_PT_game_physics(WorldButtonsPanel, Panel):
534     bl_label = "Physics"
535     COMPAT_ENGINES = {'BLENDER_GAME'}
536
537     @classmethod
538     def poll(cls, context):
539         scene = context.scene
540         return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
541
542     def draw(self, context):
543         layout = self.layout
544
545         gs = context.scene.game_settings
546
547         layout.prop(gs, "physics_engine")
548         if gs.physics_engine != 'NONE':
549             layout.prop(gs, "physics_gravity", text="Gravity")
550
551             split = layout.split()
552
553             col = split.column()
554             col.label(text="Physics Steps:")
555             sub = col.column(align=True)
556             sub.prop(gs, "physics_step_max", text="Max")
557             sub.prop(gs, "physics_step_sub", text="Substeps")
558             col.prop(gs, "fps", text="FPS")
559
560             col = split.column()
561             col.label(text="Logic Steps:")
562             col.prop(gs, "logic_step_max", text="Max")
563
564             col = layout.column()
565             col.prop(gs, "use_occlusion_culling", text="Occlusion Culling")
566             sub = col.column()
567             sub.active = gs.use_occlusion_culling
568             sub.prop(gs, "occlusion_culling_resolution", text="Resolution")
569
570         else:
571             split = layout.split()
572
573             col = split.column()
574             col.label(text="Physics Steps:")
575             col.prop(gs, "fps", text="FPS")
576
577             col = split.column()
578             col.label(text="Logic Steps:")
579             col.prop(gs, "logic_step_max", text="Max")
580
581
582 class WORLD_PT_game_physics_obstacles(WorldButtonsPanel, Panel):
583     bl_label = "Obstacle simulation"
584     COMPAT_ENGINES = {'BLENDER_GAME'}
585
586     @classmethod
587     def poll(cls, context):
588         scene = context.scene
589         return (scene.world and scene.render.engine in cls.COMPAT_ENGINES)
590
591     def draw(self, context):
592         layout = self.layout
593
594         gs = context.scene.game_settings
595
596         layout.prop(gs, "obstacle_simulation", text="Type")
597         if gs.obstacle_simulation != 'NONE':
598             layout.prop(gs, "level_height")
599             layout.prop(gs, "show_obstacle_simulation")
600
601 if __name__ == "__main__":  # only for live edit.
602     bpy.utils.register_module(__name__)