Removed game_sound property as it is not working and not necessary anymore.
[blender.git] / release / scripts / ui / space_userpref.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21
22 # General UI Theme Settings (User Interface)
23 def ui_items_general(col, context):
24     row = col.row()
25     sub = row.column()
26     sub.prop(context, "outline")
27     sub.prop(context, "item", slider=True)
28     sub = row.column()
29     sub.prop(context, "inner", slider=True)
30     sub.prop(context, "inner_sel", slider=True)
31     sub = row.column()
32     sub.prop(context, "text")
33     sub.prop(context, "text_sel")
34     sub = row.column()
35     sub.prop(context, "shaded")
36     subsub = sub.column(align=True)
37     subsub.active = context.shaded
38     subsub.prop(context, "shadetop")
39     subsub.prop(context, "shadedown")
40     
41     col.separator()
42     
43 def opengl_lamp_buttons(column, lamp):
44     split = column.split(percentage=0.1)
45
46     if lamp.enabled == True:
47         split.prop(lamp, "enabled", text="", icon='OUTLINER_OB_LAMP')
48     else:
49         split.prop(lamp, "enabled", text="", icon='LAMP_DATA')
50
51     col = split.column()
52     col.active = lamp.enabled
53     row = col.row()
54     row.label(text="Diffuse:")
55     row.prop(lamp, "diffuse_color", text="")
56     row = col.row()
57     row.label(text="Specular:")
58     row.prop(lamp, "specular_color", text="")
59
60     col = split.column()
61     col.active = lamp.enabled
62     col.prop(lamp, "direction", text="")
63
64 KM_HIERARCHY = [
65                     ('Window', 'EMPTY', 'WINDOW', []), # file save, window change, exit
66                     ('Screen', 'EMPTY', 'WINDOW', [    # full screen, undo, screenshot
67                         ('Screen Editing', 'EMPTY', 'WINDOW', []),    # resizing, action corners
68                         ]),
69
70                     ('View2D', 'EMPTY', 'WINDOW', []),    # view 2d navigation (per region)
71                     ('View2D Buttons List', 'EMPTY', 'WINDOW', []), # view 2d with buttons navigation
72                     ('Header', 'EMPTY', 'WINDOW', []),    # header stuff (per region)
73                     ('Grease Pencil', 'EMPTY', 'WINDOW', []), # grease pencil stuff (per region)
74
75                     ('3D View', 'VIEW_3D', 'WINDOW', [ # view 3d navigation and generic stuff (select, transform)
76                         ('Object Mode', 'EMPTY', 'WINDOW', []),
77                         ('Mesh', 'EMPTY', 'WINDOW', []),
78                         ('Curve', 'EMPTY', 'WINDOW', []),
79                         ('Armature', 'EMPTY', 'WINDOW', []),
80                         ('Metaball', 'EMPTY', 'WINDOW', []),
81                         ('Lattice', 'EMPTY', 'WINDOW', []),
82                         ('Font', 'EMPTY', 'WINDOW', []),
83
84                         ('Pose', 'EMPTY', 'WINDOW', []),
85
86                         ('Vertex Paint', 'EMPTY', 'WINDOW', []),
87                         ('Weight Paint', 'EMPTY', 'WINDOW', []),
88                         ('Face Mask', 'EMPTY', 'WINDOW', []),
89                         ('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
90                         ('Sculpt', 'EMPTY', 'WINDOW', []),
91
92                         ('Armature Sketch', 'EMPTY', 'WINDOW', []),
93                         ('Particle', 'EMPTY', 'WINDOW', []),
94
95                         ('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
96
97                         ('3D View Generic', 'VIEW_3D', 'WINDOW', [])    # toolbar and properties
98                         ]),
99
100                     ('Frames', 'EMPTY', 'WINDOW', []),    # frame navigation (per region)
101                     ('Markers', 'EMPTY', 'WINDOW', []),    # markers (per region)
102                     ('Animation', 'EMPTY', 'WINDOW', []),    # frame change on click, preview range (per region)
103                     ('Animation Channels', 'EMPTY', 'WINDOW', []),
104                     ('Graph Editor', 'GRAPH_EDITOR', 'WINDOW', [
105                         ('Graph Editor Generic', 'GRAPH_EDITOR', 'WINDOW', [])
106                         ]),
107                     ('Dopesheet', 'DOPESHEET_EDITOR', 'WINDOW', []),
108                     ('NLA Editor', 'NLA_EDITOR', 'WINDOW', [
109                         ('NLA Channels', 'NLA_EDITOR', 'WINDOW', []),
110                         ('NLA Generic', 'NLA_EDITOR', 'WINDOW', [])
111                         ]),
112
113                     ('Image', 'IMAGE_EDITOR', 'WINDOW', [
114                         ('UV Editor', 'EMPTY', 'WINDOW', []), # image (reverse order, UVEdit before Image
115                         ('Image Paint', 'EMPTY', 'WINDOW', []), # image and view3d
116                         ('Image Generic', 'IMAGE_EDITOR', 'WINDOW', [])
117                         ]),
118
119                     ('Timeline', 'TIMELINE', 'WINDOW', []),
120                     ('Outliner', 'OUTLINER', 'WINDOW', []),
121
122                     ('Node Editor', 'NODE_EDITOR', 'WINDOW', [
123                         ('Node Generic', 'NODE_EDITOR', 'WINDOW', [])
124                         ]),
125                     ('Sequencer', 'SEQUENCE_EDITOR', 'WINDOW', []),
126                     ('Logic Editor', 'LOGIC_EDITOR', 'WINDOW', []),
127
128                     ('File Browser', 'FILE_BROWSER', 'WINDOW', [
129                         ('File Browser Main', 'FILE_BROWSER', 'WINDOW', []),
130                         ('File Browser Buttons', 'FILE_BROWSER', 'WINDOW', [])
131                         ]),
132
133                     ('Property Editor', 'PROPERTIES', 'WINDOW', []), # align context menu
134
135                     ('Script', 'SCRIPTS_WINDOW', 'WINDOW', []),
136                     ('Text', 'TEXT_EDITOR', 'WINDOW', []),
137                     ('Console', 'CONSOLE', 'WINDOW', []),
138
139                     ('View3D Gesture Circle', 'EMPTY', 'WINDOW', []),
140                     ('Gesture Border', 'EMPTY', 'WINDOW', []),
141                     ('Standard Modal Map', 'EMPTY', 'WINDOW', []),
142                     ('Transform Modal Map', 'EMPTY', 'WINDOW', []),
143                     ('View3D Fly Modal', 'EMPTY', 'WINDOW', []),
144                     ('View3D Rotate Modal', 'EMPTY', 'WINDOW', []),
145                     ('View3D Move Modal', 'EMPTY', 'WINDOW', []),
146                     ('View3D Zoom Modal', 'EMPTY', 'WINDOW', []),
147                 ]
148
149
150 class USERPREF_HT_header(bpy.types.Header):
151     bl_space_type = 'USER_PREFERENCES'
152
153     def draw(self, context):
154         layout = self.layout
155         layout.template_header(menus=False)
156
157         userpref = context.user_preferences
158
159         layout.operator_context = 'EXEC_AREA'
160         layout.operator("wm.save_homefile", text="Save As Default")
161
162         if userpref.active_section == 'INPUT':
163             layout.operator_context = 'INVOKE_DEFAULT'
164             layout.operator("wm.keyconfig_export", "Export Key Configuration...").path = "keymap.py"
165
166
167 class USERPREF_PT_tabs(bpy.types.Panel):
168     bl_label = ""
169     bl_space_type = 'USER_PREFERENCES'
170     bl_region_type = 'WINDOW'
171     bl_show_header = False
172
173     def draw(self, context):
174         layout = self.layout
175
176         userpref = context.user_preferences
177
178         layout.prop(userpref, "active_section", expand=True)
179
180
181 class USERPREF_PT_interface(bpy.types.Panel):
182     bl_space_type = 'USER_PREFERENCES'
183     bl_label = "Interface"
184     bl_region_type = 'WINDOW'
185     bl_show_header = False
186
187     def poll(self, context):
188         userpref = context.user_preferences
189         return (userpref.active_section == 'INTERFACE')
190
191     def draw(self, context):
192         layout = self.layout
193
194         userpref = context.user_preferences
195         view = userpref.view
196
197         row = layout.row()
198
199         col = row.column()
200         col.label(text="Display:")
201         col.prop(view, "tooltips")
202         col.prop(view, "display_object_info", text="Object Info")
203         col.prop(view, "use_large_cursors")
204         col.prop(view, "show_view_name", text="View Name")
205         col.prop(view, "show_playback_fps", text="Playback FPS")
206         col.prop(view, "global_scene")
207         col.prop(view, "pin_floating_panels")
208         col.prop(view, "object_origin_size")
209
210         col.separator()
211         col.separator()
212         col.separator()
213
214         col.prop(view, "show_mini_axis", text="Display Mini Axis")
215         sub = col.column()
216         sub.enabled = view.show_mini_axis
217         sub.prop(view, "mini_axis_size", text="Size")
218         sub.prop(view, "mini_axis_brightness", text="Brightness")
219
220         row.separator()
221         row.separator()
222
223         col = row.column()
224         col.label(text="View Manipulation:")
225         col.prop(view, "auto_depth")
226         col.prop(view, "zoom_to_mouse")
227         col.prop(view, "rotate_around_selection")
228         col.prop(view, "global_pivot")
229
230         col.separator()
231
232         col.prop(view, "auto_perspective")
233         col.prop(view, "smooth_view")
234         col.prop(view, "rotation_angle")
235
236         row.separator()
237         row.separator()
238
239         col = row.column()
240         #Toolbox doesn't exist yet
241         #col.label(text="Toolbox:")
242         #col.prop(view, "use_column_layout")
243         #col.label(text="Open Toolbox Delay:")
244         #col.prop(view, "open_left_mouse_delay", text="Hold LMB")
245         #col.prop(view, "open_right_mouse_delay", text="Hold RMB")
246         col.prop(view, "use_manipulator")
247         sub = col.column()
248         sub.enabled = view.use_manipulator
249         sub.prop(view, "manipulator_size", text="Size")
250         sub.prop(view, "manipulator_handle_size", text="Handle Size")
251         sub.prop(view, "manipulator_hotspot", text="Hotspot")
252
253         col.separator()
254         col.separator()
255         col.separator()
256
257         col.label(text="Menus:")
258         col.prop(view, "open_mouse_over")
259         col.label(text="Menu Open Delay:")
260         col.prop(view, "open_toplevel_delay", text="Top Level")
261         col.prop(view, "open_sublevel_delay", text="Sub Level")
262
263
264 class USERPREF_PT_edit(bpy.types.Panel):
265     bl_space_type = 'USER_PREFERENCES'
266     bl_label = "Edit"
267     bl_region_type = 'WINDOW'
268     bl_show_header = False
269
270     def poll(self, context):
271         userpref = context.user_preferences
272         return (userpref.active_section == 'EDITING')
273
274     def draw(self, context):
275         layout = self.layout
276
277         userpref = context.user_preferences
278         edit = userpref.edit
279
280         row = layout.row()
281
282         col = row.column()
283         col.label(text="Link Materials To:")
284         col.prop(edit, "material_link", text="")
285
286         col.separator()
287         col.separator()
288         col.separator()
289
290         col.label(text="New Objects:")
291         col.prop(edit, "enter_edit_mode")
292         col.label(text="Align To:")
293         col.prop(edit, "object_align", text="")
294
295         col.separator()
296         col.separator()
297         col.separator()
298
299         col.label(text="Undo:")
300         col.prop(edit, "global_undo")
301         col.prop(edit, "undo_steps", text="Steps")
302         col.prop(edit, "undo_memory_limit", text="Memory Limit")
303
304         row.separator()
305         row.separator()
306
307         col = row.column()
308         col.label(text="Snap:")
309         col.prop(edit, "snap_translate", text="Translate")
310         col.prop(edit, "snap_rotate", text="Rotate")
311         col.prop(edit, "snap_scale", text="Scale")
312         col.separator()
313         col.separator()
314         col.separator()
315         col.label(text="Grease Pencil:")
316         col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance")
317         col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance")
318         #col.prop(edit, "grease_pencil_simplify_stroke", text="Simplify Stroke")
319         col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius")
320         col.prop(edit, "grease_pencil_smooth_stroke", text="Smooth Stroke")
321
322         row.separator()
323         row.separator()
324
325         col = row.column()
326         col.label(text="Keyframing:")
327         col.prop(edit, "use_visual_keying")
328         col.prop(edit, "keyframe_insert_needed", text="Only Insert Needed")
329
330         col.separator()
331
332         col.label(text="New F-Curve Defaults:")
333         col.prop(edit, "new_interpolation_type", text="Interpolation")
334         col.prop(edit, "insertkey_xyz_to_rgb", text="XYZ to RGB")
335
336         col.separator()
337
338         col.prop(edit, "auto_keying_enable", text="Auto Keyframing:")
339
340         sub = col.column()
341
342         sub.active = edit.auto_keying_enable
343         sub.prop(edit, "auto_keyframe_insert_keyingset", text="Only Insert for Keying Set")
344         sub.prop(edit, "auto_keyframe_insert_available", text="Only Insert Available")
345
346         col.separator()
347         col.separator()
348         col.separator()
349
350         col.label(text="Transform:")
351         col.prop(edit, "drag_immediately")
352
353         row.separator()
354         row.separator()
355
356         col = row.column()
357         col.label(text="Duplicate Data:")
358         col.prop(edit, "duplicate_mesh", text="Mesh")
359         col.prop(edit, "duplicate_surface", text="Surface")
360         col.prop(edit, "duplicate_curve", text="Curve")
361         col.prop(edit, "duplicate_text", text="Text")
362         col.prop(edit, "duplicate_metaball", text="Metaball")
363         col.prop(edit, "duplicate_armature", text="Armature")
364         col.prop(edit, "duplicate_lamp", text="Lamp")
365         col.prop(edit, "duplicate_material", text="Material")
366         col.prop(edit, "duplicate_texture", text="Texture")
367         col.prop(edit, "duplicate_fcurve", text="F-Curve")
368         col.prop(edit, "duplicate_action", text="Action")
369         col.prop(edit, "duplicate_particle", text="Particle")
370
371
372 class USERPREF_PT_system(bpy.types.Panel):
373     bl_space_type = 'USER_PREFERENCES'
374     bl_label = "System"
375     bl_region_type = 'WINDOW'
376     bl_show_header = False
377
378     def poll(self, context):
379         userpref = context.user_preferences
380         return (userpref.active_section == 'SYSTEM')
381
382     def draw(self, context):
383         layout = self.layout
384
385         userpref = context.user_preferences
386         system = userpref.system
387
388         split = layout.split()
389
390
391         # 1. Column
392         column = split.column()
393         colsplit = column.split(percentage=0.85)
394
395         col = colsplit.column()
396         col.label(text="General:")
397         col.prop(system, "dpi")
398         col.prop(system, "frame_server_port")
399         col.prop(system, "scrollback", text="Console Scrollback")
400         col.prop(system, "auto_run_python_scripts")
401
402         col.separator()
403         col.separator()
404         col.separator()
405
406         col.label(text="Sound:")
407         col.row().prop(system, "audio_device", expand=True)
408         sub = col.column()
409         sub.active = system.audio_device != 'NONE'
410         #sub.prop(system, "enable_all_codecs")
411         sub.prop(system, "audio_channels", text="Channels")
412         sub.prop(system, "audio_mixing_buffer", text="Mixing Buffer")
413         sub.prop(system, "audio_sample_rate", text="Sample Rate")
414         sub.prop(system, "audio_sample_format", text="Sample Format")
415
416         col.separator()
417         col.separator()
418         col.separator()
419
420         #column = split.column()
421         #colsplit = column.split(percentage=0.85)
422
423         # No translation in 2.5 yet
424         #col.prop(system, "language")
425         #col.label(text="Translate:")
426         #col.prop(system, "translate_tooltips", text="Tooltips")
427         #col.prop(system, "translate_buttons", text="Labels")
428         #col.prop(system, "translate_toolbox", text="Toolbox")
429
430         #col.separator()
431
432         #col.prop(system, "use_textured_fonts")
433         
434
435         # 2. Column
436         column = split.column()
437         colsplit = column.split(percentage=0.85)
438
439         col = colsplit.column()
440         col.label(text="OpenGL:")
441         col.prop(system, "clip_alpha", slider=True)
442         col.prop(system, "use_mipmaps")
443         col.prop(system, "use_vbos")
444         #Anti-aliasing is disabled as it breaks broder/lasso select
445         #col.prop(system, "use_antialiasing")
446         col.label(text="Window Draw Method:")
447         col.row().prop(system, "window_draw_method", expand=True)
448         col.label(text="Textures:")
449         col.prop(system, "gl_texture_limit", text="Limit Size")
450         col.prop(system, "texture_time_out", text="Time Out")
451         col.prop(system, "texture_collection_rate", text="Collection Rate")
452
453         col.separator()
454         col.separator()
455         col.separator()
456
457         col.label(text="Sequencer:")
458         col.prop(system, "prefetch_frames")
459         col.prop(system, "memory_cache_limit")
460         
461
462         # 3. Column
463         column = split.column()
464
465         column.label(text="Solid OpenGL lights:")
466
467         split = column.split(percentage=0.1)
468         split.label()
469         split.label(text="Colors:")
470         split.label(text="Direction:")
471         
472         lamp = system.solid_lights[0]
473         opengl_lamp_buttons(column, lamp)
474         
475         lamp = system.solid_lights[1]
476         opengl_lamp_buttons(column, lamp)
477         
478         lamp = system.solid_lights[2]
479         opengl_lamp_buttons(column, lamp)
480
481         column.separator()
482         column.separator()
483         column.separator()
484         
485         column.label(text="Color Picker Type:")
486         column.row().prop(system, "color_picker_type", text="")
487         
488         column.separator()
489         column.separator()
490         column.separator()
491         
492         column.prop(system, "use_weight_color_range", text="Custom Weight Paint Range")
493         sub = column.column()
494         sub.active = system.use_weight_color_range
495         sub.template_color_ramp(system, "weight_color_range", expand=True)
496
497
498 class USERPREF_PT_theme(bpy.types.Panel):
499     bl_space_type = 'USER_PREFERENCES'
500     bl_label = "Themes"
501     bl_region_type = 'WINDOW'
502     bl_show_header = False
503
504     def poll(self, context):
505         userpref = context.user_preferences
506         return (userpref.active_section == 'THEMES')
507
508     def draw(self, context):
509         layout = self.layout
510
511         theme = context.user_preferences.themes[0]
512
513         split_themes = layout.split(percentage=0.2)
514         split_themes.prop(theme, "theme_area", expand=True)
515
516         split = split_themes.split()
517         
518         if theme.theme_area == 'USER_INTERFACE':
519             col = split.column()
520
521             ui = theme.user_interface.wcol_regular
522             col.label(text="Regular:")
523             ui_items_general(col, ui)
524
525             ui = theme.user_interface.wcol_tool
526             col.label(text="Tool:")
527             ui_items_general(col, ui)
528
529             ui = theme.user_interface.wcol_radio
530             col.label(text="Radio Buttons:")
531             ui_items_general(col, ui)
532
533             ui = theme.user_interface.wcol_text
534             col.label(text="Text:")
535             ui_items_general(col, ui)
536
537             ui = theme.user_interface.wcol_option
538             col.label(text="Option:")
539             ui_items_general(col, ui)
540
541             ui = theme.user_interface.wcol_toggle
542             col.label(text="Toggle:")
543             ui_items_general(col, ui)
544
545             ui = theme.user_interface.wcol_num
546             col.label(text="Number Field:")
547             ui_items_general(col, ui)
548
549             ui = theme.user_interface.wcol_numslider
550             col.label(text="Value Slider:")
551             ui_items_general(col, ui)
552
553             ui = theme.user_interface.wcol_box
554             col.label(text="Box:")
555             ui_items_general(col, ui)
556
557             ui = theme.user_interface.wcol_menu
558             col.label(text="Menu:")
559             ui_items_general(col, ui)
560
561             ui = theme.user_interface.wcol_pulldown
562             col.label(text="Pulldown:")
563             ui_items_general(col, ui)
564
565             ui = theme.user_interface.wcol_menu_back
566             col.label(text="Menu Back:")
567             ui_items_general(col, ui)
568
569             ui = theme.user_interface.wcol_menu_item
570             col.label(text="Menu Item:")
571             ui_items_general(col, ui)
572
573             ui = theme.user_interface.wcol_scroll
574             col.label(text="Scroll Bar:")
575             ui_items_general(col, ui)
576
577             ui = theme.user_interface.wcol_list_item
578             col.label(text="List Item:")
579             ui_items_general(col, ui)
580
581             ui = theme.user_interface.wcol_state
582             col.label(text="State:")
583
584             row = col.row()
585             sub = row.column()
586             sub.prop(ui, "inner_anim")
587             sub.prop(ui, "inner_anim_sel")
588             sub = row.column()
589             sub.prop(ui, "inner_driven")
590             sub.prop(ui, "inner_driven_sel")
591             sub = row.column()
592             sub.prop(ui, "inner_key")
593             sub.prop(ui, "inner_key_sel")
594             sub = row.column()
595             sub.prop(ui, "blend")
596
597             ui = theme.user_interface
598             col.separator()
599             col.separator()
600             col.prop(ui, "icon_file")
601
602             layout.separator()
603             layout.separator()
604
605
606         elif theme.theme_area == 'VIEW_3D':
607             v3d = theme.view_3d
608
609             col = split.column()
610             col.prop(v3d, "back")
611             col.prop(v3d, "button")
612             col.prop(v3d, "button_title")
613             col.prop(v3d, "button_text")
614             col.prop(v3d, "header")
615
616             col = split.column()
617             col.prop(v3d, "grid")
618             col.prop(v3d, "wire")
619             col.prop(v3d, "lamp", slider=True)
620             col.prop(v3d, "editmesh_active", slider=True)
621
622             col = split.column()
623             col.prop(v3d, "object_selected")
624             col.prop(v3d, "object_active")
625             col.prop(v3d, "object_grouped")
626             col.prop(v3d, "object_grouped_active")
627             col.prop(v3d, "transform")
628
629             col = split.column()
630             col.prop(v3d, "vertex")
631             col.prop(v3d, "face", slider=True)
632             col.prop(v3d, "normal")
633             col.prop(v3d, "bone_solid")
634             col.prop(v3d, "bone_pose")
635             #col.prop(v3d, "edge") Doesn't seem to work
636
637         elif theme.theme_area == 'GRAPH_EDITOR':
638             graph = theme.graph_editor
639
640             col = split.column()
641             col.prop(graph, "back")
642             col.prop(graph, "button")
643             col.prop(graph, "button_title")
644             col.prop(graph, "button_text")
645
646             col = split.column()
647             col.prop(graph, "header")
648             col.prop(graph, "grid")
649             col.prop(graph, "list")
650             col.prop(graph, "channel_group")
651
652             col = split.column()
653             col.prop(graph, "active_channels_group")
654             col.prop(graph, "dopesheet_channel")
655             col.prop(graph, "dopesheet_subchannel")
656             col.prop(graph, "vertex")
657
658             col = split.column()
659             col.prop(graph, "current_frame")
660             col.prop(graph, "handle_vertex")
661             col.prop(graph, "handle_vertex_select")
662             col.separator()
663             col.prop(graph, "handle_vertex_size")
664
665         elif theme.theme_area == 'FILE_BROWSER':
666             file_browse = theme.file_browser
667
668             col = split.column()
669             col.prop(file_browse, "back")
670             col.prop(file_browse, "text")
671             col.prop(file_browse, "text_hi")
672
673             col = split.column()
674             col.prop(file_browse, "header")
675             col.prop(file_browse, "list")
676
677             col = split.column()
678             col.prop(file_browse, "selected_file")
679             col.prop(file_browse, "tiles")
680
681             col = split.column()
682             col.prop(file_browse, "active_file")
683             col.prop(file_browse, "active_file_text")
684
685         elif theme.theme_area == 'NLA_EDITOR':
686             nla = theme.nla_editor
687
688             col = split.column()
689             col.prop(nla, "back")
690             col.prop(nla, "button")
691             col.prop(nla, "button_title")
692
693             col = split.column()
694             col.prop(nla, "button_text")
695             col.prop(nla, "text")
696             col.prop(nla, "header")
697
698             col = split.column()
699             col.prop(nla, "grid")
700             col.prop(nla, "bars")
701             col.prop(nla, "bars_selected")
702
703             col = split.column()
704             col.prop(nla, "strips")
705             col.prop(nla, "strips_selected")
706             col.prop(nla, "current_frame")
707
708         elif theme.theme_area == 'DOPESHEET_EDITOR':
709             dope = theme.dopesheet_editor
710
711             col = split.column()
712             col.prop(dope, "back")
713             col.prop(dope, "list")
714             col.prop(dope, "text")
715             col.prop(dope, "header")
716
717             col = split.column()
718             col.prop(dope, "grid")
719             col.prop(dope, "channels")
720             col.prop(dope, "channels_selected")
721             col.prop(dope, "channel_group")
722
723             col = split.column()
724             col.prop(dope, "active_channels_group")
725             col.prop(dope, "long_key")
726             col.prop(dope, "long_key_selected")
727
728             col = split.column()
729             col.prop(dope, "current_frame")
730             col.prop(dope, "dopesheet_channel")
731             col.prop(dope, "dopesheet_subchannel")
732
733         elif theme.theme_area == 'IMAGE_EDITOR':
734             image = theme.image_editor
735
736             col = split.column()
737             col.prop(image, "back")
738             col.prop(image, "button")
739
740             col = split.column()
741             col.prop(image, "button_title")
742             col.prop(image, "button_text")
743
744             col = split.column()
745             col.prop(image, "header")
746
747             col = split.column()
748             col.prop(image, "editmesh_active", slider=True)
749
750         elif theme.theme_area == 'SEQUENCE_EDITOR':
751             seq = theme.sequence_editor
752
753             col = split.column()
754             col.prop(seq, "back")
755             col.prop(seq, "button")
756             col.prop(seq, "button_title")
757             col.prop(seq, "button_text")
758             col.prop(seq, "text")
759
760             col = split.column()
761             col.prop(seq, "header")
762             col.prop(seq, "grid")
763             col.prop(seq, "movie_strip")
764             col.prop(seq, "image_strip")
765             col.prop(seq, "scene_strip")
766
767             col = split.column()
768             col.prop(seq, "audio_strip")
769             col.prop(seq, "effect_strip")
770             col.prop(seq, "plugin_strip")
771             col.prop(seq, "transition_strip")
772
773             col = split.column()
774             col.prop(seq, "meta_strip")
775             col.prop(seq, "current_frame")
776             col.prop(seq, "keyframe")
777             col.prop(seq, "draw_action")
778
779         elif theme.theme_area == 'PROPERTIES':
780             prop = theme.properties
781
782             col = split.column()
783             col.prop(prop, "back")
784
785             col = split.column()
786             col.prop(prop, "title")
787
788             col = split.column()
789             col.prop(prop, "text")
790
791             col = split.column()
792             col.prop(prop, "header")
793
794         elif theme.theme_area == 'TEXT_EDITOR':
795             text = theme.text_editor
796
797             col = split.column()
798             col.prop(text, "back")
799             col.prop(text, "button")
800             col.prop(text, "button_title")
801             col.prop(text, "button_text")
802
803             col = split.column()
804             col.prop(text, "text")
805             col.prop(text, "text_hi")
806             col.prop(text, "header")
807             col.prop(text, "line_numbers_background")
808
809             col = split.column()
810             col.prop(text, "selected_text")
811             col.prop(text, "cursor")
812             col.prop(text, "syntax_builtin")
813             col.prop(text, "syntax_special")
814
815             col = split.column()
816             col.prop(text, "syntax_comment")
817             col.prop(text, "syntax_string")
818             col.prop(text, "syntax_numbers")
819
820         elif theme.theme_area == 'TIMELINE':
821             time = theme.timeline
822
823             col = split.column()
824             col.prop(time, "back")
825             col.prop(time, "text")
826
827             col = split.column()
828             col.prop(time, "header")
829
830             col = split.column()
831             col.prop(time, "grid")
832
833             col = split.column()
834             col.prop(time, "current_frame")
835
836         elif theme.theme_area == 'NODE_EDITOR':
837             node = theme.node_editor
838
839             col = split.column()
840             col.prop(node, "back")
841             col.prop(node, "button")
842             col.prop(node, "button_title")
843             col.prop(node, "button_text")
844
845             col = split.column()
846             col.prop(node, "text")
847             col.prop(node, "text_hi")
848             col.prop(node, "header")
849             col.prop(node, "wires")
850
851             col = split.column()
852             col.prop(node, "wire_select")
853             col.prop(node, "selected_text")
854             col.prop(node, "node_backdrop", slider=True)
855             col.prop(node, "in_out_node")
856
857             col = split.column()
858             col.prop(node, "converter_node")
859             col.prop(node, "operator_node")
860             col.prop(node, "group_node")
861
862         elif theme.theme_area == 'LOGIC_EDITOR':
863             logic = theme.logic_editor
864
865             col = split.column()
866             col.prop(logic, "back")
867             col.prop(logic, "button")
868
869             col = split.column()
870             col.prop(logic, "button_title")
871             col.prop(logic, "button_text")
872
873             col = split.column()
874             col.prop(logic, "text")
875             col.prop(logic, "header")
876
877             col = split.column()
878             col.prop(logic, "panel")
879
880         elif theme.theme_area == 'OUTLINER':
881             out = theme.outliner
882
883             col = split.column()
884             col.prop(out, "back")
885
886             col = split.column()
887             col.prop(out, "text")
888
889             col = split.column()
890             col.prop(out, "text_hi")
891
892             col = split.column()
893             col.prop(out, "header")
894
895         elif theme.theme_area == 'INFO':
896             info = theme.info
897
898             col = split.column()
899             col.prop(info, "back")
900
901             col = split.column()
902             col.prop(info, "header")
903
904             col = split.column()
905             col.prop(info, "header_text")
906
907             col = split.column()
908
909         elif theme.theme_area == 'USER_PREFERENCES':
910             prefs = theme.user_preferences
911
912             col = split.column()
913             col.prop(prefs, "back")
914
915             col = split.column()
916             col.prop(prefs, "text")
917
918             col = split.column()
919             col.prop(prefs, "header")
920
921             col = split.column()
922             col.prop(prefs, "header_text")
923
924
925 class USERPREF_PT_file(bpy.types.Panel):
926     bl_space_type = 'USER_PREFERENCES'
927     bl_label = "Files"
928     bl_region_type = 'WINDOW'
929     bl_show_header = False
930
931     def poll(self, context):
932         userpref = context.user_preferences
933         return (userpref.active_section == 'FILES')
934
935     def draw(self, context):
936         layout = self.layout
937
938         userpref = context.user_preferences
939         paths = userpref.filepaths
940
941         split = layout.split(percentage=0.7)
942
943         col = split.column()
944         col.label(text="File Paths:")
945
946         colsplit = col.split(percentage=0.95)
947         col1 = colsplit.split(percentage=0.3)
948
949         sub = col1.column()
950         sub.label(text="Fonts:")
951         sub.label(text="Textures:")
952         sub.label(text="Texture Plugins:")
953         sub.label(text="Sequence Plugins:")
954         sub.label(text="Render Output:")
955         sub.label(text="Scripts:")
956         sub.label(text="Sounds:")
957         sub.label(text="Temp:")
958         sub.label(text="Animation Player:")
959
960         sub = col1.column()
961         sub.prop(paths, "fonts_directory", text="")
962         sub.prop(paths, "textures_directory", text="")
963         sub.prop(paths, "texture_plugin_directory", text="")
964         sub.prop(paths, "sequence_plugin_directory", text="")
965         sub.prop(paths, "render_output_directory", text="")
966         sub.prop(paths, "python_scripts_directory", text="")
967         sub.prop(paths, "sounds_directory", text="")
968         sub.prop(paths, "temporary_directory", text="")
969         subsplit = sub.split(percentage=0.3)
970         subsplit.prop(paths, "animation_player_preset", text="")
971         subsplit.prop(paths, "animation_player", text="")
972
973         col = split.column()
974         col.label(text="Save & Load:")
975         col.prop(paths, "use_relative_paths")
976         col.prop(paths, "compress_file")
977         col.prop(paths, "load_ui")
978         col.prop(paths, "filter_file_extensions")
979         col.prop(paths, "hide_dot_files_datablocks")
980
981         col.separator()
982         col.separator()
983
984         col.label(text="Auto Save:")
985         col.prop(paths, "save_version")
986         col.prop(paths, "recent_files")
987         col.prop(paths, "save_preview_images")
988         col.prop(paths, "auto_save_temporary_files")
989         sub = col.column()
990         sub.enabled = paths.auto_save_temporary_files
991         sub.prop(paths, "auto_save_time", text="Timer (mins)")
992
993
994 class USERPREF_PT_input(bpy.types.Panel):
995     bl_space_type = 'USER_PREFERENCES'
996     bl_label = "Input"
997     bl_region_type = 'WINDOW'
998     bl_show_header = False
999
1000     def poll(self, context):
1001         userpref = context.user_preferences
1002         return (userpref.active_section == 'INPUT')
1003
1004     def draw_entry(self, kc, entry, col, level=0):
1005         idname, spaceid, regionid, children = entry
1006
1007         km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid)
1008
1009         if km:
1010             self.draw_km(kc, km, children, col, level)
1011
1012     def indented_layout(self, layout, level):
1013         indentpx = 16
1014         if level == 0:
1015             level = 0.0001   # Tweak so that a percentage of 0 won't split by half
1016         indent = level * indentpx / bpy.context.region.width
1017
1018         split = layout.split(percentage=indent)
1019         col = split.column()
1020         col = split.column()
1021         return col
1022
1023     def draw_km(self, kc, km, children, layout, level):
1024         km = km.active()
1025
1026         layout.set_context_pointer("keymap", km)
1027
1028         col = self.indented_layout(layout, level)
1029
1030         row = col.row()
1031         row.prop(km, "children_expanded", text="", no_bg=True)
1032         row.label(text=km.name)
1033
1034         row.label()
1035         row.label()
1036
1037         if km.user_defined:
1038             row.operator("wm.keymap_restore", text="Restore")
1039         else:
1040             row.operator("wm.keymap_edit", text="Edit")
1041
1042         if km.children_expanded:
1043             if children:
1044                 # Put the Parent key map's entries in a 'global' sub-category
1045                 # equal in hierarchy to the other children categories
1046                 subcol = self.indented_layout(col, level + 1)
1047                 subrow = subcol.row()
1048                 subrow.prop(km, "items_expanded", text="", no_bg=True)
1049                 subrow.label(text="%s (Global)" % km.name)
1050             else:
1051                 km.items_expanded = True
1052
1053             # Key Map items
1054             if km.items_expanded:
1055                 for kmi in km.items:
1056                     self.draw_kmi(kc, km, kmi, col, level + 1)
1057
1058                 # "Add New" at end of keymap item list
1059                 col = self.indented_layout(col, level + 1)
1060                 subcol = col.split(percentage=0.2).column()
1061                 subcol.active = km.user_defined
1062                 subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
1063
1064             col.separator()
1065
1066             # Child key maps
1067             if children:
1068                 subcol = col.column()
1069                 row = subcol.row()
1070
1071                 for entry in children:
1072                     self.draw_entry(kc, entry, col, level + 1)
1073
1074     def draw_kmi(self, kc, km, kmi, layout, level):
1075         layout.set_context_pointer("keyitem", kmi)
1076
1077         col = self.indented_layout(layout, level)
1078
1079         col.enabled = km.user_defined
1080
1081         if km.user_defined:
1082             col = col.column(align=True)
1083             box = col.box()
1084         else:
1085             box = col.column()
1086
1087         split = box.split(percentage=0.4)
1088
1089         # header bar
1090         row = split.row()
1091         row.prop(kmi, "expanded", text="", no_bg=True)
1092         row.prop(kmi, "active", text="", no_bg=True)
1093
1094         if km.modal:
1095             row.prop(kmi, "propvalue", text="")
1096         else:
1097             row.label(text=kmi.name)
1098
1099         row = split.row()
1100         row.prop(kmi, "map_type", text="")
1101         if kmi.map_type == 'KEYBOARD':
1102             row.prop(kmi, "type", text="", full_event=True)
1103         elif kmi.map_type == 'MOUSE':
1104             row.prop(kmi, "type", text="", full_event=True)
1105         elif kmi.map_type == 'TWEAK':
1106             subrow = row.row()
1107             subrow.prop(kmi, "type", text="")
1108             subrow.prop(kmi, "value", text="")
1109         elif kmi.map_type == 'TIMER':
1110             row.prop(kmi, "type", text="")
1111         else:
1112             row.label()
1113
1114         row.operator("wm.keyitem_restore", text="", icon='BACK')
1115         row.operator("wm.keyitem_remove", text="", icon='X')
1116
1117         # Expanded, additional event settings
1118         if kmi.expanded:
1119             box = col.box()
1120
1121             if kmi.map_type not in ('TEXTINPUT', 'TIMER'):
1122                 split = box.split(percentage=0.4)
1123                 sub = split.row()
1124
1125                 if km.modal:
1126                     sub.prop(kmi, "propvalue", text="")
1127                 else:
1128                     sub.prop(kmi, "idname", text="")
1129
1130                 sub = split.column()
1131                 subrow = sub.row(align=True)
1132
1133                 if kmi.map_type == 'KEYBOARD':
1134                     subrow.prop(kmi, "type", text="", event=True)
1135                     subrow.prop(kmi, "value", text="")
1136                 elif kmi.map_type == 'MOUSE':
1137                     subrow.prop(kmi, "type", text="")
1138                     subrow.prop(kmi, "value", text="")
1139
1140                 subrow = sub.row()
1141                 subrow.scale_x = 0.75
1142                 subrow.prop(kmi, "any")
1143                 subrow.prop(kmi, "shift")
1144                 subrow.prop(kmi, "ctrl")
1145                 subrow.prop(kmi, "alt")
1146                 subrow.prop(kmi, "oskey", text="Cmd")
1147                 subrow.prop(kmi, "key_modifier", text="", event=True)
1148
1149             # Operator properties
1150             props = kmi.properties
1151             if props is not None:
1152                 box.separator()
1153                 flow = box.column_flow(columns=2)
1154                 for pname in dir(props):
1155                     if not props.is_property_hidden(pname):
1156                         flow.prop(props, pname)
1157
1158             # Modal key maps attached to this operator
1159             if not km.modal:
1160                 kmm = kc.find_keymap_modal(kmi.idname)
1161                 if kmm:
1162                     self.draw_km(kc, kmm, None, layout, level + 1)
1163
1164     def draw_input_prefs(self, inputs, layout):
1165         # General settings
1166         row = layout.row()
1167         col = row.column()
1168
1169         sub = col.column()
1170         sub.label(text="Mouse:")
1171         sub1 = sub.column()
1172         sub1.enabled = (inputs.select_mouse == 'RIGHT')
1173         sub1.prop(inputs, "emulate_3_button_mouse")
1174         sub.prop(inputs, "continuous_mouse")
1175
1176         sub.label(text="Select With:")
1177         sub.row().prop(inputs, "select_mouse", expand=True)
1178
1179         sub = col.column()
1180         sub.label(text="Double Click:")
1181         sub.prop(inputs, "double_click_time", text="Speed")
1182
1183         sub.separator()
1184
1185         sub.prop(inputs, "emulate_numpad")
1186
1187         sub.separator()
1188
1189         sub.label(text="Orbit Style:")
1190         sub.row().prop(inputs, "view_rotation", expand=True)
1191
1192         sub.label(text="Zoom Style:")
1193         sub.row().prop(inputs, "viewport_zoom_style", expand=True)
1194         if inputs.viewport_zoom_style == 'DOLLY':
1195             sub.row().prop(inputs, "zoom_axis", expand=True)
1196             sub.prop(inputs, "invert_zoom_direction")
1197
1198         #sub.prop(inputs, "use_middle_mouse_paste")
1199
1200         #col.separator()
1201
1202         #sub = col.column()
1203         #sub.label(text="Mouse Wheel:")
1204         #sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
1205
1206         col.separator()
1207
1208         sub = col.column()
1209         sub.label(text="NDOF Device:")
1210         sub.prop(inputs, "ndof_pan_speed", text="Pan Speed")
1211         sub.prop(inputs, "ndof_rotate_speed", text="Orbit Speed")
1212
1213         row.separator()
1214
1215     def draw_filtered(self, kc, layout):
1216         filter = kc.filter.lower()
1217
1218         for km in kc.keymaps:
1219             km = km.active()
1220
1221             filtered_items = [kmi for kmi in km.items if filter in kmi.name.lower()]
1222
1223             if len(filtered_items) != 0:
1224                 layout.set_context_pointer("keymap", km)
1225                 col = layout.column()
1226
1227                 row = col.row()
1228                 row.label(text=km.name, icon="DOT")
1229
1230                 row.label()
1231                 row.label()
1232
1233                 if km.user_defined:
1234                     row.operator("wm.keymap_restore", text="Restore")
1235                 else:
1236                     row.operator("wm.keymap_edit", text="Edit")
1237
1238                 for kmi in filtered_items:
1239                     self.draw_kmi(kc, km, kmi, col, 1)
1240
1241                 # "Add New" at end of keymap item list
1242                 col = self.indented_layout(layout, 1)
1243                 subcol = col.split(percentage=0.2).column()
1244                 subcol.active = km.user_defined
1245                 subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
1246
1247     def draw_hierarchy(self, defkc, layout):
1248         for entry in KM_HIERARCHY:
1249             self.draw_entry(defkc, entry, layout)
1250
1251     def draw(self, context):
1252         layout = self.layout
1253
1254         userpref = context.user_preferences
1255         wm = context.manager
1256
1257         inputs = userpref.inputs
1258
1259         split = layout.split(percentage=0.25)
1260
1261         # Input settings
1262         self.draw_input_prefs(inputs, split)
1263
1264         # Keymap Settings
1265         col = split.column()
1266         # kc = wm.active_keyconfig
1267         kc = wm.default_keyconfig
1268
1269         sub = col.column()
1270
1271         subsplit = sub.split()
1272         subcol = subsplit.column()
1273         subcol.prop_object(wm, "active_keyconfig", wm, "keyconfigs", text="Configuration:")
1274
1275         subcol = subsplit.column()
1276         subcol.prop(kc, "filter", icon="VIEWZOOM")
1277
1278         col.separator()
1279
1280         if kc.filter != "":
1281             self.draw_filtered(kc, col)
1282         else:
1283             self.draw_hierarchy(kc, col)
1284
1285 bpy.types.register(USERPREF_HT_header)
1286 bpy.types.register(USERPREF_PT_tabs)
1287 bpy.types.register(USERPREF_PT_interface)
1288 bpy.types.register(USERPREF_PT_theme)
1289 bpy.types.register(USERPREF_PT_edit)
1290 bpy.types.register(USERPREF_PT_system)
1291 bpy.types.register(USERPREF_PT_file)
1292 bpy.types.register(USERPREF_PT_input)
1293
1294 from bpy.props import *
1295
1296
1297 class WM_OT_keyconfig_test(bpy.types.Operator):
1298     "Test keyconfig for conflicts."
1299     bl_idname = "wm.keyconfig_test"
1300     bl_label = "Test Key Configuration for Conflicts"
1301
1302     def testEntry(self, kc, entry, src=None, parent=None):
1303         result = False
1304
1305         def kmistr(kmi):
1306             if km.modal:
1307                 s = ["kmi = km.add_modal_item(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
1308             else:
1309                 s = ["kmi = km.add_item(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
1310
1311             if kmi.any:
1312                 s.append(", any=True")
1313             else:
1314                 if kmi.shift:
1315                     s.append(", shift=True")
1316                 if kmi.ctrl:
1317                     s.append(", ctrl=True")
1318                 if kmi.alt:
1319                     s.append(", alt=True")
1320                 if kmi.oskey:
1321                     s.append(", oskey=True")
1322             if kmi.key_modifier and kmi.key_modifier != 'NONE':
1323                 s.append(", key_modifier=\'%s\'" % kmi.key_modifier)
1324
1325             s.append(")\n")
1326
1327             props = kmi.properties
1328
1329             if props is not None:
1330                 for pname in dir(props):
1331                     if props.is_property_set(pname) and not props.is_property_hidden(pname):
1332                         value = eval("props.%s" % pname)
1333                         value = _string_value(value)
1334                         if value != "":
1335                             s.append("kmi.properties.%s = %s\n" % (pname, value))
1336
1337             return "".join(s).strip()
1338
1339         idname, spaceid, regionid, children = entry
1340
1341         km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid)
1342
1343         if km:
1344             km = km.active()
1345
1346             if src:
1347                 for item in km.items:
1348                     if src.compare(item):
1349                         print("===========")
1350                         print(parent.name)
1351                         print(kmistr(src))
1352                         print(km.name)
1353                         print(kmistr(item))
1354                         result = True
1355
1356                 for child in children:
1357                     if self.testEntry(kc, child, src, parent):
1358                         result = True
1359             else:
1360                 for i in range(len(km.items)):
1361                     src = km.items[i]
1362
1363                     for child in children:
1364                         if self.testEntry(kc, child, src, km):
1365                             result = True
1366
1367                     for j in range(len(km.items) - i - 1):
1368                         item = km.items[j + i + 1]
1369                         if src.compare(item):
1370                             print("===========")
1371                             print(km.name)
1372                             print(kmistr(src))
1373                             print(kmistr(item))
1374                             result = True
1375
1376                 for child in children:
1377                     if self.testEntry(kc, child):
1378                         result = True
1379
1380         return result
1381
1382     def testConfig(self, kc):
1383         result = False
1384         for entry in KM_HIERARCHY:
1385             if self.testEntry(kc, entry):
1386                 result = True
1387         return result
1388
1389     def execute(self, context):
1390         wm = context.manager
1391         kc = wm.default_keyconfig
1392
1393         if self.testConfig(kc):
1394             print("CONFLICT")
1395
1396         return {'FINISHED'}
1397
1398
1399 def _string_value(value):
1400     result = ""
1401     if isinstance(value, str):
1402         if value != "":
1403             result = "\'%s\'" % value
1404     elif isinstance(value, bool):
1405         if value:
1406             result = "True"
1407         else:
1408             result = "False"
1409     elif isinstance(value, float):
1410         result = "%.10f" % value
1411     elif isinstance(value, int):
1412         result = "%d" % value
1413     elif getattr(value, '__len__', False):
1414         if len(value):
1415             result = "["
1416             for i in range(0, len(value)):
1417                 result += _string_value(value[i])
1418                 if i != len(value)-1:
1419                     result += ", "
1420             result += "]"
1421     else:
1422         print("Export key configuration: can't write ", value)
1423
1424     return result
1425
1426
1427 class WM_OT_keyconfig_export(bpy.types.Operator):
1428     "Export key configuration to a python script."
1429     bl_idname = "wm.keyconfig_export"
1430     bl_label = "Export Key Configuration..."
1431
1432     path = bpy.props.StringProperty(name="File Path", description="File path to write file to.")
1433
1434     def execute(self, context):
1435         if not self.properties.path:
1436             raise Exception("File path not set.")
1437
1438         f = open(self.properties.path, "w")
1439         if not f:
1440             raise Exception("Could not open file.")
1441
1442         wm = context.manager
1443         kc = wm.active_keyconfig
1444
1445         f.write('# Configuration %s\n' % kc.name)
1446
1447         f.write("wm = bpy.data.windowmanagers[0]\n")
1448         f.write("kc = wm.add_keyconfig(\'%s\')\n\n" % kc.name)
1449
1450         for km in kc.keymaps:
1451             km = km.active()
1452             f.write("# Map %s\n" % km.name)
1453             f.write("km = kc.add_keymap(\'%s\', space_type=\'%s\', region_type=\'%s\', modal=%s)\n\n" % (km.name, km.space_type, km.region_type, km.modal))
1454             for kmi in km.items:
1455                 if km.modal:
1456                     f.write("kmi = km.add_modal_item(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value))
1457                 else:
1458                     f.write("kmi = km.add_item(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value))
1459                 if kmi.any:
1460                     f.write(", any=True")
1461                 else:
1462                     if kmi.shift:
1463                         f.write(", shift=True")
1464                     if kmi.ctrl:
1465                         f.write(", ctrl=True")
1466                     if kmi.alt:
1467                         f.write(", alt=True")
1468                     if kmi.oskey:
1469                         f.write(", oskey=True")
1470                 if kmi.key_modifier and kmi.key_modifier != 'NONE':
1471                     f.write(", key_modifier=\'%s\'" % kmi.key_modifier)
1472                 f.write(")\n")
1473
1474                 props = kmi.properties
1475
1476                 if props is not None:
1477                     for pname in dir(props):
1478                         if props.is_property_set(pname) and not props.is_property_hidden(pname):
1479                             value = eval("props.%s" % pname)
1480                             value = _string_value(value)
1481                             if value != "":
1482                                 f.write("kmi.properties.%s = %s\n" % (pname, value))
1483
1484             f.write("\n")
1485
1486         f.close()
1487
1488         return {'FINISHED'}
1489
1490     def invoke(self, context, event):
1491         wm = context.manager
1492         wm.add_fileselect(self)
1493         return {'RUNNING_MODAL'}
1494
1495
1496 class WM_OT_keymap_edit(bpy.types.Operator):
1497     "Edit key map."
1498     bl_idname = "wm.keymap_edit"
1499     bl_label = "Edit Key Map"
1500
1501     def execute(self, context):
1502         wm = context.manager
1503         km = context.keymap
1504         km.copy_to_user()
1505         return {'FINISHED'}
1506
1507
1508 class WM_OT_keymap_restore(bpy.types.Operator):
1509     "Restore key map(s)."
1510     bl_idname = "wm.keymap_restore"
1511     bl_label = "Restore Key Map(s)"
1512
1513     all = BoolProperty(attr="all", name="All Keymaps", description="Restore all keymaps to default.")
1514
1515     def execute(self, context):
1516         wm = context.manager
1517
1518         if self.properties.all:
1519             for km in wm.default_keyconfig.keymaps:
1520                 km.restore_to_default()
1521         else:
1522             km = context.keymap
1523             km.restore_to_default()
1524
1525         return {'FINISHED'}
1526
1527
1528 class WM_OT_keyitem_restore(bpy.types.Operator):
1529     "Restore key map item."
1530     bl_idname = "wm.keyitem_restore"
1531     bl_label = "Restore Key Map Item"
1532
1533     def poll(self, context):
1534         kmi = context.keyitem
1535         km = context.keymap
1536         return km and kmi and kmi.id != 0
1537
1538     def execute(self, context):
1539         wm = context.manager
1540         kmi = context.keyitem
1541         km = context.keymap
1542
1543         km.restore_item_to_default(kmi)
1544
1545         return {'FINISHED'}
1546
1547
1548 class WM_OT_keyitem_add(bpy.types.Operator):
1549     "Add key map item."
1550     bl_idname = "wm.keyitem_add"
1551     bl_label = "Add Key Map Item"
1552
1553     def execute(self, context):
1554         wm = context.manager
1555         km = context.keymap
1556         kc = wm.default_keyconfig
1557
1558         if km.modal:
1559             km.add_modal_item("", 'A', 'PRESS') # kmi
1560         else:
1561             km.add_item("none", 'A', 'PRESS') # kmi
1562
1563         # clear filter and expand keymap so we can see the newly added item
1564         if kc.filter != '':
1565             kc.filter = ''
1566             km.items_expanded = True
1567             km.children_expanded = True
1568
1569         return {'FINISHED'}
1570
1571
1572 class WM_OT_keyitem_remove(bpy.types.Operator):
1573     "Remove key map item."
1574     bl_idname = "wm.keyitem_remove"
1575     bl_label = "Remove Key Map Item"
1576
1577     def execute(self, context):
1578         wm = context.manager
1579         kmi = context.keyitem
1580         km = context.keymap
1581         km.remove_item(kmi)
1582         return {'FINISHED'}
1583
1584 bpy.types.register(WM_OT_keyconfig_export)
1585 bpy.types.register(WM_OT_keyconfig_test)
1586 bpy.types.register(WM_OT_keymap_edit)
1587 bpy.types.register(WM_OT_keymap_restore)
1588 bpy.types.register(WM_OT_keyitem_add)
1589 bpy.types.register(WM_OT_keyitem_remove)
1590 bpy.types.register(WM_OT_keyitem_restore)