46ebe3070ef0a355e42ef6c837f828c8356c61de
[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         col.label(text="Window Draw Method:")
415         col.row().prop(system, "window_draw_method", expand=True)
416         col.label(text="Textures:")
417         col.prop(system, "gl_texture_limit", text="Limit Size")
418         col.prop(system, "texture_time_out", text="Time Out")
419         col.prop(system, "texture_collection_rate", text="Collection Rate")
420
421         col.separator()
422         col.separator()
423         col.separator()
424
425         col.label(text="Sequencer:")
426         col.prop(system, "prefetch_frames")
427         col.prop(system, "memory_cache_limit")
428
429         column = split.column()
430
431         column.label(text="Solid OpenGL lights:")
432
433         split = column.split(percentage=0.1)
434         split.label()
435         split.label(text="Colors:")
436         split.label(text="Direction:")
437
438
439         split = column.split(percentage=0.1)
440
441         if lamp0.enabled == True:
442             split.prop(lamp0, "enabled", text="", icon='OUTLINER_OB_LAMP')
443         else:
444             split.prop(lamp0, "enabled", text="", icon='LAMP_DATA')
445
446         col = split.column()
447         col.active = lamp0.enabled
448         row = col.row()
449         row.label(text="Diffuse:")
450         row.prop(lamp0, "diffuse_color", text="")
451         row = col.row()
452         row.label(text="Specular:")
453         row.prop(lamp0, "specular_color", text="")
454
455         col = split.column()
456         col.active = lamp0.enabled
457         col.prop(lamp0, "direction", text="")
458
459
460         split = column.split(percentage=0.1)
461
462         if lamp1.enabled == True:
463             split.prop(lamp1, "enabled", text="", icon='OUTLINER_OB_LAMP')
464         else:
465             split.prop(lamp1, "enabled", text="", icon='LAMP_DATA')
466
467         col = split.column()
468         col.active = lamp1.enabled
469         row = col.row()
470         row.label(text="Diffuse:")
471         row.prop(lamp1, "diffuse_color", text="")
472         row = col.row()
473         row.label(text="Specular:")
474         row.prop(lamp1, "specular_color", text="")
475
476         col = split.column()
477         col.active = lamp1.enabled
478         col.prop(lamp1, "direction", text="")
479
480
481         split = column.split(percentage=0.1)
482
483         if lamp2.enabled == True:
484             split.prop(lamp2, "enabled", text="", icon='OUTLINER_OB_LAMP')
485         else:
486             split.prop(lamp2, "enabled", text="", icon='LAMP_DATA')
487
488         col = split.column()
489         col.active = lamp2.enabled
490         row = col.row()
491         row.label(text="Diffuse:")
492         row.prop(lamp2, "diffuse_color", text="")
493         row = col.row()
494         row.label(text="Specular:")
495         row.prop(lamp2, "specular_color", text="")
496
497         col = split.column()
498         col.active = lamp2.enabled
499         col.prop(lamp2, "direction", text="")
500
501
502         column.separator()
503         column.separator()
504         column.separator()
505
506         col = column.column()
507
508         col.prop(system, "use_weight_color_range", text="Custom Weight Paint Range")
509         sub = col.column()
510         sub.active = system.use_weight_color_range
511         sub.template_color_ramp(system, "weight_color_range", expand=True)
512
513
514 class USERPREF_PT_theme(bpy.types.Panel):
515     bl_space_type = 'USER_PREFERENCES'
516     bl_label = "Themes"
517     bl_region_type = 'WINDOW'
518     bl_show_header = False
519
520     def poll(self, context):
521         userpref = context.user_preferences
522         return (userpref.active_section == 'THEMES')
523
524     def draw(self, context):
525         layout = self.layout
526
527         theme = context.user_preferences.themes[0]
528
529         split = layout.split(percentage=0.33)
530         split.prop(theme, "active_theme", text="")
531
532         layout.separator()
533
534         split = layout.split()
535
536         if theme.active_theme == 'VIEW_3D':
537             v3d = theme.view_3d
538
539             col = split.column()
540             col.prop(v3d, "back")
541             col.prop(v3d, "button")
542             col.prop(v3d, "button_title")
543             col.prop(v3d, "button_text")
544             col.prop(v3d, "header")
545
546             col = split.column()
547             col.prop(v3d, "grid")
548             col.prop(v3d, "wire")
549             col.prop(v3d, "lamp", slider=True)
550             col.prop(v3d, "editmesh_active", slider=True)
551
552             col = split.column()
553             col.prop(v3d, "object_selected")
554             col.prop(v3d, "object_active")
555             col.prop(v3d, "object_grouped")
556             col.prop(v3d, "object_grouped_active")
557             col.prop(v3d, "transform")
558
559             col = split.column()
560             col.prop(v3d, "vertex")
561             col.prop(v3d, "face", slider=True)
562             col.prop(v3d, "normal")
563             col.prop(v3d, "bone_solid")
564             col.prop(v3d, "bone_pose")
565             #col.prop(v3d, "edge") Doesn't seem to work
566
567         elif theme.active_theme == 'USER_INTERFACE':
568             ui = theme.user_interface.wcol_regular
569             layout.label(text="Regular:")
570
571             row = layout.row()
572             sub = row.column()
573             sub.prop(ui, "outline")
574             sub.prop(ui, "item", slider=True)
575             sub = row.column()
576             sub.prop(ui, "inner", slider=True)
577             sub.prop(ui, "inner_sel", slider=True)
578             sub = row.column()
579             sub.prop(ui, "text")
580             sub.prop(ui, "text_sel")
581             sub = row.column()
582             sub.prop(ui, "shaded")
583             subsub = sub.column(align=True)
584             subsub.active = ui.shaded
585             subsub.prop(ui, "shadetop")
586             subsub.prop(ui, "shadedown")
587
588             layout.separator()
589
590             ui = theme.user_interface.wcol_tool
591             layout.label(text="Tool:")
592
593             row = layout.row()
594             sub = row.column()
595             sub.prop(ui, "outline")
596             sub.prop(ui, "item", slider=True)
597             sub = row.column()
598             sub.prop(ui, "inner", slider=True)
599             sub.prop(ui, "inner_sel", slider=True)
600             sub = row.column()
601             sub.prop(ui, "text")
602             sub.prop(ui, "text_sel")
603             sub = row.column()
604             sub.prop(ui, "shaded")
605             subsub = sub.column(align=True)
606             subsub.active = ui.shaded
607             subsub.prop(ui, "shadetop")
608             subsub.prop(ui, "shadedown")
609
610             ui = theme.user_interface.wcol_radio
611             layout.label(text="Radio Buttons:")
612
613             row = layout.row()
614             sub = row.column()
615             sub.prop(ui, "outline")
616             sub.prop(ui, "item", slider=True)
617             sub = row.column()
618             sub.prop(ui, "inner", slider=True)
619             sub.prop(ui, "inner_sel", slider=True)
620             sub = row.column()
621             sub.prop(ui, "text")
622             sub.prop(ui, "text_sel")
623             sub = row.column()
624             sub.prop(ui, "shaded")
625             subsub = sub.column(align=True)
626             subsub.active = ui.shaded
627             subsub.prop(ui, "shadetop")
628             subsub.prop(ui, "shadedown")
629
630             ui = theme.user_interface.wcol_text
631             layout.label(text="Text:")
632
633             row = layout.row()
634             sub = row.column()
635             sub.prop(ui, "outline")
636             sub.prop(ui, "item", slider=True)
637             sub = row.column()
638             sub.prop(ui, "inner", slider=True)
639             sub.prop(ui, "inner_sel", slider=True)
640             sub = row.column()
641             sub.prop(ui, "text")
642             sub.prop(ui, "text_sel")
643             sub = row.column()
644             sub.prop(ui, "shaded")
645             subsub = sub.column(align=True)
646             subsub.active = ui.shaded
647             subsub.prop(ui, "shadetop")
648             subsub.prop(ui, "shadedown")
649
650             ui = theme.user_interface.wcol_option
651             layout.label(text="Option:")
652
653             row = layout.row()
654             sub = row.column()
655             sub.prop(ui, "outline")
656             sub.prop(ui, "item", slider=True)
657             sub = row.column()
658             sub.prop(ui, "inner", slider=True)
659             sub.prop(ui, "inner_sel", slider=True)
660             sub = row.column()
661             sub.prop(ui, "text")
662             sub.prop(ui, "text_sel")
663             sub = row.column()
664             sub.prop(ui, "shaded")
665             subsub = sub.column(align=True)
666             subsub.active = ui.shaded
667             subsub.prop(ui, "shadetop")
668             subsub.prop(ui, "shadedown")
669
670             ui = theme.user_interface.wcol_toggle
671             layout.label(text="Toggle:")
672
673             row = layout.row()
674             sub = row.column()
675             sub.prop(ui, "outline")
676             sub.prop(ui, "item", slider=True)
677             sub = row.column()
678             sub.prop(ui, "inner", slider=True)
679             sub.prop(ui, "inner_sel", slider=True)
680             sub = row.column()
681             sub.prop(ui, "text")
682             sub.prop(ui, "text_sel")
683             sub = row.column()
684             sub.prop(ui, "shaded")
685             subsub = sub.column(align=True)
686             subsub.active = ui.shaded
687             subsub.prop(ui, "shadetop")
688             subsub.prop(ui, "shadedown")
689
690             ui = theme.user_interface.wcol_num
691             layout.label(text="Number Field:")
692
693             row = layout.row()
694             sub = row.column()
695             sub.prop(ui, "outline")
696             sub.prop(ui, "item", slider=True)
697             sub = row.column()
698             sub.prop(ui, "inner", slider=True)
699             sub.prop(ui, "inner_sel", slider=True)
700             sub = row.column()
701             sub.prop(ui, "text")
702             sub.prop(ui, "text_sel")
703             sub = row.column()
704             sub.prop(ui, "shaded")
705             subsub = sub.column(align=True)
706             subsub.active = ui.shaded
707             subsub.prop(ui, "shadetop")
708             subsub.prop(ui, "shadedown")
709
710             ui = theme.user_interface.wcol_numslider
711             layout.label(text="Value Slider:")
712
713             row = layout.row()
714             sub = row.column()
715             sub.prop(ui, "outline")
716             sub.prop(ui, "item", slider=True)
717             sub = row.column()
718             sub.prop(ui, "inner", slider=True)
719             sub.prop(ui, "inner_sel", slider=True)
720             sub = row.column()
721             sub.prop(ui, "text")
722             sub.prop(ui, "text_sel")
723             sub = row.column()
724             sub.prop(ui, "shaded")
725             subsub = sub.column(align=True)
726             subsub.active = ui.shaded
727             subsub.prop(ui, "shadetop")
728             subsub.prop(ui, "shadedown")
729
730             ui = theme.user_interface.wcol_box
731             layout.label(text="Box:")
732
733             row = layout.row()
734             sub = row.column()
735             sub.prop(ui, "outline")
736             sub.prop(ui, "item", slider=True)
737             sub = row.column()
738             sub.prop(ui, "inner", slider=True)
739             sub.prop(ui, "inner_sel", slider=True)
740             sub = row.column()
741             sub.prop(ui, "text")
742             sub.prop(ui, "text_sel")
743             sub = row.column()
744             sub.prop(ui, "shaded")
745             subsub = sub.column(align=True)
746             subsub.active = ui.shaded
747             subsub.prop(ui, "shadetop")
748             subsub.prop(ui, "shadedown")
749
750             ui = theme.user_interface.wcol_menu
751             layout.label(text="Menu:")
752
753             row = layout.row()
754             sub = row.column()
755             sub.prop(ui, "outline")
756             sub.prop(ui, "item", slider=True)
757             sub = row.column()
758             sub.prop(ui, "inner", slider=True)
759             sub.prop(ui, "inner_sel", slider=True)
760             sub = row.column()
761             sub.prop(ui, "text")
762             sub.prop(ui, "text_sel")
763             sub = row.column()
764             sub.prop(ui, "shaded")
765             subsub = sub.column(align=True)
766             subsub.active = ui.shaded
767             subsub.prop(ui, "shadetop")
768             subsub.prop(ui, "shadedown")
769
770             ui = theme.user_interface.wcol_pulldown
771             layout.label(text="Pulldown:")
772
773             row = layout.row()
774             sub = row.column()
775             sub.prop(ui, "outline")
776             sub.prop(ui, "item", slider=True)
777             sub = row.column()
778             sub.prop(ui, "inner", slider=True)
779             sub.prop(ui, "inner_sel", slider=True)
780             sub = row.column()
781             sub.prop(ui, "text")
782             sub.prop(ui, "text_sel")
783             sub = row.column()
784             sub.prop(ui, "shaded")
785             subsub = sub.column(align=True)
786             subsub.active = ui.shaded
787             subsub.prop(ui, "shadetop")
788             subsub.prop(ui, "shadedown")
789
790             ui = theme.user_interface.wcol_menu_back
791             layout.label(text="Menu Back:")
792
793             row = layout.row()
794             sub = row.column()
795             sub.prop(ui, "outline")
796             sub.prop(ui, "item", slider=True)
797             sub = row.column()
798             sub.prop(ui, "inner", slider=True)
799             sub.prop(ui, "inner_sel", slider=True)
800             sub = row.column()
801             sub.prop(ui, "text")
802             sub.prop(ui, "text_sel")
803             sub = row.column()
804             sub.prop(ui, "shaded")
805             subsub = sub.column(align=True)
806             subsub.active = ui.shaded
807             subsub.prop(ui, "shadetop")
808             subsub.prop(ui, "shadedown")
809
810             ui = theme.user_interface.wcol_menu_item
811             layout.label(text="Menu Item:")
812
813             row = layout.row()
814             sub = row.column()
815             sub.prop(ui, "outline")
816             sub.prop(ui, "item", slider=True)
817             sub = row.column()
818             sub.prop(ui, "inner", slider=True)
819             sub.prop(ui, "inner_sel", slider=True)
820             sub = row.column()
821             sub.prop(ui, "text")
822             sub.prop(ui, "text_sel")
823             sub = row.column()
824             sub.prop(ui, "shaded")
825             subsub = sub.column(align=True)
826             subsub.active = ui.shaded
827             subsub.prop(ui, "shadetop")
828             subsub.prop(ui, "shadedown")
829
830             ui = theme.user_interface.wcol_scroll
831             layout.label(text="Scroll Bar:")
832
833             row = layout.row()
834             sub = row.column()
835             sub.prop(ui, "outline")
836             sub.prop(ui, "item", slider=True)
837             sub = row.column()
838             sub.prop(ui, "inner", slider=True)
839             sub.prop(ui, "inner_sel", slider=True)
840             sub = row.column()
841             sub.prop(ui, "text")
842             sub.prop(ui, "text_sel")
843             sub = row.column()
844             sub.prop(ui, "shaded")
845             subsub = sub.column(align=True)
846             subsub.active = ui.shaded
847             subsub.prop(ui, "shadetop")
848             subsub.prop(ui, "shadedown")
849
850             ui = theme.user_interface.wcol_list_item
851             layout.label(text="List Item:")
852
853             row = layout.row()
854             sub = row.column()
855             sub.prop(ui, "outline")
856             sub.prop(ui, "item", slider=True)
857             sub = row.column()
858             sub.prop(ui, "inner", slider=True)
859             sub.prop(ui, "inner_sel", slider=True)
860             sub = row.column()
861             sub.prop(ui, "text")
862             sub.prop(ui, "text_sel")
863             sub = row.column()
864             sub.prop(ui, "shaded")
865             subsub = sub.column(align=True)
866             subsub.active = ui.shaded
867             subsub.prop(ui, "shadetop")
868             subsub.prop(ui, "shadedown")
869
870             ui = theme.user_interface.wcol_state
871             layout.label(text="State:")
872
873             row = layout.row()
874             sub = row.column()
875             sub.prop(ui, "inner_anim")
876             sub.prop(ui, "inner_anim_sel")
877             sub = row.column()
878             sub.prop(ui, "inner_driven")
879             sub.prop(ui, "inner_driven_sel")
880             sub = row.column()
881             sub.prop(ui, "inner_key")
882             sub.prop(ui, "inner_key_sel")
883             sub = row.column()
884             sub.prop(ui, "blend")
885
886             ui = theme.user_interface
887             layout.separator()
888
889             sub = layout.row()
890             sub.prop(ui, "icon_file")
891
892             layout.separator()
893             layout.separator()
894
895
896         elif theme.active_theme == 'GRAPH_EDITOR':
897             graph = theme.graph_editor
898
899             col = split.column()
900             col.prop(graph, "back")
901             col.prop(graph, "button")
902             col.prop(graph, "button_title")
903             col.prop(graph, "button_text")
904
905             col = split.column()
906             col.prop(graph, "header")
907             col.prop(graph, "grid")
908             col.prop(graph, "list")
909             col.prop(graph, "channel_group")
910
911             col = split.column()
912             col.prop(graph, "active_channels_group")
913             col.prop(graph, "dopesheet_channel")
914             col.prop(graph, "dopesheet_subchannel")
915             col.prop(graph, "vertex")
916
917             col = split.column()
918             col.prop(graph, "current_frame")
919             col.prop(graph, "handle_vertex")
920             col.prop(graph, "handle_vertex_select")
921             col.separator()
922             col.prop(graph, "handle_vertex_size")
923
924         elif theme.active_theme == 'FILE_BROWSER':
925             file_browse = theme.file_browser
926
927             col = split.column()
928             col.prop(file_browse, "back")
929             col.prop(file_browse, "text")
930             col.prop(file_browse, "text_hi")
931
932             col = split.column()
933             col.prop(file_browse, "header")
934             col.prop(file_browse, "list")
935
936             col = split.column()
937             col.prop(file_browse, "selected_file")
938             col.prop(file_browse, "tiles")
939
940             col = split.column()
941             col.prop(file_browse, "active_file")
942             col.prop(file_browse, "active_file_text")
943
944         elif theme.active_theme == 'NLA_EDITOR':
945             nla = theme.nla_editor
946
947             col = split.column()
948             col.prop(nla, "back")
949             col.prop(nla, "button")
950             col.prop(nla, "button_title")
951
952             col = split.column()
953             col.prop(nla, "button_text")
954             col.prop(nla, "text")
955             col.prop(nla, "header")
956
957             col = split.column()
958             col.prop(nla, "grid")
959             col.prop(nla, "bars")
960             col.prop(nla, "bars_selected")
961
962             col = split.column()
963             col.prop(nla, "strips")
964             col.prop(nla, "strips_selected")
965             col.prop(nla, "current_frame")
966
967         elif theme.active_theme == 'DOPESHEET_EDITOR':
968             dope = theme.dopesheet_editor
969
970             col = split.column()
971             col.prop(dope, "back")
972             col.prop(dope, "list")
973             col.prop(dope, "text")
974             col.prop(dope, "header")
975
976             col = split.column()
977             col.prop(dope, "grid")
978             col.prop(dope, "channels")
979             col.prop(dope, "channels_selected")
980             col.prop(dope, "channel_group")
981
982             col = split.column()
983             col.prop(dope, "active_channels_group")
984             col.prop(dope, "long_key")
985             col.prop(dope, "long_key_selected")
986
987             col = split.column()
988             col.prop(dope, "current_frame")
989             col.prop(dope, "dopesheet_channel")
990             col.prop(dope, "dopesheet_subchannel")
991
992         elif theme.active_theme == 'IMAGE_EDITOR':
993             image = theme.image_editor
994
995             col = split.column()
996             col.prop(image, "back")
997             col.prop(image, "button")
998
999             col = split.column()
1000             col.prop(image, "button_title")
1001             col.prop(image, "button_text")
1002
1003             col = split.column()
1004             col.prop(image, "header")
1005
1006             col = split.column()
1007             col.prop(image, "editmesh_active", slider=True)
1008
1009         elif theme.active_theme == 'SEQUENCE_EDITOR':
1010             seq = theme.sequence_editor
1011
1012             col = split.column()
1013             col.prop(seq, "back")
1014             col.prop(seq, "button")
1015             col.prop(seq, "button_title")
1016             col.prop(seq, "button_text")
1017             col.prop(seq, "text")
1018
1019             col = split.column()
1020             col.prop(seq, "header")
1021             col.prop(seq, "grid")
1022             col.prop(seq, "movie_strip")
1023             col.prop(seq, "image_strip")
1024             col.prop(seq, "scene_strip")
1025
1026             col = split.column()
1027             col.prop(seq, "audio_strip")
1028             col.prop(seq, "effect_strip")
1029             col.prop(seq, "plugin_strip")
1030             col.prop(seq, "transition_strip")
1031
1032             col = split.column()
1033             col.prop(seq, "meta_strip")
1034             col.prop(seq, "current_frame")
1035             col.prop(seq, "keyframe")
1036             col.prop(seq, "draw_action")
1037
1038         elif theme.active_theme == 'PROPERTIES':
1039             prop = theme.properties
1040
1041             col = split.column()
1042             col.prop(prop, "back")
1043
1044             col = split.column()
1045             col.prop(prop, "title")
1046
1047             col = split.column()
1048             col.prop(prop, "text")
1049
1050             col = split.column()
1051             col.prop(prop, "header")
1052
1053         elif theme.active_theme == 'TEXT_EDITOR':
1054             text = theme.text_editor
1055
1056             col = split.column()
1057             col.prop(text, "back")
1058             col.prop(text, "button")
1059             col.prop(text, "button_title")
1060             col.prop(text, "button_text")
1061
1062             col = split.column()
1063             col.prop(text, "text")
1064             col.prop(text, "text_hi")
1065             col.prop(text, "header")
1066             col.prop(text, "line_numbers_background")
1067
1068             col = split.column()
1069             col.prop(text, "selected_text")
1070             col.prop(text, "cursor")
1071             col.prop(text, "syntax_builtin")
1072             col.prop(text, "syntax_special")
1073
1074             col = split.column()
1075             col.prop(text, "syntax_comment")
1076             col.prop(text, "syntax_string")
1077             col.prop(text, "syntax_numbers")
1078
1079         elif theme.active_theme == 'TIMELINE':
1080             time = theme.timeline
1081
1082             col = split.column()
1083             col.prop(time, "back")
1084             col.prop(time, "text")
1085
1086             col = split.column()
1087             col.prop(time, "header")
1088
1089             col = split.column()
1090             col.prop(time, "grid")
1091
1092             col = split.column()
1093             col.prop(time, "current_frame")
1094
1095         elif theme.active_theme == 'NODE_EDITOR':
1096             node = theme.node_editor
1097
1098             col = split.column()
1099             col.prop(node, "back")
1100             col.prop(node, "button")
1101             col.prop(node, "button_title")
1102             col.prop(node, "button_text")
1103
1104             col = split.column()
1105             col.prop(node, "text")
1106             col.prop(node, "text_hi")
1107             col.prop(node, "header")
1108             col.prop(node, "wires")
1109
1110             col = split.column()
1111             col.prop(node, "wire_select")
1112             col.prop(node, "selected_text")
1113             col.prop(node, "node_backdrop", slider=True)
1114             col.prop(node, "in_out_node")
1115
1116             col = split.column()
1117             col.prop(node, "converter_node")
1118             col.prop(node, "operator_node")
1119             col.prop(node, "group_node")
1120
1121         elif theme.active_theme == 'LOGIC_EDITOR':
1122             logic = theme.logic_editor
1123
1124             col = split.column()
1125             col.prop(logic, "back")
1126             col.prop(logic, "button")
1127
1128             col = split.column()
1129             col.prop(logic, "button_title")
1130             col.prop(logic, "button_text")
1131
1132             col = split.column()
1133             col.prop(logic, "text")
1134             col.prop(logic, "header")
1135
1136             col = split.column()
1137             col.prop(logic, "panel")
1138
1139         elif theme.active_theme == 'OUTLINER':
1140             out = theme.outliner
1141
1142             col = split.column()
1143             col.prop(out, "back")
1144
1145             col = split.column()
1146             col.prop(out, "text")
1147
1148             col = split.column()
1149             col.prop(out, "text_hi")
1150
1151             col = split.column()
1152             col.prop(out, "header")
1153
1154         elif theme.active_theme == 'INFO':
1155             info = theme.info
1156
1157             col = split.column()
1158             col.prop(info, "back")
1159
1160             col = split.column()
1161             col.prop(info, "header")
1162
1163             col = split.column()
1164             col.prop(info, "header_text")
1165
1166             col = split.column()
1167
1168         elif theme.active_theme == 'USER_PREFERENCES':
1169             prefs = theme.user_preferences
1170
1171             col = split.column()
1172             col.prop(prefs, "back")
1173
1174             col = split.column()
1175             col.prop(prefs, "text")
1176
1177             col = split.column()
1178             col.prop(prefs, "header")
1179
1180             col = split.column()
1181             col.prop(prefs, "header_text")
1182
1183
1184 class USERPREF_PT_file(bpy.types.Panel):
1185     bl_space_type = 'USER_PREFERENCES'
1186     bl_label = "Files"
1187     bl_region_type = 'WINDOW'
1188     bl_show_header = False
1189
1190     def poll(self, context):
1191         userpref = context.user_preferences
1192         return (userpref.active_section == 'FILES')
1193
1194     def draw(self, context):
1195         layout = self.layout
1196
1197         userpref = context.user_preferences
1198         paths = userpref.filepaths
1199
1200         split = layout.split(percentage=0.7)
1201
1202         col = split.column()
1203         col.label(text="File Paths:")
1204
1205         colsplit = col.split(percentage=0.95)
1206         col1 = colsplit.split(percentage=0.3)
1207
1208         sub = col1.column()
1209         sub.label(text="Fonts:")
1210         sub.label(text="Textures:")
1211         sub.label(text="Texture Plugins:")
1212         sub.label(text="Sequence Plugins:")
1213         sub.label(text="Render Output:")
1214         sub.label(text="Scripts:")
1215         sub.label(text="Sounds:")
1216         sub.label(text="Temp:")
1217         sub.label(text="Animation Player:")
1218
1219         sub = col1.column()
1220         sub.prop(paths, "fonts_directory", text="")
1221         sub.prop(paths, "textures_directory", text="")
1222         sub.prop(paths, "texture_plugin_directory", text="")
1223         sub.prop(paths, "sequence_plugin_directory", text="")
1224         sub.prop(paths, "render_output_directory", text="")
1225         sub.prop(paths, "python_scripts_directory", text="")
1226         sub.prop(paths, "sounds_directory", text="")
1227         sub.prop(paths, "temporary_directory", text="")
1228         subsplit = sub.split(percentage=0.3)
1229         subsplit.prop(paths, "animation_player_preset", text="")
1230         subsplit.prop(paths, "animation_player", text="")
1231
1232         col = split.column()
1233         col.label(text="Save & Load:")
1234         col.prop(paths, "use_relative_paths")
1235         col.prop(paths, "compress_file")
1236         col.prop(paths, "load_ui")
1237         col.prop(paths, "filter_file_extensions")
1238         col.prop(paths, "hide_dot_files_datablocks")
1239
1240         col.separator()
1241         col.separator()
1242
1243         col.label(text="Auto Save:")
1244         col.prop(paths, "save_version")
1245         col.prop(paths, "recent_files")
1246         col.prop(paths, "save_preview_images")
1247         col.prop(paths, "auto_save_temporary_files")
1248         sub = col.column()
1249         sub.enabled = paths.auto_save_temporary_files
1250         sub.prop(paths, "auto_save_time", text="Timer (mins)")
1251
1252
1253 class USERPREF_PT_input(bpy.types.Panel):
1254     bl_space_type = 'USER_PREFERENCES'
1255     bl_label = "Input"
1256     bl_region_type = 'WINDOW'
1257     bl_show_header = False
1258
1259     def poll(self, context):
1260         userpref = context.user_preferences
1261         return (userpref.active_section == 'INPUT')
1262
1263     def draw_entry(self, kc, entry, col, level=0):
1264         idname, spaceid, regionid, children = entry
1265
1266         km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid)
1267
1268         if km:
1269             self.draw_km(kc, km, children, col, level)
1270
1271     def indented_layout(self, layout, level):
1272         indentpx = 16
1273         if level == 0:
1274             level = 0.0001   # Tweak so that a percentage of 0 won't split by half
1275         indent = level * indentpx / bpy.context.region.width
1276
1277         split = layout.split(percentage=indent)
1278         col = split.column()
1279         col = split.column()
1280         return col
1281
1282     def draw_km(self, kc, km, children, layout, level):
1283         km = km.active()
1284
1285         layout.set_context_pointer("keymap", km)
1286
1287         col = self.indented_layout(layout, level)
1288
1289         row = col.row()
1290         row.prop(km, "children_expanded", text="", no_bg=True)
1291         row.label(text=km.name)
1292
1293         row.label()
1294         row.label()
1295
1296         if km.user_defined:
1297             row.operator("wm.keymap_restore", text="Restore")
1298         else:
1299             row.operator("wm.keymap_edit", text="Edit")
1300
1301         if km.children_expanded:
1302             if children:
1303                 # Put the Parent key map's entries in a 'global' sub-category
1304                 # equal in hierarchy to the other children categories
1305                 subcol = self.indented_layout(col, level + 1)
1306                 subrow = subcol.row()
1307                 subrow.prop(km, "items_expanded", text="", no_bg=True)
1308                 subrow.label(text="%s (Global)" % km.name)
1309             else:
1310                 km.items_expanded = True
1311
1312             # Key Map items
1313             if km.items_expanded:
1314                 for kmi in km.items:
1315                     self.draw_kmi(kc, km, kmi, col, level + 1)
1316
1317                 # "Add New" at end of keymap item list
1318                 col = self.indented_layout(col, level + 1)
1319                 subcol = col.split(percentage=0.2).column()
1320                 subcol.active = km.user_defined
1321                 subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
1322
1323             col.separator()
1324
1325             # Child key maps
1326             if children:
1327                 subcol = col.column()
1328                 row = subcol.row()
1329
1330                 for entry in children:
1331                     self.draw_entry(kc, entry, col, level + 1)
1332
1333     def draw_kmi(self, kc, km, kmi, layout, level):
1334         layout.set_context_pointer("keyitem", kmi)
1335
1336         col = self.indented_layout(layout, level)
1337
1338         col.enabled = km.user_defined
1339
1340         if km.user_defined:
1341             col = col.column(align=True)
1342             box = col.box()
1343         else:
1344             box = col.column()
1345
1346         split = box.split(percentage=0.4)
1347
1348         # header bar
1349         row = split.row()
1350         row.prop(kmi, "expanded", text="", no_bg=True)
1351         row.prop(kmi, "active", text="", no_bg=True)
1352
1353         if km.modal:
1354             row.prop(kmi, "propvalue", text="")
1355         else:
1356             row.label(text=kmi.name)
1357
1358         row = split.row()
1359         row.prop(kmi, "map_type", text="")
1360         if kmi.map_type == 'KEYBOARD':
1361             row.prop(kmi, "type", text="", full_event=True)
1362         elif kmi.map_type == 'MOUSE':
1363             row.prop(kmi, "type", text="", full_event=True)
1364         elif kmi.map_type == 'TWEAK':
1365             subrow = row.row()
1366             subrow.prop(kmi, "type", text="")
1367             subrow.prop(kmi, "value", text="")
1368         elif kmi.map_type == 'TIMER':
1369             row.prop(kmi, "type", text="")
1370         else:
1371             row.label()
1372
1373         row.operator("wm.keyitem_restore", text="", icon='BACK')
1374         row.operator("wm.keyitem_remove", text="", icon='X')
1375
1376         # Expanded, additional event settings
1377         if kmi.expanded:
1378             box = col.box()
1379
1380             if kmi.map_type not in ('TEXTINPUT', 'TIMER'):
1381                 split = box.split(percentage=0.4)
1382                 sub = split.row()
1383
1384                 if km.modal:
1385                     sub.prop(kmi, "propvalue", text="")
1386                 else:
1387                     sub.prop(kmi, "idname", text="")
1388
1389                 sub = split.column()
1390                 subrow = sub.row(align=True)
1391
1392                 if kmi.map_type == 'KEYBOARD':
1393                     subrow.prop(kmi, "type", text="", event=True)
1394                     subrow.prop(kmi, "value", text="")
1395                 elif kmi.map_type == 'MOUSE':
1396                     subrow.prop(kmi, "type", text="")
1397                     subrow.prop(kmi, "value", text="")
1398
1399                 subrow = sub.row()
1400                 subrow.scale_x = 0.75
1401                 subrow.prop(kmi, "any")
1402                 subrow.prop(kmi, "shift")
1403                 subrow.prop(kmi, "ctrl")
1404                 subrow.prop(kmi, "alt")
1405                 subrow.prop(kmi, "oskey", text="Cmd")
1406                 subrow.prop(kmi, "key_modifier", text="", event=True)
1407
1408             # Operator properties
1409             props = kmi.properties
1410             if props is not None:
1411                 box.separator()
1412                 flow = box.column_flow(columns=2)
1413                 for pname in dir(props):
1414                     if not props.is_property_hidden(pname):
1415                         flow.prop(props, pname)
1416
1417             # Modal key maps attached to this operator
1418             if not km.modal:
1419                 kmm = kc.find_keymap_modal(kmi.idname)
1420                 if kmm:
1421                     self.draw_km(kc, kmm, None, layout, level + 1)
1422
1423     def draw_input_prefs(self, inputs, layout):
1424         # General settings
1425         row = layout.row()
1426         col = row.column()
1427
1428         sub = col.column()
1429         sub.label(text="Mouse:")
1430         sub1 = sub.column()
1431         sub1.enabled = (inputs.select_mouse == 'RIGHT')
1432         sub1.prop(inputs, "emulate_3_button_mouse")
1433         sub.prop(inputs, "continuous_mouse")
1434
1435         sub.label(text="Select With:")
1436         sub.row().prop(inputs, "select_mouse", expand=True)
1437
1438         sub = col.column()
1439         sub.label(text="Double Click:")
1440         sub.prop(inputs, "double_click_time", text="Speed")
1441
1442         sub.separator()
1443
1444         sub.prop(inputs, "emulate_numpad")
1445
1446         sub.separator()
1447
1448         sub.label(text="Orbit Style:")
1449         sub.row().prop(inputs, "view_rotation", expand=True)
1450
1451         sub.label(text="Zoom Style:")
1452         sub.row().prop(inputs, "viewport_zoom_style", expand=True)
1453         if inputs.viewport_zoom_style == 'DOLLY':
1454             sub.row().prop(inputs, "zoom_axis", expand=True)
1455             sub.prop(inputs, "invert_zoom_direction")
1456
1457         #sub.prop(inputs, "use_middle_mouse_paste")
1458
1459         #col.separator()
1460
1461         #sub = col.column()
1462         #sub.label(text="Mouse Wheel:")
1463         #sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
1464
1465         col.separator()
1466
1467         sub = col.column()
1468         sub.label(text="NDOF Device:")
1469         sub.prop(inputs, "ndof_pan_speed", text="Pan Speed")
1470         sub.prop(inputs, "ndof_rotate_speed", text="Orbit Speed")
1471
1472         row.separator()
1473
1474     def draw_filtered(self, kc, layout):
1475         filter = kc.filter.lower()
1476
1477         for km in kc.keymaps:
1478             km = km.active()
1479
1480             filtered_items = [kmi for kmi in km.items if filter in kmi.name.lower()]
1481
1482             if len(filtered_items) != 0:
1483                 layout.set_context_pointer("keymap", km)
1484                 col = layout.column()
1485
1486                 row = col.row()
1487                 row.label(text=km.name, icon="DOT")
1488
1489                 row.label()
1490                 row.label()
1491
1492                 if km.user_defined:
1493                     row.operator("wm.keymap_restore", text="Restore")
1494                 else:
1495                     row.operator("wm.keymap_edit", text="Edit")
1496
1497                 for kmi in filtered_items:
1498                     self.draw_kmi(kc, km, kmi, col, 1)
1499
1500                 # "Add New" at end of keymap item list
1501                 col = self.indented_layout(layout, 1)
1502                 subcol = col.split(percentage=0.2).column()
1503                 subcol.active = km.user_defined
1504                 subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
1505
1506     def draw_hierarchy(self, defkc, layout):
1507         for entry in KM_HIERARCHY:
1508             self.draw_entry(defkc, entry, layout)
1509
1510     def draw(self, context):
1511         layout = self.layout
1512
1513         userpref = context.user_preferences
1514         wm = context.manager
1515
1516         inputs = userpref.inputs
1517
1518         split = layout.split(percentage=0.25)
1519
1520         # Input settings
1521         self.draw_input_prefs(inputs, split)
1522
1523         # Keymap Settings
1524         col = split.column()
1525         # kc = wm.active_keyconfig
1526         kc = wm.default_keyconfig
1527
1528         sub = col.column()
1529
1530         subsplit = sub.split()
1531         subcol = subsplit.column()
1532         subcol.prop_object(wm, "active_keyconfig", wm, "keyconfigs", text="Configuration:")
1533
1534         subcol = subsplit.column()
1535         subcol.prop(kc, "filter", icon="VIEWZOOM")
1536
1537         col.separator()
1538
1539         if kc.filter != "":
1540             self.draw_filtered(kc, col)
1541         else:
1542             self.draw_hierarchy(kc, col)
1543
1544 bpy.types.register(USERPREF_HT_header)
1545 bpy.types.register(USERPREF_PT_tabs)
1546 bpy.types.register(USERPREF_PT_interface)
1547 bpy.types.register(USERPREF_PT_theme)
1548 bpy.types.register(USERPREF_PT_edit)
1549 bpy.types.register(USERPREF_PT_system)
1550 bpy.types.register(USERPREF_PT_file)
1551 bpy.types.register(USERPREF_PT_input)
1552
1553 from bpy.props import *
1554
1555
1556 class WM_OT_keyconfig_test(bpy.types.Operator):
1557     "Test keyconfig for conflicts."
1558     bl_idname = "wm.keyconfig_test"
1559     bl_label = "Test Key Configuration for Conflicts"
1560
1561     def testEntry(self, kc, entry, src=None, parent=None):
1562         result = False
1563
1564         def kmistr(kmi):
1565             if km.modal:
1566                 s = ["kmi = km.add_modal_item(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
1567             else:
1568                 s = ["kmi = km.add_item(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
1569
1570             if kmi.any:
1571                 s.append(", any=True")
1572             else:
1573                 if kmi.shift:
1574                     s.append(", shift=True")
1575                 if kmi.ctrl:
1576                     s.append(", ctrl=True")
1577                 if kmi.alt:
1578                     s.append(", alt=True")
1579                 if kmi.oskey:
1580                     s.append(", oskey=True")
1581             if kmi.key_modifier and kmi.key_modifier != 'NONE':
1582                 s.append(", key_modifier=\'%s\'" % kmi.key_modifier)
1583
1584             s.append(")\n")
1585
1586             props = kmi.properties
1587
1588             if props is not None:
1589                 for pname in dir(props):
1590                     if props.is_property_set(pname) and not props.is_property_hidden(pname):
1591                         value = eval("props.%s" % pname)
1592                         value = _string_value(value)
1593                         if value != "":
1594                             s.append("kmi.properties.%s = %s\n" % (pname, value))
1595
1596             return "".join(s).strip()
1597
1598         idname, spaceid, regionid, children = entry
1599
1600         km = kc.find_keymap(idname, space_type=spaceid, region_type=regionid)
1601
1602         if km:
1603             km = km.active()
1604
1605             if src:
1606                 for item in km.items:
1607                     if src.compare(item):
1608                         print("===========")
1609                         print(parent.name)
1610                         print(kmistr(src))
1611                         print(km.name)
1612                         print(kmistr(item))
1613                         result = True
1614
1615                 for child in children:
1616                     if self.testEntry(kc, child, src, parent):
1617                         result = True
1618             else:
1619                 for i in range(len(km.items)):
1620                     src = km.items[i]
1621
1622                     for child in children:
1623                         if self.testEntry(kc, child, src, km):
1624                             result = True
1625
1626                     for j in range(len(km.items) - i - 1):
1627                         item = km.items[j + i + 1]
1628                         if src.compare(item):
1629                             print("===========")
1630                             print(km.name)
1631                             print(kmistr(src))
1632                             print(kmistr(item))
1633                             result = True
1634
1635                 for child in children:
1636                     if self.testEntry(kc, child):
1637                         result = True
1638
1639         return result
1640
1641     def testConfig(self, kc):
1642         result = False
1643         for entry in KM_HIERARCHY:
1644             if self.testEntry(kc, entry):
1645                 result = True
1646         return result
1647
1648     def execute(self, context):
1649         wm = context.manager
1650         kc = wm.default_keyconfig
1651
1652         if self.testConfig(kc):
1653             print("CONFLICT")
1654
1655         return {'FINISHED'}
1656
1657
1658 def _string_value(value):
1659     result = ""
1660     if isinstance(value, str):
1661         if value != "":
1662             result = "\'%s\'" % value
1663     elif isinstance(value, bool):
1664         if value:
1665             result = "True"
1666         else:
1667             result = "False"
1668     elif isinstance(value, float):
1669         result = "%.10f" % value
1670     elif isinstance(value, int):
1671         result = "%d" % value
1672     elif getattr(value, '__len__', False):
1673         if len(value):
1674             result = "["
1675             for i in range(0, len(value)):
1676                 result += _string_value(value[i])
1677                 if i != len(value)-1:
1678                     result += ", "
1679             result += "]"
1680     else:
1681         print("Export key configuration: can't write ", value)
1682
1683     return result
1684
1685
1686 class WM_OT_keyconfig_export(bpy.types.Operator):
1687     "Export key configuration to a python script."
1688     bl_idname = "wm.keyconfig_export"
1689     bl_label = "Export Key Configuration..."
1690
1691     path = bpy.props.StringProperty(name="File Path", description="File path to write file to.")
1692
1693     def execute(self, context):
1694         if not self.properties.path:
1695             raise Exception("File path not set.")
1696
1697         f = open(self.properties.path, "w")
1698         if not f:
1699             raise Exception("Could not open file.")
1700
1701         wm = context.manager
1702         kc = wm.active_keyconfig
1703
1704         f.write('# Configuration %s\n' % kc.name)
1705
1706         f.write("wm = bpy.data.windowmanagers[0]\n")
1707         f.write("kc = wm.add_keyconfig(\'%s\')\n\n" % kc.name)
1708
1709         for km in kc.keymaps:
1710             km = km.active()
1711             f.write("# Map %s\n" % km.name)
1712             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))
1713             for kmi in km.items:
1714                 if km.modal:
1715                     f.write("kmi = km.add_modal_item(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value))
1716                 else:
1717                     f.write("kmi = km.add_item(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value))
1718                 if kmi.any:
1719                     f.write(", any=True")
1720                 else:
1721                     if kmi.shift:
1722                         f.write(", shift=True")
1723                     if kmi.ctrl:
1724                         f.write(", ctrl=True")
1725                     if kmi.alt:
1726                         f.write(", alt=True")
1727                     if kmi.oskey:
1728                         f.write(", oskey=True")
1729                 if kmi.key_modifier and kmi.key_modifier != 'NONE':
1730                     f.write(", key_modifier=\'%s\'" % kmi.key_modifier)
1731                 f.write(")\n")
1732
1733                 props = kmi.properties
1734
1735                 if props is not None:
1736                     for pname in dir(props):
1737                         if props.is_property_set(pname) and not props.is_property_hidden(pname):
1738                             value = eval("props.%s" % pname)
1739                             value = _string_value(value)
1740                             if value != "":
1741                                 f.write("kmi.properties.%s = %s\n" % (pname, value))
1742
1743             f.write("\n")
1744
1745         f.close()
1746
1747         return {'FINISHED'}
1748
1749     def invoke(self, context, event):
1750         wm = context.manager
1751         wm.add_fileselect(self)
1752         return {'RUNNING_MODAL'}
1753
1754
1755 class WM_OT_keymap_edit(bpy.types.Operator):
1756     "Edit key map."
1757     bl_idname = "wm.keymap_edit"
1758     bl_label = "Edit Key Map"
1759
1760     def execute(self, context):
1761         wm = context.manager
1762         km = context.keymap
1763         km.copy_to_user()
1764         return {'FINISHED'}
1765
1766
1767 class WM_OT_keymap_restore(bpy.types.Operator):
1768     "Restore key map(s)."
1769     bl_idname = "wm.keymap_restore"
1770     bl_label = "Restore Key Map(s)"
1771
1772     all = BoolProperty(attr="all", name="All Keymaps", description="Restore all keymaps to default.")
1773
1774     def execute(self, context):
1775         wm = context.manager
1776
1777         if self.properties.all:
1778             for km in wm.default_keyconfig.keymaps:
1779                 km.restore_to_default()
1780         else:
1781             km = context.keymap
1782             km.restore_to_default()
1783
1784         return {'FINISHED'}
1785
1786
1787 class WM_OT_keyitem_restore(bpy.types.Operator):
1788     "Restore key map item."
1789     bl_idname = "wm.keyitem_restore"
1790     bl_label = "Restore Key Map Item"
1791
1792     def poll(self, context):
1793         kmi = context.keyitem
1794         km = context.keymap
1795         return km and kmi and kmi.id != 0
1796
1797     def execute(self, context):
1798         wm = context.manager
1799         kmi = context.keyitem
1800         km = context.keymap
1801
1802         km.restore_item_to_default(kmi)
1803
1804         return {'FINISHED'}
1805
1806
1807 class WM_OT_keyitem_add(bpy.types.Operator):
1808     "Add key map item."
1809     bl_idname = "wm.keyitem_add"
1810     bl_label = "Add Key Map Item"
1811
1812     def execute(self, context):
1813         wm = context.manager
1814         km = context.keymap
1815         kc = wm.default_keyconfig
1816
1817         if km.modal:
1818             km.add_modal_item("", 'A', 'PRESS') # kmi
1819         else:
1820             km.add_item("none", 'A', 'PRESS') # kmi
1821
1822         # clear filter and expand keymap so we can see the newly added item
1823         if kc.filter != '':
1824             kc.filter = ''
1825             km.items_expanded = True
1826             km.children_expanded = True
1827
1828         return {'FINISHED'}
1829
1830
1831 class WM_OT_keyitem_remove(bpy.types.Operator):
1832     "Remove key map item."
1833     bl_idname = "wm.keyitem_remove"
1834     bl_label = "Remove Key Map Item"
1835
1836     def execute(self, context):
1837         wm = context.manager
1838         kmi = context.keyitem
1839         km = context.keymap
1840         km.remove_item(kmi)
1841         return {'FINISHED'}
1842
1843 bpy.types.register(WM_OT_keyconfig_export)
1844 bpy.types.register(WM_OT_keyconfig_test)
1845 bpy.types.register(WM_OT_keymap_edit)
1846 bpy.types.register(WM_OT_keymap_restore)
1847 bpy.types.register(WM_OT_keyitem_add)
1848 bpy.types.register(WM_OT_keyitem_remove)
1849 bpy.types.register(WM_OT_keyitem_restore)