Blender  V2.93
outliner_edit.c
Go to the documentation of this file.
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  * The Original Code is Copyright (C) 2004 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <string.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_ID.h"
29 #include "DNA_anim_types.h"
30 #include "DNA_collection_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_scene_types.h"
33 
34 #include "BLI_blenlib.h"
35 #include "BLI_dynstr.h"
36 #include "BLI_path_util.h"
37 #include "BLI_utildefines.h"
38 
39 #include "BLT_translation.h"
40 
41 #include "BKE_animsys.h"
42 #include "BKE_appdir.h"
43 #include "BKE_armature.h"
44 #include "BKE_blender_copybuffer.h"
45 #include "BKE_context.h"
46 #include "BKE_idtype.h"
47 #include "BKE_lib_id.h"
48 #include "BKE_lib_query.h"
49 #include "BKE_lib_remap.h"
50 #include "BKE_main.h"
51 #include "BKE_report.h"
52 #include "BKE_workspace.h"
53 
54 #include "DEG_depsgraph.h"
55 #include "DEG_depsgraph_build.h"
56 
57 #include "ED_keyframing.h"
58 #include "ED_outliner.h"
59 #include "ED_screen.h"
60 #include "ED_select_utils.h"
61 
62 #include "WM_api.h"
63 #include "WM_types.h"
64 
65 #include "UI_interface.h"
66 #include "UI_view2d.h"
67 
68 #include "RNA_access.h"
69 #include "RNA_define.h"
70 #include "RNA_enum_types.h"
71 
72 #include "GPU_material.h"
73 
74 #include "outliner_intern.h"
75 
76 static void outliner_show_active(SpaceOutliner *space_outliner,
77  ARegion *region,
78  TreeElement *te,
79  ID *id);
80 
83 /* -------------------------------------------------------------------- */
87 static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
88 {
89  /* stop highlighting if out of area */
90  if (!ED_screen_area_active(C)) {
91  return OPERATOR_PASS_THROUGH;
92  }
93 
94  /* Drag and drop does own highlighting. */
96  if (wm->drags.first) {
97  return OPERATOR_PASS_THROUGH;
98  }
99 
100  ARegion *region = CTX_wm_region(C);
101  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
102 
103  float view_mval[2];
105  &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
106 
107  TreeElement *hovered_te = outliner_find_item_at_y(
108  space_outliner, &space_outliner->tree, view_mval[1]);
109 
110  TreeElement *icon_te = NULL;
111  bool is_over_icon = false;
112  if (hovered_te) {
114  space_outliner, hovered_te, view_mval[0], NULL, &is_over_icon);
115  }
116 
117  bool changed = false;
118 
119  if (!hovered_te || !is_over_icon || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED) ||
120  !(icon_te->store_elem->flag & TSE_HIGHLIGHTED_ICON)) {
121  /* Clear highlights when nothing is hovered or when a new item is hovered. */
122  changed = outliner_flag_set(&space_outliner->tree, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false);
123  if (hovered_te) {
124  hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
125  changed = true;
126  }
127  if (is_over_icon) {
128  icon_te->store_elem->flag |= TSE_HIGHLIGHTED_ICON;
129  changed = true;
130  }
131  }
132 
133  if (changed) {
135  }
136 
137  return OPERATOR_PASS_THROUGH;
138 }
139 
141 {
142  ot->name = "Update Highlight";
143  ot->idname = "OUTLINER_OT_highlight_update";
144  ot->description = "Update the item highlight based on the current mouse position";
145 
147 
149 }
150 
153 /* -------------------------------------------------------------------- */
157 /* Open or close a tree element, optionally toggling all children recursively */
159  TreeElement *te,
160  bool open,
161  bool toggle_all)
162 {
163  /* Prevent opening leaf elements in the tree unless in the Data API display mode because in that
164  * mode subtrees are empty unless expanded. */
165  if (space_outliner->outlinevis != SO_DATA_API && BLI_listbase_is_empty(&te->subtree)) {
166  return;
167  }
168 
169  /* Don't allow collapsing the scene collection. */
170  TreeStoreElem *tselem = TREESTORE(te);
171  if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
172  return;
173  }
174 
175  if (open) {
176  tselem->flag &= ~TSE_CLOSED;
177  }
178  else {
179  tselem->flag |= TSE_CLOSED;
180  }
181 
182  if (toggle_all) {
183  outliner_flag_set(&te->subtree, TSE_CLOSED, !open);
184  }
185 }
186 
187 typedef struct OpenCloseData {
189  bool open;
192 
194 {
195  ARegion *region = CTX_wm_region(C);
196  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
197 
198  float view_mval[2];
200  &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
201 
202  if (event->type == MOUSEMOVE) {
203  TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
204 
206 
207  /* Only openclose if mouse is not over the previously toggled element */
208  if (te && TREESTORE(te) != data->prev_tselem) {
209 
210  /* Only toggle openclose on the same level as the first clicked element */
211  if (te->xs == data->x_location) {
212  outliner_item_openclose(space_outliner, te, data->open, false);
213 
214  outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
215  }
216  }
217 
218  if (te) {
219  data->prev_tselem = TREESTORE(te);
220  }
221  else {
222  data->prev_tselem = NULL;
223  }
224  }
225  else if (event->val == KM_RELEASE) {
226  MEM_freeN(op->customdata);
227 
228  return OPERATOR_FINISHED;
229  }
230 
231  return OPERATOR_RUNNING_MODAL;
232 }
233 
235 {
236  ARegion *region = CTX_wm_region(C);
237  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
238 
239  const bool toggle_all = RNA_boolean_get(op->ptr, "all");
240 
241  float view_mval[2];
243  &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
244 
245  TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
246 
247  if (te && outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
248  TreeStoreElem *tselem = TREESTORE(te);
249 
250  const bool open = (tselem->flag & TSE_CLOSED) ||
251  (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1)));
252 
253  outliner_item_openclose(space_outliner, te, open, toggle_all);
254  outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
255 
256  /* Only toggle once for single click toggling */
257  if (event->type == LEFTMOUSE) {
258  return OPERATOR_FINISHED;
259  }
260 
261  /* Store last expanded tselem and x coordinate of disclosure triangle */
262  OpenCloseData *toggle_data = MEM_callocN(sizeof(OpenCloseData), "open_close_data");
263  toggle_data->prev_tselem = tselem;
264  toggle_data->open = open;
265  toggle_data->x_location = te->xs;
266 
267  /* Store the first clicked on element */
268  op->customdata = toggle_data;
269 
271  return OPERATOR_RUNNING_MODAL;
272  }
273 
275 }
276 
278 {
279  ot->name = "Open/Close";
280  ot->idname = "OUTLINER_OT_item_openclose";
281  ot->description = "Toggle whether item under cursor is enabled or closed";
282 
285 
287 
288  RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items");
289 }
290 
293 /* -------------------------------------------------------------------- */
297 static void do_item_rename(ARegion *region,
298  TreeElement *te,
299  TreeStoreElem *tselem,
300  ReportList *reports)
301 {
302  bool add_textbut = false;
303 
304  /* can't rename rna datablocks entries or listbases */
305  if (ELEM(tselem->type,
309  TSE_ID_BASE,
311  /* do nothing */
312  }
313  else if (ELEM(tselem->type,
315  TSE_NLA,
326  BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
327  }
328  else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
329  BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
330  }
331  else if (ID_IS_LINKED(tselem->id)) {
332  BKE_report(reports, RPT_WARNING, "Cannot edit external library data");
333  }
334  else if (ID_IS_OVERRIDE_LIBRARY(tselem->id)) {
335  BKE_report(reports, RPT_WARNING, "Cannot edit name of an override data-block");
336  }
339 
340  if (collection->flag & COLLECTION_IS_MASTER) {
341  BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
342  }
343  else {
344  add_textbut = true;
345  }
346  }
347  else if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
348  BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
349  }
350  else {
351  add_textbut = true;
352  }
353 
354  if (add_textbut) {
355  tselem->flag |= TSE_TEXTBUT;
356  ED_region_tag_redraw(region);
357  }
358 }
359 
361  ReportList *reports,
362  Scene *UNUSED(scene),
363  TreeElement *te,
364  TreeStoreElem *UNUSED(tsep),
365  TreeStoreElem *tselem,
366  void *UNUSED(user_data))
367 {
368  ARegion *region = CTX_wm_region(C);
369  do_item_rename(region, te, tselem, reports);
370 }
371 
373  ReportList *reports)
374 {
375  TreeElement *active_element = outliner_find_element_with_flag(&space_outliner->tree, TSE_ACTIVE);
376 
377  if (!active_element) {
378  BKE_report(reports, RPT_WARNING, "No active item to rename");
379  return NULL;
380  }
381 
382  return active_element;
383 }
384 
386  ARegion *region,
387  const wmEvent *event)
388 {
389  float fmval[2];
390  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
391 
392  TreeElement *hovered = outliner_find_item_at_y(space_outliner, &space_outliner->tree, fmval[1]);
393  if (hovered && outliner_item_is_co_over_name(hovered, fmval[0])) {
394  return hovered;
395  }
396 
397  return NULL;
398 }
399 
400 static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *event)
401 {
402  ARegion *region = CTX_wm_region(C);
403  View2D *v2d = &region->v2d;
404  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
405  const bool use_active = RNA_boolean_get(op->ptr, "use_active");
406 
407  TreeElement *te = use_active ? outliner_item_rename_find_active(space_outliner, op->reports) :
408  outliner_item_rename_find_hovered(space_outliner, region, event);
409  if (!te) {
410  return OPERATOR_CANCELLED;
411  }
412 
413  /* Force element into view. */
414  outliner_show_active(space_outliner, region, te, TREESTORE(te)->id);
415  int size_y = BLI_rcti_size_y(&v2d->mask) + 1;
416  int ytop = (te->ys + (size_y / 2));
417  int delta_y = ytop - v2d->cur.ymax;
418  outliner_scroll_view(space_outliner, region, delta_y);
419 
420  do_item_rename(region, te, TREESTORE(te), op->reports);
421 
422  return OPERATOR_FINISHED;
423 }
424 
426 {
427  ot->name = "Rename";
428  ot->idname = "OUTLINER_OT_item_rename";
429  ot->description = "Rename the active element";
430 
432 
434 
435  /* Flags. */
437 
439  "use_active",
440  false,
441  "Use Active",
442  "Rename the active item, rather than the one the mouse is over");
443 }
444 
447 /* -------------------------------------------------------------------- */
451 static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeStoreElem *tselem)
452 {
453  Main *bmain = CTX_data_main(C);
454  ID *id = tselem->id;
455 
456  BLI_assert(id != NULL);
457  BLI_assert(((tselem->type == TSE_SOME_ID) && (te->idcode != 0)) ||
458  (tselem->type == TSE_LAYER_COLLECTION));
459  UNUSED_VARS_NDEBUG(te);
460 
461  if (te->idcode == ID_LI && ((Library *)id)->parent != NULL) {
462  BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked library '%s'", id->name);
463  return;
464  }
465  if (id->tag & LIB_TAG_INDIRECT) {
466  BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked id '%s'", id->name);
467  return;
468  }
469  if (ID_REAL_USERS(id) <= 1 && BKE_library_ID_is_indirectly_used(bmain, id)) {
470  BKE_reportf(reports,
471  RPT_WARNING,
472  "Cannot delete id '%s', indirectly used data-blocks need at least one user",
473  id->name);
474  return;
475  }
476  if (te->idcode == ID_WS) {
478  if (id->tag & LIB_TAG_DOIT) {
479  BKE_reportf(
480  reports, RPT_WARNING, "Cannot delete currently visible workspace id '%s'", id->name);
481  return;
482  }
483  }
484 
485  BKE_id_delete(bmain, id);
486 
488 }
489 
491  ReportList *reports,
492  Scene *UNUSED(scene),
493  TreeElement *te,
494  TreeStoreElem *UNUSED(tsep),
495  TreeStoreElem *tselem,
496  void *UNUSED(user_data))
497 {
498  id_delete(C, reports, te, tselem);
499 }
500 
502  ReportList *reports,
503  TreeElement *te,
504  const float mval[2])
505 {
506  if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
507  TreeStoreElem *tselem = TREESTORE(te);
508 
509  if (te->idcode != 0 && tselem->id) {
510  if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
511  BKE_reportf(reports,
513  "Cannot delete indirectly linked library '%s'",
514  ((Library *)tselem->id)->filepath_abs);
515  return OPERATOR_CANCELLED;
516  }
517  id_delete(C, reports, te, tselem);
518  return OPERATOR_FINISHED;
519  }
520  }
521  else {
522  LISTBASE_FOREACH (TreeElement *, te_sub, &te->subtree) {
523  int ret;
524  if ((ret = outliner_id_delete_invoke_do(C, reports, te_sub, mval))) {
525  return ret;
526  }
527  }
528  }
529 
530  return 0;
531 }
532 
533 static int outliner_id_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
534 {
535  ARegion *region = CTX_wm_region(C);
536  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
537  float fmval[2];
538 
539  BLI_assert(region && space_outliner);
540 
541  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
542 
543  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
544  int ret;
545 
546  if ((ret = outliner_id_delete_invoke_do(C, op->reports, te, fmval))) {
547  return ret;
548  }
549  }
550 
551  return OPERATOR_CANCELLED;
552 }
553 
555 {
556  ot->name = "Delete Data-Block";
557  ot->idname = "OUTLINER_OT_id_delete";
558  ot->description = "Delete the ID under cursor";
559 
562 
563  /* Flags. */
565 }
566 
569 /* -------------------------------------------------------------------- */
574 {
575  Main *bmain = CTX_data_main(C);
576  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
577 
578  const short id_type = (short)RNA_enum_get(op->ptr, "id_type");
579  ID *old_id = BLI_findlink(which_libbase(CTX_data_main(C), id_type),
580  RNA_enum_get(op->ptr, "old_id"));
581  ID *new_id = BLI_findlink(which_libbase(CTX_data_main(C), id_type),
582  RNA_enum_get(op->ptr, "new_id"));
583 
584  /* check for invalid states */
585  if (space_outliner == NULL) {
586  return OPERATOR_CANCELLED;
587  }
588 
589  if (!(old_id && new_id && (old_id != new_id) && (GS(old_id->name) == GS(new_id->name)))) {
590  BKE_reportf(op->reports,
592  "Invalid old/new ID pair ('%s' / '%s')",
593  old_id ? old_id->name : "Invalid ID",
594  new_id ? new_id->name : "Invalid ID");
595  return OPERATOR_CANCELLED;
596  }
597 
598  if (ID_IS_LINKED(old_id)) {
599  BKE_reportf(op->reports,
600  RPT_WARNING,
601  "Old ID '%s' is linked from a library, indirect usages of this data-block will "
602  "not be remapped",
603  old_id->name);
604  }
605 
608 
610 
611  /* recreate dependency graph to include new objects */
613 
614  /* Free gpu materials, some materials depend on existing objects,
615  * such as lights so freeing correctly refreshes. */
616  GPU_materials_free(bmain);
617 
619 
620  return OPERATOR_FINISHED;
621 }
622 
624  wmOperator *op,
625  ListBase *tree,
626  const float y)
627 {
629  if (y > te->ys && y < te->ys + UI_UNIT_Y) {
630  TreeStoreElem *tselem = TREESTORE(te);
631 
632  if ((tselem->type == TSE_SOME_ID) && tselem->id) {
633  printf("found id %s (%p)!\n", tselem->id->name, tselem->id);
634 
635  RNA_enum_set(op->ptr, "id_type", GS(tselem->id->name));
636  RNA_enum_set_identifier(C, op->ptr, "new_id", tselem->id->name + 2);
637  RNA_enum_set_identifier(C, op->ptr, "old_id", tselem->id->name + 2);
638  return true;
639  }
640  }
642  return true;
643  }
644  }
645  return false;
646 }
647 
648 static int outliner_id_remap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
649 {
650  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
651  ARegion *region = CTX_wm_region(C);
652  float fmval[2];
653 
654  if (!RNA_property_is_set(op->ptr, RNA_struct_find_property(op->ptr, "id_type"))) {
655  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
656 
657  outliner_id_remap_find_tree_element(C, op, &space_outliner->tree, fmval[1]);
658  }
659 
660  return WM_operator_props_dialog_popup(C, op, 200);
661 }
662 
664  PointerRNA *ptr,
665  PropertyRNA *UNUSED(prop),
666  bool *r_free)
667 {
668  if (C == NULL) {
669  return DummyRNA_NULL_items;
670  }
671 
672  EnumPropertyItem item_tmp = {0}, *item = NULL;
673  int totitem = 0;
674  int i = 0;
675 
676  short id_type = (short)RNA_enum_get(ptr, "id_type");
677  ID *id = which_libbase(CTX_data_main(C), id_type)->first;
678 
679  for (; id; id = id->next) {
680  item_tmp.identifier = item_tmp.name = id->name + 2;
681  item_tmp.value = i++;
682  RNA_enum_item_add(&item, &totitem, &item_tmp);
683  }
684 
685  RNA_enum_item_end(&item, &totitem);
686  *r_free = true;
687 
688  return item;
689 }
690 
692 {
693  PropertyRNA *prop;
694 
695  /* identifiers */
696  ot->name = "Outliner ID Data Remap";
697  ot->idname = "OUTLINER_OT_id_remap";
698 
699  /* callbacks */
703 
704  /* Flags. */
706 
707  prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
709 
710  prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace");
713 
714  ot->prop = RNA_def_enum(ot->srna,
715  "new_id",
717  0,
718  "New ID",
719  "New ID to remap all selected IDs' users to");
722 }
723 
725  ReportList *UNUSED(reports),
726  Scene *UNUSED(scene),
727  TreeElement *UNUSED(te),
728  TreeStoreElem *UNUSED(tsep),
729  TreeStoreElem *tselem,
730  void *UNUSED(user_data))
731 {
732  wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_id_remap", false);
733  PointerRNA op_props;
734 
735  BLI_assert(tselem->id != NULL);
736 
738 
739  RNA_enum_set(&op_props, "id_type", GS(tselem->id->name));
740  RNA_enum_set_identifier(C, &op_props, "old_id", tselem->id->name + 2);
741 
743 
744  WM_operator_properties_free(&op_props);
745 }
746 
749 /* -------------------------------------------------------------------- */
753 static int outliner_id_copy_tag(SpaceOutliner *space_outliner, ListBase *tree)
754 {
755  int num_ids = 0;
756 
758  TreeStoreElem *tselem = TREESTORE(te);
759 
760  /* if item is selected and is an ID, tag it as needing to be copied. */
761  if (tselem->flag & TSE_SELECTED && ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) {
762  ID *id = tselem->id;
763  if (!(id->tag & LIB_TAG_DOIT)) {
764  BKE_copybuffer_tag_ID(tselem->id);
765  num_ids++;
766  }
767  }
768 
769  /* go over sub-tree */
770  num_ids += outliner_id_copy_tag(space_outliner, &te->subtree);
771  }
772 
773  return num_ids;
774 }
775 
777 {
778  Main *bmain = CTX_data_main(C);
779  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
780  char str[FILE_MAX];
781 
782  BKE_copybuffer_begin(bmain);
783 
784  const int num_ids = outliner_id_copy_tag(space_outliner, &space_outliner->tree);
785  if (num_ids == 0) {
786  BKE_report(op->reports, RPT_INFO, "No selected data-blocks to copy");
787  return OPERATOR_CANCELLED;
788  }
789 
790  BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
791  BKE_copybuffer_save(bmain, str, op->reports);
792 
793  BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-block(s)", num_ids);
794 
795  return OPERATOR_FINISHED;
796 }
797 
799 {
800  /* identifiers */
801  ot->name = "Outliner ID Data Copy";
802  ot->idname = "OUTLINER_OT_id_copy";
803  ot->description = "Selected data-blocks are copied to the clipboard";
804 
805  /* callbacks */
808 
809  /* Flags, don't need any undo here (this operator does not change anything in Blender data). */
810  ot->flag = 0;
811 }
812 
815 /* -------------------------------------------------------------------- */
820 {
821  char str[FILE_MAX];
822  const short flag = FILE_AUTOSELECT | FILE_ACTIVE_COLLECTION;
823 
824  BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
825 
826  const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, 0);
827  if (num_pasted == 0) {
828  BKE_report(op->reports, RPT_INFO, "No data to paste");
829  return OPERATOR_CANCELLED;
830  }
831 
833 
834  BKE_reportf(op->reports, RPT_INFO, "%d data-block(s) pasted", num_pasted);
835 
836  return OPERATOR_FINISHED;
837 }
838 
840 {
841  /* identifiers */
842  ot->name = "Outliner ID Data Paste";
843  ot->idname = "OUTLINER_OT_id_paste";
844  ot->description = "Data-blocks from the clipboard are pasted";
845 
846  /* callbacks */
849 
850  /* flags */
852 }
853 
856 /* -------------------------------------------------------------------- */
860 static int lib_relocate(
861  bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload)
862 {
863  PointerRNA op_props;
864  int ret = 0;
865 
866  BLI_assert(te->idcode == ID_LI && tselem->id != NULL);
867  UNUSED_VARS_NDEBUG(te);
868 
870 
871  RNA_string_set(&op_props, "library", tselem->id->name + 2);
872 
873  if (reload) {
874  Library *lib = (Library *)tselem->id;
875  char dir[FILE_MAXDIR], filename[FILE_MAX];
876 
877  BLI_split_dirfile(lib->filepath_abs, dir, filename, sizeof(dir), sizeof(filename));
878 
879  printf("%s, %s\n", tselem->id->name, lib->filepath_abs);
880 
881  /* We assume if both paths in lib are not the same then `lib->filepath` was relative. */
883  &op_props, "relative_path", BLI_path_cmp(lib->filepath_abs, lib->filepath) != 0);
884 
885  RNA_string_set(&op_props, "directory", dir);
886  RNA_string_set(&op_props, "filename", filename);
887 
889  }
890  else {
892  }
893 
894  WM_operator_properties_free(&op_props);
895 
896  return ret;
897 }
898 
900  bContext *C, ReportList *reports, TreeElement *te, const float mval[2], const bool reload)
901 {
902  if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
903  TreeStoreElem *tselem = TREESTORE(te);
904 
905  if (te->idcode == ID_LI && tselem->id) {
906  if (((Library *)tselem->id)->parent && !reload) {
907  BKE_reportf(reports,
909  "Cannot relocate indirectly linked library '%s'",
910  ((Library *)tselem->id)->filepath_abs);
911  return OPERATOR_CANCELLED;
912  }
913 
914  wmOperatorType *ot = WM_operatortype_find(reload ? "WM_OT_lib_reload" : "WM_OT_lib_relocate",
915  false);
916  return lib_relocate(C, te, tselem, ot, reload);
917  }
918  }
919  else {
920  LISTBASE_FOREACH (TreeElement *, te_sub, &te->subtree) {
921  int ret;
922  if ((ret = outliner_lib_relocate_invoke_do(C, reports, te_sub, mval, reload))) {
923  return ret;
924  }
925  }
926  }
927 
928  return 0;
929 }
930 
932 {
933  ARegion *region = CTX_wm_region(C);
934  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
935  float fmval[2];
936 
937  BLI_assert(region && space_outliner);
938 
939  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
940 
941  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
942  int ret;
943 
944  if ((ret = outliner_lib_relocate_invoke_do(C, op->reports, te, fmval, false))) {
945  return ret;
946  }
947  }
948 
949  return OPERATOR_CANCELLED;
950 }
951 
953 {
954  ot->name = "Relocate Library";
955  ot->idname = "OUTLINER_OT_lib_relocate";
956  ot->description = "Relocate the library under cursor";
957 
960 
961  /* Flags. */
963 }
964 
965 /* XXX This does not work with several items
966  * (it is only called once in the end, due to the 'deferred'
967  * filebrowser invocation through event system...). */
969  ReportList *UNUSED(reports),
970  Scene *UNUSED(scene),
971  TreeElement *te,
972  TreeStoreElem *UNUSED(tsep),
973  TreeStoreElem *tselem,
974  void *UNUSED(user_data))
975 {
976  wmOperatorType *ot = WM_operatortype_find("WM_OT_lib_relocate", false);
977 
978  lib_relocate(C, te, tselem, ot, false);
979 }
980 
981 static int outliner_lib_reload_invoke(bContext *C, wmOperator *op, const wmEvent *event)
982 {
983  ARegion *region = CTX_wm_region(C);
984  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
985  float fmval[2];
986 
987  BLI_assert(region && space_outliner);
988 
989  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
990 
991  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
992  int ret;
993 
994  if ((ret = outliner_lib_relocate_invoke_do(C, op->reports, te, fmval, true))) {
995  return ret;
996  }
997  }
998 
999  return OPERATOR_CANCELLED;
1000 }
1001 
1004 /* -------------------------------------------------------------------- */
1009 {
1010  ot->name = "Reload Library";
1011  ot->idname = "OUTLINER_OT_lib_reload";
1012  ot->description = "Reload the library under cursor";
1013 
1016 
1017  /* Flags. */
1019 }
1020 
1022  ReportList *UNUSED(reports),
1023  Scene *UNUSED(scene),
1024  TreeElement *te,
1025  TreeStoreElem *UNUSED(tsep),
1026  TreeStoreElem *tselem,
1027  void *UNUSED(user_data))
1028 {
1029  wmOperatorType *ot = WM_operatortype_find("WM_OT_lib_reload", false);
1030 
1031  lib_relocate(C, te, tselem, ot, true);
1032 }
1033 
1036 /* -------------------------------------------------------------------- */
1040 static int outliner_count_levels(ListBase *lb, const int curlevel)
1041 {
1042  int level = curlevel;
1043 
1044  LISTBASE_FOREACH (TreeElement *, te, lb) {
1045  int lev = outliner_count_levels(&te->subtree, curlevel + 1);
1046  if (lev > level) {
1047  level = lev;
1048  }
1049  }
1050  return level;
1051 }
1052 
1053 int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel)
1054 {
1055  LISTBASE_FOREACH (TreeElement *, te, lb) {
1056  TreeStoreElem *tselem = TREESTORE(te);
1057  if (tselem->flag & flag) {
1058  return curlevel;
1059  }
1060 
1061  int level = outliner_flag_is_any_test(&te->subtree, flag, curlevel + 1);
1062  if (level) {
1063  return level;
1064  }
1065  }
1066  return 0;
1067 }
1068 
1073 bool outliner_flag_set(ListBase *lb, short flag, short set)
1074 {
1075  bool changed = false;
1076 
1077  LISTBASE_FOREACH (TreeElement *, te, lb) {
1078  TreeStoreElem *tselem = TREESTORE(te);
1079  bool has_flag = (tselem->flag & flag);
1080  if (set == 0) {
1081  if (has_flag) {
1082  tselem->flag &= ~flag;
1083  changed = true;
1084  }
1085  }
1086  else if (!has_flag) {
1087  tselem->flag |= flag;
1088  changed = true;
1089  }
1090  changed |= outliner_flag_set(&te->subtree, flag, set);
1091  }
1092 
1093  return changed;
1094 }
1095 
1096 bool outliner_flag_flip(ListBase *lb, short flag)
1097 {
1098  bool changed = false;
1099 
1100  LISTBASE_FOREACH (TreeElement *, te, lb) {
1101  TreeStoreElem *tselem = TREESTORE(te);
1102  tselem->flag ^= flag;
1103  changed |= outliner_flag_flip(&te->subtree, flag);
1104  }
1105 
1106  return changed;
1107 }
1108 
1111 /* -------------------------------------------------------------------- */
1116 {
1117  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1118  ARegion *region = CTX_wm_region(C);
1119 
1120  if (outliner_flag_is_any_test(&space_outliner->tree, TSE_CLOSED, 1)) {
1121  outliner_flag_set(&space_outliner->tree, TSE_CLOSED, 0);
1122  }
1123  else {
1124  outliner_flag_set(&space_outliner->tree, TSE_CLOSED, 1);
1125  }
1126 
1127  ED_region_tag_redraw(region);
1128 
1129  return OPERATOR_FINISHED;
1130 }
1131 
1133 {
1134  /* identifiers */
1135  ot->name = "Expand/Collapse All";
1136  ot->idname = "OUTLINER_OT_expanded_toggle";
1137  ot->description = "Expand/Collapse all items";
1138 
1139  /* callbacks */
1142 
1143  /* no undo or registry, UI option */
1144 }
1145 
1148 /* -------------------------------------------------------------------- */
1153 {
1154  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1155  ARegion *region = CTX_wm_region(C);
1157  int action = RNA_enum_get(op->ptr, "action");
1158  if (action == SEL_TOGGLE) {
1159  action = outliner_flag_is_any_test(&space_outliner->tree, TSE_SELECTED, 1) ? SEL_DESELECT :
1160  SEL_SELECT;
1161  }
1162 
1163  switch (action) {
1164  case SEL_SELECT:
1165  outliner_flag_set(&space_outliner->tree, TSE_SELECTED, 1);
1166  break;
1167  case SEL_DESELECT:
1168  outliner_flag_set(&space_outliner->tree, TSE_SELECTED, 0);
1169  break;
1170  case SEL_INVERT:
1171  outliner_flag_flip(&space_outliner->tree, TSE_SELECTED);
1172  break;
1173  }
1174 
1175  ED_outliner_select_sync_from_outliner(C, space_outliner);
1176 
1180 
1181  return OPERATOR_FINISHED;
1182 }
1183 
1185 {
1186  /* identifiers */
1187  ot->name = "Toggle Selected";
1188  ot->idname = "OUTLINER_OT_select_all";
1189  ot->description = "Toggle the Outliner selection of items";
1190 
1191  /* callbacks */
1194 
1195  /* no undo or registry */
1196 
1197  /* rna */
1199 }
1200 
1203 /* -------------------------------------------------------------------- */
1208  TreeElement *te,
1209  int startx,
1210  int *starty)
1211 {
1212  TreeStoreElem *tselem = TREESTORE(te);
1213 
1214  /* store coord and continue, we need coordinates for elements outside view too */
1215  te->xs = (float)startx;
1216  te->ys = (float)(*starty);
1217  *starty -= UI_UNIT_Y;
1218 
1219  if (TSELEM_OPEN(tselem, space_outliner)) {
1220  LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
1221  outliner_set_coordinates_element_recursive(space_outliner, ten, startx + UI_UNIT_X, starty);
1222  }
1223  }
1224 }
1225 
1226 /* to retrieve coordinates with redrawing the entire tree */
1227 void outliner_set_coordinates(ARegion *region, SpaceOutliner *space_outliner)
1228 {
1229  int starty = (int)(region->v2d.tot.ymax) - UI_UNIT_Y;
1230 
1231  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
1232  outliner_set_coordinates_element_recursive(space_outliner, te, 0, &starty);
1233  }
1234 }
1235 
1236 /* return 1 when levels were opened */
1238 {
1239  TreeStoreElem *tselem;
1240  int retval = 0;
1241 
1242  for (te = te->parent; te; te = te->parent) {
1243  tselem = TREESTORE(te);
1244  if (tselem->flag & TSE_CLOSED) {
1245  tselem->flag &= ~TSE_CLOSED;
1246  retval = 1;
1247  }
1248  }
1249  return retval;
1250 }
1251 
1252 /* Return element representing the active base or bone in the outliner, or NULL if none exists */
1254  SpaceOutliner *space_outliner,
1255  ViewLayer *view_layer)
1256 {
1257  TreeElement *te;
1258 
1259  Object *obact = OBACT(view_layer);
1260 
1261  if (!obact) {
1262  return NULL;
1263  }
1264 
1265  te = outliner_find_id(space_outliner, &space_outliner->tree, &obact->id);
1266 
1267  if (te != NULL && obact->type == OB_ARMATURE) {
1268  /* traverse down the bone hierarchy in case of armature */
1269  TreeElement *te_obact = te;
1270 
1271  if (obact->mode & OB_MODE_POSE) {
1273  if (pchan) {
1274  te = outliner_find_posechannel(&te_obact->subtree, pchan);
1275  }
1276  }
1277  else if (obact->mode & OB_MODE_EDIT) {
1278  EditBone *ebone = CTX_data_active_bone(C);
1279  if (ebone) {
1280  te = outliner_find_editbone(&te_obact->subtree, ebone);
1281  }
1282  }
1283  }
1284 
1285  return te;
1286 }
1287 
1288 static void outliner_show_active(SpaceOutliner *space_outliner,
1289  ARegion *region,
1290  TreeElement *te,
1291  ID *id)
1292 {
1293  /* open up tree to active object/bone */
1294  if (TREESTORE(te)->id == id) {
1295  if (outliner_open_back(te)) {
1296  outliner_set_coordinates(region, space_outliner);
1297  }
1298  return;
1299  }
1300 
1301  LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
1302  outliner_show_active(space_outliner, region, ten, id);
1303  }
1304 }
1305 
1307 {
1308  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1309  ViewLayer *view_layer = CTX_data_view_layer(C);
1310  ARegion *region = CTX_wm_region(C);
1311  View2D *v2d = &region->v2d;
1312 
1313  TreeElement *active_element = outliner_show_active_get_element(C, space_outliner, view_layer);
1314 
1315  if (active_element) {
1316  ID *id = TREESTORE(active_element)->id;
1317 
1318  /* Expand all elements in the outliner with matching ID */
1319  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
1320  outliner_show_active(space_outliner, region, te, id);
1321  }
1322 
1323  /* Also open back from the active_element (only done for the first found occurrence of ID
1324  * though). */
1325  outliner_show_active(space_outliner, region, active_element, id);
1326 
1327  /* Center view on first element found */
1328  int size_y = BLI_rcti_size_y(&v2d->mask) + 1;
1329  int ytop = (active_element->ys + (size_y / 2));
1330  int delta_y = ytop - v2d->cur.ymax;
1331 
1332  outliner_scroll_view(space_outliner, region, delta_y);
1333  }
1334  else {
1335  return OPERATOR_CANCELLED;
1336  }
1337 
1339 
1340  return OPERATOR_FINISHED;
1341 }
1342 
1344 {
1345  /* identifiers */
1346  ot->name = "Show Active";
1347  ot->idname = "OUTLINER_OT_show_active";
1348  ot->description =
1349  "Open up the tree and adjust the view so that the active object is shown centered";
1350 
1351  /* callbacks */
1354 }
1355 
1358 /* -------------------------------------------------------------------- */
1363 {
1364  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1365  ARegion *region = CTX_wm_region(C);
1366  int size_y = BLI_rcti_size_y(&region->v2d.mask) + 1;
1367 
1368  bool up = RNA_boolean_get(op->ptr, "up");
1369 
1370  if (!up) {
1371  size_y = -size_y;
1372  }
1373 
1374  outliner_scroll_view(space_outliner, region, size_y);
1375 
1377 
1378  return OPERATOR_FINISHED;
1379 }
1380 
1382 {
1383  PropertyRNA *prop;
1384 
1385  /* identifiers */
1386  ot->name = "Scroll Page";
1387  ot->idname = "OUTLINER_OT_scroll_page";
1388  ot->description = "Scroll page up or down";
1389 
1390  /* callbacks */
1393 
1394  /* properties */
1395  prop = RNA_def_boolean(ot->srna, "up", 0, "Up", "Scroll up one page");
1397 }
1398 
1401 #if 0 /* TODO: probably obsolete now with filtering? */
1402 
1403 /* -------------------------------------------------------------------- */
1408 /* find next element that has this name */
1409 static TreeElement *outliner_find_name(
1410  SpaceOutliner *space_outliner, ListBase *lb, char *name, int flags, TreeElement *prev, int *prevFound)
1411 {
1412  TreeElement *te, *tes;
1413 
1414  for (te = lb->first; te; te = te->next) {
1415  int found = outliner_filter_has_name(te, name, flags);
1416 
1417  if (found) {
1418  /* name is right, but is element the previous one? */
1419  if (prev) {
1420  if ((te != prev) && (*prevFound)) {
1421  return te;
1422  }
1423  if (te == prev) {
1424  *prevFound = 1;
1425  }
1426  }
1427  else {
1428  return te;
1429  }
1430  }
1431 
1432  tes = outliner_find_name(space_outliner, &te->subtree, name, flags, prev, prevFound);
1433  if (tes) {
1434  return tes;
1435  }
1436  }
1437 
1438  /* nothing valid found */
1439  return NULL;
1440 }
1441 
1442 static void outliner_find_panel(
1443  Scene *UNUSED(scene), ARegion *region, SpaceOutliner *space_outliner, int again, int flags)
1444 {
1445  ReportList *reports = NULL; /* CTX_wm_reports(C); */
1446  TreeElement *te = NULL;
1447  TreeElement *last_find;
1448  TreeStoreElem *tselem;
1449  int ytop, xdelta, prevFound = 0;
1450  char name[sizeof(space_outliner->search_string)];
1451 
1452  /* get last found tree-element based on stored search_tse */
1453  last_find = outliner_find_tse(space_outliner, &space_outliner->search_tse);
1454 
1455  /* determine which type of search to do */
1456  if (again && last_find) {
1457  /* no popup panel - previous + user wanted to search for next after previous */
1458  BLI_strncpy(name, space_outliner->search_string, sizeof(name));
1459  flags = space_outliner->search_flags;
1460 
1461  /* try to find matching element */
1462  te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, last_find, &prevFound);
1463  if (te == NULL) {
1464  /* no more matches after previous, start from beginning again */
1465  prevFound = 1;
1466  te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, last_find, &prevFound);
1467  }
1468  }
1469  else {
1470  /* pop up panel - no previous, or user didn't want search after previous */
1471  name[0] = '\0';
1472  /* XXX if (sbutton(name, 0, sizeof(name) - 1, "Find: ") && name[0]) { */
1473  /* te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, NULL, &prevFound); */
1474  /* } */
1475  /* else return; XXX RETURN! XXX */
1476  }
1477 
1478  /* do selection and reveal */
1479  if (te) {
1480  tselem = TREESTORE(te);
1481  if (tselem) {
1482  /* expand branches so that it will be visible, we need to get correct coordinates */
1483  if (outliner_open_back(space_outliner, te)) {
1484  outliner_set_coordinates(region, space_outliner);
1485  }
1486 
1487  /* deselect all visible, and select found element */
1488  outliner_flag_set(space_outliner, &space_outliner->tree, TSE_SELECTED, 0);
1489  tselem->flag |= TSE_SELECTED;
1490 
1491  /* make te->ys center of view */
1492  ytop = (int)(te->ys + BLI_rctf_size_y(&region->v2d.mask) / 2);
1493  if (ytop > 0) {
1494  ytop = 0;
1495  }
1496  region->v2d.cur.ymax = (float)ytop;
1497  region->v2d.cur.ymin = (float)(ytop - BLI_rctf_size_y(&region->v2d.mask));
1498 
1499  /* make te->xs ==> te->xend center of view */
1500  xdelta = (int)(te->xs - region->v2d.cur.xmin);
1501  region->v2d.cur.xmin += xdelta;
1502  region->v2d.cur.xmax += xdelta;
1503 
1504  /* store selection */
1505  space_outliner->search_tse = *tselem;
1506 
1507  BLI_strncpy(space_outliner->search_string, name, sizeof(space_outliner->search_string));
1508  space_outliner->search_flags = flags;
1509 
1510  /* redraw */
1512  }
1513  }
1514  else {
1515  /* no tree-element found */
1516  BKE_reportf(reports, RPT_WARNING, "Not found: %s", name);
1517  }
1518 }
1519 
1522 #endif /* if 0 */
1523 
1524 /* -------------------------------------------------------------------- */
1528 /* helper function for Show/Hide one level operator */
1529 static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int open)
1530 {
1531  LISTBASE_FOREACH (TreeElement *, te, lb) {
1532  TreeStoreElem *tselem = TREESTORE(te);
1533 
1534  if (open) {
1535  if (curlevel <= level) {
1536  tselem->flag &= ~TSE_CLOSED;
1537  }
1538  }
1539  else {
1540  if (curlevel >= level) {
1541  tselem->flag |= TSE_CLOSED;
1542  }
1543  }
1544 
1545  outliner_openclose_level(&te->subtree, curlevel + 1, level, open);
1546  }
1547 }
1548 
1550 {
1551  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1552  ARegion *region = CTX_wm_region(C);
1553  const bool add = RNA_boolean_get(op->ptr, "open");
1554  int level;
1555 
1556  level = outliner_flag_is_any_test(&space_outliner->tree, TSE_CLOSED, 1);
1557  if (add == 1) {
1558  if (level) {
1559  outliner_openclose_level(&space_outliner->tree, 1, level, 1);
1560  }
1561  }
1562  else {
1563  if (level == 0) {
1564  level = outliner_count_levels(&space_outliner->tree, 0);
1565  }
1566  if (level) {
1567  outliner_openclose_level(&space_outliner->tree, 1, level - 1, 0);
1568  }
1569  }
1570 
1571  ED_region_tag_redraw(region);
1572 
1573  return OPERATOR_FINISHED;
1574 }
1575 
1577 {
1578  PropertyRNA *prop;
1579 
1580  /* identifiers */
1581  ot->name = "Show/Hide One Level";
1582  ot->idname = "OUTLINER_OT_show_one_level";
1583  ot->description = "Expand/collapse all entries by one level";
1584 
1585  /* callbacks */
1588 
1589  /* no undo or registry, UI option */
1590 
1591  /* properties */
1592  prop = RNA_def_boolean(ot->srna, "open", 1, "Open", "Expand all entries one level deep");
1594 }
1595 
1598 /* -------------------------------------------------------------------- */
1602 /* Helper function for tree_element_shwo_hierarchy() -
1603  * recursively checks whether subtrees have any objects. */
1605 {
1606  LISTBASE_FOREACH (TreeElement *, te, lb) {
1607  TreeStoreElem *tselem = TREESTORE(te);
1608  if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
1609  return 1;
1610  }
1611  if (subtree_has_objects(&te->subtree)) {
1612  return 1;
1613  }
1614  }
1615  return 0;
1616 }
1617 
1618 /* recursive helper function for Show Hierarchy operator */
1619 static void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *space_outliner, ListBase *lb)
1620 {
1621  /* open all object elems, close others */
1622  LISTBASE_FOREACH (TreeElement *, te, lb) {
1623  TreeStoreElem *tselem = TREESTORE(te);
1624 
1625  if (ELEM(tselem->type,
1626  TSE_SOME_ID,
1630  if (te->idcode == ID_SCE) {
1631  if (tselem->id != (ID *)scene) {
1632  tselem->flag |= TSE_CLOSED;
1633  }
1634  else {
1635  tselem->flag &= ~TSE_CLOSED;
1636  }
1637  }
1638  else if (te->idcode == ID_OB) {
1639  if (subtree_has_objects(&te->subtree)) {
1640  tselem->flag &= ~TSE_CLOSED;
1641  }
1642  else {
1643  tselem->flag |= TSE_CLOSED;
1644  }
1645  }
1646  }
1647  else {
1648  tselem->flag |= TSE_CLOSED;
1649  }
1650 
1651  if (TSELEM_OPEN(tselem, space_outliner)) {
1652  tree_element_show_hierarchy(scene, space_outliner, &te->subtree);
1653  }
1654  }
1655 }
1656 
1657 /* show entire object level hierarchy */
1659 {
1660  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1661  ARegion *region = CTX_wm_region(C);
1663 
1664  /* recursively open/close levels */
1665  tree_element_show_hierarchy(scene, space_outliner, &space_outliner->tree);
1666 
1667  ED_region_tag_redraw(region);
1668 
1669  return OPERATOR_FINISHED;
1670 }
1671 
1673 {
1674  /* identifiers */
1675  ot->name = "Show Hierarchy";
1676  ot->idname = "OUTLINER_OT_show_hierarchy";
1677  ot->description = "Open all object entries and close all others";
1678 
1679  /* callbacks */
1681  ot->poll = ED_operator_outliner_active; /* TODO: shouldn't be allowed in RNA views... */
1682 
1683  /* no undo or registry, UI option */
1684 }
1685 
1688 /* -------------------------------------------------------------------- */
1696 {
1697  ScrArea *area = CTX_wm_area(C);
1698  if ((area) && (area->spacetype == SPACE_OUTLINER)) {
1699  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1700  return (space_outliner->outlinevis == SO_DATA_API);
1701  }
1702  return 0;
1703 }
1704 
1705 /* Helper func to extract an RNA path from selected tree element
1706  * NOTE: the caller must zero-out all values of the pointers that it passes here first, as
1707  * this function does not do that yet
1708  */
1710  TreeStoreElem *tselem,
1711  ID **id,
1712  char **path,
1713  int *array_index,
1714  short *flag,
1715  short *UNUSED(groupmode))
1716 {
1717  ListBase hierarchy = {NULL, NULL};
1718  LinkData *ld;
1719  TreeElement *tem, *temnext;
1720  TreeStoreElem *tse /* , *tsenext */ /* UNUSED */;
1721  PointerRNA *ptr, *nextptr;
1722  PropertyRNA *prop;
1723  char *newpath = NULL;
1724 
1725  /* optimize tricks:
1726  * - Don't do anything if the selected item is a 'struct', but arrays are allowed
1727  */
1728  if (tselem->type == TSE_RNA_STRUCT) {
1729  return;
1730  }
1731 
1732  /* Overview of Algorithm:
1733  * 1. Go up the chain of parents until we find the 'root', taking note of the
1734  * levels encountered in reverse-order (i.e. items are added to the start of the list
1735  * for more convenient looping later)
1736  * 2. Walk down the chain, adding from the first ID encountered
1737  * (which will become the 'ID' for the KeyingSet Path), and build a
1738  * path as we step through the chain
1739  */
1740 
1741  /* step 1: flatten out hierarchy of parents into a flat chain */
1742  for (tem = te->parent; tem; tem = tem->parent) {
1743  ld = MEM_callocN(sizeof(LinkData), "LinkData for tree_element_to_path()");
1744  ld->data = tem;
1745  BLI_addhead(&hierarchy, ld);
1746  }
1747 
1748  /* step 2: step down hierarchy building the path
1749  * (NOTE: addhead in previous loop was needed so that we can loop like this) */
1750  for (ld = hierarchy.first; ld; ld = ld->next) {
1751  /* get data */
1752  tem = (TreeElement *)ld->data;
1753  tse = TREESTORE(tem);
1754  ptr = &tem->rnaptr;
1755  prop = tem->directdata;
1756 
1757  /* check if we're looking for first ID, or appending to path */
1758  if (*id) {
1759  /* just 'append' property to path
1760  * - to prevent memory leaks, we must write to newpath not path,
1761  * then free old path + swap them.
1762  */
1763  if (tse->type == TSE_RNA_PROPERTY) {
1764  if (RNA_property_type(prop) == PROP_POINTER) {
1765  /* for pointer we just append property name */
1766  newpath = RNA_path_append(*path, ptr, prop, 0, NULL);
1767  }
1768  else if (RNA_property_type(prop) == PROP_COLLECTION) {
1769  char buf[128], *name;
1770 
1771  temnext = (TreeElement *)(ld->next->data);
1772  /* tsenext = TREESTORE(temnext); */ /* UNUSED */
1773 
1774  nextptr = &temnext->rnaptr;
1775  name = RNA_struct_name_get_alloc(nextptr, buf, sizeof(buf), NULL);
1776 
1777  if (name) {
1778  /* if possible, use name as a key in the path */
1779  newpath = RNA_path_append(*path, NULL, prop, 0, name);
1780 
1781  if (name != buf) {
1782  MEM_freeN(name);
1783  }
1784  }
1785  else {
1786  /* otherwise use index */
1787  int index = 0;
1788 
1789  LISTBASE_FOREACH (TreeElement *, temsub, &tem->subtree) {
1790  if (temsub == temnext) {
1791  break;
1792  }
1793  }
1794  newpath = RNA_path_append(*path, NULL, prop, index, NULL);
1795  }
1796 
1797  ld = ld->next;
1798  }
1799  }
1800 
1801  if (newpath) {
1802  if (*path) {
1803  MEM_freeN(*path);
1804  }
1805  *path = newpath;
1806  newpath = NULL;
1807  }
1808  }
1809  else {
1810  /* no ID, so check if entry is RNA-struct,
1811  * and if that RNA-struct is an ID datablock to extract info from. */
1812  if (tse->type == TSE_RNA_STRUCT) {
1813  /* ptr->data not ptr->owner_id seems to be the one we want,
1814  * since ptr->data is sometimes the owner of this ID? */
1815  if (RNA_struct_is_ID(ptr->type)) {
1816  *id = ptr->data;
1817 
1818  /* clear path */
1819  if (*path) {
1820  MEM_freeN(*path);
1821  path = NULL;
1822  }
1823  }
1824  }
1825  }
1826  }
1827 
1828  /* step 3: if we've got an ID, add the current item to the path */
1829  if (*id) {
1830  /* add the active property to the path */
1831  ptr = &te->rnaptr;
1832  prop = te->directdata;
1833 
1834  /* array checks */
1835  if (tselem->type == TSE_RNA_ARRAY_ELEM) {
1836  /* item is part of an array, so must set the array_index */
1837  *array_index = te->index;
1838  }
1839  else if (RNA_property_array_check(prop)) {
1840  /* entire array was selected, so keyframe all */
1841  *flag |= KSP_FLAG_WHOLE_ARRAY;
1842  }
1843 
1844  /* path */
1845  newpath = RNA_path_append(*path, NULL, prop, 0, NULL);
1846  if (*path) {
1847  MEM_freeN(*path);
1848  }
1849  *path = newpath;
1850  }
1851 
1852  /* free temp data */
1853  BLI_freelistN(&hierarchy);
1854 }
1855 
1858 /* -------------------------------------------------------------------- */
1868 enum {
1871 } /*eDrivers_EditModes*/;
1872 
1873 /* Recursively iterate over tree, finding and working on selected items */
1874 static void do_outliner_drivers_editop(SpaceOutliner *space_outliner,
1875  ListBase *tree,
1876  ReportList *reports,
1877  short mode)
1878 {
1879  LISTBASE_FOREACH (TreeElement *, te, tree) {
1880  TreeStoreElem *tselem = TREESTORE(te);
1881 
1882  /* if item is selected, perform operation */
1883  if (tselem->flag & TSE_SELECTED) {
1884  ID *id = NULL;
1885  char *path = NULL;
1886  int array_index = 0;
1887  short flag = 0;
1888  short groupmode = KSP_GROUP_KSNAME;
1889 
1890  /* check if RNA-property described by this selected element is an animatable prop */
1891  if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) &&
1893  /* get id + path + index info from the selected element */
1894  tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
1895  }
1896 
1897  /* only if ID and path were set, should we perform any actions */
1898  if (id && path) {
1899  short dflags = CREATEDRIVER_WITH_DEFAULT_DVAR;
1900  int arraylen = 1;
1901 
1902  /* array checks */
1903  if (flag & KSP_FLAG_WHOLE_ARRAY) {
1904  /* entire array was selected, so add drivers for all */
1905  arraylen = RNA_property_array_length(&te->rnaptr, te->directdata);
1906  }
1907  else {
1908  arraylen = array_index;
1909  }
1910 
1911  /* we should do at least one step */
1912  if (arraylen == array_index) {
1913  arraylen++;
1914  }
1915 
1916  /* for each array element we should affect, add driver */
1917  for (; array_index < arraylen; array_index++) {
1918  /* action depends on mode */
1919  switch (mode) {
1920  case DRIVERS_EDITMODE_ADD: {
1921  /* add a new driver with the information obtained (only if valid) */
1922  ANIM_add_driver(reports, id, path, array_index, dflags, DRIVER_TYPE_PYTHON);
1923  break;
1924  }
1925  case DRIVERS_EDITMODE_REMOVE: {
1926  /* remove driver matching the information obtained (only if valid) */
1927  ANIM_remove_driver(reports, id, path, array_index, dflags);
1928  break;
1929  }
1930  }
1931  }
1932 
1933  /* free path, since it had to be generated */
1934  MEM_freeN(path);
1935  }
1936  }
1937 
1938  /* go over sub-tree */
1939  if (TSELEM_OPEN(tselem, space_outliner)) {
1940  do_outliner_drivers_editop(space_outliner, &te->subtree, reports, mode);
1941  }
1942  }
1943 }
1944 
1947 /* -------------------------------------------------------------------- */
1952 {
1953  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1954 
1955  /* check for invalid states */
1956  if (space_outliner == NULL) {
1957  return OPERATOR_CANCELLED;
1958  }
1959 
1960  /* recursively go into tree, adding selected items */
1962  space_outliner, &space_outliner->tree, op->reports, DRIVERS_EDITMODE_ADD);
1963 
1964  /* send notifiers */
1966 
1967  return OPERATOR_FINISHED;
1968 }
1969 
1971 {
1972  /* api callbacks */
1973  ot->idname = "OUTLINER_OT_drivers_add_selected";
1974  ot->name = "Add Drivers for Selected";
1975  ot->description = "Add drivers to selected items";
1976 
1977  /* api callbacks */
1980 
1981  /* flags */
1983 }
1984 
1987 /* -------------------------------------------------------------------- */
1992 {
1993  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1994 
1995  /* check for invalid states */
1996  if (space_outliner == NULL) {
1997  return OPERATOR_CANCELLED;
1998  }
1999 
2000  /* recursively go into tree, adding selected items */
2002  space_outliner, &space_outliner->tree, op->reports, DRIVERS_EDITMODE_REMOVE);
2003 
2004  /* send notifiers */
2005  WM_event_add_notifier(C, ND_KEYS, NULL); /* XXX */
2006 
2007  return OPERATOR_FINISHED;
2008 }
2009 
2011 {
2012  /* identifiers */
2013  ot->idname = "OUTLINER_OT_drivers_delete_selected";
2014  ot->name = "Delete Drivers for Selected";
2015  ot->description = "Delete drivers assigned to selected items";
2016 
2017  /* api callbacks */
2020 
2021  /* flags */
2023 }
2024 
2027 /* -------------------------------------------------------------------- */
2037 enum {
2040 } /*eKeyingSet_EditModes*/;
2041 
2042 /* Find the 'active' KeyingSet, and add if not found (if adding is allowed). */
2043 /* TODO: should this be an API func? */
2045 {
2046  KeyingSet *ks = NULL;
2047 
2048  /* sanity check */
2049  if (scene == NULL) {
2050  return NULL;
2051  }
2052 
2053  /* try to find one from scene */
2054  if (scene->active_keyingset > 0) {
2056  }
2057 
2058  /* Add if none found */
2059  /* XXX the default settings have yet to evolve. */
2060  if ((add) && (ks == NULL)) {
2063  }
2064 
2065  return ks;
2066 }
2067 
2068 /* Recursively iterate over tree, finding and working on selected items */
2069 static void do_outliner_keyingset_editop(SpaceOutliner *space_outliner,
2070  KeyingSet *ks,
2071  ListBase *tree,
2072  short mode)
2073 {
2074  LISTBASE_FOREACH (TreeElement *, te, tree) {
2075  TreeStoreElem *tselem = TREESTORE(te);
2076 
2077  /* if item is selected, perform operation */
2078  if (tselem->flag & TSE_SELECTED) {
2079  ID *id = NULL;
2080  char *path = NULL;
2081  int array_index = 0;
2082  short flag = 0;
2083  short groupmode = KSP_GROUP_KSNAME;
2084 
2085  /* check if RNA-property described by this selected element is an animatable prop */
2086  if (ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM) &&
2088  /* get id + path + index info from the selected element */
2089  tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
2090  }
2091 
2092  /* only if ID and path were set, should we perform any actions */
2093  if (id && path) {
2094  /* action depends on mode */
2095  switch (mode) {
2096  case KEYINGSET_EDITMODE_ADD: {
2097  /* add a new path with the information obtained (only if valid) */
2098  /* TODO: what do we do with group name?
2099  * for now, we don't supply one, and just let this use the KeyingSet name */
2100  BKE_keyingset_add_path(ks, id, NULL, path, array_index, flag, groupmode);
2101  ks->active_path = BLI_listbase_count(&ks->paths);
2102  break;
2103  }
2105  /* find the relevant path, then remove it from the KeyingSet */
2106  KS_Path *ksp = BKE_keyingset_find_path(ks, id, NULL, path, array_index, groupmode);
2107 
2108  if (ksp) {
2109  /* free path's data */
2110  BKE_keyingset_free_path(ks, ksp);
2111 
2112  ks->active_path = 0;
2113  }
2114  break;
2115  }
2116  }
2117 
2118  /* free path, since it had to be generated */
2119  MEM_freeN(path);
2120  }
2121  }
2122 
2123  /* go over sub-tree */
2124  if (TSELEM_OPEN(tselem, space_outliner)) {
2125  do_outliner_keyingset_editop(space_outliner, ks, &te->subtree, mode);
2126  }
2127  }
2128 }
2129 
2132 /* -------------------------------------------------------------------- */
2137 {
2138  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2141 
2142  /* check for invalid states */
2143  if (ks == NULL) {
2144  BKE_report(op->reports, RPT_ERROR, "Operation requires an active keying set");
2145  return OPERATOR_CANCELLED;
2146  }
2147  if (space_outliner == NULL) {
2148  return OPERATOR_CANCELLED;
2149  }
2150 
2151  /* recursively go into tree, adding selected items */
2152  do_outliner_keyingset_editop(space_outliner, ks, &space_outliner->tree, KEYINGSET_EDITMODE_ADD);
2153 
2154  /* send notifiers */
2156 
2157  return OPERATOR_FINISHED;
2158 }
2159 
2161 {
2162  /* identifiers */
2163  ot->idname = "OUTLINER_OT_keyingset_add_selected";
2164  ot->name = "Keying Set Add Selected";
2165  ot->description = "Add selected items (blue-gray rows) to active Keying Set";
2166 
2167  /* api callbacks */
2170 
2171  /* flags */
2173 }
2174 
2177 /* -------------------------------------------------------------------- */
2182 {
2183  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2186 
2187  /* check for invalid states */
2188  if (space_outliner == NULL) {
2189  return OPERATOR_CANCELLED;
2190  }
2191 
2192  /* recursively go into tree, adding selected items */
2194  space_outliner, ks, &space_outliner->tree, KEYINGSET_EDITMODE_REMOVE);
2195 
2196  /* send notifiers */
2198 
2199  return OPERATOR_FINISHED;
2200 }
2201 
2203 {
2204  /* identifiers */
2205  ot->idname = "OUTLINER_OT_keyingset_remove_selected";
2206  ot->name = "Keying Set Remove Selected";
2207  ot->description = "Remove selected items (blue-gray rows) from active Keying Set";
2208 
2209  /* api callbacks */
2212 
2213  /* flags */
2215 }
2216 
2219 /* -------------------------------------------------------------------- */
2224 {
2225  ScrArea *area = CTX_wm_area(C);
2226  if (area != NULL && area->spacetype == SPACE_OUTLINER) {
2227  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2228  return (space_outliner->outlinevis == SO_ID_ORPHANS);
2229  }
2230  return true;
2231 }
2232 
2236 {
2237  Main *bmain = CTX_data_main(C);
2238  int num_tagged[INDEX_ID_MAX] = {0};
2239 
2240  const bool do_local_ids = RNA_boolean_get(op->ptr, "do_local_ids");
2241  const bool do_linked_ids = RNA_boolean_get(op->ptr, "do_linked_ids");
2242  const bool do_recursive_cleanup = RNA_boolean_get(op->ptr, "do_recursive");
2243 
2244  /* Tag all IDs to delete. */
2246  bmain, LIB_TAG_DOIT, do_local_ids, do_linked_ids, do_recursive_cleanup, num_tagged);
2247 
2248  RNA_int_set(op->ptr, "num_deleted", num_tagged[INDEX_ID_NULL]);
2249 
2250  if (num_tagged[INDEX_ID_NULL] == 0) {
2251  BKE_report(op->reports, RPT_INFO, "No orphaned data-blocks to purge");
2252  return OPERATOR_CANCELLED;
2253  }
2254 
2255  DynStr *dyn_str = BLI_dynstr_new();
2256  BLI_dynstr_appendf(dyn_str, "Purging %d unused data-blocks (", num_tagged[INDEX_ID_NULL]);
2257  bool is_first = true;
2258  for (int i = 0; i < INDEX_ID_MAX - 2; i++) {
2259  if (num_tagged[i] != 0) {
2260  if (!is_first) {
2261  BLI_dynstr_append(dyn_str, ", ");
2262  }
2263  else {
2264  is_first = false;
2265  }
2266  BLI_dynstr_appendf(dyn_str,
2267  "%d %s",
2268  num_tagged[i],
2270  }
2271  }
2272  BLI_dynstr_append(dyn_str, TIP_("). Click here to proceed..."));
2273 
2274  char *message = BLI_dynstr_get_cstring(dyn_str);
2275  int ret = WM_operator_confirm_message(C, op, message);
2276 
2277  MEM_freeN(message);
2278  BLI_dynstr_free(dyn_str);
2279  return ret;
2280 }
2281 
2283 {
2284  Main *bmain = CTX_data_main(C);
2285  ScrArea *area = CTX_wm_area(C);
2286  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2287  int num_tagged[INDEX_ID_MAX] = {0};
2288 
2289  if ((num_tagged[INDEX_ID_NULL] = RNA_int_get(op->ptr, "num_deleted")) == 0) {
2290  const bool do_local_ids = RNA_boolean_get(op->ptr, "do_local_ids");
2291  const bool do_linked_ids = RNA_boolean_get(op->ptr, "do_linked_ids");
2292  const bool do_recursive_cleanup = RNA_boolean_get(op->ptr, "do_recursive");
2293 
2294  /* Tag all IDs to delete. */
2296  bmain, LIB_TAG_DOIT, do_local_ids, do_linked_ids, do_recursive_cleanup, num_tagged);
2297 
2298  if (num_tagged[INDEX_ID_NULL] == 0) {
2299  BKE_report(op->reports, RPT_INFO, "No orphaned data-blocks to purge");
2300  return OPERATOR_CANCELLED;
2301  }
2302  }
2303 
2305 
2306  BKE_reportf(op->reports, RPT_INFO, "Deleted %d data-block(s)", num_tagged[INDEX_ID_NULL]);
2307 
2308  /* XXX: tree management normally happens from draw_outliner(), but when
2309  * you're clicking to fast on Delete object from context menu in
2310  * outliner several mouse events can be handled in one cycle without
2311  * handling notifiers/redraw which leads to deleting the same object twice.
2312  * cleanup tree here to prevent such cases. */
2313  if ((area != NULL) && (area->spacetype == SPACE_OUTLINER)) {
2314  outliner_cleanup_tree(space_outliner);
2315  }
2316 
2317  DEG_relations_tag_update(bmain);
2319  /* Force full redraw of the UI. */
2321 
2322  return OPERATOR_FINISHED;
2323 }
2324 
2326 {
2327  /* identifiers */
2328  ot->idname = "OUTLINER_OT_orphans_purge";
2329  ot->name = "Purge All";
2330  ot->description = "Clear all orphaned data-blocks without any users from the file";
2331 
2332  /* callbacks */
2336 
2337  /* flags */
2339 
2340  /* properties */
2341  PropertyRNA *prop = RNA_def_int(ot->srna, "num_deleted", 0, 0, INT_MAX, "", "", 0, INT_MAX);
2343 
2345  "do_local_ids",
2346  true,
2347  "Local Data-blocks",
2348  "Include unused local data-blocks into deletion");
2350  "do_linked_ids",
2351  true,
2352  "Linked Data-blocks",
2353  "Include unused linked data-blocks into deletion");
2354 
2356  "do_recursive",
2357  false,
2358  "Recursive Delete",
2359  "Recursively check for indirectly unused data-blocks, ensuring that no orphaned "
2360  "data-blocks remain after execution");
2361 }
2362 
typedef float(TangentPoint)[2]
struct KS_Path * BKE_keyingset_add_path(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode)
Definition: anim_sys.c:178
struct KeyingSet * BKE_keyingset_add(struct ListBase *list, const char idname[], const char name[], short flag, short keyingflag)
Definition: anim_sys.c:144
struct KS_Path * BKE_keyingset_find_path(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode)
void BKE_keyingset_free_path(struct KeyingSet *ks, struct KS_Path *ksp)
Definition: anim_sys.c:242
const char * BKE_tempdir_base(void)
Definition: appdir.c:1182
bool BKE_copybuffer_save(struct Main *bmain_src, const char *filename, struct ReportList *reports)
int BKE_copybuffer_paste(struct bContext *C, const char *libname, const short flag, struct ReportList *reports, const uint64_t id_types_mask)
void BKE_copybuffer_begin(struct Main *bmain_src)
void BKE_copybuffer_tag_ID(struct ID *id)
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct SpaceOutliner * CTX_wm_space_outliner(const bContext *C)
Definition: context.c:836
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct EditBone * CTX_data_active_bone(const bContext *C)
Definition: context.c:1321
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct bPoseChannel * CTX_data_active_pose_bone(const bContext *C)
Definition: context.c:1351
const char * BKE_idtype_idcode_to_name_plural(const short idcode)
Definition: idtype.c:182
short BKE_idtype_idcode_from_index(const int index)
Definition: idtype.c:407
void BKE_main_lib_objects_recalc_all(struct Main *bmain)
Definition: lib_id.c:997
void BKE_id_delete(struct Main *bmain, void *idv) ATTR_NONNULL()
size_t BKE_id_multi_tagged_delete(struct Main *bmain) ATTR_NONNULL()
bool BKE_library_ID_is_indirectly_used(struct Main *bmain, void *idv)
Definition: lib_query.c:588
void BKE_lib_query_unused_ids_tag(struct Main *bmain, const int tag, const bool do_local_ids, const bool do_linked_ids, const bool do_tag_recursive, int *r_num_tagged)
Definition: lib_query.c:726
void void BKE_libblock_remap(struct Main *bmain, void *old_idv, void *new_idv, const short remap_flags) ATTR_NONNULL(1
@ ID_REMAP_SKIP_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:55
@ ID_REMAP_SKIP_INDIRECT_USAGE
Definition: BKE_lib_remap.h:46
struct ListBase * which_libbase(struct Main *bmain, short type)
Definition: main.c:447
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_workspace_id_tag_all_visible(struct Main *bmain, int tag) ATTR_NONNULL()
Definition: workspace.c:519
#define BLI_assert(a)
Definition: BLI_assert.h:58
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:71
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:358
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
char * BLI_dynstr_get_cstring(DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:323
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:107
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define FILE_MAX
void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1737
void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
Definition: path_util.c:1654
#define FILE_MAXDIR
#define BLI_path_cmp
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:165
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define ELEM(...)
#define BLT_I18NCONTEXT_ID_ID
#define TIP_(msgid)
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
ID and Library types, which are fundamental for sdna.
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
@ LIB_TAG_INDIRECT
Definition: DNA_ID.h:524
@ LIB_TAG_DOIT
Definition: DNA_ID.h:554
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:413
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:445
@ INDEX_ID_NULL
Definition: DNA_ID.h:858
@ INDEX_ID_MAX
Definition: DNA_ID.h:859
@ ID_LI
Definition: DNA_ID_enums.h:58
@ ID_WS
Definition: DNA_ID_enums.h:91
@ ID_SCE
Definition: DNA_ID_enums.h:57
@ ID_OB
Definition: DNA_ID_enums.h:59
@ KEYINGSET_ABSOLUTE
@ DRIVER_TYPE_PYTHON
@ KSP_GROUP_KSNAME
@ KSP_FLAG_WHOLE_ARRAY
Object groups, one object can be in many groups at once.
@ COLLECTION_IS_MASTER
@ OB_MODE_EDIT
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ TSE_CONSTRAINT_BASE
@ TSE_MODIFIER_BASE
@ TSE_SEQUENCE_DUP
@ TSE_RNA_ARRAY_ELEM
@ TSE_SEQUENCE
@ TSE_POSEGRP_BASE
@ TSE_VIEW_COLLECTION_BASE
@ TSE_ANIM_DATA
@ TSE_RNA_PROPERTY
@ TSE_LIBRARY_OVERRIDE_BASE
@ TSE_DEFGROUP_BASE
@ TSE_SCENE_COLLECTION_BASE
@ TSE_SCENE_OBJECTS_BASE
@ TSE_R_LAYER_BASE
@ TSE_LAYER_COLLECTION
@ TSE_SEQ_STRIP
@ TSE_NLA
@ TSE_ID_BASE
@ TSE_SOME_ID
@ TSE_DRIVER_BASE
@ TSE_RNA_STRUCT
@ TSE_POSE_BASE
@ TSE_HIGHLIGHTED_ANY
@ TSE_SELECTED
@ TSE_CLOSED
@ TSE_HIGHLIGHTED_ICON
@ TSE_HIGHLIGHTED
@ TSE_DRAG_ANY
@ TSE_ACTIVE
@ TSE_TEXTBUT
#define OBACT(_view_layer)
@ SPACE_OUTLINER
@ FILE_ACTIVE_COLLECTION
@ FILE_AUTOSELECT
@ SO_DATA_API
@ SO_ID_ORPHANS
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
@ RPT_ERROR_INVALID_INPUT
@ CREATEDRIVER_WITH_DEFAULT_DVAR
void ED_outliner_select_sync_from_outliner(struct bContext *C, struct SpaceOutliner *space_outliner)
void ED_region_tag_redraw_no_rebuild(struct ARegion *region)
Definition: area.c:686
bool ED_operator_outliner_active(struct bContext *C)
Definition: screen_ops.c:259
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:667
int ED_screen_area_active(const struct bContext *C)
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
void GPU_materials_free(struct Main *bmain)
Definition: gpu_material.c:805
Read Guarded memory(de)allocation.
@ PROP_POINTER
Definition: RNA_types.h:78
@ PROP_COLLECTION
Definition: RNA_types.h:79
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:279
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
@ PROP_HIDDEN
Definition: RNA_types.h:202
#define C
Definition: RandGen.cpp:39
#define UI_UNIT_Y
#define UI_UNIT_X
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
#define NC_WINDOW
Definition: WM_types.h:277
#define NC_ID
Definition: WM_types.h:296
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define NC_ANIMATION
Definition: WM_types.h:289
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:197
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:204
#define ND_OB_SELECT
Definition: WM_types.h:342
#define ND_KEYINGSET
Definition: WM_types.h:348
#define NC_SCENE
Definition: WM_types.h:279
#define ND_FCURVES_ORDER
Definition: WM_types.h:399
#define NA_REMOVED
Definition: WM_types.h:465
#define ND_KEYS
Definition: WM_types.h:364
#define KM_RELEASE
Definition: WM_types.h:243
Scene scene
void * user_data
bool ANIM_remove_driver(ReportList *UNUSED(reports), ID *id, const char rna_path[], int array_index, short UNUSED(flag))
Definition: drivers.c:552
int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
Definition: drivers.c:427
void * tree
DRWShaderLibrary * lib
#define str(s)
#define GS(x)
Definition: iris.c:241
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static void add(GHash *messages, MemArena *memarena, const Message *msg)
Definition: msgfmt.c:268
static void area(int d1, int d2, int e1, int e2, float weights[2])
Collection * outliner_collection_from_tree_element(const TreeElement *te)
bool outliner_is_collection_tree_element(const TreeElement *te)
static KeyingSet * verify_active_keyingset(Scene *scene, short add)
void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot)
static int outliner_open_back(TreeElement *te)
void OUTLINER_OT_show_active(wmOperatorType *ot)
static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *event)
static const EnumPropertyItem * outliner_id_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), bool *r_free)
static int outliner_one_level_exec(bContext *C, wmOperator *op)
void OUTLINER_OT_lib_reload(wmOperatorType *ot)
static void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *space_outliner, ListBase *lb)
static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op)
void id_remap_fn(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
void OUTLINER_OT_orphans_purge(wmOperatorType *ot)
static int outliner_count_levels(ListBase *lb, const int curlevel)
void OUTLINER_OT_id_remap(wmOperatorType *ot)
static int outliner_toggle_expanded_exec(bContext *C, wmOperator *UNUSED(op))
static int outliner_lib_reload_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool outliner_flag_flip(ListBase *lb, short flag)
static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int open)
static int outliner_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int outliner_show_hierarchy_exec(bContext *C, wmOperator *UNUSED(op))
static int outliner_scroll_page_exec(bContext *C, wmOperator *op)
static void tree_element_to_path(TreeElement *te, TreeStoreElem *tselem, ID **id, char **path, int *array_index, short *flag, short *UNUSED(groupmode))
void OUTLINER_OT_lib_relocate(wmOperatorType *ot)
static void do_item_rename(ARegion *region, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
void OUTLINER_OT_drivers_delete_selected(wmOperatorType *ot)
static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op)
static int outliner_id_paste_exec(bContext *C, wmOperator *op)
static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmEvent *event)
void OUTLINER_OT_id_paste(wmOperatorType *ot)
static TreeElement * outliner_show_active_get_element(bContext *C, SpaceOutliner *space_outliner, ViewLayer *view_layer)
void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot)
static int outliner_lib_relocate_invoke_do(bContext *C, ReportList *reports, TreeElement *te, const float mval[2], const bool reload)
static void do_outliner_keyingset_editop(SpaceOutliner *space_outliner, KeyingSet *ks, ListBase *tree, short mode)
static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
Definition: outliner_edit.c:87
static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool ed_operator_outliner_id_orphans_active(bContext *C)
struct OpenCloseData OpenCloseData
void OUTLINER_OT_item_rename(wmOperatorType *ot)
void OUTLINER_OT_scroll_page(wmOperatorType *ot)
void OUTLINER_OT_expanded_toggle(wmOperatorType *ot)
static int outliner_id_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static int subtree_has_objects(ListBase *lb)
@ DRIVERS_EDITMODE_ADD
@ DRIVERS_EDITMODE_REMOVE
static void outliner_set_coordinates_element_recursive(SpaceOutliner *space_outliner, TreeElement *te, int startx, int *starty)
void OUTLINER_OT_highlight_update(wmOperatorType *ot)
static bool outliner_id_remap_find_tree_element(bContext *C, wmOperator *op, ListBase *tree, const float y)
void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot)
static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeStoreElem *tselem)
void outliner_set_coordinates(ARegion *region, SpaceOutliner *space_outliner)
@ KEYINGSET_EDITMODE_ADD
@ KEYINGSET_EDITMODE_REMOVE
int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel)
static int lib_relocate(bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload)
void OUTLINER_OT_show_one_level(wmOperatorType *ot)
static int outliner_id_remap_exec(bContext *C, wmOperator *op)
void OUTLINER_OT_id_delete(wmOperatorType *ot)
static int outliner_orphans_purge_exec(bContext *C, wmOperator *op)
static int outliner_id_copy_exec(bContext *C, wmOperator *op)
static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
void OUTLINER_OT_select_all(wmOperatorType *ot)
void lib_reload_fn(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
void OUTLINER_OT_item_openclose(wmOperatorType *ot)
static int outliner_id_delete_invoke_do(bContext *C, ReportList *reports, TreeElement *te, const float mval[2])
static void do_outliner_drivers_editop(SpaceOutliner *space_outliner, ListBase *tree, ReportList *reports, short mode)
void id_delete_fn(bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
void item_rename_fn(bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *UNUSED(op))
static int outliner_id_copy_tag(SpaceOutliner *space_outliner, ListBase *tree)
void outliner_item_openclose(SpaceOutliner *space_outliner, TreeElement *te, bool open, bool toggle_all)
void lib_relocate_fn(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
static int outliner_id_remap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static TreeElement * outliner_item_rename_find_active(const SpaceOutliner *space_outliner, ReportList *reports)
static bool ed_operator_outliner_datablocks_active(bContext *C)
static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op)
void OUTLINER_OT_show_hierarchy(wmOperatorType *ot)
static int outliner_orphans_purge_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
bool outliner_flag_set(ListBase *lb, short flag, short set)
static void outliner_show_active(SpaceOutliner *space_outliner, ARegion *region, TreeElement *te, ID *id)
static TreeElement * outliner_item_rename_find_hovered(const SpaceOutliner *space_outliner, ARegion *region, const wmEvent *event)
void OUTLINER_OT_id_copy(wmOperatorType *ot)
static int outliner_select_all_exec(bContext *C, wmOperator *op)
TreeElement * outliner_find_editbone(ListBase *lb, const struct EditBone *ebone)
TreeElement * outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan)
TreeElement * outliner_find_element_with_flag(const ListBase *lb, short flag)
bool outliner_item_is_co_within_close_toggle(const TreeElement *te, float view_co_x)
bool outliner_item_is_co_over_name(const TreeElement *te, float view_co_x)
void outliner_scroll_view(struct SpaceOutliner *space_outliner, struct ARegion *region, int delta_y)
#define TREESTORE(a)
void outliner_cleanup_tree(struct SpaceOutliner *space_outliner)
TreeElement * outliner_find_item_at_y(const SpaceOutliner *space_outliner, const ListBase *tree, float view_co_y)
TreeElement * outliner_find_id(struct SpaceOutliner *space_outliner, ListBase *lb, const struct ID *id)
TreeElement * outliner_find_tse(struct SpaceOutliner *space_outliner, const TreeStoreElem *tse)
#define TSELEM_OPEN(telm, sv)
TreeElement * outliner_find_item_at_x_in_row(const SpaceOutliner *space_outliner, TreeElement *parent_te, float view_co_x, bool *r_is_merged_icon, bool *r_is_over_icon)
void outliner_tag_redraw_avoid_rebuild_on_open_change(const struct SpaceOutliner *space_outliner, struct ARegion *region)
static bool outliner_filter_has_name(TreeElement *te, const char *name, int flags)
return ret
const EnumPropertyItem rna_enum_id_type_items[]
Definition: rna_ID.c:46
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1223
bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2168
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:6550
bool RNA_struct_is_ID(const StructRNA *type)
Definition: rna_access.c:797
char * RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
Definition: rna_access.c:1049
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:6272
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:6655
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1155
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6319
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
char * RNA_path_append(const char *path, PointerRNA *UNUSED(ptr), PropertyRNA *prop, int intkey, const char *strkey)
Definition: rna_access.c:5529
void RNA_enum_set_identifier(bContext *C, PointerRNA *ptr, const char *name, const char *id)
Definition: rna_access.c:6425
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6308
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1218
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_enum_funcs_runtime(PropertyRNA *prop, EnumPropertyGetFunc getfunc, EnumPropertySetFunc setfunc, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3285
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4470
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4416
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
Definition: rna_define.c:2870
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3585
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:40
const char * identifier
Definition: RNA_types.h:446
const char * name
Definition: RNA_types.h:450
Definition: DNA_ID.h:273
int tag
Definition: DNA_ID.h:292
void * next
Definition: DNA_ID.h:274
char name[66]
Definition: DNA_ID.h:283
ListBase paths
void * data
Definition: DNA_listBase.h:42
struct LinkData * next
Definition: DNA_listBase.h:41
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
TreeStoreElem * prev_tselem
struct StructRNA * type
Definition: RNA_types.h:51
void * data
Definition: RNA_types.h:52
int active_keyingset
ListBase keyingsets
struct TreeStoreElem search_tse
char search_string[64]
struct TreeElement * parent
ListBase subtree
TreeStoreElem * store_elem
void * directdata
PointerRNA rnaptr
struct TreeElement * next
float xmax
Definition: DNA_vec_types.h:85
float xmin
Definition: DNA_vec_types.h:85
float ymax
Definition: DNA_vec_types.h:86
float ymin
Definition: DNA_vec_types.h:86
short val
Definition: WM_types.h:579
int mval[2]
Definition: WM_types.h:583
short type
Definition: WM_types.h:577
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, short context, PointerRNA *properties)
@ MOUSEMOVE
@ LEFTMOUSE
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
void WM_operator_properties_select_all(wmOperatorType *ot)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message)
void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
Definition: wm_operators.c:584
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width)
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:711