Blender  V3.3
rna_access_compare_override.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <string.h>
8 
9 #include <CLG_log.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "DNA_ID.h"
14 #include "DNA_anim_types.h"
15 #include "DNA_camera_types.h"
16 #include "DNA_constraint_types.h"
18 #include "DNA_key_types.h"
19 #include "DNA_modifier_types.h"
20 #include "DNA_object_types.h"
21 
22 #include "BLI_listbase.h"
23 #include "BLI_string.h"
24 #include "BLI_utildefines.h"
25 
26 //#define DEBUG_OVERRIDE_TIMEIT
27 
28 #ifdef DEBUG_OVERRIDE_TIMEIT
29 # include "PIL_time_utildefines.h"
30 #endif
31 
32 #include "BKE_armature.h"
33 #include "BKE_idprop.h"
34 #include "BKE_idtype.h"
35 #include "BKE_lib_override.h"
36 #include "BKE_main.h"
37 
38 #include "RNA_access.h"
39 #include "RNA_define.h"
40 #include "RNA_enum_types.h"
41 #include "RNA_path.h"
42 #include "RNA_prototypes.h"
43 
44 #include "rna_access_internal.h"
45 #include "rna_internal.h"
46 
47 static CLG_LogRef LOG = {"rna.access_compare_override"};
48 
58  PointerRNA *ptr,
59  PropertyRNA *prop,
60  char **r_rna_path)
61 {
62  ID *id = ptr->owner_id;
63  ID *owner_id = id;
64  const char *rna_path_prefix = NULL;
65 
66  if (r_rna_path != NULL) {
67  *r_rna_path = NULL;
68  }
69 
70  if (id == NULL) {
71  return NULL;
72  }
73 
75  /* XXX this is very bad band-aid code, but for now it will do.
76  * We should at least use a #define for those prop names.
77  * Ideally RNA as a whole should be aware of those PITA of embedded IDs, and have a way to
78  * retrieve their owner IDs and generate paths from those.
79  */
80 
81  switch (GS(id->name)) {
82  case ID_KE:
83  owner_id = ((Key *)id)->from;
84  rna_path_prefix = "shape_keys.";
85  break;
86  case ID_GR:
87  case ID_NT:
88  /* Master collections, Root node trees. */
89  owner_id = RNA_find_real_ID_and_path(bmain, id, &rna_path_prefix);
90  break;
91  default:
93  }
94  }
95 
96  if (r_rna_path == NULL) {
97  return owner_id;
98  }
99 
100  char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
101  if (rna_path) {
102  *r_rna_path = rna_path;
103  if (rna_path_prefix != NULL) {
104  *r_rna_path = BLI_sprintfN("%s%s", rna_path_prefix, rna_path);
105  MEM_freeN(rna_path);
106  }
107 
108  return owner_id;
109  }
110  return NULL;
111 }
112 
114 {
115  return rna_ensure_property(prop)->flag_override;
116 }
117 
119 {
120  if (prop->magic == RNA_MAGIC) {
121  /* Special handling for insertions of constraints or modifiers... */
122  /* TODO: Note We may want to add a more generic system to RNA
123  * (like a special property in struct of items)
124  * if we get more overridable collections,
125  * for now we can live with those special-cases handling I think. */
126  if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
127  bConstraint *con = ptr->data;
129  return true;
130  }
131  }
132  else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
133  ModifierData *mod = ptr->data;
135  return true;
136  }
137  }
138  else if (RNA_struct_is_a(ptr->type, &RNA_GpencilModifier)) {
139  GpencilModifierData *gp_mod = ptr->data;
141  return true;
142  }
143  }
144  else if (RNA_struct_is_a(ptr->type, &RNA_NlaTrack)) {
145  NlaTrack *nla_track = ptr->data;
146  if (nla_track->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) {
147  return true;
148  }
149  }
150  else if (RNA_struct_is_a(ptr->type, &RNA_CameraBackgroundImage)) {
151  CameraBGImage *bgpic = ptr->data;
153  return true;
154  }
155  }
156  /* If this is a RNA-defined property (real or 'virtual' IDProp),
157  * we want to use RNA prop flag. */
158  return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) &&
160  }
161  /* If this is a real 'pure' IDProp (aka custom property), we want to use the IDProp flag. */
162  IDProperty *idprop = (IDProperty *)prop;
163  return (idprop->flag & IDP_FLAG_OVERRIDABLE_LIBRARY) != 0;
164 }
165 
167  PropertyRNA *prop,
168  const bool is_overridable)
169 {
170  /* Only works for pure custom properties IDProps. */
171  if (prop->magic != RNA_MAGIC) {
172  IDProperty *idprop = (IDProperty *)prop;
173 
174  idprop->flag = is_overridable ? (idprop->flag | IDP_FLAG_OVERRIDABLE_LIBRARY) :
175  (idprop->flag & ~IDP_FLAG_OVERRIDABLE_LIBRARY);
176  return true;
177  }
178 
179  return false;
180 }
181 
183 {
184  char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
185  ID *id = ptr->owner_id;
186 
187  if (rna_path == NULL || id == NULL || !ID_IS_OVERRIDE_LIBRARY(id)) {
188  return false;
189  }
190 
192 }
193 
195 {
196  prop = rna_ensure_property(prop);
197 
198  return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON);
199 }
200 
202  PointerRNA *ptr_dst,
203  PointerRNA *ptr_src,
204  PointerRNA *ptr_storage,
205  PropertyRNA *prop_dst,
206  PropertyRNA *prop_src,
207  PropertyRNA *prop_storage,
208  PointerRNA *ptr_item_dst,
209  PointerRNA *ptr_item_src,
210  PointerRNA *ptr_item_storage,
212 
214  Main *bmain, PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
215 {
216  if (!RNA_property_editable(ptr, prop)) {
217  return false;
218  }
219 
220  PropertyRNA *prop_dst = prop;
221  PropertyRNA *prop_src = prop;
222 
223  /* Ensure we get real property data,
224  * be it an actual RNA property, or an #IDProperty in disguise. */
225  prop_dst = rna_ensure_property_realdata(&prop_dst, ptr);
226  prop_src = rna_ensure_property_realdata(&prop_src, fromptr);
227 
228  /* IDprops: destination may not exist, if source does and is set, try to create it. */
229  /* NOTE: this is sort of quick hack/bandage to fix the issue,
230  * we need to rethink how IDProps are handled in 'diff' RNA code completely, IMHO. */
231  if (prop_src != NULL && prop_dst == NULL && RNA_property_is_set(fromptr, prop)) {
232  BLI_assert(prop_src->magic != RNA_MAGIC);
233  IDProperty *idp_dst = RNA_struct_idprops(ptr, true);
234  IDProperty *prop_idp_dst = IDP_CopyProperty((IDProperty *)prop_src);
235  IDP_AddToGroup(idp_dst, prop_idp_dst);
236  rna_idproperty_touch(prop_idp_dst);
237  /* Nothing else to do here... */
238  return true;
239  }
240 
241  if (ELEM(NULL, prop_dst, prop_src)) {
242  return false;
243  }
244 
247  .subitem_reference_index = index,
248  .subitem_local_index = index,
249  };
251  bmain, ptr, fromptr, NULL, prop_dst, prop_src, NULL, NULL, NULL, NULL, &opop);
252 }
253 
254 static int rna_property_override_diff(Main *bmain,
255  PropertyRNAOrID *prop_a,
256  PropertyRNAOrID *prop_b,
257  const char *rna_path,
258  const size_t rna_path_len,
259  eRNACompareMode mode,
260  IDOverrideLibrary *override,
261  const eRNAOverrideMatch flags,
262  eRNAOverrideMatchResult *r_report_flags);
263 
265  Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, eRNACompareMode mode)
266 {
268 
269  PropertyRNAOrID prop_a, prop_b;
270 
271  rna_property_rna_or_id_get(prop, ptr_a, &prop_a);
272  rna_property_rna_or_id_get(prop, ptr_b, &prop_b);
273 
274  return (rna_property_override_diff(bmain, &prop_a, &prop_b, NULL, 0, mode, NULL, 0, NULL) == 0);
275 }
276 
277 bool RNA_struct_equals(Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode)
278 {
280  PropertyRNA *iterprop;
281  bool equals = true;
282 
283  if (ptr_a == NULL && ptr_b == NULL) {
284  return true;
285  }
286  if (ptr_a == NULL || ptr_b == NULL) {
287  return false;
288  }
289  if (ptr_a->type != ptr_b->type) {
290  return false;
291  }
292 
293  iterprop = RNA_struct_iterator_property(ptr_a->type);
294 
295  RNA_property_collection_begin(ptr_a, iterprop, &iter);
296  for (; iter.valid; RNA_property_collection_next(&iter)) {
297  PropertyRNA *prop = iter.ptr.data;
298 
299  if (!RNA_property_equals(bmain, ptr_a, ptr_b, prop, mode)) {
300  equals = false;
301  break;
302  }
303  }
305 
306  return equals;
307 }
308 
309 /* Low-level functions, also used by non-override RNA API like copy or equality check. */
310 
326  PropertyRNAOrID *prop_a,
327  PropertyRNAOrID *prop_b,
328  const char *rna_path,
329  const size_t rna_path_len,
330  eRNACompareMode mode,
331  IDOverrideLibrary *override,
332  const eRNAOverrideMatch flags,
333  eRNAOverrideMatchResult *r_report_flags)
334 {
335  BLI_assert(!ELEM(NULL, prop_a, prop_b));
336 
339  return 0;
340  }
341 
342  if (mode == RNA_EQ_UNSET_MATCH_ANY) {
343  /* Unset properties are assumed to match anything. */
344  if (!prop_a->is_set || !prop_b->is_set) {
345  return 0;
346  }
347  }
348  else if (mode == RNA_EQ_UNSET_MATCH_NONE) {
349  /* Unset properties never match set properties. */
350  if (prop_a->is_set != prop_b->is_set) {
351  return 1;
352  }
353  }
354 
355  if (prop_a->is_idprop && ELEM(NULL, prop_a->idprop, prop_b->idprop)) {
356  return (prop_a->idprop == prop_b->idprop) ? 0 : 1;
357  }
358 
359  /* Check if we are working with arrays. */
360  const bool is_array_a = prop_a->is_array;
361  const bool is_array_b = prop_b->is_array;
362 
363  if (is_array_a != is_array_b) {
364  /* Should probably never happen actually... */
366  return is_array_a ? 1 : -1;
367  }
368 
369  /* Get the length of the array to work with. */
370  const uint len_a = prop_a->array_len;
371  const uint len_b = prop_b->array_len;
372 
373  if (len_a != len_b) {
374  /* Do not handle override in that case,
375  * we do not support insertion/deletion from arrays for now. */
376  return len_a > len_b ? 1 : -1;
377  }
378 
379  if (is_array_a && len_a == 0) {
380  /* Empty arrays, will happen in some case with dynamic ones. */
381  return 0;
382  }
383 
384  RNAPropOverrideDiff override_diff = NULL;
385  /* Special case for IDProps, we use default callback then. */
386  if (prop_a->is_idprop) {
387  override_diff = rna_property_override_diff_default;
388  if (!prop_b->is_idprop && prop_b->rnaprop->override_diff != override_diff) {
389  override_diff = NULL;
390  }
391  }
392  else if (prop_b->is_idprop) {
393  override_diff = rna_property_override_diff_default;
394  if (prop_a->rnaprop->override_diff != override_diff) {
395  override_diff = NULL;
396  }
397  }
398  else if (prop_a->rnaprop->override_diff == prop_b->rnaprop->override_diff) {
399  override_diff = prop_a->rnaprop->override_diff;
400  if (override_diff == NULL) {
401  override_diff = rna_property_override_diff_default;
402  }
403  }
404 
405  if (override_diff == NULL) {
406  CLOG_ERROR(&LOG,
407  "'%s' gives unmatching or NULL RNA diff callbacks, should not happen (%d vs. %d)",
408  rna_path ? rna_path : prop_a->identifier,
409  !prop_a->is_idprop,
410  !prop_b->is_idprop);
412  return 1;
413  }
414 
415  bool override_changed = false;
416  eRNAOverrideMatch diff_flags = flags;
417  if (!RNA_property_overridable_get(&prop_a->ptr, prop_a->rawprop) ||
419  !RNA_property_editable_flag(&prop_a->ptr, prop_a->rawprop))) {
420  diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE;
421  }
422  const int diff = override_diff(bmain,
423  prop_a,
424  prop_b,
425  mode,
426  override,
427  rna_path,
428  rna_path_len,
429  diff_flags,
430  &override_changed);
431  if (override_changed && r_report_flags) {
432  *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_CREATED;
433  }
434 
435  return diff;
436 }
437 
438 /* Modify local data-block to make it ready for override application
439  * (only needed for diff operations, where we use
440  * the local data-block's data as second operand). */
442  PointerRNA *ptr_local,
443  PointerRNA *ptr_reference,
444  PointerRNA *ptr_storage,
445  PropertyRNA *prop_local,
446  PropertyRNA *prop_reference,
447  PropertyRNA *prop_storage,
449 {
450  int len_local, len_reference, len_storage = 0;
451  bool changed = false;
452 
453  if (ptr_storage == NULL) {
454  return changed;
455  }
456 
457  /* get the length of the array to work with */
458  len_local = RNA_property_array_length(ptr_local, prop_local);
459  len_reference = RNA_property_array_length(ptr_reference, prop_reference);
460  if (prop_storage) {
461  len_storage = RNA_property_array_length(ptr_storage, prop_storage);
462  }
463 
464  if (len_local != len_reference || len_local != len_storage) {
465  /* Do not handle override in that case,
466  * we do not support insertion/deletion from arrays for now. */
467  return changed;
468  }
469 
470  RNAPropOverrideStore override_store = NULL;
471  /* Special case for IDProps, we use default callback then. */
472  if (prop_local->magic != RNA_MAGIC) {
473  override_store = rna_property_override_store_default;
474  if (prop_reference->magic == RNA_MAGIC && prop_reference->override_store != override_store) {
475  override_store = NULL;
476  }
477  }
478  else if (prop_reference->magic != RNA_MAGIC) {
479  override_store = rna_property_override_store_default;
480  if (prop_local->override_store != override_store) {
481  override_store = NULL;
482  }
483  }
484  else if (prop_local->override_store == prop_reference->override_store) {
485  override_store = prop_local->override_store;
486  if (override_store == NULL) {
487  override_store = rna_property_override_store_default;
488  }
489  }
490 
491  if (ptr_storage != NULL && prop_storage->magic == RNA_MAGIC &&
492  !ELEM(prop_storage->override_store, NULL, override_store)) {
493  override_store = NULL;
494  }
495 
496  if (override_store == NULL) {
497  CLOG_ERROR(&LOG,
498  "'%s' gives unmatching or NULL RNA store callbacks, should not happen (%d vs. %d)",
499  op->rna_path,
500  prop_local->magic == RNA_MAGIC,
501  prop_reference->magic == RNA_MAGIC);
503  return changed;
504  }
505 
507  /* Only needed for diff operations. */
508  if (!ELEM(opop->operation,
512  continue;
513  }
514 
515  if (override_store(bmain,
516  ptr_local,
517  ptr_reference,
518  ptr_storage,
519  prop_local,
520  prop_reference,
521  prop_storage,
522  len_local,
523  len_reference,
524  len_storage,
525  opop)) {
526  changed = true;
527  }
528  }
529 
530  return changed;
531 }
532 
534  PointerRNA *ptr_dst,
535  PointerRNA *ptr_src,
536  PointerRNA *ptr_storage,
537  PropertyRNA *prop_dst,
538  PropertyRNA *prop_src,
539  PropertyRNA *prop_storage,
540  PointerRNA *ptr_item_dst,
541  PointerRNA *ptr_item_src,
542  PointerRNA *ptr_item_storage,
544 {
545  int len_dst, len_src, len_storage = 0;
546 
547  const short override_op = opop->operation;
548 
550  opop, ptr_dst, ptr_src, ptr_storage, prop_dst, prop_src, prop_storage)) {
551  return false;
552  }
553 
554  if (override_op == IDOVERRIDE_LIBRARY_OP_NOOP) {
555  return true;
556  }
557 
558  RNAPropOverrideApply override_apply = NULL;
559  /* Special case for IDProps, we use default callback then. */
560  if (prop_dst->magic != RNA_MAGIC) {
561  override_apply = rna_property_override_apply_default;
562  if (prop_src->magic == RNA_MAGIC && !ELEM(prop_src->override_apply, NULL, override_apply)) {
563  override_apply = NULL;
564  }
565  }
566  else if (prop_src->magic != RNA_MAGIC) {
567  override_apply = rna_property_override_apply_default;
568  if (!ELEM(prop_dst->override_apply, NULL, override_apply)) {
569  override_apply = NULL;
570  }
571  }
572  else if (prop_dst->override_apply == prop_src->override_apply) {
573  override_apply = prop_dst->override_apply;
574  if (override_apply == NULL) {
575  override_apply = rna_property_override_apply_default;
576  }
577  }
578 
579  if (ptr_storage && prop_storage->magic == RNA_MAGIC &&
580  !ELEM(prop_storage->override_apply, NULL, override_apply)) {
581  override_apply = NULL;
582  }
583 
584  if (override_apply == NULL) {
585  CLOG_ERROR(&LOG,
586  "'%s' gives unmatching or NULL RNA apply callbacks, should not happen (%d vs. %d)",
587  prop_dst->magic != RNA_MAGIC ? ((IDProperty *)prop_dst)->name :
588  prop_dst->identifier,
589  prop_dst->magic == RNA_MAGIC,
590  prop_src->magic == RNA_MAGIC);
592  return false;
593  }
594 
595  /* get the length of the array to work with */
596  len_dst = RNA_property_array_length(ptr_dst, prop_dst);
597  len_src = RNA_property_array_length(ptr_src, prop_src);
598  if (ptr_storage) {
599  len_storage = RNA_property_array_length(ptr_storage, prop_storage);
600  }
601 
602  if (len_dst != len_src || (ptr_storage && len_dst != len_storage)) {
603  /* Do not handle override in that case,
604  * we do not support insertion/deletion from arrays for now. */
605  return false;
606  }
607 
608  /* get and set the default values as appropriate for the various types */
609  const bool success = override_apply(bmain,
610  ptr_dst,
611  ptr_src,
612  ptr_storage,
613  prop_dst,
614  prop_src,
615  prop_storage,
616  len_dst,
617  len_src,
618  len_storage,
619  ptr_item_dst,
620  ptr_item_src,
621  ptr_item_storage,
622  opop);
623  return success;
624 }
625 
627  PointerRNA *ptr_local,
628  PointerRNA *ptr_reference,
629  const char *root_path,
630  const size_t root_path_len,
631  IDOverrideLibrary *override,
632  const eRNAOverrideMatch flags,
633  eRNAOverrideMatchResult *r_report_flags)
634 {
636  PropertyRNA *iterprop;
637  bool matching = true;
638 
639  BLI_assert(ptr_local->type == ptr_reference->type);
640  BLI_assert(ptr_local->owner_id && ptr_reference->owner_id);
641 
642  const bool ignore_non_overridable = (flags & RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE) != 0;
643  const bool ignore_overridden = (flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN) != 0;
644  const bool do_create = (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0;
645  const bool do_restore = (flags & RNA_OVERRIDE_COMPARE_RESTORE) != 0;
646 
647 #ifdef DEBUG_OVERRIDE_TIMEIT
648  static float _sum_time_global = 0.0f;
649  static float _num_time_global = 0.0f;
650  double _timeit_time_global;
651  static float _sum_time_diffing = 0.0f;
652  static float _delta_time_diffing = 0.0f;
653  static int _num_delta_time_diffing = 0.0f;
654  static float _num_time_diffing = 0.0f;
655  double _timeit_time_diffing;
656 
657  if (!root_path) {
658  _delta_time_diffing = 0.0f;
659  _num_delta_time_diffing = 0;
660  _timeit_time_global = PIL_check_seconds_timer();
661  }
662 #endif
663 
664  if (ptr_local->owner_id == ptr_local->data && GS(ptr_local->owner_id->name) == ID_OB) {
665  /* Our beloved pose's bone cross-data pointers. Usually, depsgraph evaluation would
666  * ensure this is valid, but in some situations (like hidden collections etc.) this won't
667  * be the case, so we need to take care of this ourselves.
668  *
669  * NOTE: Typically callers of this function (from BKE_lib_override area) will already have
670  * ensured this. However, studio is still reporting sporadic, unreproducible crashes due to
671  * invalid pose data, so think there are still some cases where some armatures are somehow
672  * missing updates (possibly due to dependencies?). Since calling this function on same ID
673  * several time is almost free, and safe even in a threaded context as long as it has been done
674  * at least once first outside of threaded processing, we do it another time here. */
675  Object *ob_local = (Object *)ptr_local->owner_id;
676  if (ob_local->type == OB_ARMATURE) {
677  Object *ob_reference = (Object *)ptr_local->owner_id->override_library->reference;
678  BLI_assert(ob_local->data != NULL);
679  BLI_assert(ob_reference->data != NULL);
680  BKE_pose_ensure(bmain, ob_local, ob_local->data, true);
681  BKE_pose_ensure(bmain, ob_reference, ob_reference->data, true);
682  }
683  }
684 
685  iterprop = RNA_struct_iterator_property(ptr_local->type);
686 
687  for (RNA_property_collection_begin(ptr_local, iterprop, &iter); iter.valid;
689  PropertyRNA *rawprop = iter.ptr.data;
690 
691  PropertyRNAOrID prop_local;
692  PropertyRNAOrID prop_reference;
693 
694  rna_property_rna_or_id_get(rawprop, ptr_local, &prop_local);
695  rna_property_rna_or_id_get(rawprop, ptr_reference, &prop_reference);
696 
697  BLI_assert(prop_local.rnaprop != NULL);
698  BLI_assert(prop_local.rnaprop == prop_reference.rnaprop);
699  BLI_assert(prop_local.is_idprop == prop_reference.is_idprop);
700 
701  if ((prop_local.is_idprop && prop_local.idprop == NULL) ||
702  (prop_reference.is_idprop && prop_reference.idprop == NULL)) {
703  continue;
704  }
705 
706  if (ignore_non_overridable && !RNA_property_overridable_get(&prop_local.ptr, rawprop)) {
707  continue;
708  }
709 
710  if (!prop_local.is_idprop &&
712  continue;
713  }
714 
715 #if 0 /* This actually makes things slower, since it has to check for animation paths etc! */
716  if (RNA_property_animated(ptr_local, prop_local)) {
717  /* We cannot do anything here really, animation is some kind of dynamic overrides that has
718  * precedence over static one... */
719  continue;
720  }
721 #endif
722 
723 #define RNA_PATH_BUFFSIZE 8192
724 
725  char rna_path_buffer[RNA_PATH_BUFFSIZE];
726  char *rna_path = rna_path_buffer;
727  size_t rna_path_len = 0;
728 
729  /* XXX TODO: this will have to be refined to handle collections insertions, and array items. */
730  if (root_path) {
731  BLI_assert(strlen(root_path) == root_path_len);
732 
733  const char *prop_name = prop_local.identifier;
734  const size_t prop_name_len = strlen(prop_name);
735 
736  /* Inlined building (significantly more efficient). */
737  if (!prop_local.is_idprop) {
738  rna_path_len = root_path_len + 1 + prop_name_len;
739  if (rna_path_len >= RNA_PATH_BUFFSIZE) {
740  rna_path = MEM_mallocN(rna_path_len + 1, __func__);
741  }
742 
743  memcpy(rna_path, root_path, root_path_len);
744  rna_path[root_path_len] = '.';
745  memcpy(rna_path + root_path_len + 1, prop_name, prop_name_len);
746  rna_path[rna_path_len] = '\0';
747  }
748  else {
749  rna_path_len = root_path_len + 2 + prop_name_len + 2;
750  if (rna_path_len >= RNA_PATH_BUFFSIZE) {
751  rna_path = MEM_mallocN(rna_path_len + 1, __func__);
752  }
753 
754  memcpy(rna_path, root_path, root_path_len);
755  rna_path[root_path_len] = '[';
756  rna_path[root_path_len + 1] = '"';
757  memcpy(rna_path + root_path_len + 2, prop_name, prop_name_len);
758  rna_path[root_path_len + 2 + prop_name_len] = '"';
759  rna_path[root_path_len + 2 + prop_name_len + 1] = ']';
760  rna_path[rna_path_len] = '\0';
761  }
762  }
763  else {
764  /* This is rather slow, but is not much called, so not really worth optimizing. */
765  rna_path = RNA_path_from_ID_to_property(ptr_local, rawprop);
766  if (rna_path != NULL) {
767  rna_path_len = strlen(rna_path);
768  }
769  }
770  if (rna_path == NULL) {
771  continue;
772  }
773 
774  CLOG_INFO(&LOG, 5, "Override Checking %s", rna_path);
775 
777  if (ignore_overridden && op != NULL) {
779 
780  if (rna_path != rna_path_buffer) {
781  MEM_freeN(rna_path);
782  }
783  continue;
784  }
785 
786 #ifdef DEBUG_OVERRIDE_TIMEIT
787  if (!root_path) {
788  _timeit_time_diffing = PIL_check_seconds_timer();
789  }
790 #endif
791 
792  eRNAOverrideMatchResult report_flags = 0;
793  const int diff = rna_property_override_diff(bmain,
794  &prop_local,
795  &prop_reference,
796  rna_path,
797  rna_path_len,
799  override,
800  flags,
801  &report_flags);
802 
803 #ifdef DEBUG_OVERRIDE_TIMEIT
804  if (!root_path) {
805  const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_diffing);
806  _delta_time_diffing += _delta_time;
807  _num_delta_time_diffing++;
808  }
809 #endif
810 
811  matching = matching && diff == 0;
812  if (r_report_flags) {
813  *r_report_flags |= report_flags;
814  }
815 
816  if (diff != 0) {
817  /* XXX TODO: refine this for per-item overriding of arrays... */
818  op = BKE_lib_override_library_property_find(override, rna_path);
820 
821  if (op != NULL) {
823  }
824 
825  if (do_restore && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0) {
826  /* We are allowed to restore to reference's values. */
827  if (ELEM(NULL, op, opop) || opop->operation == IDOVERRIDE_LIBRARY_OP_NOOP) {
828  /* We should restore that property to its reference value */
829  if (RNA_property_editable(ptr_local, rawprop)) {
832  .subitem_reference_index = -1,
833  .subitem_local_index = -1,
834  };
836  ptr_local,
837  ptr_reference,
838  NULL,
839  rawprop,
840  rawprop,
841  NULL,
842  NULL,
843  NULL,
844  NULL,
845  &opop_tmp);
846  if (r_report_flags) {
847  *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_RESTORED;
848  }
849  }
850  else {
851  /* Too noisy for now, this triggers on runtime props like transform matrices etc. */
852 #if 0
853  BLI_assert_msg(0, "We have differences between reference and "
854  "overriding data on non-editable property.");
855 #endif
856  matching = false;
857  }
858  }
859  }
860  else if ((report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0 && ELEM(NULL, op, opop)) {
861  /* This property is not overridden, and differs from reference, so we have no match. */
862  matching = false;
863  if (!(do_create || do_restore)) {
864  /* Since we have no 'changing' action allowed, we can break here. */
865  if (rna_path != rna_path_buffer) {
866  MEM_freeN(rna_path);
867  }
868  break;
869  }
870  }
871  }
872 
873  if (rna_path != rna_path_buffer) {
874  MEM_freeN(rna_path);
875  }
876 #undef RNA_PATH_BUFFSIZE
877  }
879 
880 #ifdef DEBUG_OVERRIDE_TIMEIT
881  if (!root_path) {
882  const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_global);
883  _sum_time_global += _delta_time;
884  _num_time_global++;
885  _sum_time_diffing += _delta_time_diffing;
886  _num_time_diffing++;
887  printf("ID: %s\n", ((ID *)ptr_local->owner_id)->name);
888  printf("time end (%s): %.6f\n", __func__, _delta_time);
889  printf("time averaged (%s): %.6f (total: %.6f, in %d runs)\n",
890  __func__,
891  (_sum_time_global / _num_time_global),
892  _sum_time_global,
893  (int)_num_time_global);
894  printf("diffing time end (%s): %.6f (in %d runs)\n",
895  __func__,
896  _delta_time_diffing,
897  _num_delta_time_diffing);
898  printf("diffing time averaged (%s): %.6f (total: %.6f, in %d runs)\n",
899  __func__,
900  (_sum_time_diffing / _num_time_diffing),
901  _sum_time_diffing,
902  (int)_num_time_diffing);
903  }
904 #endif
905 
906  return matching;
907 }
908 
910  PointerRNA *ptr_local,
911  PointerRNA *ptr_reference,
912  PointerRNA *ptr_storage,
913  IDOverrideLibrary *override)
914 {
915  bool changed = false;
916 
917 #ifdef DEBUG_OVERRIDE_TIMEIT
919 #endif
920  LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &override->properties) {
921  /* Simplified for now! */
922  PointerRNA data_reference, data_local;
923  PropertyRNA *prop_reference, *prop_local;
924 
925  if (RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local) &&
926  RNA_path_resolve_property(ptr_reference, op->rna_path, &data_reference, &prop_reference)) {
927  PointerRNA data_storage;
928  PropertyRNA *prop_storage = NULL;
929 
930  /* It is totally OK if this does not success,
931  * only a subset of override operations actually need storage. */
932  if (ptr_storage && (ptr_storage->owner_id != NULL)) {
933  RNA_path_resolve_property(ptr_storage, op->rna_path, &data_storage, &prop_storage);
934  }
935 
937  &data_local,
938  &data_reference,
939  &data_storage,
940  prop_reference,
941  prop_local,
942  prop_storage,
943  op)) {
944  changed = true;
945  }
946  }
947  }
948 #ifdef DEBUG_OVERRIDE_TIMEIT
950 #endif
951 
952  return changed;
953 }
954 
956  PointerRNA *ptr_dst,
957  PointerRNA *ptr_src,
958  PointerRNA *ptr_storage,
959  PropertyRNA *prop_dst,
960  PropertyRNA *prop_src,
961  PropertyRNA *prop_storage,
962  PointerRNA **r_ptr_item_dst,
963  PointerRNA **r_ptr_item_src,
964  PointerRNA **r_ptr_item_storage,
965  PointerRNA *private_ptr_item_dst,
966  PointerRNA *private_ptr_item_src,
967  PointerRNA *private_ptr_item_storage,
970 {
971  if ((RNA_property_type(prop_dst) != PROP_COLLECTION ||
972  RNA_property_type(prop_src) != PROP_COLLECTION ||
973  (prop_storage != NULL && RNA_property_type(prop_storage) != PROP_COLLECTION)) ||
974  (opop->subitem_local_name == NULL && opop->subitem_reference_name == NULL &&
975  opop->subitem_local_index == -1 && opop->subitem_reference_index == -1)) {
976  return;
977  }
978 
979  RNA_POINTER_INVALIDATE(private_ptr_item_dst);
980  RNA_POINTER_INVALIDATE(private_ptr_item_src);
981  if (prop_storage != NULL) {
982  RNA_POINTER_INVALIDATE(private_ptr_item_storage);
983  }
984  if (opop->subitem_local_name != NULL) {
986  ptr_src, prop_src, opop->subitem_local_name, private_ptr_item_src);
987  if (opop->subitem_reference_name != NULL &&
989  ptr_dst, prop_dst, opop->subitem_reference_name, private_ptr_item_dst)) {
990  /* This is rather fragile, but the fact that local override IDs may have a different name
991  * than their linked reference makes it necessary.
992  * Basically, here we are considering that if we cannot find the original linked ID in
993  * the local override we are (re-)applying the operations, then it may be because some of
994  * those operations have already been applied, and we may already have the local ID
995  * pointer we want to set.
996  * This happens e.g. during re-sync of an override, since we have already remapped all ID
997  * pointers to their expected values.
998  * In that case we simply try to get the property from the local expected name. */
999  }
1000  else {
1002  ptr_dst, prop_dst, opop->subitem_local_name, private_ptr_item_dst);
1003  }
1004  }
1005  else if (opop->subitem_reference_name != NULL) {
1007  ptr_src, prop_src, opop->subitem_reference_name, private_ptr_item_src);
1009  ptr_dst, prop_dst, opop->subitem_reference_name, private_ptr_item_dst);
1010  }
1011  else if (opop->subitem_local_index != -1) {
1013  ptr_src, prop_src, opop->subitem_local_index, private_ptr_item_src);
1014  if (opop->subitem_reference_index != -1) {
1016  ptr_dst, prop_dst, opop->subitem_reference_index, private_ptr_item_dst);
1017  }
1018  else {
1020  ptr_dst, prop_dst, opop->subitem_local_index, private_ptr_item_dst);
1021  }
1022  }
1023  else if (opop->subitem_reference_index != -1) {
1025  ptr_src, prop_src, opop->subitem_reference_index, private_ptr_item_src);
1027  ptr_dst, prop_dst, opop->subitem_reference_index, private_ptr_item_dst);
1028  }
1029  if (prop_storage != NULL) {
1030  if (opop->subitem_local_name != NULL) {
1032  ptr_storage, prop_storage, opop->subitem_local_name, private_ptr_item_storage);
1033  }
1034  else if (opop->subitem_reference_name != NULL) {
1036  ptr_storage, prop_storage, opop->subitem_reference_name, private_ptr_item_storage);
1037  }
1038  else if (opop->subitem_local_index != -1) {
1040  ptr_storage, prop_storage, opop->subitem_local_index, private_ptr_item_storage);
1041  }
1042  else if (opop->subitem_reference_index != -1) {
1044  ptr_storage, prop_storage, opop->subitem_reference_index, private_ptr_item_storage);
1045  }
1046  }
1047  *r_ptr_item_dst = private_ptr_item_dst;
1048  *r_ptr_item_src = private_ptr_item_src;
1049  if (prop_storage != NULL) {
1050  *r_ptr_item_storage = private_ptr_item_storage;
1051  }
1052 
1053  /* Note that there is no reason to report in case no item is expected, i.e. in case subitem name
1054  * and index are invalid. This can often happen when inserting new items (constraint,
1055  * modifier...) in a collection that supports it. */
1056  if ((*r_ptr_item_dst)->type == NULL &&
1057  ((opop->subitem_reference_name != NULL && opop->subitem_reference_name[0] != '\0') ||
1058  opop->subitem_reference_index != -1)) {
1059  CLOG_INFO(&LOG,
1060  2,
1061  "Failed to find destination sub-item '%s' (%d) of '%s' in new override data '%s'",
1062  opop->subitem_reference_name,
1064  op->rna_path,
1065  ptr_dst->owner_id->name);
1066  }
1067  if ((*r_ptr_item_src)->type == NULL &&
1068  ((opop->subitem_local_name != NULL && opop->subitem_local_name[0] != '\0') ||
1069  opop->subitem_local_index != -1)) {
1070  CLOG_INFO(&LOG,
1071  2,
1072  "Failed to find source sub-item '%s' (%d) of '%s' in old override data '%s'",
1073  opop->subitem_local_name,
1074  opop->subitem_local_index,
1075  op->rna_path,
1076  ptr_src->owner_id->name);
1077  }
1078 }
1079 
1081  PointerRNA *ptr_dst,
1082  PointerRNA *ptr_src,
1083  PointerRNA *ptr_item_dst,
1084  PointerRNA *ptr_item_src)
1085 {
1086  ID *id_owner_src = rna_property_override_property_real_id_owner(bmain, ptr_src, NULL, NULL);
1087  ID *id_owner_dst = rna_property_override_property_real_id_owner(bmain, ptr_dst, NULL, NULL);
1088  ID *id_src = rna_property_override_property_real_id_owner(bmain, ptr_item_src, NULL, NULL);
1089  ID *id_dst = rna_property_override_property_real_id_owner(bmain, ptr_item_dst, NULL, NULL);
1090 
1091  BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_owner_src));
1092 
1093  /* If the owner ID is not part of an override hierarchy, there is no possible resync. */
1095  return;
1096  }
1097 
1098  /* If `id_src` is not a liboverride, we cannot perform any further 'need resync' checks from
1099  * here. */
1100  if (id_src != NULL && !ID_IS_OVERRIDE_LIBRARY_REAL(id_src)) {
1101  return;
1102  }
1103 
1104  if (/* We might be in a case where id_dst has already been processed and its usages
1105  * remapped to its new local override. In that case overrides and linked data
1106  * are always properly matching. */
1107  id_src != id_dst &&
1108  /* If one of the pointers is NULL and not the other, we are in a non-matching case. */
1109  (ELEM(NULL, id_src, id_dst) ||
1110  /* If `id_dst` is not from same lib as id_src, and linked reference ID of `id_src` is not
1111  * `id_dst`, we are in a non-matching case. */
1112  (id_dst->lib != id_src->lib && id_src->override_library->reference != id_dst) ||
1113  /* If `id_dst` is from same lib as id_src, and is not same as `id_owner`, we are in a
1114  * non-matching case.
1115  *
1116  * NOTE: Here we are testing if `id_owner` is referencing itself, in that case the new
1117  * override copy generated by `BKE_lib_override_library_update` will already have its
1118  * self-references updated to itself, instead of still pointing to its linked source. */
1119  (id_dst->lib == id_src->lib && id_dst != id_owner_dst))) {
1120  id_owner_dst->tag |= LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
1121  if (ID_IS_LINKED(id_owner_src)) {
1122  id_owner_src->lib->tag |= LIBRARY_TAG_RESYNC_REQUIRED;
1123  }
1124  CLOG_INFO(&LOG, 3, "Local override %s detected as needing resync", id_owner_dst->name);
1125  }
1126 }
1127 
1129  PointerRNA *ptr_dst,
1130  PointerRNA *ptr_src,
1131  PointerRNA *ptr_storage,
1132  PropertyRNA *prop_dst,
1133  PropertyRNA *prop_src,
1134  PropertyRNA *prop_storage,
1135  PointerRNA *ptr_item_dst,
1136  PointerRNA *ptr_item_src,
1137  PointerRNA *ptr_item_storage,
1139  const bool do_insert)
1140 {
1142  if (!do_insert != !ELEM(opop->operation,
1145  if (!do_insert) {
1146  CLOG_INFO(&LOG, 5, "Skipping insert override operations in first pass (%s)", op->rna_path);
1147  }
1148  continue;
1149  }
1150 
1151  /* NOTE: will have to think about putting that logic into its own function maybe?
1152  * Would be nice to have it in a single place...
1153  * Note that here, src is the local saved ID, and dst is a copy of the linked ID (since we use
1154  * local ID as storage to apply local changes on top of a clean copy of the linked data). */
1155  PointerRNA private_ptr_item_dst, private_ptr_item_src, private_ptr_item_storage;
1157  ptr_src,
1158  ptr_storage,
1159  prop_dst,
1160  prop_src,
1161  prop_storage,
1162  &ptr_item_dst,
1163  &ptr_item_src,
1164  &ptr_item_storage,
1165  &private_ptr_item_dst,
1166  &private_ptr_item_src,
1167  &private_ptr_item_storage,
1168  op,
1169  opop);
1170 
1172  ptr_dst,
1173  ptr_src,
1174  ptr_storage,
1175  prop_dst,
1176  prop_src,
1177  prop_storage,
1178  ptr_item_dst,
1179  ptr_item_src,
1180  ptr_item_storage,
1181  opop)) {
1182  CLOG_INFO(&LOG,
1183  4,
1184  "Failed to apply '%s' override operation on %s\n",
1185  op->rna_path,
1186  ptr_src->owner_id->name);
1187  }
1188  /* Ensure RNA type of the liboverride property matches the one of the RNA property. These types
1189  * may become desynchronized for 'valid' reasons in very rare cases (in case the same RNA path
1190  * changes to a different type of data!). See also start of
1191  * #rna_property_override_apply_default for details. */
1192  op->rna_prop_type = RNA_property_type(prop_dst);
1193  }
1194 }
1195 
1197  PointerRNA *ptr_dst,
1198  PointerRNA *ptr_src,
1199  PointerRNA *ptr_storage,
1200  IDOverrideLibrary *override,
1201  const eRNAOverrideApplyFlag flag)
1202 {
1203 #ifdef DEBUG_OVERRIDE_TIMEIT
1205 #endif
1206  /* NOTE: Applying insert operations in a separate pass is mandatory.
1207  * We could optimize this later, but for now, as inefficient as it is,
1208  * don't think this is a critical point.
1209  */
1210  bool do_insert = false;
1211  for (int i = 0; i < 2; i++, do_insert = true) {
1212  LISTBASE_FOREACH (IDOverrideLibraryProperty *, op, &override->properties) {
1213  /* Simplified for now! */
1214  PointerRNA data_src, data_dst;
1215  PointerRNA data_item_src, data_item_dst;
1216  PropertyRNA *prop_src, *prop_dst;
1217 
1219  ptr_dst, op->rna_path, &data_dst, &prop_dst, &data_item_dst) &&
1221  ptr_src, op->rna_path, &data_src, &prop_src, &data_item_src)) {
1222  PointerRNA data_storage, data_item_storage;
1223  PropertyRNA *prop_storage = NULL;
1224 
1225  /* It is totally OK if this does not success,
1226  * only a subset of override operations actually need storage. */
1227  if (ptr_storage && (ptr_storage->owner_id != NULL)) {
1229  ptr_storage, op->rna_path, &data_storage, &prop_storage, &data_item_storage);
1230  }
1231 
1232  /* Check if an overridden ID pointer supposed to be in sync with linked data gets out of
1233  * sync. */
1234  if ((ptr_dst->owner_id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0) {
1235  if (op->rna_prop_type == PROP_POINTER &&
1236  (((IDOverrideLibraryPropertyOperation *)op->operations.first)->flag &
1238  BLI_assert(RNA_struct_is_ID(RNA_property_pointer_type(&data_src, prop_src)));
1239  BLI_assert(ptr_src->owner_id ==
1241  BLI_assert(ptr_dst->owner_id ==
1243 
1244  PointerRNA prop_ptr_src = RNA_property_pointer_get(&data_src, prop_src);
1245  PointerRNA prop_ptr_dst = RNA_property_pointer_get(&data_dst, prop_dst);
1247  bmain, ptr_dst, ptr_src, &prop_ptr_dst, &prop_ptr_src);
1248  }
1249  else if (op->rna_prop_type == PROP_COLLECTION) {
1250  if (RNA_struct_is_ID(RNA_property_pointer_type(&data_src, prop_src))) {
1252  bmain, &data_src, NULL, NULL));
1254  bmain, &data_dst, NULL, NULL));
1255 
1256  LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
1257  if ((opop->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) == 0) {
1258  continue;
1259  }
1260 
1261  PointerRNA *ptr_item_dst, *ptr_item_src;
1262  PointerRNA private_ptr_item_dst, private_ptr_item_src;
1264  &data_src,
1265  NULL,
1266  prop_dst,
1267  prop_src,
1268  NULL,
1269  &ptr_item_dst,
1270  &ptr_item_src,
1271  NULL,
1272  &private_ptr_item_dst,
1273  &private_ptr_item_src,
1274  NULL,
1275  op,
1276  opop);
1277 
1279  bmain, ptr_dst, ptr_src, ptr_item_dst, ptr_item_src);
1280  }
1281  }
1282  }
1283  }
1284 
1285  /* Workaround for older broken overrides, we then assume that non-matching ID pointers
1286  * override operations that replace a non-NULL value are 'mistakes', and ignore (do not
1287  * apply) them. */
1288  if ((flag & RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS) != 0 &&
1289  op->rna_prop_type == PROP_POINTER &&
1290  (((IDOverrideLibraryPropertyOperation *)op->operations.first)->flag &
1292  BLI_assert(ptr_src->owner_id ==
1294  BLI_assert(ptr_dst->owner_id ==
1296 
1297  PointerRNA prop_ptr_dst = RNA_property_pointer_get(&data_dst, prop_dst);
1298  if (prop_ptr_dst.type != NULL && RNA_struct_is_ID(prop_ptr_dst.type)) {
1299 #ifndef NDEBUG
1300  PointerRNA prop_ptr_src = RNA_property_pointer_get(&data_src, prop_src);
1301  BLI_assert(prop_ptr_src.type == NULL || RNA_struct_is_ID(prop_ptr_src.type));
1302 #endif
1304  bmain, &prop_ptr_dst, NULL, NULL);
1305 
1306  if (id_dst != NULL) {
1307  CLOG_INFO(&LOG,
1308  4,
1309  "%s: Ignoring local override on ID pointer property '%s', as requested by "
1310  "RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS flag",
1311  ptr_dst->owner_id->name,
1312  op->rna_path);
1313  continue;
1314  }
1315  }
1316  }
1317 
1319  &data_dst,
1320  &data_src,
1321  prop_storage ? &data_storage : NULL,
1322  prop_dst,
1323  prop_src,
1324  prop_storage,
1325  &data_item_dst,
1326  &data_item_src,
1327  prop_storage ? &data_item_storage : NULL,
1328  op,
1329  do_insert);
1330  }
1331  else {
1332  CLOG_INFO(&LOG,
1333  4,
1334  "Failed to apply library override operation to '%s.%s' "
1335  "(could not resolve some properties, local: %d, override: %d)",
1336  ((ID *)ptr_src->owner_id)->name,
1337  op->rna_path,
1338  RNA_path_resolve_property(ptr_dst, op->rna_path, &data_dst, &prop_dst),
1339  RNA_path_resolve_property(ptr_src, op->rna_path, &data_src, &prop_src));
1340  }
1341  }
1342  }
1343 
1344  /* Some cases (like point caches) may require additional post-processing. */
1345  if (RNA_struct_is_a(ptr_dst->type, &RNA_ID)) {
1346  ID *id_dst = ptr_dst->data;
1347  ID *id_src = ptr_src->data;
1348  const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id_dst);
1349  if (id_type->lib_override_apply_post != NULL) {
1350  id_type->lib_override_apply_post(id_dst, id_src);
1351  }
1352  }
1353 
1354 #ifdef DEBUG_OVERRIDE_TIMEIT
1356 #endif
1357 }
1358 
1360  PointerRNA *ptr,
1361  PropertyRNA *prop,
1362  ID **r_owner_id)
1363 {
1364  char *rna_path;
1365 
1366  *r_owner_id = rna_property_override_property_real_id_owner(bmain, ptr, prop, &rna_path);
1367  if (rna_path != NULL) {
1369  (*r_owner_id)->override_library, rna_path);
1370  MEM_freeN(rna_path);
1371  return op;
1372  }
1373  return NULL;
1374 }
1375 
1377  PointerRNA *ptr,
1378  PropertyRNA *prop,
1379  bool *r_created)
1380 {
1381  char *rna_path;
1382 
1383  if (r_created != NULL) {
1384  *r_created = false;
1385  }
1386 
1387  ID *id = rna_property_override_property_real_id_owner(bmain, ptr, prop, &rna_path);
1388  if (rna_path != NULL) {
1390  id->override_library, rna_path, r_created);
1391  MEM_freeN(rna_path);
1392  return op;
1393  }
1394  return NULL;
1395 }
1396 
1398  Main *bmain,
1399  PointerRNA *ptr,
1400  PropertyRNA *prop,
1401  const int index,
1402  const bool strict,
1403  bool *r_strict)
1404 {
1405  ID *owner_id;
1406  IDOverrideLibraryProperty *op = RNA_property_override_property_find(bmain, ptr, prop, &owner_id);
1407 
1408  if (!op) {
1409  return NULL;
1410  }
1411 
1413  op, NULL, NULL, index, index, strict, r_strict);
1414 }
1415 
1417  Main *bmain,
1418  PointerRNA *ptr,
1419  PropertyRNA *prop,
1420  const short operation,
1421  const int index,
1422  const bool strict,
1423  bool *r_strict,
1424  bool *r_created)
1425 {
1426  if (r_created != NULL) {
1427  *r_created = false;
1428  }
1429 
1431 
1432  if (!op) {
1433  return NULL;
1434  }
1435 
1437  op, operation, NULL, NULL, index, index, strict, r_strict, r_created);
1438 }
1439 
1441  PointerRNA *ptr,
1442  PropertyRNA *prop,
1443  const int index)
1444 {
1445  uint override_status = 0;
1446 
1447  if (!ptr || !prop || !ptr->owner_id || !ID_IS_OVERRIDE_LIBRARY(ptr->owner_id)) {
1448  return override_status;
1449  }
1450 
1452  override_status |= RNA_OVERRIDE_STATUS_OVERRIDABLE;
1453  }
1454 
1456  bmain, ptr, prop, index, false, NULL);
1457  if (opop != NULL) {
1458  override_status |= RNA_OVERRIDE_STATUS_OVERRIDDEN;
1460  override_status |= RNA_OVERRIDE_STATUS_MANDATORY;
1461  }
1462  if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_LOCKED) {
1463  override_status |= RNA_OVERRIDE_STATUS_LOCKED;
1464  }
1465  }
1466 
1467  return override_status;
1468 }
typedef float(TangentPoint)[2]
void BKE_pose_ensure(struct Main *bmain, struct Object *ob, struct bArmature *arm, bool do_id_user)
Definition: armature.c:2419
bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL()
Definition: idprop.c:631
struct IDProperty * IDP_CopyProperty(const struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
const struct IDTypeInfo * BKE_idtype_get_info_from_id(const struct ID *id)
struct IDOverrideLibraryProperty * BKE_lib_override_library_property_get(struct IDOverrideLibrary *override, const char *rna_path, bool *r_created)
struct IDOverrideLibraryPropertyOperation * BKE_lib_override_library_property_operation_find(struct IDOverrideLibraryProperty *override_property, const char *subitem_refname, const char *subitem_locname, int subitem_refindex, int subitem_locindex, bool strict, bool *r_strict)
struct IDOverrideLibraryProperty * BKE_lib_override_library_property_find(struct IDOverrideLibrary *override, const char *rna_path)
void BKE_lib_override_library_operations_tag(struct IDOverrideLibraryProperty *override_property, short tag, bool do_set)
struct IDOverrideLibraryPropertyOperation * BKE_lib_override_library_property_operation_get(struct IDOverrideLibraryProperty *override_property, short operation, const char *subitem_refname, const char *subitem_locname, int subitem_refindex, int subitem_locindex, bool strict, bool *r_strict, bool *r_created)
bool BKE_lib_override_library_property_operation_operands_validate(struct IDOverrideLibraryPropertyOperation *override_property_operation, struct PointerRNA *ptr_dst, struct PointerRNA *ptr_src, struct PointerRNA *ptr_storage, struct PropertyRNA *prop_dst, struct PropertyRNA *prop_src, struct PropertyRNA *prop_storage)
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
#define CLOG_INFO(clg_ref, level,...)
Definition: CLG_log.h:187
ID and Library types, which are fundamental for sdna.
@ IDOVERRIDE_LIBRARY_FLAG_LOCKED
Definition: DNA_ID.h:240
@ IDOVERRIDE_LIBRARY_FLAG_MANDATORY
Definition: DNA_ID.h:238
@ IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE
Definition: DNA_ID.h:244
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition: DNA_ID.h:581
@ IDP_FLAG_OVERRIDABLE_LIBRARY
Definition: DNA_ID.h:172
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
@ IDOVERRIDE_LIBRARY_OP_MULTIPLY
Definition: DNA_ID.h:227
@ IDOVERRIDE_LIBRARY_OP_INSERT_AFTER
Definition: DNA_ID.h:230
@ IDOVERRIDE_LIBRARY_OP_NOOP
Definition: DNA_ID.h:218
@ IDOVERRIDE_LIBRARY_OP_SUBTRACT
Definition: DNA_ID.h:225
@ IDOVERRIDE_LIBRARY_OP_ADD
Definition: DNA_ID.h:223
@ IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE
Definition: DNA_ID.h:231
@ IDOVERRIDE_LIBRARY_OP_REPLACE
Definition: DNA_ID.h:220
@ LIB_TAG_LIB_OVERRIDE_NEED_RESYNC
Definition: DNA_ID.h:762
@ LIB_EMBEDDED_DATA
Definition: DNA_ID.h:635
@ LIB_EMBEDDED_DATA_LIB_OVERRIDE
Definition: DNA_ID.h:646
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ LIBRARY_TAG_RESYNC_REQUIRED
Definition: DNA_ID.h:492
@ IDOVERRIDE_LIBRARY_TAG_UNUSED
Definition: DNA_ID.h:275
@ IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY
Definition: DNA_ID.h:322
@ ID_NT
Definition: DNA_ID_enums.h:68
@ ID_KE
Definition: DNA_ID_enums.h:58
@ ID_GR
Definition: DNA_ID_enums.h:65
@ ID_OB
Definition: DNA_ID_enums.h:47
@ NLATRACK_OVERRIDELIBRARY_LOCAL
@ CAM_BGIMG_FLAG_OVERRIDE_LIBRARY_LOCAL
@ CONSTRAINT_OVERRIDE_LIBRARY_LOCAL
@ eGpencilModifierFlag_OverrideLibrary_Local
@ eModifierFlag_OverrideLibrary_Local
Object is a sort of wrapper for general info.
@ OB_ARMATURE
Read Guarded memory(de)allocation.
Utility defines for timing/benchmarks.
#define TIMEIT_START_AVERAGED(var)
#define TIMEIT_END_AVERAGED(var)
#define RNA_POINTER_INVALIDATE(ptr)
Definition: RNA_access.h:744
eRNAOverrideStatus
Definition: RNA_access.h:815
@ RNA_OVERRIDE_STATUS_OVERRIDABLE
Definition: RNA_access.h:817
@ RNA_OVERRIDE_STATUS_MANDATORY
Definition: RNA_access.h:821
@ RNA_OVERRIDE_STATUS_OVERRIDDEN
Definition: RNA_access.h:819
@ RNA_OVERRIDE_STATUS_LOCKED
Definition: RNA_access.h:823
eRNAOverrideApplyFlag
Definition: RNA_access.h:855
@ RNA_OVERRIDE_APPLY_FLAG_IGNORE_ID_POINTERS
Definition: RNA_access.h:861
eRNAOverrideMatch
Definition: RNA_access.h:793
@ RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN
Definition: RNA_access.h:797
@ RNA_OVERRIDE_COMPARE_CREATE
Definition: RNA_access.h:800
@ RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE
Definition: RNA_access.h:795
@ RNA_OVERRIDE_COMPARE_RESTORE
Definition: RNA_access.h:802
eRNACompareMode
Definition: RNA_access.h:768
@ RNA_EQ_UNSET_MATCH_ANY
Definition: RNA_access.h:773
@ RNA_EQ_STRICT
Definition: RNA_access.h:771
@ RNA_EQ_UNSET_MATCH_NONE
Definition: RNA_access.h:775
eRNAOverrideMatchResult
Definition: RNA_access.h:805
@ RNA_OVERRIDE_MATCH_RESULT_RESTORED
Definition: RNA_access.h:812
@ RNA_OVERRIDE_MATCH_RESULT_CREATED
Definition: RNA_access.h:810
@ PROP_POINTER
Definition: RNA_types.h:64
@ PROP_COLLECTION
Definition: RNA_types.h:65
@ PROPOVERRIDE_OVERRIDABLE_LIBRARY
Definition: RNA_types.h:312
@ PROPOVERRIDE_NO_COMPARISON
Definition: RNA_types.h:320
@ PROPOVERRIDE_IGNORE
Definition: RNA_types.h:332
#define GS(x)
Definition: iris.c:225
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1966
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
Definition: rna_access.c:695
void rna_property_rna_or_id_get(PropertyRNA *prop, PointerRNA *ptr, PropertyRNAOrID *r_prop_rna_or_id)
Definition: rna_access.c:431
PropertyRNA * rna_ensure_property(PropertyRNA *prop)
Definition: rna_access.c:524
bool RNA_struct_is_ID(const StructRNA *type)
Definition: rna_access.c:655
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
void RNA_property_collection_begin(PointerRNA *ptr, PropertyRNA *prop, CollectionPropertyIterator *iter)
Definition: rna_access.c:3675
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
PropertyRNA * rna_ensure_property_realdata(PropertyRNA **prop, PointerRNA *ptr)
Definition: rna_access.c:512
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3493
int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
Definition: rna_access.c:4097
void rna_idproperty_touch(IDProperty *idprop)
Definition: rna_access.c:232
IDProperty * RNA_struct_idprops(PointerRNA *ptr, bool create)
Definition: rna_access.c:251
void RNA_property_collection_next(CollectionPropertyIterator *iter)
Definition: rna_access.c:3709
bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1976
int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
Definition: rna_access.c:4184
StructRNA * RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1405
int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:1075
void RNA_property_collection_end(CollectionPropertyIterator *iter)
Definition: rna_access.c:3750
PropertyRNA * RNA_struct_iterator_property(StructRNA *type)
Definition: rna_access.c:634
bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2009
static void rna_porperty_override_collection_subitem_lookup(PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, PropertyRNA *prop_dst, PropertyRNA *prop_src, PropertyRNA *prop_storage, PointerRNA **r_ptr_item_dst, PointerRNA **r_ptr_item_src, PointerRNA **r_ptr_item_storage, PointerRNA *private_ptr_item_dst, PointerRNA *private_ptr_item_src, PointerRNA *private_ptr_item_storage, IDOverrideLibraryProperty *op, IDOverrideLibraryPropertyOperation *opop)
bool RNA_struct_equals(Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode)
static ID * rna_property_override_property_real_id_owner(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, char **r_rna_path)
IDOverrideLibraryPropertyOperation * RNA_property_override_property_operation_get(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, const short operation, const int index, const bool strict, bool *r_strict, bool *r_created)
static bool rna_property_override_operation_store(Main *bmain, PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage, PropertyRNA *prop_local, PropertyRNA *prop_reference, PropertyRNA *prop_storage, IDOverrideLibraryProperty *op)
int RNA_property_override_flag(PropertyRNA *prop)
static bool rna_property_override_operation_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, PropertyRNA *prop_dst, PropertyRNA *prop_src, PropertyRNA *prop_storage, PointerRNA *ptr_item_dst, PointerRNA *ptr_item_src, PointerRNA *ptr_item_storage, IDOverrideLibraryPropertyOperation *opop)
IDOverrideLibraryProperty * RNA_property_override_property_find(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, ID **r_owner_id)
#define RNA_PATH_BUFFSIZE
IDOverrideLibraryPropertyOperation * RNA_property_override_property_operation_find(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict)
bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_overridable_library_set(PointerRNA *UNUSED(ptr), PropertyRNA *prop, const bool is_overridable)
bool RNA_struct_override_store(Main *bmain, PointerRNA *ptr_local, PointerRNA *ptr_reference, PointerRNA *ptr_storage, IDOverrideLibrary *override)
void RNA_struct_override_apply(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, IDOverrideLibrary *override, const eRNAOverrideApplyFlag flag)
static int rna_property_override_diff(Main *bmain, PropertyRNAOrID *prop_a, PropertyRNAOrID *prop_b, const char *rna_path, const size_t rna_path_len, eRNACompareMode mode, IDOverrideLibrary *override, const eRNAOverrideMatch flags, eRNAOverrideMatchResult *r_report_flags)
bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop)
bool RNA_property_comparable(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
static CLG_LogRef LOG
IDOverrideLibraryProperty * RNA_property_override_property_get(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, bool *r_created)
eRNAOverrideStatus RNA_property_override_library_status(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, const int index)
bool RNA_property_equals(Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, eRNACompareMode mode)
bool RNA_struct_override_matches(Main *bmain, PointerRNA *ptr_local, PointerRNA *ptr_reference, const char *root_path, const size_t root_path_len, IDOverrideLibrary *override, const eRNAOverrideMatch flags, eRNAOverrideMatchResult *r_report_flags)
static void rna_property_override_check_resync(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_item_dst, PointerRNA *ptr_item_src)
static void rna_property_override_apply_ex(Main *bmain, PointerRNA *ptr_dst, PointerRNA *ptr_src, PointerRNA *ptr_storage, PropertyRNA *prop_dst, PropertyRNA *prop_src, PropertyRNA *prop_storage, PointerRNA *ptr_item_dst, PointerRNA *ptr_item_src, PointerRNA *ptr_item_storage, IDOverrideLibraryProperty *op, const bool do_insert)
bool RNA_property_copy(Main *bmain, PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
bool rna_property_override_store_default(struct Main *bmain, struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, struct PointerRNA *ptr_storage, struct PropertyRNA *prop_local, struct PropertyRNA *prop_reference, struct PropertyRNA *prop_storage, int len_local, int len_reference, int len_storage, struct IDOverrideLibraryPropertyOperation *opop)
int rna_property_override_diff_default(struct Main *bmain, struct PropertyRNAOrID *prop_a, struct PropertyRNAOrID *prop_b, int mode, struct IDOverrideLibrary *override, const char *rna_path, size_t rna_path_len, int flags, bool *r_override_changed)
#define RNA_MAGIC
Definition: rna_internal.h:21
bool rna_property_override_apply_default(struct Main *bmain, struct PointerRNA *ptr_dst, struct PointerRNA *ptr_src, struct PointerRNA *ptr_storage, struct PropertyRNA *prop_dst, struct PropertyRNA *prop_src, struct PropertyRNA *prop_storage, int len_dst, int len_src, int len_storage, struct PointerRNA *ptr_item_dst, struct PointerRNA *ptr_item_src, struct PointerRNA *ptr_item_storage, struct IDOverrideLibraryPropertyOperation *opop)
bool(* RNAPropOverrideApply)(struct Main *bmain, struct PointerRNA *ptr_dst, struct PointerRNA *ptr_src, struct PointerRNA *ptr_storage, struct PropertyRNA *prop_dst, struct PropertyRNA *prop_src, struct PropertyRNA *prop_storage, int len_dst, int len_src, int len_storage, struct PointerRNA *ptr_item_dst, struct PointerRNA *ptr_item_src, struct PointerRNA *ptr_item_storage, struct IDOverrideLibraryPropertyOperation *opop)
int(* RNAPropOverrideDiff)(struct Main *bmain, struct PropertyRNAOrID *prop_a, struct PropertyRNAOrID *prop_b, int mode, struct IDOverrideLibrary *override, const char *rna_path, size_t rna_path_len, int flags, bool *r_override_changed)
bool(* RNAPropOverrideStore)(struct Main *bmain, struct PointerRNA *ptr_local, struct PointerRNA *ptr_reference, struct PointerRNA *ptr_storage, struct PropertyRNA *prop_local, struct PropertyRNA *prop_reference, struct PropertyRNA *prop_storage, int len_local, int len_reference, int len_storage, struct IDOverrideLibraryPropertyOperation *opop)
ID * RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path)
Definition: rna_path.cc:919
bool RNA_path_resolve_property_and_item_pointer(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, PointerRNA *r_item_ptr)
Definition: rna_path.cc:553
char * RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_path.cc:1127
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_path.cc:531
unsigned int rna_prop_type
Definition: DNA_ID.h:269
unsigned int flag
Definition: DNA_ID.h:312
struct ID * reference
Definition: DNA_ID.h:294
short flag
Definition: DNA_ID.h:109
IDTypeLibOverrideApplyPost lib_override_apply_post
Definition: BKE_idtype.h:225
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
struct Library * lib
Definition: DNA_ID.h:372
IDOverrideLibrary * override_library
Definition: DNA_ID.h:412
short flag
Definition: DNA_ID.h:383
char name[66]
Definition: DNA_ID.h:378
ushort tag
Definition: DNA_ID.h:478
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
void * data
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
const char * identifier
PropertyRNA * rawprop
PropertyRNA * rnaprop
RNAPropOverrideApply override_apply
RNAPropOverrideStore override_store
RNAPropOverrideDiff override_diff
double PIL_check_seconds_timer(void)
Definition: time.c:64
ccl_device_inline int mod(int x, int m)
Definition: util/math.h:490
PointerRNA * ptr
Definition: wm_files.c:3480
bool override
Definition: wm_files.c:1022