1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 /** \file
18  * \ingroup RNA
19  */
20 
21 #include <stdlib.h>
22 
23 #include "DNA_screen_types.h"
24 #include "DNA_space_types.h"
25 
26 #include "BLT_translation.h"
27 
28 #include "BKE_idprop.h"
29 
30 #include "BLI_listbase.h"
31 
32 #include "RNA_define.h"
33 
34 #include "RNA_enum_types.h"
35 #include "rna_internal.h"
36 
37 #include "UI_interface.h"
38 
39 #include "WM_toolsystem.h"
40 #include "WM_types.h"
41 
42 /* see WM_types.h */
43 const EnumPropertyItem rna_enum_operator_context_items[] = {
44     {WM_OP_INVOKE_DEFAULT, "INVOKE_DEFAULT", 0, "Invoke Default", ""},
45     {WM_OP_INVOKE_REGION_WIN, "INVOKE_REGION_WIN", 0, "Invoke Region Window", ""},
46     {WM_OP_INVOKE_REGION_CHANNELS, "INVOKE_REGION_CHANNELS", 0, "Invoke Region Channels", ""},
47     {WM_OP_INVOKE_REGION_PREVIEW, "INVOKE_REGION_PREVIEW", 0, "Invoke Region Preview", ""},
48     {WM_OP_INVOKE_AREA, "INVOKE_AREA", 0, "Invoke Area", ""},
49     {WM_OP_INVOKE_SCREEN, "INVOKE_SCREEN", 0, "Invoke Screen", ""},
50     {WM_OP_EXEC_DEFAULT, "EXEC_DEFAULT", 0, "Exec Default", ""},
51     {WM_OP_EXEC_REGION_WIN, "EXEC_REGION_WIN", 0, "Exec Region Window", ""},
52     {WM_OP_EXEC_REGION_CHANNELS, "EXEC_REGION_CHANNELS", 0, "Exec Region Channels", ""},
53     {WM_OP_EXEC_REGION_PREVIEW, "EXEC_REGION_PREVIEW", 0, "Exec Region Preview", ""},
54     {WM_OP_EXEC_AREA, "EXEC_AREA", 0, "Exec Area", ""},
55     {WM_OP_EXEC_SCREEN, "EXEC_SCREEN", 0, "Exec Screen", ""},
56     {0, NULL, 0, NULL, NULL},
57 };
58 
59 const EnumPropertyItem rna_enum_uilist_layout_type_items[] = {
60     {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout", "Use the default, multi-rows layout"},
61     {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout", "Use the compact, single-row layout"},
62     {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout", "Use the grid-based layout"},
63     {0, NULL, 0, NULL, NULL},
64 };
65 
66 #ifdef RNA_RUNTIME
67 
68 #  include "MEM_guardedalloc.h"
69 
70 #  include "RNA_access.h"
71 
72 #  include "BLI_dynstr.h"
73 
74 #  include "BKE_context.h"
75 #  include "BKE_report.h"
76 #  include "BKE_screen.h"
77 
78 #  include "WM_api.h"
79 
region_type_find(ReportList * reports,int space_type,int region_type)80 static ARegionType *region_type_find(ReportList *reports, int space_type, int region_type)
81 {
82   SpaceType *st;
83   ARegionType *art;
84 
85   st = BKE_spacetype_from_id(space_type);
86 
87   for (art = (st) ? st->regiontypes.first : NULL; art; art = art->next) {
88     if (art->regionid == region_type) {
89       break;
90     }
91   }
92 
93   /* region type not found? abort */
94   if (art == NULL) {
95     BKE_report(reports, RPT_ERROR, "Region not found in space type");
96     return NULL;
97   }
98 
99   return art;
100 }
101 
102 /* Panel */
103 
panel_poll(const bContext * C,PanelType * pt)104 static bool panel_poll(const bContext *C, PanelType *pt)
105 {
106   extern FunctionRNA rna_Panel_poll_func;
107 
108   PointerRNA ptr;
109   ParameterList list;
110   FunctionRNA *func;
111   void *ret;
112   bool visible;
113 
114   RNA_pointer_create(NULL, pt->rna_ext.srna, NULL, &ptr); /* dummy */
115   func = &rna_Panel_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
116 
117   RNA_parameter_list_create(&list, &ptr, func);
118   RNA_parameter_set_lookup(&list, "context", &C);
119   pt->rna_ext.call((bContext *)C, &ptr, func, &list);
120 
121   RNA_parameter_get_lookup(&list, "visible", &ret);
122   visible = *(bool *)ret;
123 
124   RNA_parameter_list_free(&list);
125 
126   return visible;
127 }
128 
panel_draw(const bContext * C,Panel * panel)129 static void panel_draw(const bContext *C, Panel *panel)
130 {
131   extern FunctionRNA rna_Panel_draw_func;
132 
133   PointerRNA ptr;
134   ParameterList list;
135   FunctionRNA *func;
136 
137   RNA_pointer_create(&CTX_wm_screen(C)->id, panel->type->rna_ext.srna, panel, &ptr);
138   func = &rna_Panel_draw_func; /* RNA_struct_find_function(&ptr, "draw"); */
139 
140   RNA_parameter_list_create(&list, &ptr, func);
141   RNA_parameter_set_lookup(&list, "context", &C);
142   panel->type->rna_ext.call((bContext *)C, &ptr, func, &list);
143 
144   RNA_parameter_list_free(&list);
145 }
146 
panel_draw_header(const bContext * C,Panel * panel)147 static void panel_draw_header(const bContext *C, Panel *panel)
148 {
149   extern FunctionRNA rna_Panel_draw_header_func;
150 
151   PointerRNA ptr;
152   ParameterList list;
153   FunctionRNA *func;
154 
155   RNA_pointer_create(&CTX_wm_screen(C)->id, panel->type->rna_ext.srna, panel, &ptr);
156   func = &rna_Panel_draw_header_func; /* RNA_struct_find_function(&ptr, "draw_header"); */
157 
158   RNA_parameter_list_create(&list, &ptr, func);
159   RNA_parameter_set_lookup(&list, "context", &C);
160   panel->type->rna_ext.call((bContext *)C, &ptr, func, &list);
161 
162   RNA_parameter_list_free(&list);
163 }
164 
panel_draw_header_preset(const bContext * C,Panel * panel)165 static void panel_draw_header_preset(const bContext *C, Panel *panel)
166 {
167   extern FunctionRNA rna_Panel_draw_header_preset_func;
168 
169   PointerRNA ptr;
170   ParameterList list;
171   FunctionRNA *func;
172 
173   RNA_pointer_create(&CTX_wm_screen(C)->id, panel->type->rna_ext.srna, panel, &ptr);
174   func = &rna_Panel_draw_header_preset_func;
175 
176   RNA_parameter_list_create(&list, &ptr, func);
177   RNA_parameter_set_lookup(&list, "context", &C);
178   panel->type->rna_ext.call((bContext *)C, &ptr, func, &list);
179 
180   RNA_parameter_list_free(&list);
181 }
182 
panel_type_clear_recursive(Panel * panel,const PanelType * type)183 static void panel_type_clear_recursive(Panel *panel, const PanelType *type)
184 {
185   if (panel->type == type) {
186     panel->type = NULL;
187   }
188 
189   LISTBASE_FOREACH (Panel *, child_panel, &panel->children) {
190     panel_type_clear_recursive(child_panel, type);
191   }
192 }
193 
rna_Panel_unregister(Main * bmain,StructRNA * type)194 static void rna_Panel_unregister(Main *bmain, StructRNA *type)
195 {
196   ARegionType *art;
197   PanelType *pt = RNA_struct_blender_type_get(type);
198 
199   if (!pt) {
200     return;
201   }
202   if (!(art = region_type_find(NULL, pt->space_type, pt->region_type))) {
203     return;
204   }
205 
206   RNA_struct_free_extension(type, &pt->rna_ext);
207   RNA_struct_free(&BLENDER_RNA, type);
208 
209   if (pt->parent) {
210     LinkData *link = BLI_findptr(&pt->parent->children, pt, offsetof(LinkData, data));
211     BLI_freelinkN(&pt->parent->children, link);
212   }
213 
214   WM_paneltype_remove(pt);
215 
216   LISTBASE_FOREACH (LinkData *, link, &pt->children) {
217     PanelType *child_pt = link->data;
218     child_pt->parent = NULL;
219   }
220 
221   const char space_type = pt->space_type;
222   BLI_freelistN(&pt->children);
223   BLI_freelinkN(&art->paneltypes, pt);
224 
225   for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
226     LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
227       LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
228         if (sl->spacetype == space_type) {
229           ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase :
230                                                                  &sl->regionbase;
231           LISTBASE_FOREACH (ARegion *, region, regionbase) {
232             if (region->type == art) {
233               LISTBASE_FOREACH (Panel *, panel, &region->panels) {
234                 panel_type_clear_recursive(panel, pt);
235               }
236             }
237             /* The unregistered panel might have had a template that added instanced panels,
238              * so remove them just in case. They can be re-added on redraw anyway. */
239             UI_panels_free_instanced(NULL, region);
240           }
241         }
242       }
243     }
244   }
245 
246   /* update while blender is running */
247   WM_main_add_notifier(NC_WINDOW, NULL);
248 }
249 
rna_Panel_register(Main * bmain,ReportList * reports,void * data,const char * identifier,StructValidateFunc validate,StructCallbackFunc call,StructFreeFunc free)250 static StructRNA *rna_Panel_register(Main *bmain,
251                                      ReportList *reports,
252                                      void *data,
253                                      const char *identifier,
254                                      StructValidateFunc validate,
255                                      StructCallbackFunc call,
256                                      StructFreeFunc free)
257 {
258   ARegionType *art;
259   PanelType *pt, *parent = NULL, dummypt = {NULL};
260   Panel dummypanel = {NULL};
261   PointerRNA dummyptr;
262   int have_function[4];
263 
264   /* setup dummy panel & panel type to store static properties in */
265   dummypanel.type = &dummypt;
266   RNA_pointer_create(NULL, &RNA_Panel, &dummypanel, &dummyptr);
267 
268   /* We have to set default context! Else we get a void string... */
269   strcpy(dummypt.translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
270 
271   /* validate the python class */
272   if (validate(&dummyptr, data, have_function) != 0) {
273     return NULL;
274   }
275 
276   if (strlen(identifier) >= sizeof(dummypt.idname)) {
277     BKE_reportf(reports,
278                 RPT_ERROR,
279                 "Registering panel class: '%s' is too long, maximum length is %d",
280                 identifier,
281                 (int)sizeof(dummypt.idname));
282     return NULL;
283   }
284 
285   if ((1 << dummypt.region_type) & RGN_TYPE_HAS_CATEGORY_MASK) {
286     if (dummypt.category[0] == '\0') {
287       /* Use a fallback, otherwise an empty value will draw the panel in every category. */
288       strcpy(dummypt.category, PNL_CATEGORY_FALLBACK);
289 #  ifndef NDEBUG
290       printf("Registering panel class: '%s' misses category, please update the script\n",
291              dummypt.idname);
292 #  endif
293     }
294   }
295   else {
296     if (dummypt.category[0] != '\0') {
297       if ((1 << dummypt.space_type) & WM_TOOLSYSTEM_SPACE_MASK) {
298         BKE_reportf(reports,
299                     RPT_ERROR,
300                     "Registering panel class: '%s' has category '%s' ",
301                     dummypt.idname,
302                     dummypt.category);
303         return NULL;
304       }
305     }
306   }
307 
308   if (!(art = region_type_find(reports, dummypt.space_type, dummypt.region_type))) {
309     return NULL;
310   }
311 
312   /* check if we have registered this panel type before, and remove it */
313   for (pt = art->paneltypes.first; pt; pt = pt->next) {
314     if (STREQ(pt->idname, dummypt.idname)) {
315       PanelType *pt_next = pt->next;
316       if (pt->rna_ext.srna) {
317         rna_Panel_unregister(bmain, pt->rna_ext.srna);
318       }
319       else {
320         BLI_freelinkN(&art->paneltypes, pt);
321       }
322 
323       /* The order of panel types will be altered on re-registration. */
324       if (dummypt.parent_id[0] && (parent == NULL)) {
325         for (pt = pt_next; pt; pt = pt->next) {
326           if (STREQ(pt->idname, dummypt.parent_id)) {
327             parent = pt;
328             break;
329           }
330         }
331       }
332 
333       break;
334     }
335 
336     if (dummypt.parent_id[0] && STREQ(pt->idname, dummypt.parent_id)) {
337       parent = pt;
338     }
339   }
340 
341   if (!RNA_struct_available_or_report(reports, dummypt.idname)) {
342     return NULL;
343   }
344   if (!RNA_struct_bl_idname_ok_or_report(reports, dummypt.idname, "_PT_")) {
345     return NULL;
346   }
347   if (dummypt.parent_id[0] && !parent) {
348     BKE_reportf(reports,
349                 RPT_ERROR,
350                 "Registering panel class: parent '%s' for '%s' not found",
351                 dummypt.parent_id,
352                 dummypt.idname);
353     return NULL;
354   }
355 
356   /* create a new panel type */
357   pt = MEM_mallocN(sizeof(PanelType), "python buttons panel");
358   memcpy(pt, &dummypt, sizeof(dummypt));
359 
360   pt->rna_ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, pt->idname, &RNA_Panel);
361   RNA_def_struct_translation_context(pt->rna_ext.srna, pt->translation_context);
362   pt->rna_ext.data = data;
363   pt->rna_ext.call = call;
364   pt->rna_ext.free = free;
365   RNA_struct_blender_type_set(pt->rna_ext.srna, pt);
366   RNA_def_struct_flag(pt->rna_ext.srna, STRUCT_NO_IDPROPERTIES);
367 
368   pt->poll = (have_function[0]) ? panel_poll : NULL;
369   pt->draw = (have_function[1]) ? panel_draw : NULL;
370   pt->draw_header = (have_function[2]) ? panel_draw_header : NULL;
371   pt->draw_header_preset = (have_function[3]) ? panel_draw_header_preset : NULL;
372 
373   /* Find position to insert panel based on order. */
374   PanelType *pt_iter = art->paneltypes.last;
375 
376   for (; pt_iter; pt_iter = pt_iter->prev) {
377     /* No header has priority. */
378     if ((pt->flag & PNL_NO_HEADER) && !(pt_iter->flag & PNL_NO_HEADER)) {
379       continue;
380     }
381     if (pt_iter->order <= pt->order) {
382       break;
383     }
384   }
385 
386   /* Insert into list. */
387   BLI_insertlinkafter(&art->paneltypes, pt_iter, pt);
388 
389   if (parent) {
390     pt->parent = parent;
391     BLI_addtail(&parent->children, BLI_genericNodeN(pt));
392   }
393 
394   {
395     const char *owner_id = RNA_struct_state_owner_get();
396     if (owner_id) {
397       BLI_strncpy(pt->owner_id, owner_id, sizeof(pt->owner_id));
398     }
399   }
400 
401   WM_paneltype_add(pt);
402 
403   /* update while blender is running */
404   WM_main_add_notifier(NC_WINDOW, NULL);
405 
406   return pt->rna_ext.srna;
407 }
408 
rna_Panel_refine(PointerRNA * ptr)409 static StructRNA *rna_Panel_refine(PointerRNA *ptr)
410 {
411   Panel *menu = (Panel *)ptr->data;
412   return (menu->type && menu->type->rna_ext.srna) ? menu->type->rna_ext.srna : &RNA_Panel;
413 }
414 
rna_Panel_custom_data_typef(PointerRNA * ptr)415 static StructRNA *rna_Panel_custom_data_typef(PointerRNA *ptr)
416 {
417   Panel *panel = (Panel *)ptr->data;
418 
419   return UI_panel_custom_data_get(panel)->type;
420 }
421 
rna_Panel_custom_data_get(PointerRNA * ptr)422 static PointerRNA rna_Panel_custom_data_get(PointerRNA *ptr)
423 {
424   Panel *panel = (Panel *)ptr->data;
425 
426   /* Because the panel custom data is general we can't refine the pointer type here. */
427   return *UI_panel_custom_data_get(panel);
428 }
429 
430 /* UIList */
rna_UIList_filter_const_FILTER_ITEM_get(PointerRNA * UNUSED (ptr))431 static unsigned int rna_UIList_filter_const_FILTER_ITEM_get(PointerRNA *UNUSED(ptr))
432 {
433   return UILST_FLT_ITEM;
434 }
435 
rna_UIList_idprops(PointerRNA * ptr,bool create)436 static IDProperty *rna_UIList_idprops(PointerRNA *ptr, bool create)
437 {
438   uiList *ui_list = (uiList *)ptr->data;
439   if (create && !ui_list->properties) {
440     IDPropertyTemplate val = {0};
441     ui_list->properties = IDP_New(IDP_GROUP, &val, "RNA_UIList IDproperties group");
442   }
443 
444   return ui_list->properties;
445 }
446 
uilist_draw_item(uiList * ui_list,bContext * C,uiLayout * layout,PointerRNA * dataptr,PointerRNA * itemptr,int icon,PointerRNA * active_dataptr,const char * active_propname,int index,int flt_flag)447 static void uilist_draw_item(uiList *ui_list,
448                              bContext *C,
449                              uiLayout *layout,
450                              PointerRNA *dataptr,
451                              PointerRNA *itemptr,
452                              int icon,
453                              PointerRNA *active_dataptr,
454                              const char *active_propname,
455                              int index,
456                              int flt_flag)
457 {
458   extern FunctionRNA rna_UIList_draw_item_func;
459 
460   PointerRNA ul_ptr;
461   ParameterList list;
462   FunctionRNA *func;
463 
464   RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->rna_ext.srna, ui_list, &ul_ptr);
465   func = &rna_UIList_draw_item_func; /* RNA_struct_find_function(&ul_ptr, "draw_item"); */
466 
467   RNA_parameter_list_create(&list, &ul_ptr, func);
468   RNA_parameter_set_lookup(&list, "context", &C);
469   RNA_parameter_set_lookup(&list, "layout", &layout);
470   RNA_parameter_set_lookup(&list, "data", dataptr);
471   RNA_parameter_set_lookup(&list, "item", itemptr);
472   RNA_parameter_set_lookup(&list, "icon", &icon);
473   RNA_parameter_set_lookup(&list, "active_data", active_dataptr);
474   RNA_parameter_set_lookup(&list, "active_property", &active_propname);
475   RNA_parameter_set_lookup(&list, "index", &index);
476   RNA_parameter_set_lookup(&list, "flt_flag", &flt_flag);
477   ui_list->type->rna_ext.call((bContext *)C, &ul_ptr, func, &list);
478 
479   RNA_parameter_list_free(&list);
480 }
481 
uilist_draw_filter(uiList * ui_list,bContext * C,uiLayout * layout)482 static void uilist_draw_filter(uiList *ui_list, bContext *C, uiLayout *layout)
483 {
484   extern FunctionRNA rna_UIList_draw_filter_func;
485 
486   PointerRNA ul_ptr;
487   ParameterList list;
488   FunctionRNA *func;
489 
490   RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->rna_ext.srna, ui_list, &ul_ptr);
491   func = &rna_UIList_draw_filter_func; /* RNA_struct_find_function(&ul_ptr, "draw_filter"); */
492 
493   RNA_parameter_list_create(&list, &ul_ptr, func);
494   RNA_parameter_set_lookup(&list, "context", &C);
495   RNA_parameter_set_lookup(&list, "layout", &layout);
496   ui_list->type->rna_ext.call((bContext *)C, &ul_ptr, func, &list);
497 
498   RNA_parameter_list_free(&list);
499 }
500 
uilist_filter_items(uiList * ui_list,bContext * C,PointerRNA * dataptr,const char * propname)501 static void uilist_filter_items(uiList *ui_list,
502                                 bContext *C,
503                                 PointerRNA *dataptr,
504                                 const char *propname)
505 {
506   extern FunctionRNA rna_UIList_filter_items_func;
507 
508   PointerRNA ul_ptr;
509   ParameterList list;
510   FunctionRNA *func;
511   PropertyRNA *parm;
512 
513   uiListDyn *flt_data = ui_list->dyn_data;
514   int *filter_flags, *filter_neworder;
515   void *ret1, *ret2;
516   int ret_len;
517   int len = flt_data->items_len = RNA_collection_length(dataptr, propname);
518 
519   RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->rna_ext.srna, ui_list, &ul_ptr);
520   func = &rna_UIList_filter_items_func; /* RNA_struct_find_function(&ul_ptr, "filter_items"); */
521 
522   RNA_parameter_list_create(&list, &ul_ptr, func);
523   RNA_parameter_set_lookup(&list, "context", &C);
524   RNA_parameter_set_lookup(&list, "data", dataptr);
525   RNA_parameter_set_lookup(&list, "property", &propname);
526 
527   ui_list->type->rna_ext.call((bContext *)C, &ul_ptr, func, &list);
528 
529   parm = RNA_function_find_parameter(NULL, func, "filter_flags");
530   ret_len = RNA_parameter_dynamic_length_get(&list, parm);
531   if (ret_len != len && ret_len != 0) {
532     printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n",
533            __func__,
534            RNA_parameter_dynamic_length_get(&list, parm),
535            "filter_flags",
536            len);
537     /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */
538     filter_flags = NULL;
539   }
540   else {
541     RNA_parameter_get(&list, parm, &ret1);
542     filter_flags = (int *)ret1;
543   }
544 
545   parm = RNA_function_find_parameter(NULL, func, "filter_neworder");
546   ret_len = RNA_parameter_dynamic_length_get(&list, parm);
547   if (ret_len != len && ret_len != 0) {
548     printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n",
549            __func__,
550            RNA_parameter_dynamic_length_get(&list, parm),
551            "filter_neworder",
552            len);
553     /* Note: we cannot return here, we would let flt_data in inconsistent state... see T38356. */
554     filter_neworder = NULL;
555   }
556   else {
557     RNA_parameter_get(&list, parm, &ret2);
558     filter_neworder = (int *)ret2;
559   }
560 
561   /* We have to do some final checks and transforms... */
562   {
563     int i, filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE;
564     if (filter_flags) {
565       flt_data->items_filter_flags = MEM_mallocN(sizeof(int) * len, __func__);
566       memcpy(flt_data->items_filter_flags, filter_flags, sizeof(int) * len);
567 
568       if (filter_neworder) {
569         /* For sake of simplicity, py filtering is expected to filter all items,
570          * but we actually only want reordering data for shown items!
571          */
572         int items_shown, shown_idx;
573         int t_idx, t_ni, prev_ni;
574         flt_data->items_shown = 0;
575         for (i = 0, shown_idx = 0; i < len; i++) {
576           if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) {
577             filter_neworder[shown_idx++] = filter_neworder[i];
578           }
579         }
580         items_shown = flt_data->items_shown = shown_idx;
581         flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * items_shown, __func__);
582         /* And now, bring back new indices into the [0, items_shown[ range!
583          * XXX This is O(N²)... :/
584          */
585         for (shown_idx = 0, prev_ni = -1; shown_idx < items_shown; shown_idx++) {
586           for (i = 0, t_ni = len, t_idx = -1; i < items_shown; i++) {
587             int ni = filter_neworder[i];
588             if (ni > prev_ni && ni < t_ni) {
589               t_idx = i;
590               t_ni = ni;
591             }
592           }
593           if (t_idx >= 0) {
594             prev_ni = t_ni;
595             flt_data->items_filter_neworder[t_idx] = shown_idx;
596           }
597         }
598       }
599       else {
600         /* we still have to set flt_data->items_shown... */
601         flt_data->items_shown = 0;
602         for (i = 0; i < len; i++) {
603           if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) {
604             flt_data->items_shown++;
605           }
606         }
607       }
608     }
609     else {
610       flt_data->items_shown = len;
611 
612       if (filter_neworder) {
613         flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * len, __func__);
614         memcpy(flt_data->items_filter_neworder, filter_neworder, sizeof(int) * len);
615       }
616     }
617   }
618 
619   RNA_parameter_list_free(&list);
620 }
621 
rna_UIList_unregister(Main * UNUSED (bmain),StructRNA * type)622 static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
623 {
624   uiListType *ult = RNA_struct_blender_type_get(type);
625 
626   if (!ult) {
627     return;
628   }
629 
630   RNA_struct_free_extension(type, &ult->rna_ext);
631   RNA_struct_free(&BLENDER_RNA, type);
632 
633   WM_uilisttype_freelink(ult);
634 
635   /* update while blender is running */
636   WM_main_add_notifier(NC_WINDOW, NULL);
637 }
638 
rna_UIList_register(Main * bmain,ReportList * reports,void * data,const char * identifier,StructValidateFunc validate,StructCallbackFunc call,StructFreeFunc free)639 static StructRNA *rna_UIList_register(Main *bmain,
640                                       ReportList *reports,
641                                       void *data,
642                                       const char *identifier,
643                                       StructValidateFunc validate,
644                                       StructCallbackFunc call,
645                                       StructFreeFunc free)
646 {
647   uiListType *ult, dummyult = {NULL};
648   uiList dummyuilist = {NULL};
649   PointerRNA dummyul_ptr;
650   int have_function[3];
651   size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
652 
653   /* setup dummy menu & menu type to store static properties in */
654   dummyuilist.type = &dummyult;
655   RNA_pointer_create(NULL, &RNA_UIList, &dummyuilist, &dummyul_ptr);
656 
657   /* validate the python class */
658   if (validate(&dummyul_ptr, data, have_function) != 0) {
659     return NULL;
660   }
661 
662   if (strlen(identifier) >= sizeof(dummyult.idname)) {
663     BKE_reportf(reports,
664                 RPT_ERROR,
665                 "Registering uilist class: '%s' is too long, maximum length is %d",
666                 identifier,
667                 (int)sizeof(dummyult.idname));
668     return NULL;
669   }
670 
671   /* check if we have registered this uilist type before, and remove it */
672   ult = WM_uilisttype_find(dummyult.idname, true);
673   if (ult && ult->rna_ext.srna) {
674     rna_UIList_unregister(bmain, ult->rna_ext.srna);
675   }
676   if (!RNA_struct_available_or_report(reports, dummyult.idname)) {
677     return NULL;
678   }
679   if (!RNA_struct_bl_idname_ok_or_report(reports, dummyult.idname, "_UL_")) {
680     return NULL;
681   }
682 
683   /* create a new menu type */
684   ult = MEM_callocN(sizeof(uiListType) + over_alloc, "python uilist");
685   memcpy(ult, &dummyult, sizeof(dummyult));
686 
687   ult->rna_ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ult->idname, &RNA_UIList);
688   ult->rna_ext.data = data;
689   ult->rna_ext.call = call;
690   ult->rna_ext.free = free;
691   RNA_struct_blender_type_set(ult->rna_ext.srna, ult);
692 
693   ult->draw_item = (have_function[0]) ? uilist_draw_item : NULL;
694   ult->draw_filter = (have_function[1]) ? uilist_draw_filter : NULL;
695   ult->filter_items = (have_function[2]) ? uilist_filter_items : NULL;
696 
697   WM_uilisttype_add(ult);
698 
699   /* update while blender is running */
700   WM_main_add_notifier(NC_WINDOW, NULL);
701 
702   return ult->rna_ext.srna;
703 }
704 
rna_UIList_refine(PointerRNA * ptr)705 static StructRNA *rna_UIList_refine(PointerRNA *ptr)
706 {
707   uiList *ui_list = (uiList *)ptr->data;
708   return (ui_list->type && ui_list->type->rna_ext.srna) ? ui_list->type->rna_ext.srna :
709                                                           &RNA_UIList;
710 }
711 
712 /* Header */
713 
header_draw(const bContext * C,Header * hdr)714 static void header_draw(const bContext *C, Header *hdr)
715 {
716   extern FunctionRNA rna_Header_draw_func;
717 
718   PointerRNA htr;
719   ParameterList list;
720   FunctionRNA *func;
721 
722   RNA_pointer_create(&CTX_wm_screen(C)->id, hdr->type->rna_ext.srna, hdr, &htr);
723   func = &rna_Header_draw_func; /* RNA_struct_find_function(&htr, "draw"); */
724 
725   RNA_parameter_list_create(&list, &htr, func);
726   RNA_parameter_set_lookup(&list, "context", &C);
727   hdr->type->rna_ext.call((bContext *)C, &htr, func, &list);
728 
729   RNA_parameter_list_free(&list);
730 }
731 
rna_Header_unregister(Main * UNUSED (bmain),StructRNA * type)732 static void rna_Header_unregister(Main *UNUSED(bmain), StructRNA *type)
733 {
734   ARegionType *art;
735   HeaderType *ht = RNA_struct_blender_type_get(type);
736 
737   if (!ht) {
738     return;
739   }
740   if (!(art = region_type_find(NULL, ht->space_type, ht->region_type))) {
741     return;
742   }
743 
744   RNA_struct_free_extension(type, &ht->rna_ext);
745   RNA_struct_free(&BLENDER_RNA, type);
746 
747   BLI_freelinkN(&art->headertypes, ht);
748 
749   /* update while blender is running */
750   WM_main_add_notifier(NC_WINDOW, NULL);
751 }
752 
rna_Header_register(Main * bmain,ReportList * reports,void * data,const char * identifier,StructValidateFunc validate,StructCallbackFunc call,StructFreeFunc free)753 static StructRNA *rna_Header_register(Main *bmain,
754                                       ReportList *reports,
755                                       void *data,
756                                       const char *identifier,
757                                       StructValidateFunc validate,
758                                       StructCallbackFunc call,
759                                       StructFreeFunc free)
760 {
761   ARegionType *art;
762   HeaderType *ht, dummyht = {NULL};
763   Header dummyheader = {NULL};
764   PointerRNA dummyhtr;
765   int have_function[1];
766 
767   /* setup dummy header & header type to store static properties in */
768   dummyheader.type = &dummyht;
769   dummyht.region_type = RGN_TYPE_HEADER; /* RGN_TYPE_HEADER by default, may be overridden */
770   RNA_pointer_create(NULL, &RNA_Header, &dummyheader, &dummyhtr);
771 
772   /* validate the python class */
773   if (validate(&dummyhtr, data, have_function) != 0) {
774     return NULL;
775   }
776 
777   if (strlen(identifier) >= sizeof(dummyht.idname)) {
778     BKE_reportf(reports,
779                 RPT_ERROR,
780                 "Registering header class: '%s' is too long, maximum length is %d",
781                 identifier,
782                 (int)sizeof(dummyht.idname));
783     return NULL;
784   }
785 
786   if (!(art = region_type_find(reports, dummyht.space_type, dummyht.region_type))) {
787     return NULL;
788   }
789 
790   /* check if we have registered this header type before, and remove it */
791   for (ht = art->headertypes.first; ht; ht = ht->next) {
792     if (STREQ(ht->idname, dummyht.idname)) {
793       if (ht->rna_ext.srna) {
794         rna_Header_unregister(bmain, ht->rna_ext.srna);
795       }
796       break;
797     }
798   }
799   if (!RNA_struct_available_or_report(reports, dummyht.idname)) {
800     return NULL;
801   }
802   if (!RNA_struct_bl_idname_ok_or_report(reports, dummyht.idname, "_HT_")) {
803     return NULL;
804   }
805 
806   /* create a new header type */
807   ht = MEM_mallocN(sizeof(HeaderType), "python buttons header");
808   memcpy(ht, &dummyht, sizeof(dummyht));
809 
810   ht->rna_ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, ht->idname, &RNA_Header);
811   ht->rna_ext.data = data;
812   ht->rna_ext.call = call;
813   ht->rna_ext.free = free;
814   RNA_struct_blender_type_set(ht->rna_ext.srna, ht);
815 
816   ht->draw = (have_function[0]) ? header_draw : NULL;
817 
818   BLI_addtail(&art->headertypes, ht);
819 
820   /* update while blender is running */
821   WM_main_add_notifier(NC_WINDOW, NULL);
822 
823   return ht->rna_ext.srna;
824 }
825 
rna_Header_refine(PointerRNA * htr)826 static StructRNA *rna_Header_refine(PointerRNA *htr)
827 {
828   Header *hdr = (Header *)htr->data;
829   return (hdr->type && hdr->type->rna_ext.srna) ? hdr->type->rna_ext.srna : &RNA_Header;
830 }
831 
832 /* Menu */
833 
menu_poll(const bContext * C,MenuType * pt)834 static bool menu_poll(const bContext *C, MenuType *pt)
835 {
836   extern FunctionRNA rna_Menu_poll_func;
837 
838   PointerRNA ptr;
839   ParameterList list;
840   FunctionRNA *func;
841   void *ret;
842   bool visible;
843 
844   RNA_pointer_create(NULL, pt->rna_ext.srna, NULL, &ptr); /* dummy */
845   func = &rna_Menu_poll_func; /* RNA_struct_find_function(&ptr, "poll"); */
846 
847   RNA_parameter_list_create(&list, &ptr, func);
848   RNA_parameter_set_lookup(&list, "context", &C);
849   pt->rna_ext.call((bContext *)C, &ptr, func, &list);
850 
851   RNA_parameter_get_lookup(&list, "visible", &ret);
852   visible = *(bool *)ret;
853 
854   RNA_parameter_list_free(&list);
855 
856   return visible;
857 }
858 
menu_draw(const bContext * C,Menu * menu)859 static void menu_draw(const bContext *C, Menu *menu)
860 {
861   extern FunctionRNA rna_Menu_draw_func;
862 
863   PointerRNA mtr;
864   ParameterList list;
865   FunctionRNA *func;
866 
867   RNA_pointer_create(&CTX_wm_screen(C)->id, menu->type->rna_ext.srna, menu, &mtr);
868   func = &rna_Menu_draw_func; /* RNA_struct_find_function(&mtr, "draw"); */
869 
870   RNA_parameter_list_create(&list, &mtr, func);
871   RNA_parameter_set_lookup(&list, "context", &C);
872   menu->type->rna_ext.call((bContext *)C, &mtr, func, &list);
873 
874   RNA_parameter_list_free(&list);
875 }
876 
rna_Menu_unregister(Main * UNUSED (bmain),StructRNA * type)877 static void rna_Menu_unregister(Main *UNUSED(bmain), StructRNA *type)
878 {
879   MenuType *mt = RNA_struct_blender_type_get(type);
880 
881   if (!mt) {
882     return;
883   }
884 
885   RNA_struct_free_extension(type, &mt->rna_ext);
886   RNA_struct_free(&BLENDER_RNA, type);
887 
888   WM_menutype_freelink(mt);
889 
890   /* update while blender is running */
891   WM_main_add_notifier(NC_WINDOW, NULL);
892 }
893 
rna_Menu_register(Main * bmain,ReportList * reports,void * data,const char * identifier,StructValidateFunc validate,StructCallbackFunc call,StructFreeFunc free)894 static StructRNA *rna_Menu_register(Main *bmain,
895                                     ReportList *reports,
896                                     void *data,
897                                     const char *identifier,
898                                     StructValidateFunc validate,
899                                     StructCallbackFunc call,
900                                     StructFreeFunc free)
901 {
902   MenuType *mt, dummymt = {NULL};
903   Menu dummymenu = {NULL};
904   PointerRNA dummymtr;
905   int have_function[2];
906   size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
907   size_t description_size = 0;
908   char _menu_descr[RNA_DYN_DESCR_MAX];
909 
910   /* setup dummy menu & menu type to store static properties in */
911   dummymenu.type = &dummymt;
912   _menu_descr[0] = '\0';
913   dummymenu.type->description = _menu_descr;
914   RNA_pointer_create(NULL, &RNA_Menu, &dummymenu, &dummymtr);
915 
916   /* We have to set default context! Else we get a void string... */
917   strcpy(dummymt.translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
918 
919   /* validate the python class */
920   if (validate(&dummymtr, data, have_function) != 0) {
921     return NULL;
922   }
923 
924   if (strlen(identifier) >= sizeof(dummymt.idname)) {
925     BKE_reportf(reports,
926                 RPT_ERROR,
927                 "Registering menu class: '%s' is too long, maximum length is %d",
928                 identifier,
929                 (int)sizeof(dummymt.idname));
930     return NULL;
931   }
932 
933   /* check if we have registered this menu type before, and remove it */
934   mt = WM_menutype_find(dummymt.idname, true);
935   if (mt && mt->rna_ext.srna) {
936     rna_Menu_unregister(bmain, mt->rna_ext.srna);
937   }
938   if (!RNA_struct_available_or_report(reports, dummymt.idname)) {
939     return NULL;
940   }
941   if (!RNA_struct_bl_idname_ok_or_report(reports, dummymt.idname, "_MT_")) {
942     return NULL;
943   }
944 
945   /* create a new menu type */
946   if (_menu_descr[0]) {
947     description_size = strlen(_menu_descr) + 1;
948     over_alloc += description_size;
949   }
950 
951   mt = MEM_callocN(sizeof(MenuType) + over_alloc, "python buttons menu");
952   memcpy(mt, &dummymt, sizeof(dummymt));
953 
954   if (_menu_descr[0]) {
955     char *buf = (char *)(mt + 1);
956     memcpy(buf, _menu_descr, description_size);
957     mt->description = buf;
958   }
959   else {
960     mt->description = NULL;
961   }
962 
963   mt->rna_ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, mt->idname, &RNA_Menu);
964   RNA_def_struct_translation_context(mt->rna_ext.srna, mt->translation_context);
965   mt->rna_ext.data = data;
966   mt->rna_ext.call = call;
967   mt->rna_ext.free = free;
968   RNA_struct_blender_type_set(mt->rna_ext.srna, mt);
969   RNA_def_struct_flag(mt->rna_ext.srna, STRUCT_NO_IDPROPERTIES);
970 
971   mt->poll = (have_function[0]) ? menu_poll : NULL;
972   mt->draw = (have_function[1]) ? menu_draw : NULL;
973 
974   {
975     const char *owner_id = RNA_struct_state_owner_get();
976     if (owner_id) {
977       BLI_strncpy(mt->owner_id, owner_id, sizeof(mt->owner_id));
978     }
979   }
980 
981   WM_menutype_add(mt);
982 
983   /* update while blender is running */
984   WM_main_add_notifier(NC_WINDOW, NULL);
985 
986   return mt->rna_ext.srna;
987 }
988 
rna_Menu_refine(PointerRNA * mtr)989 static StructRNA *rna_Menu_refine(PointerRNA *mtr)
990 {
991   Menu *menu = (Menu *)mtr->data;
992   return (menu->type && menu->type->rna_ext.srna) ? menu->type->rna_ext.srna : &RNA_Menu;
993 }
994 
rna_Menu_bl_description_set(PointerRNA * ptr,const char * value)995 static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
996 {
997   Menu *data = (Menu *)(ptr->data);
998   char *str = (char *)data->type->description;
999   if (!str[0]) {
1000     BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */
1001   }
1002   else {
1003     BLI_assert(!"setting the bl_description on a non-builtin menu");
1004   }
1005 }
1006 
1007 /* UILayout */
1008 
rna_UILayout_active_get(PointerRNA * ptr)1009 static bool rna_UILayout_active_get(PointerRNA *ptr)
1010 {
1011   return uiLayoutGetActive(ptr->data);
1012 }
1013 
rna_UILayout_active_set(PointerRNA * ptr,bool value)1014 static void rna_UILayout_active_set(PointerRNA *ptr, bool value)
1015 {
1016   uiLayoutSetActive(ptr->data, value);
1017 }
1018 
rna_UILayout_active_default_get(PointerRNA * ptr)1019 static bool rna_UILayout_active_default_get(PointerRNA *ptr)
1020 {
1021   return uiLayoutGetActiveDefault(ptr->data);
1022 }
1023 
rna_UILayout_active_default_set(PointerRNA * ptr,bool value)1024 static void rna_UILayout_active_default_set(PointerRNA *ptr, bool value)
1025 {
1026   uiLayoutSetActiveDefault(ptr->data, value);
1027 }
1028 
rna_UILayout_activate_init_get(PointerRNA * ptr)1029 static bool rna_UILayout_activate_init_get(PointerRNA *ptr)
1030 {
1031   return uiLayoutGetActivateInit(ptr->data);
1032 }
1033 
rna_UILayout_activate_init_set(PointerRNA * ptr,bool value)1034 static void rna_UILayout_activate_init_set(PointerRNA *ptr, bool value)
1035 {
1036   uiLayoutSetActivateInit(ptr->data, value);
1037 }
1038 
rna_UILayout_alert_get(PointerRNA * ptr)1039 static bool rna_UILayout_alert_get(PointerRNA *ptr)
1040 {
1041   return uiLayoutGetRedAlert(ptr->data);
1042 }
1043 
rna_UILayout_alert_set(PointerRNA * ptr,bool value)1044 static void rna_UILayout_alert_set(PointerRNA *ptr, bool value)
1045 {
1046   uiLayoutSetRedAlert(ptr->data, value);
1047 }
1048 
rna_UILayout_op_context_set(PointerRNA * ptr,int value)1049 static void rna_UILayout_op_context_set(PointerRNA *ptr, int value)
1050 {
1051   uiLayoutSetOperatorContext(ptr->data, value);
1052 }
1053 
rna_UILayout_op_context_get(PointerRNA * ptr)1054 static int rna_UILayout_op_context_get(PointerRNA *ptr)
1055 {
1056   return uiLayoutGetOperatorContext(ptr->data);
1057 }
1058 
rna_UILayout_enabled_get(PointerRNA * ptr)1059 static bool rna_UILayout_enabled_get(PointerRNA *ptr)
1060 {
1061   return uiLayoutGetEnabled(ptr->data);
1062 }
1063 
rna_UILayout_enabled_set(PointerRNA * ptr,bool value)1064 static void rna_UILayout_enabled_set(PointerRNA *ptr, bool value)
1065 {
1066   uiLayoutSetEnabled(ptr->data, value);
1067 }
1068 
1069 #  if 0
1070 static int rna_UILayout_red_alert_get(PointerRNA *ptr)
1071 {
1072   return uiLayoutGetRedAlert(ptr->data);
1073 }
1074 
1075 static void rna_UILayout_red_alert_set(PointerRNA *ptr, bool value)
1076 {
1077   uiLayoutSetRedAlert(ptr->data, value);
1078 }
1079 
1080 static bool rna_UILayout_keep_aspect_get(PointerRNA *ptr)
1081 {
1082   return uiLayoutGetKeepAspect(ptr->data);
1083 }
1084 
1085 static void rna_UILayout_keep_aspect_set(PointerRNA *ptr, int value)
1086 {
1087   uiLayoutSetKeepAspect(ptr->data, value);
1088 }
1089 #  endif
1090 
rna_UILayout_alignment_get(PointerRNA * ptr)1091 static int rna_UILayout_alignment_get(PointerRNA *ptr)
1092 {
1093   return uiLayoutGetAlignment(ptr->data);
1094 }
1095 
rna_UILayout_alignment_set(PointerRNA * ptr,int value)1096 static void rna_UILayout_alignment_set(PointerRNA *ptr, int value)
1097 {
1098   uiLayoutSetAlignment(ptr->data, value);
1099 }
1100 
rna_UILayout_direction_get(PointerRNA * ptr)1101 static int rna_UILayout_direction_get(PointerRNA *ptr)
1102 {
1103   return uiLayoutGetLocalDir(ptr->data);
1104 }
1105 
rna_UILayout_scale_x_get(PointerRNA * ptr)1106 static float rna_UILayout_scale_x_get(PointerRNA *ptr)
1107 {
1108   return uiLayoutGetScaleX(ptr->data);
1109 }
1110 
rna_UILayout_scale_x_set(PointerRNA * ptr,float value)1111 static void rna_UILayout_scale_x_set(PointerRNA *ptr, float value)
1112 {
1113   uiLayoutSetScaleX(ptr->data, value);
1114 }
1115 
rna_UILayout_scale_y_get(PointerRNA * ptr)1116 static float rna_UILayout_scale_y_get(PointerRNA *ptr)
1117 {
1118   return uiLayoutGetScaleY(ptr->data);
1119 }
1120 
rna_UILayout_scale_y_set(PointerRNA * ptr,float value)1121 static void rna_UILayout_scale_y_set(PointerRNA *ptr, float value)
1122 {
1123   uiLayoutSetScaleY(ptr->data, value);
1124 }
1125 
rna_UILayout_units_x_get(PointerRNA * ptr)1126 static float rna_UILayout_units_x_get(PointerRNA *ptr)
1127 {
1128   return uiLayoutGetUnitsX(ptr->data);
1129 }
1130 
rna_UILayout_units_x_set(PointerRNA * ptr,float value)1131 static void rna_UILayout_units_x_set(PointerRNA *ptr, float value)
1132 {
1133   uiLayoutSetUnitsX(ptr->data, value);
1134 }
1135 
rna_UILayout_units_y_get(PointerRNA * ptr)1136 static float rna_UILayout_units_y_get(PointerRNA *ptr)
1137 {
1138   return uiLayoutGetUnitsY(ptr->data);
1139 }
1140 
rna_UILayout_units_y_set(PointerRNA * ptr,float value)1141 static void rna_UILayout_units_y_set(PointerRNA *ptr, float value)
1142 {
1143   uiLayoutSetUnitsY(ptr->data, value);
1144 }
1145 
rna_UILayout_emboss_get(PointerRNA * ptr)1146 static int rna_UILayout_emboss_get(PointerRNA *ptr)
1147 {
1148   return uiLayoutGetEmboss(ptr->data);
1149 }
1150 
rna_UILayout_emboss_set(PointerRNA * ptr,int value)1151 static void rna_UILayout_emboss_set(PointerRNA *ptr, int value)
1152 {
1153   uiLayoutSetEmboss(ptr->data, value);
1154 }
1155 
rna_UILayout_property_split_get(PointerRNA * ptr)1156 static bool rna_UILayout_property_split_get(PointerRNA *ptr)
1157 {
1158   return uiLayoutGetPropSep(ptr->data);
1159 }
1160 
rna_UILayout_property_split_set(PointerRNA * ptr,bool value)1161 static void rna_UILayout_property_split_set(PointerRNA *ptr, bool value)
1162 {
1163   uiLayoutSetPropSep(ptr->data, value);
1164 }
1165 
rna_UILayout_property_decorate_get(PointerRNA * ptr)1166 static bool rna_UILayout_property_decorate_get(PointerRNA *ptr)
1167 {
1168   return uiLayoutGetPropDecorate(ptr->data);
1169 }
1170 
rna_UILayout_property_decorate_set(PointerRNA * ptr,bool value)1171 static void rna_UILayout_property_decorate_set(PointerRNA *ptr, bool value)
1172 {
1173   uiLayoutSetPropDecorate(ptr->data, value);
1174 }
1175 
1176 #else /* RNA_RUNTIME */
1177 
rna_def_ui_layout(BlenderRNA * brna)1178 static void rna_def_ui_layout(BlenderRNA *brna)
1179 {
1180   StructRNA *srna;
1181   PropertyRNA *prop;
1182 
1183   static const EnumPropertyItem alignment_items[] = {
1184       {UI_LAYOUT_ALIGN_EXPAND, "EXPAND", 0, "Expand", ""},
1185       {UI_LAYOUT_ALIGN_LEFT, "LEFT", 0, "Left", ""},
1186       {UI_LAYOUT_ALIGN_CENTER, "CENTER", 0, "Center", ""},
1187       {UI_LAYOUT_ALIGN_RIGHT, "RIGHT", 0, "Right", ""},
1188       {0, NULL, 0, NULL, NULL},
1189   };
1190 
1191   static const EnumPropertyItem direction_items[] = {
1192       {UI_LAYOUT_HORIZONTAL, "HORIZONTAL", 0, "Horizontal", ""},
1193       {UI_LAYOUT_VERTICAL, "VERTICAL", 0, "Vertical", ""},
1194       {0, NULL, 0, NULL, NULL},
1195   };
1196 
1197   static const EnumPropertyItem emboss_items[] = {
1198       {UI_EMBOSS, "NORMAL", 0, "Regular", "Draw standard button emboss style"},
1199       {UI_EMBOSS_NONE, "NONE", 0, "None", "Draw only text and icons"},
1200       {UI_EMBOSS_PULLDOWN, "PULLDOWN_MENU", 0, "Pulldown Menu", "Draw pulldown menu style"},
1201       {UI_EMBOSS_RADIAL, "RADIAL_MENU", 0, "Radial Menu", "Draw radial menu style"},
1202       {0, NULL, 0, NULL, NULL},
1203   };
1204 
1205   /* layout */
1206 
1207   srna = RNA_def_struct(brna, "UILayout", NULL);
1208   RNA_def_struct_sdna(srna, "uiLayout");
1209   RNA_def_struct_ui_text(srna, "UI Layout", "User interface layout in a panel or header");
1210 
1211   prop = RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE);
1212   RNA_def_property_boolean_funcs(prop, "rna_UILayout_active_get", "rna_UILayout_active_set");
1213 
1214   prop = RNA_def_property(srna, "active_default", PROP_BOOLEAN, PROP_NONE);
1215   RNA_def_property_boolean_funcs(
1216       prop, "rna_UILayout_active_default_get", "rna_UILayout_active_default_set");
1217   RNA_def_property_ui_text(
1218       prop,
1219       "Active Default",
1220       "When true, an operator button defined after this will be activated when pressing return"
1221       "(use with popup dialogs)");
1222 
1223   prop = RNA_def_property(srna, "activate_init", PROP_BOOLEAN, PROP_NONE);
1224   RNA_def_property_boolean_funcs(
1225       prop, "rna_UILayout_activate_init_get", "rna_UILayout_activate_init_set");
1226   RNA_def_property_ui_text(
1227       prop,
1228       "Activate on Init",
1229       "When true, buttons defined in popups will be activated on first display "
1230       "(use so you can type into a field without having to click on it first)");
1231 
1232   prop = RNA_def_property(srna, "operator_context", PROP_ENUM, PROP_NONE);
1233   RNA_def_property_enum_items(prop, rna_enum_operator_context_items);
1234   RNA_def_property_enum_funcs(
1235       prop, "rna_UILayout_op_context_get", "rna_UILayout_op_context_set", NULL);
1236 
1237   prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
1238   RNA_def_property_boolean_funcs(prop, "rna_UILayout_enabled_get", "rna_UILayout_enabled_set");
1239   RNA_def_property_ui_text(prop, "Enabled", "When false, this (sub)layout is grayed out");
1240 
1241   prop = RNA_def_property(srna, "alert", PROP_BOOLEAN, PROP_NONE);
1242   RNA_def_property_boolean_funcs(prop, "rna_UILayout_alert_get", "rna_UILayout_alert_set");
1243 
1244   prop = RNA_def_property(srna, "alignment", PROP_ENUM, PROP_NONE);
1245   RNA_def_property_enum_items(prop, alignment_items);
1246   RNA_def_property_enum_funcs(
1247       prop, "rna_UILayout_alignment_get", "rna_UILayout_alignment_set", NULL);
1248 
1249   prop = RNA_def_property(srna, "direction", PROP_ENUM, PROP_NONE);
1250   RNA_def_property_enum_items(prop, direction_items);
1251   RNA_def_property_enum_funcs(prop, "rna_UILayout_direction_get", NULL, NULL);
1252   RNA_def_property_clear_flag(prop, PROP_EDITABLE);
1253 
1254 #  if 0
1255   prop = RNA_def_property(srna, "keep_aspect", PROP_BOOLEAN, PROP_NONE);
1256   RNA_def_property_boolean_funcs(
1257       prop, "rna_UILayout_keep_aspect_get", "rna_UILayout_keep_aspect_set");
1258 #  endif
1259 
1260   prop = RNA_def_property(srna, "scale_x", PROP_FLOAT, PROP_UNSIGNED);
1261   RNA_def_property_float_funcs(prop, "rna_UILayout_scale_x_get", "rna_UILayout_scale_x_set", NULL);
1262   RNA_def_property_ui_text(
1263       prop, "Scale X", "Scale factor along the X for items in this (sub)layout");
1264 
1265   prop = RNA_def_property(srna, "scale_y", PROP_FLOAT, PROP_UNSIGNED);
1266   RNA_def_property_float_funcs(prop, "rna_UILayout_scale_y_get", "rna_UILayout_scale_y_set", NULL);
1267   RNA_def_property_ui_text(
1268       prop, "Scale Y", "Scale factor along the Y for items in this (sub)layout");
1269 
1270   prop = RNA_def_property(srna, "ui_units_x", PROP_FLOAT, PROP_UNSIGNED);
1271   RNA_def_property_float_funcs(prop, "rna_UILayout_units_x_get", "rna_UILayout_units_x_set", NULL);
1272   RNA_def_property_ui_text(
1273       prop, "Units X", "Fixed Size along the X for items in this (sub)layout");
1274 
1275   prop = RNA_def_property(srna, "ui_units_y", PROP_FLOAT, PROP_UNSIGNED);
1276   RNA_def_property_float_funcs(prop, "rna_UILayout_units_y_get", "rna_UILayout_units_y_set", NULL);
1277   RNA_def_property_ui_text(
1278       prop, "Units Y", "Fixed Size along the Y for items in this (sub)layout");
1279   RNA_api_ui_layout(srna);
1280 
1281   prop = RNA_def_property(srna, "emboss", PROP_ENUM, PROP_NONE);
1282   RNA_def_property_enum_items(prop, emboss_items);
1283   RNA_def_property_enum_funcs(prop, "rna_UILayout_emboss_get", "rna_UILayout_emboss_set", NULL);
1284 
1285   prop = RNA_def_property(srna, "use_property_split", PROP_BOOLEAN, PROP_NONE);
1286   RNA_def_property_boolean_funcs(
1287       prop, "rna_UILayout_property_split_get", "rna_UILayout_property_split_set");
1288 
1289   prop = RNA_def_property(srna, "use_property_decorate", PROP_BOOLEAN, PROP_NONE);
1290   RNA_def_property_boolean_funcs(
1291       prop, "rna_UILayout_property_decorate_get", "rna_UILayout_property_decorate_set");
1292 }
1293 
rna_def_panel(BlenderRNA * brna)1294 static void rna_def_panel(BlenderRNA *brna)
1295 {
1296   StructRNA *srna;
1297   PropertyRNA *prop;
1298   PropertyRNA *parm;
1299   FunctionRNA *func;
1300 
1301   static const EnumPropertyItem panel_flag_items[] = {
1302       {PNL_DEFAULT_CLOSED,
1303        "DEFAULT_CLOSED",
1304        0,
1305        "Default Closed",
1306        "Defines if the panel has to be open or collapsed at the time of its creation"},
1307       {PNL_NO_HEADER,
1308        "HIDE_HEADER",
1309        0,
1310        "Hide Header",
1311        "If set to False, the panel shows a header, which contains a clickable "
1312        "arrow to collapse the panel and the label (see bl_label)"},
1313       {PNL_INSTANCED,
1314        "INSTANCED",
1315        0,
1316        "Instanced Panel",
1317        "Multiple panels with this type can be used as part of a list depending on data external "
1318        "to the UI. Used to create panels for the modifiers and other stacks"},
1319       {PNL_LAYOUT_HEADER_EXPAND,
1320        "HEADER_LAYOUT_EXPAND",
1321        0,
1322        "Expand Header Layout",
1323        "Allow buttons in the header to stretch and shrink to fill the entire layout width"},
1324       {PNL_DRAW_BOX, "DRAW_BOX", 0, "Box Style", "Draw panel with the box widget theme"},
1325       {0, NULL, 0, NULL, NULL},
1326   };
1327 
1328   srna = RNA_def_struct(brna, "Panel", NULL);
1329   RNA_def_struct_ui_text(srna, "Panel", "Panel containing UI elements");
1330   RNA_def_struct_sdna(srna, "Panel");
1331   RNA_def_struct_refine_func(srna, "rna_Panel_refine");
1332   RNA_def_struct_register_funcs(srna, "rna_Panel_register", "rna_Panel_unregister", NULL);
1333   RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1334   RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
1335 
1336   /* poll */
1337   func = RNA_def_function(srna, "poll", NULL);
1338   RNA_def_function_ui_description(
1339       func, "If this method returns a non-null output, then the panel can be drawn");
1340   RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
1341   RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
1342   parm = RNA_def_pointer(func, "context", "Context", "", "");
1343   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1344 
1345   /* draw */
1346   func = RNA_def_function(srna, "draw", NULL);
1347   RNA_def_function_ui_description(func, "Draw UI elements into the panel UI layout");
1348   RNA_def_function_flag(func, FUNC_REGISTER);
1349   parm = RNA_def_pointer(func, "context", "Context", "", "");
1350   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1351 
1352   func = RNA_def_function(srna, "draw_header", NULL);
1353   RNA_def_function_ui_description(func, "Draw UI elements into the panel's header UI layout");
1354   RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1355   parm = RNA_def_pointer(func, "context", "Context", "", "");
1356   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1357 
1358   func = RNA_def_function(srna, "draw_header_preset", NULL);
1359   RNA_def_function_ui_description(func, "Draw UI elements for presets in the panel's header");
1360   RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1361   parm = RNA_def_pointer(func, "context", "Context", "", "");
1362   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1363 
1364   prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
1365   RNA_def_property_struct_type(prop, "UILayout");
1366   RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the panel in the UI");
1367 
1368   prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
1369   RNA_def_property_string_sdna(prop, NULL, "drawname");
1370   RNA_def_property_ui_text(prop, "Text", "XXX todo");
1371 
1372   prop = RNA_def_property(srna, "custom_data", PROP_POINTER, PROP_NONE);
1373   RNA_def_property_struct_type(prop, "Constraint");
1374   RNA_def_property_pointer_sdna(prop, NULL, "runtime.custom_data_ptr");
1375   RNA_def_property_pointer_funcs(
1376       prop, "rna_Panel_custom_data_get", NULL, "rna_Panel_custom_data_typef", NULL);
1377   RNA_def_property_ui_text(prop, "Custom Data", "Panel Data");
1378   RNA_def_property_clear_flag(prop, PROP_EDITABLE);
1379 
1380   /* registration */
1381   prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
1382   RNA_def_property_string_sdna(prop, NULL, "type->idname");
1383   RNA_def_property_flag(prop, PROP_REGISTER);
1384   RNA_def_property_ui_text(prop,
1385                            "ID Name",
1386                            "If this is set, the panel gets a custom ID, otherwise it takes the "
1387                            "name of the class used to define the panel. For example, if the "
1388                            "class name is \"OBJECT_PT_hello\", and bl_idname is not set by the "
1389                            "script, then bl_idname = \"OBJECT_PT_hello\"");
1390 
1391   prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
1392   RNA_def_property_string_sdna(prop, NULL, "type->label");
1393   RNA_def_property_flag(prop, PROP_REGISTER);
1394   RNA_def_property_ui_text(prop,
1395                            "Label",
1396                            "The panel label, shows up in the panel header at the right of the "
1397                            "triangle used to collapse the panel");
1398 
1399   prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
1400   RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
1401   RNA_def_property_string_default(prop, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1402   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1403   RNA_define_verify_sdna(true);
1404 
1405   prop = RNA_def_property(srna, "bl_category", PROP_STRING, PROP_NONE);
1406   RNA_def_property_string_sdna(prop, NULL, "type->category");
1407   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1408 
1409   prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
1410   RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
1411   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1412 
1413   prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
1414   RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
1415   RNA_def_property_enum_items(prop, rna_enum_space_type_items);
1416   RNA_def_property_flag(prop, PROP_REGISTER);
1417   RNA_def_property_ui_text(prop, "Space type", "The space where the panel is going to be used in");
1418 
1419   prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
1420   RNA_def_property_enum_sdna(prop, NULL, "type->region_type");
1421   RNA_def_property_enum_items(prop, rna_enum_region_type_items);
1422   RNA_def_property_flag(prop, PROP_REGISTER);
1423   RNA_def_property_ui_text(
1424       prop, "Region Type", "The region where the panel is going to be used in");
1425 
1426   prop = RNA_def_property(srna, "bl_context", PROP_STRING, PROP_NONE);
1427   RNA_def_property_string_sdna(prop, NULL, "type->context");
1428   RNA_def_property_flag(
1429       prop, PROP_REGISTER_OPTIONAL); /* Only used in Properties Editor and 3D View - Thomas */
1430   RNA_def_property_ui_text(prop,
1431                            "Context",
1432                            "The context in which the panel belongs to. (TODO: explain the "
1433                            "possible combinations bl_context/bl_region_type/bl_space_type)");
1434 
1435   prop = RNA_def_property(srna, "bl_options", PROP_ENUM, PROP_NONE);
1436   RNA_def_property_enum_sdna(prop, NULL, "type->flag");
1437   RNA_def_property_enum_items(prop, panel_flag_items);
1438   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
1439   RNA_def_property_ui_text(prop, "Options", "Options for this panel type");
1440 
1441   prop = RNA_def_property(srna, "bl_parent_id", PROP_STRING, PROP_NONE);
1442   RNA_def_property_string_sdna(prop, NULL, "type->parent_id");
1443   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1444   RNA_def_property_ui_text(
1445       prop, "Parent ID Name", "If this is set, the panel becomes a sub-panel");
1446 
1447   prop = RNA_def_property(srna, "bl_ui_units_x", PROP_INT, PROP_UNSIGNED);
1448   RNA_def_property_int_sdna(prop, NULL, "type->ui_units_x");
1449   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1450   RNA_def_property_ui_text(prop, "Units X", "When set, defines popup panel width");
1451 
1452   prop = RNA_def_property(srna, "bl_order", PROP_INT, PROP_UNSIGNED);
1453   RNA_def_property_int_sdna(prop, NULL, "type->order");
1454   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1455   RNA_def_property_ui_text(
1456       prop,
1457       "Order",
1458       "Panels with lower numbers are default ordered before panels with higher numbers");
1459 
1460   prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE);
1461   RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_PIN);
1462   RNA_def_property_ui_text(prop, "Pin", "Show the panel on all tabs");
1463   /* XXX, should only tag region for redraw */
1464   RNA_def_property_update(prop, NC_WINDOW, NULL);
1465 
1466   prop = RNA_def_property(srna, "is_popover", PROP_BOOLEAN, PROP_NONE);
1467   RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_POPOVER);
1468   RNA_def_property_clear_flag(prop, PROP_EDITABLE);
1469   RNA_def_property_ui_text(prop, "Popover", "");
1470 }
1471 
rna_def_uilist(BlenderRNA * brna)1472 static void rna_def_uilist(BlenderRNA *brna)
1473 {
1474   StructRNA *srna;
1475   PropertyRNA *prop;
1476   PropertyRNA *parm;
1477   FunctionRNA *func;
1478 
1479   srna = RNA_def_struct(brna, "UIList", NULL);
1480   RNA_def_struct_ui_text(srna, "UIList", "UI list containing the elements of a collection");
1481   RNA_def_struct_sdna(srna, "uiList");
1482   RNA_def_struct_refine_func(srna, "rna_UIList_refine");
1483   RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL);
1484   RNA_def_struct_idprops_func(srna, "rna_UIList_idprops");
1485   RNA_def_struct_flag(srna, STRUCT_NO_DATABLOCK_IDPROPERTIES | STRUCT_PUBLIC_NAMESPACE_INHERIT);
1486 
1487   /* Registration */
1488   prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
1489   RNA_def_property_string_sdna(prop, NULL, "type->idname");
1490   RNA_def_property_flag(prop, PROP_REGISTER);
1491   RNA_def_property_ui_text(prop,
1492                            "ID Name",
1493                            "If this is set, the uilist gets a custom ID, otherwise it takes the "
1494                            "name of the class used to define the uilist (for example, if the "
1495                            "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the "
1496                            "script, then bl_idname = \"OBJECT_UL_vgroups\")");
1497 
1498   /* Data */
1499   prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
1500   RNA_def_property_enum_items(prop, rna_enum_uilist_layout_type_items);
1501   RNA_def_property_clear_flag(prop, PROP_EDITABLE);
1502 
1503   /* Filter options */
1504   prop = RNA_def_property(srna, "use_filter_show", PROP_BOOLEAN, PROP_NONE);
1505   RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", UILST_FLT_SHOW);
1506   RNA_def_property_ui_text(prop, "Show Filter", "Show filtering options");
1507 
1508   prop = RNA_def_property(srna, "filter_name", PROP_STRING, PROP_NONE);
1509   RNA_def_property_string_sdna(prop, NULL, "filter_byname");
1510   RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
1511   RNA_def_property_ui_text(
1512       prop, "Filter by Name", "Only show items matching this name (use '*' as wildcard)");
1513 
1514   prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE);
1515   RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", UILST_FLT_EXCLUDE);
1516   RNA_def_property_ui_text(prop, "Invert", "Invert filtering (show hidden items, and vice-versa)");
1517 
1518   /* WARNING: This is sort of an abuse, sort-by-alpha is actually a value,
1519    * should even be an enum in full logic (of two values, sort by index and sort by name).
1520    * But for default UIList, it's nicer (better UI-wise) to show this as a boolean bit-flag option,
1521    * avoids having to define custom setters/getters using UILST_FLT_SORT_MASK to mask out
1522    * actual bitflags on same var, etc.
1523    */
1524   prop = RNA_def_property(srna, "use_filter_sort_alpha", PROP_BOOLEAN, PROP_NONE);
1525   RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_ALPHA);
1526   RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0);
1527   RNA_def_property_ui_text(prop, "Sort by Name", "Sort items by their name");
1528 
1529   prop = RNA_def_property(srna, "use_filter_sort_reverse", PROP_BOOLEAN, PROP_NONE);
1530   RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_REVERSE);
1531   RNA_def_property_ui_text(prop, "Reverse", "Reverse the order of shown items");
1532 
1533   prop = RNA_def_property(srna, "use_filter_sort_lock", PROP_BOOLEAN, PROP_NONE);
1534   RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_LOCK);
1535   RNA_def_property_ui_text(
1536       prop, "Lock Order", "Lock the order of shown items (user cannot change it)");
1537 
1538   /* draw_item */
1539   func = RNA_def_function(srna, "draw_item", NULL);
1540   RNA_def_function_ui_description(
1541       func,
1542       "Draw an item in the list (NOTE: when you define your own draw_item "
1543       "function, you may want to check given 'item' is of the right type...)");
1544   RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1545   parm = RNA_def_pointer(func, "context", "Context", "", "");
1546   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1547   parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
1548   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1549   parm = RNA_def_pointer(
1550       func, "data", "AnyType", "", "Data from which to take Collection property");
1551   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
1552   parm = RNA_def_pointer(func, "item", "AnyType", "", "Item of the collection property");
1553   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
1554   parm = RNA_def_int(
1555       func, "icon", 0, 0, INT_MAX, "", "Icon of the item in the collection", 0, INT_MAX);
1556   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1557   parm = RNA_def_pointer(func,
1558                          "active_data",
1559                          "AnyType",
1560                          "",
1561                          "Data from which to take property for the active element");
1562   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
1563   parm = RNA_def_string(func,
1564                         "active_property",
1565                         NULL,
1566                         0,
1567                         "",
1568                         "Identifier of property in active_data, for the active element");
1569   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1570   RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the item in the collection", 0, INT_MAX);
1571   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_PYFUNC_OPTIONAL);
1572   prop = RNA_def_property(func, "flt_flag", PROP_INT, PROP_UNSIGNED);
1573   RNA_def_property_ui_text(prop, "", "The filter-flag result for this item");
1574   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_PYFUNC_OPTIONAL);
1575 
1576   /* draw_filter */
1577   func = RNA_def_function(srna, "draw_filter", NULL);
1578   RNA_def_function_ui_description(func, "Draw filtering options");
1579   RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1580   parm = RNA_def_pointer(func, "context", "Context", "", "");
1581   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1582   parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
1583   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
1584 
1585   /* filter */
1586   func = RNA_def_function(srna, "filter_items", NULL);
1587   RNA_def_function_ui_description(
1588       func,
1589       "Filter and/or re-order items of the collection (output filter results in "
1590       "filter_flags, and reorder results in filter_neworder arrays)");
1591   RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL);
1592   parm = RNA_def_pointer(func, "context", "Context", "", "");
1593   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1594   parm = RNA_def_pointer(
1595       func, "data", "AnyType", "", "Data from which to take Collection property");
1596   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED | PARM_RNAPTR);
1597   parm = RNA_def_string(
1598       func, "property", NULL, 0, "", "Identifier of property in data, for the collection");
1599   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1600   prop = RNA_def_property(func, "filter_flags", PROP_INT, PROP_UNSIGNED);
1601   RNA_def_property_flag(prop, PARM_REQUIRED | PROP_DYNAMIC);
1602   RNA_def_property_array(prop, 1); /* XXX Dummy value, default 0 does not work */
1603   RNA_def_property_ui_text(
1604       prop,
1605       "",
1606       "An array of filter flags, one for each item in the collection (NOTE: "
1607       "FILTER_ITEM bit is reserved, it defines whether the item is shown or not)");
1608   RNA_def_function_output(func, prop);
1609   prop = RNA_def_property(func, "filter_neworder", PROP_INT, PROP_UNSIGNED);
1610   RNA_def_property_flag(prop, PARM_REQUIRED | PROP_DYNAMIC);
1611   RNA_def_property_array(prop, 1); /* XXX Dummy value, default 0 does not work */
1612   RNA_def_property_ui_text(
1613       prop,
1614       "",
1615       "An array of indices, one for each item in the collection, mapping the org "
1616       "index to the new one");
1617   RNA_def_function_output(func, prop);
1618 
1619   /* "Constants"! */
1620   RNA_define_verify_sdna(0); /* not in sdna */
1621 
1622   prop = RNA_def_property(srna, "bitflag_filter_item", PROP_INT, PROP_UNSIGNED);
1623   RNA_def_property_ui_text(
1624       prop,
1625       "FILTER_ITEM",
1626       "The value of the reserved bitflag 'FILTER_ITEM' (in filter_flags values)");
1627   RNA_def_property_int_funcs(prop, "rna_UIList_filter_const_FILTER_ITEM_get", NULL, NULL);
1628   RNA_def_property_clear_flag(prop, PROP_EDITABLE);
1629 }
1630 
rna_def_header(BlenderRNA * brna)1631 static void rna_def_header(BlenderRNA *brna)
1632 {
1633   StructRNA *srna;
1634   PropertyRNA *prop;
1635   PropertyRNA *parm;
1636   FunctionRNA *func;
1637 
1638   srna = RNA_def_struct(brna, "Header", NULL);
1639   RNA_def_struct_ui_text(srna, "Header", "Editor header containing UI elements");
1640   RNA_def_struct_sdna(srna, "Header");
1641   RNA_def_struct_refine_func(srna, "rna_Header_refine");
1642   RNA_def_struct_register_funcs(srna, "rna_Header_register", "rna_Header_unregister", NULL);
1643   RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
1644 
1645   /* draw */
1646   func = RNA_def_function(srna, "draw", NULL);
1647   RNA_def_function_ui_description(func, "Draw UI elements into the header UI layout");
1648   RNA_def_function_flag(func, FUNC_REGISTER);
1649   parm = RNA_def_pointer(func, "context", "Context", "", "");
1650   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1651 
1652   RNA_define_verify_sdna(0); /* not in sdna */
1653 
1654   prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
1655   RNA_def_property_pointer_sdna(prop, NULL, "layout");
1656   RNA_def_property_struct_type(prop, "UILayout");
1657   RNA_def_property_ui_text(prop, "Layout", "Structure of the header in the UI");
1658 
1659   /* registration */
1660   prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
1661   RNA_def_property_string_sdna(prop, NULL, "type->idname");
1662   RNA_def_property_flag(prop, PROP_REGISTER);
1663   RNA_def_property_ui_text(prop,
1664                            "ID Name",
1665                            "If this is set, the header gets a custom ID, otherwise it takes the "
1666                            "name of the class used to define the panel; for example, if the "
1667                            "class name is \"OBJECT_HT_hello\", and bl_idname is not set by the "
1668                            "script, then bl_idname = \"OBJECT_HT_hello\"");
1669 
1670   prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
1671   RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
1672   RNA_def_property_enum_items(prop, rna_enum_space_type_items);
1673   RNA_def_property_flag(prop, PROP_REGISTER);
1674   RNA_def_property_ui_text(
1675       prop, "Space type", "The space where the header is going to be used in");
1676 
1677   prop = RNA_def_property(srna, "bl_region_type", PROP_ENUM, PROP_NONE);
1678   RNA_def_property_enum_sdna(prop, NULL, "type->region_type");
1679   RNA_def_property_enum_default(prop, RGN_TYPE_HEADER);
1680   RNA_def_property_enum_items(prop, rna_enum_region_type_items);
1681   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1682   RNA_def_property_ui_text(prop,
1683                            "Region Type",
1684                            "The region where the header is going to be used in "
1685                            "(defaults to header region)");
1686 
1687   RNA_define_verify_sdna(1);
1688 }
1689 
rna_def_menu(BlenderRNA * brna)1690 static void rna_def_menu(BlenderRNA *brna)
1691 {
1692   StructRNA *srna;
1693   PropertyRNA *prop;
1694   PropertyRNA *parm;
1695   FunctionRNA *func;
1696 
1697   srna = RNA_def_struct(brna, "Menu", NULL);
1698   RNA_def_struct_ui_text(srna, "Menu", "Editor menu containing buttons");
1699   RNA_def_struct_sdna(srna, "Menu");
1700   RNA_def_struct_refine_func(srna, "rna_Menu_refine");
1701   RNA_def_struct_register_funcs(srna, "rna_Menu_register", "rna_Menu_unregister", NULL);
1702   RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1703   RNA_def_struct_flag(srna, STRUCT_PUBLIC_NAMESPACE_INHERIT);
1704 
1705   /* poll */
1706   func = RNA_def_function(srna, "poll", NULL);
1707   RNA_def_function_ui_description(
1708       func, "If this method returns a non-null output, then the menu can be drawn");
1709   RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
1710   RNA_def_function_return(func, RNA_def_boolean(func, "visible", 1, "", ""));
1711   parm = RNA_def_pointer(func, "context", "Context", "", "");
1712   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1713 
1714   /* draw */
1715   func = RNA_def_function(srna, "draw", NULL);
1716   RNA_def_function_ui_description(func, "Draw UI elements into the menu UI layout");
1717   RNA_def_function_flag(func, FUNC_REGISTER);
1718   parm = RNA_def_pointer(func, "context", "Context", "", "");
1719   RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
1720 
1721   RNA_define_verify_sdna(false); /* not in sdna */
1722 
1723   prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE);
1724   RNA_def_property_pointer_sdna(prop, NULL, "layout");
1725   RNA_def_property_struct_type(prop, "UILayout");
1726   RNA_def_property_ui_text(prop, "Layout", "Defines the structure of the menu in the UI");
1727 
1728   /* registration */
1729   prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
1730   RNA_def_property_string_sdna(prop, NULL, "type->idname");
1731   RNA_def_property_flag(prop, PROP_REGISTER);
1732   RNA_def_property_ui_text(prop,
1733                            "ID Name",
1734                            "If this is set, the menu gets a custom ID, otherwise it takes the "
1735                            "name of the class used to define the menu (for example, if the "
1736                            "class name is \"OBJECT_MT_hello\", and bl_idname is not set by the "
1737                            "script, then bl_idname = \"OBJECT_MT_hello\")");
1738 
1739   prop = RNA_def_property(srna, "bl_label", PROP_STRING, PROP_NONE);
1740   RNA_def_property_string_sdna(prop, NULL, "type->label");
1741   RNA_def_property_flag(prop, PROP_REGISTER);
1742   RNA_def_property_ui_text(prop, "Label", "The menu label");
1743 
1744   prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE);
1745   RNA_def_property_string_sdna(prop, NULL, "type->translation_context");
1746   RNA_def_property_string_default(prop, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
1747   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1748 
1749   prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE);
1750   RNA_def_property_string_sdna(prop, NULL, "type->description");
1751   RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */
1752   RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Menu_bl_description_set");
1753   /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */
1754   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1755   RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */
1756 
1757   prop = RNA_def_property(srna, "bl_owner_id", PROP_STRING, PROP_NONE);
1758   RNA_def_property_string_sdna(prop, NULL, "type->owner_id");
1759   RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
1760 
1761   RNA_define_verify_sdna(1);
1762 }
1763 
RNA_def_ui(BlenderRNA * brna)1764 void RNA_def_ui(BlenderRNA *brna)
1765 {
1766   rna_def_ui_layout(brna);
1767   rna_def_panel(brna);
1768   rna_def_uilist(brna);
1769   rna_def_header(brna);
1770   rna_def_menu(brna);
1771 }
1772 
1773 #endif /* RNA_RUNTIME */
1774