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