Blender  V3.3
outliner_edit.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2004 Blender Foundation. All rights reserved. */
3 
8 #include <cstring>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_ID.h"
13 #include "DNA_anim_types.h"
14 #include "DNA_collection_types.h"
15 #include "DNA_object_types.h"
16 #include "DNA_scene_types.h"
17 
18 #include "BLI_blenlib.h"
19 #include "BLI_dynstr.h"
20 #include "BLI_path_util.h"
21 #include "BLI_utildefines.h"
22 
23 #include "BLT_translation.h"
24 
25 #include "BKE_action.h"
26 #include "BKE_animsys.h"
27 #include "BKE_appdir.h"
28 #include "BKE_armature.h"
29 #include "BKE_blender_copybuffer.h"
30 #include "BKE_context.h"
31 #include "BKE_idtype.h"
32 #include "BKE_lib_id.h"
33 #include "BKE_lib_override.h"
34 #include "BKE_lib_query.h"
35 #include "BKE_lib_remap.h"
36 #include "BKE_main.h"
37 #include "BKE_object.h"
38 #include "BKE_report.h"
39 #include "BKE_workspace.h"
40 
41 #include "DEG_depsgraph.h"
42 #include "DEG_depsgraph_build.h"
43 
44 #include "ED_keyframing.h"
45 #include "ED_outliner.h"
46 #include "ED_screen.h"
47 #include "ED_select_utils.h"
48 
49 #include "WM_api.h"
50 #include "WM_types.h"
51 
52 #include "UI_interface.h"
53 #include "UI_view2d.h"
54 
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57 #include "RNA_enum_types.h"
58 #include "RNA_path.h"
59 
60 #include "GPU_material.h"
61 
62 #include "outliner_intern.hh"
63 #include "tree/tree_element_rna.hh"
64 #include "tree/tree_iterator.hh"
65 
66 using namespace blender::ed::outliner;
67 
68 static void outliner_show_active(SpaceOutliner *space_outliner,
69  ARegion *region,
70  TreeElement *te,
71  ID *id);
72 
73 /* -------------------------------------------------------------------- */
77 static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
78 {
79  /* stop highlighting if out of area */
80  if (!ED_screen_area_active(C)) {
81  return OPERATOR_PASS_THROUGH;
82  }
83 
84  /* Drag and drop does own highlighting. */
86  if (wm->drags.first) {
87  return OPERATOR_PASS_THROUGH;
88  }
89 
90  ARegion *region = CTX_wm_region(C);
91  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
92 
93  float view_mval[2];
95  &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
96 
98  space_outliner, &space_outliner->tree, view_mval[1]);
99 
100  TreeElement *icon_te = nullptr;
101  bool is_over_icon = false;
102  if (hovered_te) {
104  space_outliner, hovered_te, view_mval[0], nullptr, &is_over_icon);
105  }
106 
107  bool changed = false;
108 
109  if (!hovered_te || !is_over_icon || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED) ||
110  !(icon_te->store_elem->flag & TSE_HIGHLIGHTED_ICON)) {
111  /* Clear highlights when nothing is hovered or when a new item is hovered. */
112  changed = outliner_flag_set(*space_outliner, TSE_HIGHLIGHTED_ANY | TSE_DRAG_ANY, false);
113  if (hovered_te) {
114  hovered_te->store_elem->flag |= TSE_HIGHLIGHTED;
115  changed = true;
116  }
117  if (is_over_icon) {
118  icon_te->store_elem->flag |= TSE_HIGHLIGHTED_ICON;
119  changed = true;
120  }
121  }
122 
123  if (changed) {
125  }
126 
127  return OPERATOR_PASS_THROUGH;
128 }
129 
131 {
132  ot->name = "Update Highlight";
133  ot->idname = "OUTLINER_OT_highlight_update";
134  ot->description = "Update the item highlight based on the current mouse position";
135 
137 
139 }
140 
143 /* -------------------------------------------------------------------- */
147 void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all)
148 {
149  /* Only allow opening elements with children. */
151  return;
152  }
153 
154  /* Don't allow collapsing the scene collection. */
155  TreeStoreElem *tselem = TREESTORE(te);
156  if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
157  return;
158  }
159 
160  if (open) {
161  tselem->flag &= ~TSE_CLOSED;
162  }
163  else {
164  tselem->flag |= TSE_CLOSED;
165  }
166 
167  if (toggle_all) {
168  outliner_flag_set(te->subtree, TSE_CLOSED, !open);
169  }
170 }
171 
174  bool open;
176 };
177 
178 static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEvent *event)
179 {
180  ARegion *region = CTX_wm_region(C);
181  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
182 
183  float view_mval[2];
185  &region->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
186 
187  if (event->type == MOUSEMOVE) {
188  TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
189 
191 
192  /* Only openclose if mouse is not over the previously toggled element */
193  if (te && TREESTORE(te) != data->prev_tselem) {
194 
195  /* Only toggle openclose on the same level as the first clicked element */
196  if (te->xs == data->x_location) {
197  outliner_item_openclose(te, data->open, false);
198 
199  outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
200  }
201  }
202 
203  if (te) {
204  data->prev_tselem = TREESTORE(te);
205  }
206  else {
207  data->prev_tselem = nullptr;
208  }
209  }
210  else if (event->val == KM_RELEASE) {
211  MEM_freeN(op->customdata);
212 
213  return OPERATOR_FINISHED;
214  }
215 
216  return OPERATOR_RUNNING_MODAL;
217 }
218 
220 {
221  ARegion *region = CTX_wm_region(C);
222  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
223 
224  const bool toggle_all = RNA_boolean_get(op->ptr, "all");
225 
226  float view_mval[2];
227 
228  int mval[2];
229  WM_event_drag_start_mval(event, region, mval);
230 
231  UI_view2d_region_to_view(&region->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
232 
233  TreeElement *te = outliner_find_item_at_y(space_outliner, &space_outliner->tree, view_mval[1]);
234 
235  if (te && outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
236  TreeStoreElem *tselem = TREESTORE(te);
237 
238  const bool open = (tselem->flag & TSE_CLOSED) ||
239  (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1)));
240 
241  outliner_item_openclose(te, open, toggle_all);
242  outliner_tag_redraw_avoid_rebuild_on_open_change(space_outliner, region);
243 
244  /* Only toggle once for single click toggling */
245  if ((event->type == LEFTMOUSE) && (event->val != KM_CLICK_DRAG)) {
246  return OPERATOR_FINISHED;
247  }
248 
249  /* Store last expanded tselem and x coordinate of disclosure triangle */
250  OpenCloseData *toggle_data = MEM_cnew<OpenCloseData>("open_close_data");
251  toggle_data->prev_tselem = tselem;
252  toggle_data->open = open;
253  toggle_data->x_location = te->xs;
254 
255  /* Store the first clicked on element */
256  op->customdata = toggle_data;
257 
259  return OPERATOR_RUNNING_MODAL;
260  }
261 
263 }
264 
266 {
267  ot->name = "Open/Close";
268  ot->idname = "OUTLINER_OT_item_openclose";
269  ot->description = "Toggle whether item under cursor is enabled or closed";
270 
273 
275 
276  RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items");
277 }
278 
281 /* -------------------------------------------------------------------- */
285 static void do_item_rename(ARegion *region,
286  TreeElement *te,
287  TreeStoreElem *tselem,
288  ReportList *reports)
289 {
290  bool add_textbut = false;
291 
292  /* can't rename rna datablocks entries or listbases */
293  if (ELEM(tselem->type,
297  TSE_ID_BASE,
299  /* do nothing */
300  }
301  else if (ELEM(tselem->type,
303  TSE_NLA,
314  BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
315  }
316  else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
317  BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
318  }
319  else if (ID_IS_LINKED(tselem->id)) {
320  BKE_report(reports, RPT_WARNING, "Cannot edit external library data");
321  }
322  else if (ID_IS_OVERRIDE_LIBRARY(tselem->id)) {
323  BKE_report(reports, RPT_WARNING, "Cannot edit name of an override data-block");
324  }
327 
328  if (collection->flag & COLLECTION_IS_MASTER) {
329  BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
330  }
331  else {
332  add_textbut = true;
333  }
334  }
335  else if (te->idcode == ID_LI) {
336  if (reinterpret_cast<Library *>(tselem->id)->parent) {
337  BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
338  }
339  else {
340  BKE_report(
341  reports,
342  RPT_WARNING,
343  "Library path is not editable from here anymore, please use Relocate operation instead");
344  }
345  }
346  else {
347  add_textbut = true;
348  }
349 
350  if (add_textbut) {
351  tselem->flag |= TSE_TEXTBUT;
352  ED_region_tag_redraw(region);
353  }
354 }
355 
357  ReportList *reports,
358  Scene *UNUSED(scene),
359  TreeElement *te,
360  TreeStoreElem *UNUSED(tsep),
361  TreeStoreElem *tselem,
362  void *UNUSED(user_data))
363 {
364  ARegion *region = CTX_wm_region(C);
365  do_item_rename(region, te, tselem, reports);
366 }
367 
369  ReportList *reports)
370 {
371  TreeElement *active_element = outliner_find_element_with_flag(&space_outliner->tree, TSE_ACTIVE);
372 
373  if (!active_element) {
374  BKE_report(reports, RPT_WARNING, "No active item to rename");
375  return nullptr;
376  }
377 
378  return active_element;
379 }
380 
382  ARegion *region,
383  const wmEvent *event)
384 {
385  float fmval[2];
386  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
387 
388  TreeElement *hovered = outliner_find_item_at_y(space_outliner, &space_outliner->tree, fmval[1]);
389  if (hovered && outliner_item_is_co_over_name(hovered, fmval[0])) {
390  return hovered;
391  }
392 
393  return nullptr;
394 }
395 
396 static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *event)
397 {
398  ARegion *region = CTX_wm_region(C);
399  View2D *v2d = &region->v2d;
400  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
401  const bool use_active = RNA_boolean_get(op->ptr, "use_active");
402 
403  TreeElement *te = use_active ? outliner_item_rename_find_active(space_outliner, op->reports) :
404  outliner_item_rename_find_hovered(space_outliner, region, event);
405  if (!te) {
406  return OPERATOR_CANCELLED;
407  }
408 
409  /* Force element into view. */
410  outliner_show_active(space_outliner, region, te, TREESTORE(te)->id);
411  int size_y = BLI_rcti_size_y(&v2d->mask) + 1;
412  int ytop = (te->ys + (size_y / 2));
413  int delta_y = ytop - v2d->cur.ymax;
414  outliner_scroll_view(space_outliner, region, delta_y);
415 
416  do_item_rename(region, te, TREESTORE(te), op->reports);
417 
418  return OPERATOR_FINISHED;
419 }
420 
422 {
423  ot->name = "Rename";
424  ot->idname = "OUTLINER_OT_item_rename";
425  ot->description = "Rename the active element";
426 
428 
430 
431  /* Flags. */
433 
435  "use_active",
436  false,
437  "Use Active",
438  "Rename the active item, rather than the one the mouse is over");
439 }
440 
443 /* -------------------------------------------------------------------- */
447 static void id_delete_tag(bContext *C, ReportList *reports, TreeElement *te, TreeStoreElem *tselem)
448 {
449  Main *bmain = CTX_data_main(C);
450  ID *id = tselem->id;
451 
452  BLI_assert(id != nullptr);
453  BLI_assert(((tselem->type == TSE_SOME_ID) && (te->idcode != 0)) ||
454  (tselem->type == TSE_LAYER_COLLECTION));
455  UNUSED_VARS_NDEBUG(te);
456 
457  if (ID_IS_OVERRIDE_LIBRARY(id)) {
458  if (!ID_IS_OVERRIDE_LIBRARY_REAL(id) ||
460  BKE_reportf(reports,
461  RPT_WARNING,
462  "Cannot delete library override id '%s', it is part of an override hierarchy",
463  id->name);
464  return;
465  }
466  }
467 
468  if (te->idcode == ID_LI && ((Library *)id)->parent != nullptr) {
469  BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked library '%s'", id->name);
470  return;
471  }
472  if (id->tag & LIB_TAG_INDIRECT) {
473  BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked id '%s'", id->name);
474  return;
475  }
476  if (ID_REAL_USERS(id) <= 1 && BKE_library_ID_is_indirectly_used(bmain, id)) {
477  BKE_reportf(reports,
478  RPT_WARNING,
479  "Cannot delete id '%s', indirectly used data-blocks need at least one user",
480  id->name);
481  return;
482  }
483  if (te->idcode == ID_WS) {
485  if (id->tag & LIB_TAG_PRE_EXISTING) {
486  BKE_reportf(
487  reports, RPT_WARNING, "Cannot delete currently visible workspace id '%s'", id->name);
489  return;
490  }
492  }
493 
494  id->tag |= LIB_TAG_DOIT;
495 
496  WM_event_add_notifier(C, NC_WINDOW, nullptr);
497 }
498 
500  ReportList *reports,
501  Scene *UNUSED(scene),
502  TreeElement *te,
503  TreeStoreElem *UNUSED(tsep),
504  TreeStoreElem *tselem,
505  void *UNUSED(user_data))
506 {
507  id_delete_tag(C, reports, te, tselem);
508 }
509 
511  ReportList *reports,
512  TreeElement *te,
513  const float mval[2])
514 {
515  int id_tagged_num = 0;
516 
517  if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
518  TreeStoreElem *tselem = TREESTORE(te);
519 
520  if (te->idcode != 0 && tselem->id) {
521  if (te->idcode == ID_LI && ((Library *)tselem->id)->parent) {
522  BKE_reportf(reports,
524  "Cannot delete indirectly linked library '%s'",
525  ((Library *)tselem->id)->filepath_abs);
526  }
527  else {
528  id_delete_tag(C, reports, te, tselem);
529  id_tagged_num++;
530  }
531  }
532  }
533  else {
534  LISTBASE_FOREACH (TreeElement *, te_sub, &te->subtree) {
535  if ((id_tagged_num += outliner_id_delete_tag(C, reports, te_sub, mval)) != 0) {
536  break;
537  }
538  }
539  }
540 
541  return id_tagged_num;
542 }
543 
544 static int outliner_id_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event)
545 {
546  Main *bmain = CTX_data_main(C);
547  ARegion *region = CTX_wm_region(C);
548  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
549  float fmval[2];
550 
551  BLI_assert(region && space_outliner);
552 
553  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
554 
555  int id_tagged_num = 0;
556  BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
557  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
558  if ((id_tagged_num += outliner_id_delete_tag(C, op->reports, te, fmval)) != 0) {
559  break;
560  }
561  }
562  if (id_tagged_num == 0) {
563  BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
564  return OPERATOR_CANCELLED;
565  }
566 
568  BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
569  return OPERATOR_FINISHED;
570 }
571 
573 {
574  ot->name = "Delete Data-Block";
575  ot->idname = "OUTLINER_OT_id_delete";
576  ot->description = "Delete the ID under cursor";
577 
580 
581  /* Flags. */
583 }
584 
587 /* -------------------------------------------------------------------- */
592 {
593  Main *bmain = CTX_data_main(C);
594  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
595 
596  const short id_type = (short)RNA_enum_get(op->ptr, "id_type");
597  ID *old_id = reinterpret_cast<ID *>(
598  BLI_findlink(which_libbase(CTX_data_main(C), id_type), RNA_enum_get(op->ptr, "old_id")));
599  ID *new_id = reinterpret_cast<ID *>(
600  BLI_findlink(which_libbase(CTX_data_main(C), id_type), RNA_enum_get(op->ptr, "new_id")));
601 
602  /* check for invalid states */
603  if (space_outliner == nullptr) {
604  return OPERATOR_CANCELLED;
605  }
606 
607  if (!(old_id && new_id && (old_id != new_id) && (GS(old_id->name) == GS(new_id->name)))) {
608  BKE_reportf(op->reports,
610  "Invalid old/new ID pair ('%s' / '%s')",
611  old_id ? old_id->name : "Invalid ID",
612  new_id ? new_id->name : "Invalid ID");
613  return OPERATOR_CANCELLED;
614  }
615 
616  if (ID_IS_LINKED(old_id)) {
617  BKE_reportf(op->reports,
618  RPT_WARNING,
619  "Old ID '%s' is linked from a library, indirect usages of this data-block will "
620  "not be remapped",
621  old_id->name);
622  }
623 
626 
628 
629  /* recreate dependency graph to include new objects */
631 
632  /* Free gpu materials, some materials depend on existing objects,
633  * such as lights so freeing correctly refreshes. */
634  GPU_materials_free(bmain);
635 
636  WM_event_add_notifier(C, NC_WINDOW, nullptr);
637 
638  return OPERATOR_FINISHED;
639 }
640 
642  wmOperator *op,
643  ListBase *tree,
644  const float y)
645 {
647  if (y > te->ys && y < te->ys + UI_UNIT_Y) {
648  TreeStoreElem *tselem = TREESTORE(te);
649 
650  if ((tselem->type == TSE_SOME_ID) && tselem->id) {
651  RNA_enum_set(op->ptr, "id_type", GS(tselem->id->name));
652  RNA_enum_set_identifier(C, op->ptr, "new_id", tselem->id->name + 2);
653  RNA_enum_set_identifier(C, op->ptr, "old_id", tselem->id->name + 2);
654  return true;
655  }
656  }
658  return true;
659  }
660  }
661  return false;
662 }
663 
664 static int outliner_id_remap_invoke(bContext *C, wmOperator *op, const wmEvent *event)
665 {
666  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
667  ARegion *region = CTX_wm_region(C);
668  float fmval[2];
669 
670  if (!RNA_property_is_set(op->ptr, RNA_struct_find_property(op->ptr, "id_type"))) {
671  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
672 
673  outliner_id_remap_find_tree_element(C, op, &space_outliner->tree, fmval[1]);
674  }
675 
676  return WM_operator_props_dialog_popup(C, op, 400);
677 }
678 
680  PointerRNA *ptr,
681  PropertyRNA *UNUSED(prop),
682  bool *r_free)
683 {
684  if (C == nullptr) {
685  return DummyRNA_NULL_items;
686  }
687 
688  EnumPropertyItem item_tmp = {0}, *item = nullptr;
689  int totitem = 0;
690  int i = 0;
691 
692  short id_type = (short)RNA_enum_get(ptr, "id_type");
693  ID *id = reinterpret_cast<ID *>(which_libbase(CTX_data_main(C), id_type)->first);
694 
695  for (; id; id = reinterpret_cast<ID *>(id->next)) {
696  item_tmp.identifier = item_tmp.name = id->name + 2;
697  item_tmp.value = i++;
698  RNA_enum_item_add(&item, &totitem, &item_tmp);
699  }
700 
701  RNA_enum_item_end(&item, &totitem);
702  *r_free = true;
703 
704  return item;
705 }
706 
708 {
709  PropertyRNA *prop;
710 
711  /* identifiers */
712  ot->name = "Outliner ID Data Remap";
713  ot->idname = "OUTLINER_OT_id_remap";
714 
715  /* callbacks */
719 
720  /* Flags. */
722 
723  prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
725  /* Changing ID type wont make sense, would return early with "Invalid old/new ID pair" anyways.
726  */
728 
729  prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace");
732 
733  ot->prop = RNA_def_enum(ot->srna,
734  "new_id",
736  0,
737  "New ID",
738  "New ID to remap all selected IDs' users to");
741 }
742 
744  ReportList *UNUSED(reports),
745  Scene *UNUSED(scene),
746  TreeElement *UNUSED(te),
747  TreeStoreElem *UNUSED(tsep),
748  TreeStoreElem *tselem,
749  void *UNUSED(user_data))
750 {
751  wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_id_remap", false);
752  PointerRNA op_props;
753 
754  BLI_assert(tselem->id != nullptr);
755 
757 
758  RNA_enum_set(&op_props, "id_type", GS(tselem->id->name));
759  RNA_enum_set_identifier(C, &op_props, "old_id", tselem->id->name + 2);
760 
761  WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr);
762 
763  WM_operator_properties_free(&op_props);
764 }
765 
768 /* -------------------------------------------------------------------- */
772 static int outliner_id_copy_tag(SpaceOutliner *space_outliner, ListBase *tree)
773 {
774  int num_ids = 0;
775 
777  TreeStoreElem *tselem = TREESTORE(te);
778 
779  /* if item is selected and is an ID, tag it as needing to be copied. */
780  if (tselem->flag & TSE_SELECTED && ELEM(tselem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) {
781  ID *id = tselem->id;
782  if (!(id->tag & LIB_TAG_DOIT)) {
784  num_ids++;
785  }
786  }
787 
788  /* go over sub-tree */
789  num_ids += outliner_id_copy_tag(space_outliner, &te->subtree);
790  }
791 
792  return num_ids;
793 }
794 
796 {
797  Main *bmain = CTX_data_main(C);
798  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
799  char str[FILE_MAX];
800 
802 
803  const int num_ids = outliner_id_copy_tag(space_outliner, &space_outliner->tree);
804  if (num_ids == 0) {
805  BKE_report(op->reports, RPT_INFO, "No selected data-blocks to copy");
806  return OPERATOR_CANCELLED;
807  }
808 
809  BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
810  BKE_copybuffer_copy_end(bmain, str, op->reports);
811 
812  BKE_reportf(op->reports, RPT_INFO, "Copied %d selected data-block(s)", num_ids);
813 
814  return OPERATOR_FINISHED;
815 }
816 
818 {
819  /* identifiers */
820  ot->name = "Outliner ID Data Copy";
821  ot->idname = "OUTLINER_OT_id_copy";
822  ot->description = "Selected data-blocks are copied to the clipboard";
823 
824  /* callbacks */
827 
828  /* Flags, don't need any undo here (this operator does not change anything in Blender data). */
829  ot->flag = 0;
830 }
831 
834 /* -------------------------------------------------------------------- */
839 {
840  char str[FILE_MAX];
841  const short flag = FILE_AUTOSELECT | FILE_ACTIVE_COLLECTION;
842 
843  BLI_join_dirfile(str, sizeof(str), BKE_tempdir_base(), "copybuffer.blend");
844 
845  const int num_pasted = BKE_copybuffer_paste(C, str, flag, op->reports, 0);
846  if (num_pasted == 0) {
847  BKE_report(op->reports, RPT_INFO, "No data to paste");
848  return OPERATOR_CANCELLED;
849  }
850 
851  WM_event_add_notifier(C, NC_WINDOW, nullptr);
852 
853  BKE_reportf(op->reports, RPT_INFO, "%d data-block(s) pasted", num_pasted);
854 
855  return OPERATOR_FINISHED;
856 }
857 
859 {
860  /* identifiers */
861  ot->name = "Outliner ID Data Paste";
862  ot->idname = "OUTLINER_OT_id_paste";
863  ot->description = "Data-blocks from the clipboard are pasted";
864 
865  /* callbacks */
868 
869  /* flags */
871 }
872 
875 /* -------------------------------------------------------------------- */
879 static int lib_relocate(
880  bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload)
881 {
882  PointerRNA op_props;
883  int ret = 0;
884 
885  BLI_assert(te->idcode == ID_LI && tselem->id != nullptr);
886  UNUSED_VARS_NDEBUG(te);
887 
889 
890  RNA_string_set(&op_props, "library", tselem->id->name + 2);
891 
892  if (reload) {
893  Library *lib = (Library *)tselem->id;
894  char dir[FILE_MAXDIR], filename[FILE_MAX];
895 
896  BLI_split_dirfile(lib->filepath_abs, dir, filename, sizeof(dir), sizeof(filename));
897 
898  printf("%s, %s\n", tselem->id->name, lib->filepath_abs);
899 
900  /* We assume if both paths in lib are not the same then `lib->filepath` was relative. */
902  &op_props, "relative_path", BLI_path_cmp(lib->filepath_abs, lib->filepath) != 0);
903 
904  RNA_string_set(&op_props, "directory", dir);
905  RNA_string_set(&op_props, "filename", filename);
906 
907  ret = WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &op_props, nullptr);
908  }
909  else {
910  ret = WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &op_props, nullptr);
911  }
912 
913  WM_operator_properties_free(&op_props);
914 
915  return ret;
916 }
917 
919  bContext *C, ReportList *reports, TreeElement *te, const float mval[2], const bool reload)
920 {
921  if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
922  TreeStoreElem *tselem = TREESTORE(te);
923 
924  if (te->idcode == ID_LI && tselem->id) {
925  if (((Library *)tselem->id)->parent && !reload) {
926  BKE_reportf(reports,
928  "Cannot relocate indirectly linked library '%s'",
929  ((Library *)tselem->id)->filepath_abs);
930  return OPERATOR_CANCELLED;
931  }
932 
933  wmOperatorType *ot = WM_operatortype_find(reload ? "WM_OT_lib_reload" : "WM_OT_lib_relocate",
934  false);
935  return lib_relocate(C, te, tselem, ot, reload);
936  }
937  }
938  else {
939  LISTBASE_FOREACH (TreeElement *, te_sub, &te->subtree) {
940  int ret;
941  if ((ret = outliner_lib_relocate_invoke_do(C, reports, te_sub, mval, reload))) {
942  return ret;
943  }
944  }
945  }
946 
947  return 0;
948 }
949 
950 static int outliner_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
951 {
952  ARegion *region = CTX_wm_region(C);
953  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
954  float fmval[2];
955 
956  BLI_assert(region && space_outliner);
957 
958  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
959 
960  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
961  int ret;
962 
963  if ((ret = outliner_lib_relocate_invoke_do(C, op->reports, te, fmval, false))) {
964  return ret;
965  }
966  }
967 
968  return OPERATOR_CANCELLED;
969 }
970 
972 {
973  ot->name = "Relocate Library";
974  ot->idname = "OUTLINER_OT_lib_relocate";
975  ot->description = "Relocate the library under cursor";
976 
979 
980  /* Flags. */
982 }
983 
985  ReportList *UNUSED(reports),
986  Scene *UNUSED(scene),
987  TreeElement *te,
988  TreeStoreElem *UNUSED(tsep),
989  TreeStoreElem *tselem,
990  void *UNUSED(user_data))
991 {
992  /* XXX: This does not work with several items
993  * (it is only called once in the end, due to the 'deferred'
994  * file-browser invocation through event system...). */
995 
996  wmOperatorType *ot = WM_operatortype_find("WM_OT_lib_relocate", false);
997 
998  lib_relocate(C, te, tselem, ot, false);
999 }
1000 
1001 static int outliner_lib_reload_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1002 {
1003  ARegion *region = CTX_wm_region(C);
1004  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1005  float fmval[2];
1006 
1007  BLI_assert(region && space_outliner);
1008 
1009  UI_view2d_region_to_view(&region->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
1010 
1011  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
1012  int ret;
1013 
1014  if ((ret = outliner_lib_relocate_invoke_do(C, op->reports, te, fmval, true))) {
1015  return ret;
1016  }
1017  }
1018 
1019  return OPERATOR_CANCELLED;
1020 }
1021 
1024 /* -------------------------------------------------------------------- */
1029 {
1030  ot->name = "Reload Library";
1031  ot->idname = "OUTLINER_OT_lib_reload";
1032  ot->description = "Reload the library under cursor";
1033 
1036 
1037  /* Flags. */
1039 }
1040 
1042  ReportList *UNUSED(reports),
1043  Scene *UNUSED(scene),
1044  TreeElement *te,
1045  TreeStoreElem *UNUSED(tsep),
1046  TreeStoreElem *tselem,
1047  void *UNUSED(user_data))
1048 {
1049  wmOperatorType *ot = WM_operatortype_find("WM_OT_lib_reload", false);
1050 
1051  lib_relocate(C, te, tselem, ot, true);
1052 }
1053 
1056 /* -------------------------------------------------------------------- */
1060 static int outliner_count_levels(ListBase *lb, const int curlevel)
1061 {
1062  int level = curlevel;
1063 
1064  LISTBASE_FOREACH (TreeElement *, te, lb) {
1065  int lev = outliner_count_levels(&te->subtree, curlevel + 1);
1066  if (lev > level) {
1067  level = lev;
1068  }
1069  }
1070  return level;
1071 }
1072 
1073 int outliner_flag_is_any_test(ListBase *lb, short flag, const int curlevel)
1074 {
1075  LISTBASE_FOREACH (TreeElement *, te, lb) {
1076  TreeStoreElem *tselem = TREESTORE(te);
1077  if (tselem->flag & flag) {
1078  return curlevel;
1079  }
1080 
1081  int level = outliner_flag_is_any_test(&te->subtree, flag, curlevel + 1);
1082  if (level) {
1083  return level;
1084  }
1085  }
1086  return 0;
1087 }
1088 
1089 bool outliner_flag_set(const SpaceOutliner &space_outliner, const short flag, const short set)
1090 {
1091  return outliner_flag_set(space_outliner.tree, flag, set);
1092 }
1093 
1094 bool outliner_flag_set(const ListBase &lb, const short flag, const short set)
1095 {
1096  bool changed = false;
1097 
1098  tree_iterator::all(lb, [&](TreeElement *te) {
1099  TreeStoreElem *tselem = TREESTORE(te);
1100  bool has_flag = (tselem->flag & flag);
1101  if (set == 0) {
1102  if (has_flag) {
1103  tselem->flag &= ~flag;
1104  changed = true;
1105  }
1106  }
1107  else if (!has_flag) {
1108  tselem->flag |= flag;
1109  changed = true;
1110  }
1111  });
1112 
1113  return changed;
1114 }
1115 
1116 bool outliner_flag_flip(const SpaceOutliner &space_outliner, const short flag)
1117 {
1118  return outliner_flag_flip(space_outliner.tree, flag);
1119 }
1120 
1121 bool outliner_flag_flip(const ListBase &lb, const short flag)
1122 {
1123  bool changed = false;
1124 
1125  tree_iterator::all(lb, [&](TreeElement *te) {
1126  TreeStoreElem *tselem = TREESTORE(te);
1127  tselem->flag ^= flag;
1128  });
1129 
1130  return changed;
1131 }
1132 
1135 /* -------------------------------------------------------------------- */
1140 {
1141  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1142  ARegion *region = CTX_wm_region(C);
1143 
1144  if (outliner_flag_is_any_test(&space_outliner->tree, TSE_CLOSED, 1)) {
1145  outliner_flag_set(*space_outliner, TSE_CLOSED, 0);
1146  }
1147  else {
1148  outliner_flag_set(*space_outliner, TSE_CLOSED, 1);
1149  }
1150 
1151  ED_region_tag_redraw(region);
1152 
1153  return OPERATOR_FINISHED;
1154 }
1155 
1157 {
1158  /* identifiers */
1159  ot->name = "Expand/Collapse All";
1160  ot->idname = "OUTLINER_OT_expanded_toggle";
1161  ot->description = "Expand/Collapse all items";
1162 
1163  /* callbacks */
1166 
1167  /* no undo or registry, UI option */
1168 }
1169 
1172 /* -------------------------------------------------------------------- */
1177 {
1178  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1179  ARegion *region = CTX_wm_region(C);
1181  int action = RNA_enum_get(op->ptr, "action");
1182  if (action == SEL_TOGGLE) {
1183  action = outliner_flag_is_any_test(&space_outliner->tree, TSE_SELECTED, 1) ? SEL_DESELECT :
1184  SEL_SELECT;
1185  }
1186 
1187  switch (action) {
1188  case SEL_SELECT:
1189  outliner_flag_set(*space_outliner, TSE_SELECTED, 1);
1190  break;
1191  case SEL_DESELECT:
1192  outliner_flag_set(*space_outliner, TSE_SELECTED, 0);
1193  break;
1194  case SEL_INVERT:
1195  outliner_flag_flip(*space_outliner, TSE_SELECTED);
1196  break;
1197  }
1198 
1199  ED_outliner_select_sync_from_outliner(C, space_outliner);
1200 
1204 
1205  return OPERATOR_FINISHED;
1206 }
1207 
1209 {
1210  /* identifiers */
1211  ot->name = "Toggle Selected";
1212  ot->idname = "OUTLINER_OT_select_all";
1213  ot->description = "Toggle the Outliner selection of items";
1214 
1215  /* callbacks */
1218 
1219  /* no undo or registry */
1220 
1221  /* rna */
1223 }
1224 
1227 /* -------------------------------------------------------------------- */
1231 void outliner_set_coordinates(const ARegion *region, const SpaceOutliner *space_outliner)
1232 {
1233  int starty = (int)(region->v2d.tot.ymax) - UI_UNIT_Y;
1234 
1235  tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
1236  /* store coord and continue, we need coordinates for elements outside view too */
1237  te->xs = 0;
1238  te->ys = (float)starty;
1239  starty -= UI_UNIT_Y;
1240  });
1241 }
1242 
1243 /* return 1 when levels were opened */
1245 {
1246  TreeStoreElem *tselem;
1247  int retval = 0;
1248 
1249  for (te = te->parent; te; te = te->parent) {
1250  tselem = TREESTORE(te);
1251  if (tselem->flag & TSE_CLOSED) {
1252  tselem->flag &= ~TSE_CLOSED;
1253  retval = 1;
1254  }
1255  }
1256  return retval;
1257 }
1258 
1259 /* Return element representing the active base or bone in the outliner, or NULL if none exists */
1261  SpaceOutliner *space_outliner,
1262  ViewLayer *view_layer)
1263 {
1264  TreeElement *te;
1265 
1266  Object *obact = OBACT(view_layer);
1267 
1268  if (!obact) {
1269  return nullptr;
1270  }
1271 
1272  te = outliner_find_id(space_outliner, &space_outliner->tree, &obact->id);
1273 
1274  if (te != nullptr && obact->type == OB_ARMATURE) {
1275  /* traverse down the bone hierarchy in case of armature */
1276  TreeElement *te_obact = te;
1277 
1278  if (obact->mode & OB_MODE_POSE) {
1279  Object *obpose = BKE_object_pose_armature_get(obact);
1280  bPoseChannel *pchan = BKE_pose_channel_active(obpose, false);
1281  if (pchan) {
1282  te = outliner_find_posechannel(&te_obact->subtree, pchan);
1283  }
1284  }
1285  else if (obact->mode & OB_MODE_EDIT) {
1286  EditBone *ebone = CTX_data_active_bone(C);
1287  if (ebone) {
1288  te = outliner_find_editbone(&te_obact->subtree, ebone);
1289  }
1290  }
1291  }
1292 
1293  return te;
1294 }
1295 
1296 static void outliner_show_active(SpaceOutliner *space_outliner,
1297  ARegion *region,
1298  TreeElement *te,
1299  ID *id)
1300 {
1301  /* open up tree to active object/bone */
1302  if (TREESTORE(te)->id == id) {
1303  if (outliner_open_back(te)) {
1304  outliner_set_coordinates(region, space_outliner);
1305  }
1306  return;
1307  }
1308 
1309  LISTBASE_FOREACH (TreeElement *, ten, &te->subtree) {
1310  outliner_show_active(space_outliner, region, ten, id);
1311  }
1312 }
1313 
1315 {
1316  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1317  ViewLayer *view_layer = CTX_data_view_layer(C);
1318  ARegion *region = CTX_wm_region(C);
1319  View2D *v2d = &region->v2d;
1320 
1321  TreeElement *active_element = outliner_show_active_get_element(C, space_outliner, view_layer);
1322 
1323  if (active_element) {
1324  ID *id = TREESTORE(active_element)->id;
1325 
1326  /* Expand all elements in the outliner with matching ID */
1327  LISTBASE_FOREACH (TreeElement *, te, &space_outliner->tree) {
1328  outliner_show_active(space_outliner, region, te, id);
1329  }
1330 
1331  /* Also open back from the active_element (only done for the first found occurrence of ID
1332  * though). */
1333  outliner_show_active(space_outliner, region, active_element, id);
1334 
1335  /* Center view on first element found */
1336  int size_y = BLI_rcti_size_y(&v2d->mask) + 1;
1337  int ytop = (active_element->ys + (size_y / 2));
1338  int delta_y = ytop - v2d->cur.ymax;
1339 
1340  outliner_scroll_view(space_outliner, region, delta_y);
1341  }
1342  else {
1343  return OPERATOR_CANCELLED;
1344  }
1345 
1347 
1348  return OPERATOR_FINISHED;
1349 }
1350 
1352 {
1353  /* identifiers */
1354  ot->name = "Show Active";
1355  ot->idname = "OUTLINER_OT_show_active";
1356  ot->description =
1357  "Open up the tree and adjust the view so that the active object is shown centered";
1358 
1359  /* callbacks */
1362 }
1363 
1366 /* -------------------------------------------------------------------- */
1371 {
1372  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1373  ARegion *region = CTX_wm_region(C);
1374  int size_y = BLI_rcti_size_y(&region->v2d.mask) + 1;
1375 
1376  bool up = RNA_boolean_get(op->ptr, "up");
1377 
1378  if (!up) {
1379  size_y = -size_y;
1380  }
1381 
1382  outliner_scroll_view(space_outliner, region, size_y);
1383 
1385 
1386  return OPERATOR_FINISHED;
1387 }
1388 
1390 {
1391  PropertyRNA *prop;
1392 
1393  /* identifiers */
1394  ot->name = "Scroll Page";
1395  ot->idname = "OUTLINER_OT_scroll_page";
1396  ot->description = "Scroll page up or down";
1397 
1398  /* callbacks */
1401 
1402  /* properties */
1403  prop = RNA_def_boolean(ot->srna, "up", false, "Up", "Scroll up one page");
1405 }
1406 
1409 #if 0 /* TODO: probably obsolete now with filtering? */
1410 
1411 /* -------------------------------------------------------------------- */
1416 /* find next element that has this name */
1417 static TreeElement *outliner_find_name(
1418  SpaceOutliner *space_outliner, ListBase *lb, char *name, int flags, TreeElement *prev, int *prevFound)
1419 {
1420  TreeElement *te, *tes;
1421 
1422  for (te = lb->first; te; te = te->next) {
1423  int found = outliner_filter_has_name(te, name, flags);
1424 
1425  if (found) {
1426  /* name is right, but is element the previous one? */
1427  if (prev) {
1428  if ((te != prev) && (*prevFound)) {
1429  return te;
1430  }
1431  if (te == prev) {
1432  *prevFound = 1;
1433  }
1434  }
1435  else {
1436  return te;
1437  }
1438  }
1439 
1440  tes = outliner_find_name(space_outliner, &te->subtree, name, flags, prev, prevFound);
1441  if (tes) {
1442  return tes;
1443  }
1444  }
1445 
1446  /* nothing valid found */
1447  return nullptr;
1448 }
1449 
1450 static void outliner_find_panel(
1451  Scene *UNUSED(scene), ARegion *region, SpaceOutliner *space_outliner, int again, int flags)
1452 {
1453  ReportList *reports = nullptr; /* CTX_wm_reports(C); */
1454  TreeElement *te = nullptr;
1455  TreeElement *last_find;
1456  TreeStoreElem *tselem;
1457  int ytop, xdelta, prevFound = 0;
1458  char name[sizeof(space_outliner->search_string)];
1459 
1460  /* get last found tree-element based on stored search_tse */
1461  last_find = outliner_find_tse(space_outliner, &space_outliner->search_tse);
1462 
1463  /* determine which type of search to do */
1464  if (again && last_find) {
1465  /* no popup panel - previous + user wanted to search for next after previous */
1466  BLI_strncpy(name, space_outliner->search_string, sizeof(name));
1467  flags = space_outliner->search_flags;
1468 
1469  /* try to find matching element */
1470  te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, last_find, &prevFound);
1471  if (te == nullptr) {
1472  /* no more matches after previous, start from beginning again */
1473  prevFound = 1;
1474  te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, last_find, &prevFound);
1475  }
1476  }
1477  else {
1478  /* pop up panel - no previous, or user didn't want search after previous */
1479  name[0] = '\0';
1480  // XXX if (sbutton(name, 0, sizeof(name) - 1, "Find: ") && name[0]) {
1481  // te = outliner_find_name(space_outliner, &space_outliner->tree, name, flags, nullptr, &prevFound);
1482  // }
1483  // else return; XXX RETURN! XXX
1484  }
1485 
1486  /* do selection and reveal */
1487  if (te) {
1488  tselem = TREESTORE(te);
1489  if (tselem) {
1490  /* expand branches so that it will be visible, we need to get correct coordinates */
1491  if (outliner_open_back(space_outliner, te)) {
1492  outliner_set_coordinates(region, space_outliner);
1493  }
1494 
1495  /* deselect all visible, and select found element */
1496  outliner_flag_set(space_outliner, &space_outliner->tree, TSE_SELECTED, 0);
1497  tselem->flag |= TSE_SELECTED;
1498 
1499  /* Make `te->ys` center of view. */
1500  ytop = (int)(te->ys + BLI_rctf_size_y(&region->v2d.mask) / 2);
1501  if (ytop > 0) {
1502  ytop = 0;
1503  }
1504  region->v2d.cur.ymax = (float)ytop;
1505  region->v2d.cur.ymin = (float)(ytop - BLI_rctf_size_y(&region->v2d.mask));
1506 
1507  /* Make `te->xs` ==> `te->xend` center of view. */
1508  xdelta = (int)(te->xs - region->v2d.cur.xmin);
1509  region->v2d.cur.xmin += xdelta;
1510  region->v2d.cur.xmax += xdelta;
1511 
1512  /* store selection */
1513  space_outliner->search_tse = *tselem;
1514 
1515  BLI_strncpy(space_outliner->search_string, name, sizeof(space_outliner->search_string));
1516  space_outliner->search_flags = flags;
1517 
1518  /* redraw */
1520  }
1521  }
1522  else {
1523  /* no tree-element found */
1524  BKE_reportf(reports, RPT_WARNING, "Not found: %s", name);
1525  }
1526 }
1527 
1530 #endif /* if 0 */
1531 
1532 /* -------------------------------------------------------------------- */
1536 /* helper function for Show/Hide one level operator */
1537 static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int open)
1538 {
1539  LISTBASE_FOREACH (TreeElement *, te, lb) {
1540  TreeStoreElem *tselem = TREESTORE(te);
1541 
1542  if (open) {
1543  if (curlevel <= level) {
1544  tselem->flag &= ~TSE_CLOSED;
1545  }
1546  }
1547  else {
1548  if (curlevel >= level) {
1549  tselem->flag |= TSE_CLOSED;
1550  }
1551  }
1552 
1553  outliner_openclose_level(&te->subtree, curlevel + 1, level, open);
1554  }
1555 }
1556 
1558 {
1559  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1560  ARegion *region = CTX_wm_region(C);
1561  const bool add = RNA_boolean_get(op->ptr, "open");
1562  int level;
1563 
1564  level = outliner_flag_is_any_test(&space_outliner->tree, TSE_CLOSED, 1);
1565  if (add == 1) {
1566  if (level) {
1567  outliner_openclose_level(&space_outliner->tree, 1, level, 1);
1568  }
1569  }
1570  else {
1571  if (level == 0) {
1572  level = outliner_count_levels(&space_outliner->tree, 0);
1573  }
1574  if (level) {
1575  outliner_openclose_level(&space_outliner->tree, 1, level - 1, 0);
1576  }
1577  }
1578 
1579  ED_region_tag_redraw(region);
1580 
1581  return OPERATOR_FINISHED;
1582 }
1583 
1585 {
1586  PropertyRNA *prop;
1587 
1588  /* identifiers */
1589  ot->name = "Show/Hide One Level";
1590  ot->idname = "OUTLINER_OT_show_one_level";
1591  ot->description = "Expand/collapse all entries by one level";
1592 
1593  /* callbacks */
1596 
1597  /* no undo or registry, UI option */
1598 
1599  /* properties */
1600  prop = RNA_def_boolean(ot->srna, "open", true, "Open", "Expand all entries one level deep");
1602 }
1603 
1606 /* -------------------------------------------------------------------- */
1615 {
1616  LISTBASE_FOREACH (TreeElement *, te, lb) {
1617  TreeStoreElem *tselem = TREESTORE(te);
1618  if ((tselem->type == TSE_SOME_ID) && (te->idcode == ID_OB)) {
1619  return 1;
1620  }
1621  if (subtree_has_objects(&te->subtree)) {
1622  return 1;
1623  }
1624  }
1625  return 0;
1626 }
1627 
1628 /* Helper function for Show Hierarchy operator */
1630 {
1631  /* open all object elems, close others */
1632  tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
1633  TreeStoreElem *tselem = TREESTORE(te);
1634 
1635  if (ELEM(tselem->type,
1636  TSE_SOME_ID,
1640  if (te->idcode == ID_SCE) {
1641  if (tselem->id != (ID *)scene) {
1642  tselem->flag |= TSE_CLOSED;
1643  }
1644  else {
1645  tselem->flag &= ~TSE_CLOSED;
1646  }
1647  }
1648  else if (te->idcode == ID_OB) {
1649  if (subtree_has_objects(&te->subtree)) {
1650  tselem->flag &= ~TSE_CLOSED;
1651  }
1652  else {
1653  tselem->flag |= TSE_CLOSED;
1654  }
1655  }
1656  }
1657  else {
1658  tselem->flag |= TSE_CLOSED;
1659  }
1660  });
1661 }
1662 
1663 /* show entire object level hierarchy */
1665 {
1666  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1667  ARegion *region = CTX_wm_region(C);
1669 
1670  /* recursively open/close levels */
1671  tree_element_show_hierarchy(scene, space_outliner);
1672 
1673  ED_region_tag_redraw(region);
1674 
1675  return OPERATOR_FINISHED;
1676 }
1677 
1679 {
1680  /* identifiers */
1681  ot->name = "Show Hierarchy";
1682  ot->idname = "OUTLINER_OT_show_hierarchy";
1683  ot->description = "Open all object entries and close all others";
1684 
1685  /* callbacks */
1687  ot->poll = ED_operator_outliner_active; /* TODO: shouldn't be allowed in RNA views... */
1688 
1689  /* no undo or registry, UI option */
1690 }
1691 
1694 /* -------------------------------------------------------------------- */
1702 {
1703  ScrArea *area = CTX_wm_area(C);
1704  if ((area) && (area->spacetype == SPACE_OUTLINER)) {
1705  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1706  return (space_outliner->outlinevis == SO_DATA_API);
1707  }
1708  return false;
1709 }
1710 
1711 /* Helper func to extract an RNA path from selected tree element
1712  * NOTE: the caller must zero-out all values of the pointers that it passes here first, as
1713  * this function does not do that yet
1714  */
1716  TreeStoreElem *tselem,
1717  ID **id,
1718  char **path,
1719  int *array_index,
1720  short *flag,
1721  short *UNUSED(groupmode))
1722 {
1723  ListBase hierarchy = {nullptr, nullptr};
1724  char *newpath = nullptr;
1725 
1726  /* optimize tricks:
1727  * - Don't do anything if the selected item is a 'struct', but arrays are allowed
1728  */
1729  if (tselem->type == TSE_RNA_STRUCT) {
1730  return;
1731  }
1732 
1733  /* Overview of Algorithm:
1734  * 1. Go up the chain of parents until we find the 'root', taking note of the
1735  * levels encountered in reverse-order (i.e. items are added to the start of the list
1736  * for more convenient looping later)
1737  * 2. Walk down the chain, adding from the first ID encountered
1738  * (which will become the 'ID' for the KeyingSet Path), and build a
1739  * path as we step through the chain
1740  */
1741 
1742  /* step 1: flatten out hierarchy of parents into a flat chain */
1743  for (TreeElement *tem = te->parent; tem; tem = tem->parent) {
1744  LinkData *ld = MEM_cnew<LinkData>("LinkData for tree_element_to_path()");
1745  ld->data = tem;
1746  BLI_addhead(&hierarchy, ld);
1747  }
1748 
1749  /* step 2: step down hierarchy building the path
1750  * (NOTE: addhead in previous loop was needed so that we can loop like this) */
1751  LISTBASE_FOREACH (LinkData *, ld, &hierarchy) {
1752  /* get data */
1753  TreeElement *tem = (TreeElement *)ld->data;
1754  TreeElementRNACommon *tem_rna = tree_element_cast<TreeElementRNACommon>(tem);
1755  PointerRNA ptr = tem_rna->getPointerRNA();
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 (TreeElementRNAProperty *tem_rna_prop = tree_element_cast<TreeElementRNAProperty>(tem)) {
1764  PropertyRNA *prop = tem_rna_prop->getPropertyRNA();
1765 
1766  if (RNA_property_type(prop) == PROP_POINTER) {
1767  /* for pointer we just append property name */
1768  newpath = RNA_path_append(*path, &ptr, prop, 0, nullptr);
1769  }
1770  else if (RNA_property_type(prop) == PROP_COLLECTION) {
1771  char buf[128], *name;
1772 
1773  TreeElement *temnext = (TreeElement *)(ld->next->data);
1774  PointerRNA nextptr = tree_element_cast<TreeElementRNACommon>(temnext)->getPointerRNA();
1775  name = RNA_struct_name_get_alloc(&nextptr, buf, sizeof(buf), nullptr);
1776 
1777  if (name) {
1778  /* if possible, use name as a key in the path */
1779  newpath = RNA_path_append(*path, nullptr, 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  index++;
1794  }
1795  newpath = RNA_path_append(*path, nullptr, prop, index, nullptr);
1796  }
1797 
1798  ld = ld->next;
1799  }
1800  }
1801 
1802  if (newpath) {
1803  if (*path) {
1804  MEM_freeN(*path);
1805  }
1806  *path = newpath;
1807  newpath = nullptr;
1808  }
1809  }
1810  else {
1811  /* no ID, so check if entry is RNA-struct,
1812  * and if that RNA-struct is an ID datablock to extract info from. */
1813  if (tree_element_cast<TreeElementRNAStruct>(tem)) {
1814  /* ptr->data not ptr->owner_id seems to be the one we want,
1815  * since ptr->data is sometimes the owner of this ID? */
1816  if (RNA_struct_is_ID(ptr.type)) {
1817  *id = reinterpret_cast<ID *>(ptr.data);
1818 
1819  /* clear path */
1820  if (*path) {
1821  MEM_freeN(*path);
1822  path = nullptr;
1823  }
1824  }
1825  }
1826  }
1827  }
1828 
1829  /* step 3: if we've got an ID, add the current item to the path */
1830  if (*id) {
1831  /* add the active property to the path */
1832  PropertyRNA *prop = tree_element_cast<TreeElementRNACommon>(te)->getPropertyRNA();
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, nullptr, prop, 0, nullptr);
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 /* Iterate over tree, finding and working on selected items */
1874 static void do_outliner_drivers_editop(SpaceOutliner *space_outliner,
1875  ReportList *reports,
1876  short mode)
1877 {
1878  tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
1879  TreeStoreElem *tselem = TREESTORE(te);
1880 
1881  /* if item is selected, perform operation */
1882  if (!(tselem->flag & TSE_SELECTED)) {
1883  return;
1884  }
1885 
1886  ID *id = nullptr;
1887  char *path = nullptr;
1888  int array_index = 0;
1889  short flag = 0;
1890  short groupmode = KSP_GROUP_KSNAME;
1891 
1892  TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te);
1893  PointerRNA ptr = te_rna ? te_rna->getPointerRNA() : PointerRNA_NULL;
1894  PropertyRNA *prop = te_rna ? te_rna->getPropertyRNA() : nullptr;
1895 
1896  /* check if RNA-property described by this selected element is an animatable prop */
1897  if (prop && RNA_property_animateable(&ptr, prop)) {
1898  /* get id + path + index info from the selected element */
1899  tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
1900  }
1901 
1902  /* only if ID and path were set, should we perform any actions */
1903  if (id && path) {
1904  short dflags = CREATEDRIVER_WITH_DEFAULT_DVAR;
1905  int arraylen = 1;
1906 
1907  /* array checks */
1908  if (flag & KSP_FLAG_WHOLE_ARRAY) {
1909  /* entire array was selected, so add drivers for all */
1910  arraylen = RNA_property_array_length(&ptr, prop);
1911  }
1912  else {
1913  arraylen = array_index;
1914  }
1915 
1916  /* we should do at least one step */
1917  if (arraylen == array_index) {
1918  arraylen++;
1919  }
1920 
1921  /* for each array element we should affect, add driver */
1922  for (; array_index < arraylen; array_index++) {
1923  /* action depends on mode */
1924  switch (mode) {
1925  case DRIVERS_EDITMODE_ADD: {
1926  /* add a new driver with the information obtained (only if valid) */
1927  ANIM_add_driver(reports, id, path, array_index, dflags, DRIVER_TYPE_PYTHON);
1928  break;
1929  }
1930  case DRIVERS_EDITMODE_REMOVE: {
1931  /* remove driver matching the information obtained (only if valid) */
1932  ANIM_remove_driver(reports, id, path, array_index, dflags);
1933  break;
1934  }
1935  }
1936  }
1937 
1938  /* free path, since it had to be generated */
1939  MEM_freeN(path);
1940  }
1941  });
1942 }
1943 
1946 /* -------------------------------------------------------------------- */
1951 {
1952  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1953 
1954  /* check for invalid states */
1955  if (space_outliner == nullptr) {
1956  return OPERATOR_CANCELLED;
1957  }
1958 
1959  /* recursively go into tree, adding selected items */
1961 
1962  /* send notifiers */
1963  WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, nullptr); /* XXX */
1964 
1965  return OPERATOR_FINISHED;
1966 }
1967 
1969 {
1970  /* api callbacks */
1971  ot->idname = "OUTLINER_OT_drivers_add_selected";
1972  ot->name = "Add Drivers for Selected";
1973  ot->description = "Add drivers to selected items";
1974 
1975  /* api callbacks */
1978 
1979  /* flags */
1981 }
1982 
1985 /* -------------------------------------------------------------------- */
1990 {
1991  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
1992 
1993  /* check for invalid states */
1994  if (space_outliner == nullptr) {
1995  return OPERATOR_CANCELLED;
1996  }
1997 
1998  /* recursively go into tree, adding selected items */
2000 
2001  /* send notifiers */
2002  WM_event_add_notifier(C, ND_KEYS, nullptr); /* XXX */
2003 
2004  return OPERATOR_FINISHED;
2005 }
2006 
2008 {
2009  /* identifiers */
2010  ot->idname = "OUTLINER_OT_drivers_delete_selected";
2011  ot->name = "Delete Drivers for Selected";
2012  ot->description = "Delete drivers assigned to selected items";
2013 
2014  /* api callbacks */
2017 
2018  /* flags */
2020 }
2021 
2024 /* -------------------------------------------------------------------- */
2034 enum {
2037 } /*eKeyingSet_EditModes*/;
2038 
2039 /* Find the 'active' KeyingSet, and add if not found (if adding is allowed). */
2040 /* TODO: should this be an API func? */
2042 {
2043  KeyingSet *ks = nullptr;
2044 
2045  /* sanity check */
2046  if (scene == nullptr) {
2047  return nullptr;
2048  }
2049 
2050  /* try to find one from scene */
2051  if (scene->active_keyingset > 0) {
2052  ks = reinterpret_cast<KeyingSet *>(
2054  }
2055 
2056  /* Add if none found */
2057  /* XXX the default settings have yet to evolve. */
2058  if ((add) && (ks == nullptr)) {
2059  ks = BKE_keyingset_add(&scene->keyingsets, nullptr, nullptr, KEYINGSET_ABSOLUTE, 0);
2061  }
2062 
2063  return ks;
2064 }
2065 
2066 /* Iterate over tree, finding and working on selected items */
2067 static void do_outliner_keyingset_editop(SpaceOutliner *space_outliner,
2068  KeyingSet *ks,
2069  const short mode)
2070 {
2071  tree_iterator::all_open(*space_outliner, [&](TreeElement *te) {
2072  TreeStoreElem *tselem = TREESTORE(te);
2073 
2074  /* if item is selected, perform operation */
2075  if (!(tselem->flag & TSE_SELECTED)) {
2076  return;
2077  }
2078 
2079  ID *id = nullptr;
2080  char *path = nullptr;
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  const TreeElementRNACommon *te_rna = tree_element_cast<TreeElementRNACommon>(te);
2087  PointerRNA ptr = te_rna->getPointerRNA();
2088  if (te_rna && te_rna->getPropertyRNA() &&
2090  /* get id + path + index info from the selected element */
2091  tree_element_to_path(te, tselem, &id, &path, &array_index, &flag, &groupmode);
2092  }
2093 
2094  /* only if ID and path were set, should we perform any actions */
2095  if (id && path) {
2096  /* action depends on mode */
2097  switch (mode) {
2098  case KEYINGSET_EDITMODE_ADD: {
2099  /* add a new path with the information obtained (only if valid) */
2100  /* TODO: what do we do with group name?
2101  * for now, we don't supply one, and just let this use the KeyingSet name */
2102  BKE_keyingset_add_path(ks, id, nullptr, path, array_index, flag, groupmode);
2103  ks->active_path = BLI_listbase_count(&ks->paths);
2104  break;
2105  }
2107  /* find the relevant path, then remove it from the KeyingSet */
2108  KS_Path *ksp = BKE_keyingset_find_path(ks, id, nullptr, path, array_index, groupmode);
2109 
2110  if (ksp) {
2111  /* free path's data */
2112  BKE_keyingset_free_path(ks, ksp);
2113 
2114  ks->active_path = 0;
2115  }
2116  break;
2117  }
2118  }
2119 
2120  /* free path, since it had to be generated */
2121  MEM_freeN(path);
2122  }
2123  });
2124 }
2125 
2128 /* -------------------------------------------------------------------- */
2133 {
2134  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2137 
2138  /* check for invalid states */
2139  if (ks == nullptr) {
2140  BKE_report(op->reports, RPT_ERROR, "Operation requires an active keying set");
2141  return OPERATOR_CANCELLED;
2142  }
2143  if (space_outliner == nullptr) {
2144  return OPERATOR_CANCELLED;
2145  }
2146 
2147  /* recursively go into tree, adding selected items */
2149 
2150  /* send notifiers */
2152 
2153  return OPERATOR_FINISHED;
2154 }
2155 
2157 {
2158  /* identifiers */
2159  ot->idname = "OUTLINER_OT_keyingset_add_selected";
2160  ot->name = "Keying Set Add Selected";
2161  ot->description = "Add selected items (blue-gray rows) to active Keying Set";
2162 
2163  /* api callbacks */
2166 
2167  /* flags */
2169 }
2170 
2173 /* -------------------------------------------------------------------- */
2178 {
2179  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2182 
2183  /* check for invalid states */
2184  if (space_outliner == nullptr) {
2185  return OPERATOR_CANCELLED;
2186  }
2187 
2188  /* recursively go into tree, adding selected items */
2190 
2191  /* send notifiers */
2193 
2194  return OPERATOR_FINISHED;
2195 }
2196 
2198 {
2199  /* identifiers */
2200  ot->idname = "OUTLINER_OT_keyingset_remove_selected";
2201  ot->name = "Keying Set Remove Selected";
2202  ot->description = "Remove selected items (blue-gray rows) from active Keying Set";
2203 
2204  /* api callbacks */
2207 
2208  /* flags */
2210 }
2211 
2214 /* -------------------------------------------------------------------- */
2219 {
2220  ScrArea *area = CTX_wm_area(C);
2221  if (area != nullptr && area->spacetype == SPACE_OUTLINER) {
2222  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2223  return (space_outliner->outlinevis == SO_ID_ORPHANS);
2224  }
2225  return true;
2226 }
2227 
2229 {
2230  Main *bmain = CTX_data_main(C);
2231  int num_tagged[INDEX_ID_MAX] = {0};
2232 
2233  const bool do_local_ids = RNA_boolean_get(op->ptr, "do_local_ids");
2234  const bool do_linked_ids = RNA_boolean_get(op->ptr, "do_linked_ids");
2235  const bool do_recursive_cleanup = RNA_boolean_get(op->ptr, "do_recursive");
2236 
2237  /* Tag all IDs to delete. */
2239  bmain, LIB_TAG_DOIT, do_local_ids, do_linked_ids, do_recursive_cleanup, num_tagged);
2240 
2241  RNA_int_set(op->ptr, "num_deleted", num_tagged[INDEX_ID_NULL]);
2242 
2243  if (num_tagged[INDEX_ID_NULL] == 0) {
2244  BKE_report(op->reports, RPT_INFO, "No orphaned data-blocks to purge");
2245  return OPERATOR_CANCELLED;
2246  }
2247 
2248  DynStr *dyn_str = BLI_dynstr_new();
2249  BLI_dynstr_appendf(dyn_str, "Purging %d unused data-blocks (", num_tagged[INDEX_ID_NULL]);
2250  bool is_first = true;
2251  for (int i = 0; i < INDEX_ID_MAX - 2; i++) {
2252  if (num_tagged[i] != 0) {
2253  if (!is_first) {
2254  BLI_dynstr_append(dyn_str, ", ");
2255  }
2256  else {
2257  is_first = false;
2258  }
2259  BLI_dynstr_appendf(dyn_str,
2260  "%d %s",
2261  num_tagged[i],
2263  }
2264  }
2265  BLI_dynstr_append(dyn_str, TIP_("). Click here to proceed..."));
2266 
2267  char *message = BLI_dynstr_get_cstring(dyn_str);
2268  int ret = WM_operator_confirm_message(C, op, message);
2269 
2270  MEM_freeN(message);
2271  BLI_dynstr_free(dyn_str);
2272  return ret;
2273 }
2274 
2276 {
2277  Main *bmain = CTX_data_main(C);
2278  ScrArea *area = CTX_wm_area(C);
2279  SpaceOutliner *space_outliner = CTX_wm_space_outliner(C);
2280  int num_tagged[INDEX_ID_MAX] = {0};
2281 
2282  if ((num_tagged[INDEX_ID_NULL] = RNA_int_get(op->ptr, "num_deleted")) == 0) {
2283  const bool do_local_ids = RNA_boolean_get(op->ptr, "do_local_ids");
2284  const bool do_linked_ids = RNA_boolean_get(op->ptr, "do_linked_ids");
2285  const bool do_recursive_cleanup = RNA_boolean_get(op->ptr, "do_recursive");
2286 
2287  /* Tag all IDs to delete. */
2289  bmain, LIB_TAG_DOIT, do_local_ids, do_linked_ids, do_recursive_cleanup, num_tagged);
2290 
2291  if (num_tagged[INDEX_ID_NULL] == 0) {
2292  BKE_report(op->reports, RPT_INFO, "No orphaned data-blocks to purge");
2293  return OPERATOR_CANCELLED;
2294  }
2295  }
2296 
2298 
2299  BKE_reportf(op->reports, RPT_INFO, "Deleted %d data-block(s)", num_tagged[INDEX_ID_NULL]);
2300 
2301  /* XXX: tree management normally happens from draw_outliner(), but when
2302  * you're clicking to fast on Delete object from context menu in
2303  * outliner several mouse events can be handled in one cycle without
2304  * handling notifiers/redraw which leads to deleting the same object twice.
2305  * cleanup tree here to prevent such cases. */
2306  if ((area != nullptr) && (area->spacetype == SPACE_OUTLINER)) {
2307  outliner_cleanup_tree(space_outliner);
2308  }
2309 
2310  DEG_relations_tag_update(bmain);
2311  WM_event_add_notifier(C, NC_ID | NA_REMOVED, nullptr);
2312  /* Force full redraw of the UI. */
2313  WM_main_add_notifier(NC_WINDOW, nullptr);
2314 
2315  return OPERATOR_FINISHED;
2316 }
2317 
2319 {
2320  /* identifiers */
2321  ot->idname = "OUTLINER_OT_orphans_purge";
2322  ot->name = "Purge All";
2323  ot->description = "Clear all orphaned data-blocks without any users from the file";
2324 
2325  /* callbacks */
2329 
2330  /* flags */
2332 
2333  /* properties */
2334  PropertyRNA *prop = RNA_def_int(ot->srna, "num_deleted", 0, 0, INT_MAX, "", "", 0, INT_MAX);
2336 
2338  "do_local_ids",
2339  true,
2340  "Local Data-blocks",
2341  "Include unused local data-blocks into deletion");
2343  "do_linked_ids",
2344  true,
2345  "Linked Data-blocks",
2346  "Include unused linked data-blocks into deletion");
2347 
2349  "do_recursive",
2350  false,
2351  "Recursive Delete",
2352  "Recursively check for indirectly unused data-blocks, ensuring that no orphaned "
2353  "data-blocks remain after execution");
2354 }
2355 
typedef float(TangentPoint)[2]
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_active(struct Object *ob, bool check_arm_layer)
Definition: action.c:699
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:160
struct KeyingSet * BKE_keyingset_add(struct ListBase *list, const char idname[], const char name[], short flag, short keyingflag)
Definition: anim_sys.c:126
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:223
const char * BKE_tempdir_base(void)
Definition: appdir.c:1154
bool BKE_copybuffer_copy_end(struct Main *bmain_src, const char *filename, struct ReportList *reports)
void BKE_copybuffer_copy_begin(struct Main *bmain_src)
void BKE_copybuffer_copy_tag_ID(struct ID *id)
int BKE_copybuffer_paste(struct bContext *C, const char *libname, int flag, struct ReportList *reports, uint64_t id_types_mask)
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct SpaceOutliner * CTX_wm_space_outliner(const bContext *C)
Definition: context.c:860
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct EditBone * CTX_data_active_bone(const bContext *C)
Definition: context.c:1395
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
const char * BKE_idtype_idcode_to_name_plural(short idcode)
Definition: idtype.c:149
short BKE_idtype_idcode_from_index(int index)
Definition: idtype.c:383
void BKE_main_id_tag_idcode(struct Main *mainvar, short type, int tag, bool value)
Definition: lib_id.c:920
void BKE_main_id_tag_all(struct Main *mainvar, int tag, bool value)
Definition: lib_id.c:930
void BKE_main_lib_objects_recalc_all(struct Main *bmain)
Definition: lib_id.c:998
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:615
void BKE_lib_query_unused_ids_tag(struct Main *bmain, int tag, bool do_local_ids, bool do_linked_ids, bool do_tag_recursive, int *r_num_tagged)
Definition: lib_query.c:778
@ ID_REMAP_SKIP_NEVER_NULL_USAGE
Definition: BKE_lib_remap.h:45
@ ID_REMAP_SKIP_INDIRECT_USAGE
Definition: BKE_lib_remap.h:36
void void BKE_libblock_remap(struct Main *bmain, void *old_idv, void *new_idv, short remap_flags) ATTR_NONNULL(1
struct ListBase * which_libbase(struct Main *bmain, short type)
Definition: main.c:567
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.cc:2511
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
void BKE_workspace_id_tag_all_visible(struct Main *bmain, int tag) ATTR_NONNULL()
Definition: workspace.c:500
#define BLI_assert(a)
Definition: BLI_assert.h:46
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:50
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:256
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:281
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:75
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:60
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
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)
void BLI_split_dirfile(const char *string, char *dir, char *file, size_t dirlen, size_t filelen)
Definition: path_util.c:1465
#define FILE_MAX
#define FILE_MAXDIR
#define BLI_path_cmp
void BLI_join_dirfile(char *__restrict dst, size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1531
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition: BLI_rect.h:198
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#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:818
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition: DNA_ID.h:581
@ INDEX_ID_NULL
Definition: DNA_ID.h:1057
@ INDEX_ID_MAX
Definition: DNA_ID.h:1058
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ LIB_TAG_INDIRECT
Definition: DNA_ID.h:677
@ LIB_TAG_PRE_EXISTING
Definition: DNA_ID.h:709
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
#define ID_REAL_USERS(id)
Definition: DNA_ID.h:553
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY
Definition: DNA_ID.h:322
@ ID_LI
Definition: DNA_ID_enums.h:46
@ ID_WS
Definition: DNA_ID_enums.h:79
@ ID_SCE
Definition: DNA_ID_enums.h:45
@ ID_OB
Definition: DNA_ID_enums.h:47
@ 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:674
bool ED_operator_outliner_active(struct bContext *C)
Definition: screen_ops.c:253
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
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:747
Read Guarded memory(de)allocation.
@ PROP_POINTER
Definition: RNA_types.h:64
@ PROP_COLLECTION
Definition: RNA_types.h:65
PropertyFlag
Definition: RNA_types.h:183
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:294
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
#define C
Definition: RandGen.cpp:25
#define UI_UNIT_Y
void UI_view2d_region_to_view(const struct View2D *v2d, float x, float y, float *r_view_x, float *r_view_y) ATTR_NONNULL()
@ KM_CLICK_DRAG
Definition: WM_types.h:275
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_WINDOW
Definition: WM_types.h:325
#define NC_ID
Definition: WM_types.h:345
#define NC_ANIMATION
Definition: WM_types.h:338
#define ND_OB_SELECT
Definition: WM_types.h:390
#define ND_KEYINGSET
Definition: WM_types.h:396
#define NC_SCENE
Definition: WM_types.h:328
#define ND_FCURVES_ORDER
Definition: WM_types.h:447
#define NA_REMOVED
Definition: WM_types.h:526
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:201
@ WM_OP_EXEC_DEFAULT
Definition: WM_types.h:208
#define ND_KEYS
Definition: WM_types.h:412
virtual PropertyRNA * getPropertyRNA() const
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:517
int ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
Main Driver Management API calls.
Definition: drivers.c:395
void * tree
DRWShaderLibrary * lib
#define str(s)
#define GS(x)
Definition: iris.c:225
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
bool add(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
static void area(int d1, int d2, int e1, int e2, float weights[2])
void all_open(const SpaceOutliner &space_outliner, const VisitorFn visitor)
void all(const SpaceOutliner &space_outliner, const VisitorFn visitor)
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
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 do_outliner_drivers_editop(SpaceOutliner *space_outliner, ReportList *reports, short mode)
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)
void outliner_set_coordinates(const ARegion *region, const SpaceOutliner *space_outliner)
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)
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 void tree_element_show_hierarchy(Scene *scene, SpaceOutliner *space_outliner)
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 int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEvent *event)
static bool ed_operator_outliner_id_orphans_active(bContext *C)
@ DRIVERS_EDITMODE_ADD
@ DRIVERS_EDITMODE_REMOVE
bool outliner_flag_set(const SpaceOutliner &space_outliner, const short flag, const short set)
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)
@ KEYINGSET_EDITMODE_ADD
@ KEYINGSET_EDITMODE_REMOVE
void OUTLINER_OT_highlight_update(wmOperatorType *ot)
static void do_outliner_keyingset_editop(SpaceOutliner *space_outliner, KeyingSet *ks, const short mode)
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)
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)
static int outliner_id_delete_tag(bContext *C, ReportList *reports, TreeElement *te, const float mval[2])
void OUTLINER_OT_show_one_level(wmOperatorType *ot)
static void id_delete_tag(bContext *C, ReportList *reports, TreeElement *te, TreeStoreElem *tselem)
static int outliner_id_remap_exec(bContext *C, wmOperator *op)
void OUTLINER_OT_id_delete(wmOperatorType *ot)
bool outliner_flag_flip(const SpaceOutliner &space_outliner, const short flag)
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 outliner_item_openclose(TreeElement *te, bool open, bool toggle_all)
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)
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 id_delete_tag_fn(bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
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))
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)
@ TE_PRETEND_HAS_CHILDREN
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)
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:33
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1080
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
Definition: rna_access.c:5155
bool RNA_struct_is_ID(const StructRNA *type)
Definition: rna_access.c:655
bool RNA_property_animateable(const PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1993
char * RNA_struct_name_get_alloc(PointerRNA *ptr, char *fixedbuf, int fixedlen, int *r_len)
Definition: rna_access.c:907
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:4874
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
const PointerRNA PointerRNA_NULL
Definition: rna_access.c:61
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:4921
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
void RNA_enum_set_identifier(bContext *C, PointerRNA *ptr, const char *name, const char *id)
Definition: rna_access.c:5027
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1075
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_enum_funcs_runtime(PropertyRNA *prop, EnumPropertyGetFunc getfunc, EnumPropertySetFunc setfunc, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3258
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4487
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4436
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
Definition: rna_define.c:2848
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
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:3597
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:3783
char * RNA_path_append(const char *path, const PointerRNA *UNUSED(ptr), PropertyRNA *prop, int intkey, const char *strkey)
Definition: rna_path.cc:584
const EnumPropertyItem DummyRNA_NULL_items[]
Definition: rna_rna.c:26
const char * identifier
Definition: RNA_types.h:461
const char * name
Definition: RNA_types.h:465
unsigned int flag
Definition: DNA_ID.h:312
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
IDOverrideLibrary * override_library
Definition: DNA_ID.h:412
char name[66]
Definition: DNA_ID.h:378
ListBase paths
struct Library * parent
Definition: DNA_ID.h:474
void * data
Definition: DNA_listBase.h:26
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
TreeStoreElem * prev_tselem
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
int active_keyingset
ListBase keyingsets
struct TreeStoreElem search_tse
char search_string[64]
struct TreeElement * parent
ListBase subtree
TreeStoreElem * store_elem
struct TreeElement * next
float xmax
Definition: DNA_vec_types.h:69
float xmin
Definition: DNA_vec_types.h:69
float ymax
Definition: DNA_vec_types.h:70
float ymin
Definition: DNA_vec_types.h:70
short val
Definition: WM_types.h:680
int mval[2]
Definition: WM_types.h:684
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_drag_start_mval(const wmEvent *event, const ARegion *region, int r_mval[2])
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_main_add_notifier(unsigned int type, void *reference)
int WM_operator_name_call_ptr(bContext *C, wmOperatorType *ot, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ MOUSEMOVE
@ LEFTMOUSE
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
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:661
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width)
void WM_operator_properties_free(PointerRNA *ptr)
Definition: wm_operators.c:783