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