Merge branch 'master' into blender2.8
[blender.git] / release / scripts / startup / bl_ui / __init__.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20
21 # note, properties_animviz is a helper module only.
22
23 # support reloading sub-modules
24 if "bpy" in locals():
25     from importlib import reload
26     _modules_loaded[:] = [reload(val) for val in _modules_loaded]
27     del reload
28
29 _modules = [
30     "properties_animviz",
31     "properties_collection",
32     "properties_constraint",
33     "properties_data_armature",
34     "properties_data_bone",
35     "properties_data_camera",
36     "properties_data_curve",
37     "properties_data_empty",
38     "properties_data_lamp",
39     "properties_data_lattice",
40     "properties_data_mesh",
41     "properties_data_metaball",
42     "properties_data_modifier",
43     "properties_data_lightprobe",
44     "properties_data_speaker",
45     "properties_data_workspace",
46     "properties_game",
47     "properties_mask_common",
48     "properties_material",
49     "properties_object",
50     "properties_paint_common",
51     "properties_grease_pencil_common",
52     "properties_particle",
53     "properties_physics_cloth",
54     "properties_physics_common",
55     "properties_physics_dynamicpaint",
56     "properties_physics_field",
57     "properties_physics_fluid",
58     "properties_physics_rigidbody",
59     "properties_physics_rigidbody_constraint",
60     "properties_physics_smoke",
61     "properties_physics_softbody",
62     "properties_render",
63     "properties_render_layer",
64     "properties_scene",
65     "properties_texture",
66     "properties_world",
67
68     # Generic Space Modules
69     #
70     # Depends on DNA_WORKSPACE_TOOL (C define).
71     "space_toolsystem_common",
72     "space_toolsystem_toolbar",
73
74     "space_clip",
75     "space_console",
76     "space_dopesheet",
77     "space_filebrowser",
78     "space_graph",
79     "space_image",
80     "space_info",
81     "space_logic",
82     "space_nla",
83     "space_node",
84     "space_outliner",
85     "space_properties",
86     "space_sequencer",
87     "space_text",
88     "space_time",
89     "space_userpref",
90     "space_view3d",
91     "space_view3d_toolbar",
92     ]
93
94 import bpy
95
96 if bpy.app.build_options.freestyle:
97     _modules.append("properties_freestyle")
98
99 __import__(name=__name__, fromlist=_modules)
100 _namespace = globals()
101 _modules_loaded = [_namespace[name] for name in _modules]
102 del _namespace
103
104
105 def register():
106     from bpy.utils import register_class
107     for mod in _modules_loaded:
108         for cls in mod.classes:
109             register_class(cls)
110
111     # space_userprefs.py
112     from bpy.props import StringProperty, EnumProperty
113     from bpy.types import WindowManager
114
115     def addon_filter_items(self, context):
116         import addon_utils
117
118         items = [('All', "All", "All Add-ons"),
119                  ('User', "User", "All Add-ons Installed by User"),
120                  ('Enabled', "Enabled", "All Enabled Add-ons"),
121                  ('Disabled', "Disabled", "All Disabled Add-ons"),
122                  ]
123
124         items_unique = set()
125
126         for mod in addon_utils.modules(refresh=False):
127             info = addon_utils.module_bl_info(mod)
128             items_unique.add(info["category"])
129
130         items.extend([(cat, cat, "") for cat in sorted(items_unique)])
131         return items
132
133     WindowManager.addon_search = StringProperty(
134             name="Search",
135             description="Search within the selected filter",
136             options={'TEXTEDIT_UPDATE'},
137             )
138     WindowManager.addon_filter = EnumProperty(
139             items=addon_filter_items,
140             name="Category",
141             description="Filter add-ons by category",
142             )
143
144     WindowManager.addon_support = EnumProperty(
145             items=[('OFFICIAL', "Official", "Officially supported"),
146                    ('COMMUNITY', "Community", "Maintained by community developers"),
147                    ('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)")
148                    ],
149             name="Support",
150             description="Display support level",
151             default={'OFFICIAL', 'COMMUNITY'},
152             options={'ENUM_FLAG'},
153             )
154     # done...
155
156
157 def unregister():
158     from bpy.utils import unregister_class
159     for mod in reversed(_modules_loaded):
160         for cls in reversed(mod.classes):
161             if cls.is_registered:
162                 unregister_class(cls)
163
164 # Define a default UIList, when a list does not need any custom drawing...
165 # Keep in sync with its #defined name in UI_interface.h
166 class UI_UL_list(bpy.types.UIList):
167     # These are common filtering or ordering operations (same as the default C ones!).
168     @staticmethod
169     def filter_items_by_name(pattern, bitflag, items, propname="name", flags=None, reverse=False):
170         """
171         Set FILTER_ITEM for items which name matches filter_name one (case-insensitive).
172         pattern is the filtering pattern.
173         propname is the name of the string property to use for filtering.
174         flags must be a list of integers the same length as items, or None!
175         return a list of flags (based on given flags if not None),
176         or an empty list if no flags were given and no filtering has been done.
177         """
178         import fnmatch
179
180         if not pattern or not items:  # Empty pattern or list = no filtering!
181             return flags or []
182
183         if flags is None:
184             flags = [0] * len(items)
185
186         # Implicitly add heading/trailing wildcards.
187         pattern = "*" + pattern + "*"
188
189         for i, item in enumerate(items):
190             name = getattr(item, propname, None)
191             # This is similar to a logical xor
192             if bool(name and fnmatch.fnmatchcase(name, pattern)) is not bool(reverse):
193                 flags[i] |= bitflag
194         return flags
195
196     @staticmethod
197     def sort_items_helper(sort_data, key, reverse=False):
198         """
199         Common sorting utility. Returns a neworder list mapping org_idx -> new_idx.
200         sort_data must be an (unordered) list of tuples [(org_idx, ...), (org_idx, ...), ...].
201         key must be the same kind of callable you would use for sorted() builtin function.
202         reverse will reverse the sorting!
203         """
204         sort_data.sort(key=key, reverse=reverse)
205         neworder = [None] * len(sort_data)
206         for newidx, (orgidx, *_) in enumerate(sort_data):
207             neworder[orgidx] = newidx
208         return neworder
209
210     @classmethod
211     def sort_items_by_name(cls, items, propname="name"):
212         """
213         Re-order items using their names (case-insensitive).
214         propname is the name of the string property to use for sorting.
215         return a list mapping org_idx -> new_idx,
216                or an empty list if no sorting has been done.
217         """
218         _sort = [(idx, getattr(it, propname, "")) for idx, it in enumerate(items)]
219         return cls.sort_items_helper(_sort, lambda e: e[1].lower())
220
221
222 bpy.utils.register_class(UI_UL_list)