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