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_view_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 (
113         EnumProperty,
114         StringProperty,
115     )
116     from bpy.types import WindowManager
117
118     def addon_filter_items(self, context):
119         import addon_utils
120
121         items = [
122             ('All', "All", "All Add-ons"),
123             ('User', "User", "All Add-ons Installed by User"),
124             ('Enabled', "Enabled", "All Enabled Add-ons"),
125             ('Disabled', "Disabled", "All Disabled Add-ons"),
126         ]
127
128         items_unique = set()
129
130         for mod in addon_utils.modules(refresh=False):
131             info = addon_utils.module_bl_info(mod)
132             items_unique.add(info["category"])
133
134         items.extend([(cat, cat, "") for cat in sorted(items_unique)])
135         return items
136
137     WindowManager.addon_search = StringProperty(
138         name="Search",
139         description="Search within the selected filter",
140         options={'TEXTEDIT_UPDATE'},
141     )
142     WindowManager.addon_filter = EnumProperty(
143         items=addon_filter_items,
144         name="Category",
145         description="Filter add-ons by category",
146     )
147
148     WindowManager.addon_support = EnumProperty(
149         items=[
150             ('OFFICIAL', "Official", "Officially supported"),
151             ('COMMUNITY', "Community", "Maintained by community developers"),
152             ('TESTING', "Testing", "Newly contributed scripts (excluded from release builds)")
153         ],
154         name="Support",
155         description="Display support level",
156         default={'OFFICIAL', 'COMMUNITY'},
157         options={'ENUM_FLAG'},
158     )
159     # done...
160
161
162 def unregister():
163     from bpy.utils import unregister_class
164     for mod in reversed(_modules_loaded):
165         for cls in reversed(mod.classes):
166             if cls.is_registered:
167                 unregister_class(cls)
168
169 # Define a default UIList, when a list does not need any custom drawing...
170 # Keep in sync with its #defined name in UI_interface.h
171 class UI_UL_list(bpy.types.UIList):
172     # These are common filtering or ordering operations (same as the default C ones!).
173     @staticmethod
174     def filter_items_by_name(pattern, bitflag, items, propname="name", flags=None, reverse=False):
175         """
176         Set FILTER_ITEM for items which name matches filter_name one (case-insensitive).
177         pattern is the filtering pattern.
178         propname is the name of the string property to use for filtering.
179         flags must be a list of integers the same length as items, or None!
180         return a list of flags (based on given flags if not None),
181         or an empty list if no flags were given and no filtering has been done.
182         """
183         import fnmatch
184
185         if not pattern or not items:  # Empty pattern or list = no filtering!
186             return flags or []
187
188         if flags is None:
189             flags = [0] * len(items)
190
191         # Implicitly add heading/trailing wildcards.
192         pattern = "*" + pattern + "*"
193
194         for i, item in enumerate(items):
195             name = getattr(item, propname, None)
196             # This is similar to a logical xor
197             if bool(name and fnmatch.fnmatchcase(name, pattern)) is not bool(reverse):
198                 flags[i] |= bitflag
199         return flags
200
201     @staticmethod
202     def sort_items_helper(sort_data, key, reverse=False):
203         """
204         Common sorting utility. Returns a neworder list mapping org_idx -> new_idx.
205         sort_data must be an (unordered) list of tuples [(org_idx, ...), (org_idx, ...), ...].
206         key must be the same kind of callable you would use for sorted() builtin function.
207         reverse will reverse the sorting!
208         """
209         sort_data.sort(key=key, reverse=reverse)
210         neworder = [None] * len(sort_data)
211         for newidx, (orgidx, *_) in enumerate(sort_data):
212             neworder[orgidx] = newidx
213         return neworder
214
215     @classmethod
216     def sort_items_by_name(cls, items, propname="name"):
217         """
218         Re-order items using their names (case-insensitive).
219         propname is the name of the string property to use for sorting.
220         return a list mapping org_idx -> new_idx,
221                or an empty list if no sorting has been done.
222         """
223         _sort = [(idx, getattr(it, propname, "")) for idx, it in enumerate(items)]
224         return cls.sort_items_helper(_sort, lambda e: e[1].lower())
225
226
227 bpy.utils.register_class(UI_UL_list)