Blender  V3.3
rna_path.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <cstdlib>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include "BLI_alloca.h"
12 #include "BLI_dynstr.h"
13 #include "BLI_listbase.h"
14 #include "BLI_string.h"
15 #include "BLI_utildefines.h"
16 
17 #include "BKE_idprop.h"
18 #include "BKE_idtype.h"
19 
20 #include "DNA_ID.h" /* For ID properties. */
21 
22 #include "MEM_guardedalloc.h"
23 
24 #include "RNA_access.h"
25 #include "RNA_define.h"
26 #include "RNA_path.h"
27 #include "RNA_prototypes.h"
28 
29 #include "rna_access_internal.h"
30 #include "rna_internal.h"
31 
38 static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen)
39 {
40  int len = 0;
41 
42  /* Get data until `.` or `[`. */
43  const char *p = *path;
44  while (*p && !ELEM(*p, '.', '[')) {
45  len++;
46  p++;
47  }
48 
49  /* Empty, return. */
50  if (UNLIKELY(len == 0)) {
51  return NULL;
52  }
53 
54  /* Try to use fixed buffer if possible. */
55  char *buf = (len + 1 < fixedlen) ? fixedbuf :
56  (char *)MEM_mallocN(sizeof(char) * (len + 1), __func__);
57  memcpy(buf, *path, sizeof(char) * len);
58  buf[len] = '\0';
59 
60  if (*p == '.') {
61  p++;
62  }
63  *path = p;
64 
65  return buf;
66 }
67 
78 static char *rna_path_token_in_brackets(const char **path,
79  char *fixedbuf,
80  int fixedlen,
81  bool *r_quoted)
82 {
83  int len = 0;
84  bool quoted = false;
85 
86  BLI_assert(r_quoted != NULL);
87 
88  /* Get data between `[]`, check escaping quotes and back-slashes with #BLI_str_unescape. */
89  if (UNLIKELY(**path != '[')) {
90  return NULL;
91  }
92 
93  (*path)++;
94  const char *p = *path;
95 
96  /* 2 kinds of look-ups now, quoted or unquoted. */
97  if (*p == '"') {
98  /* Find the matching quote. */
99  (*path)++;
100  p = *path;
101  const char *p_end = BLI_str_escape_find_quote(p);
102  if (p_end == NULL) {
103  /* No Matching quote. */
104  return NULL;
105  }
106  /* Exclude the last quote from the length. */
107  len += (p_end - p);
108 
109  /* Skip the last quoted char to get the `]`. */
110  p_end += 1;
111  p = p_end;
112  quoted = true;
113  }
114  else {
115  /* Find the matching bracket. */
116  while (*p && (*p != ']')) {
117  len++;
118  p++;
119  }
120  }
121 
122  if (UNLIKELY(*p != ']')) {
123  return NULL;
124  }
125 
126  /* Empty, return. */
127  if (UNLIKELY(len == 0)) {
128  return NULL;
129  }
130 
131  /* Try to use fixed buffer if possible. */
132  char *buf = (len + 1 < fixedlen) ? fixedbuf :
133  (char *)MEM_mallocN(sizeof(char) * (len + 1), __func__);
134 
135  /* Copy string, taking into account escaped ']' */
136  if (quoted) {
137  BLI_str_unescape(buf, *path, len);
138  /* +1 to step over the last quote. */
139  BLI_assert((*path)[len] == '"');
140  p = (*path) + len + 1;
141  }
142  else {
143  memcpy(buf, *path, sizeof(char) * len);
144  buf[len] = '\0';
145  }
146  /* Set path to start of next token. */
147  if (*p == ']') {
148  p++;
149  }
150  if (*p == '.') {
151  p++;
152  }
153  *path = p;
154 
155  *r_quoted = quoted;
156 
157  return buf;
158 }
159 
164 static bool rna_path_parse_collection_key(const char **path,
165  PointerRNA *ptr,
166  PropertyRNA *prop,
167  PointerRNA *r_nextptr)
168 {
169  char fixedbuf[256];
170  int intkey;
171 
172  *r_nextptr = *ptr;
173 
174  /* end of path, ok */
175  if (!(**path)) {
176  return true;
177  }
178 
179  bool found = false;
180  if (**path == '[') {
181  bool quoted;
182  char *token;
183 
184  /* resolve the lookup with [] brackets */
185  token = rna_path_token_in_brackets(path, fixedbuf, sizeof(fixedbuf), &quoted);
186 
187  if (!token) {
188  return false;
189  }
190 
191  /* check for "" to see if it is a string */
192  if (quoted) {
193  if (RNA_property_collection_lookup_string(ptr, prop, token, r_nextptr)) {
194  found = true;
195  }
196  else {
197  r_nextptr->data = NULL;
198  }
199  }
200  else {
201  /* otherwise do int lookup */
202  intkey = atoi(token);
203  if (intkey == 0 && (token[0] != '0' || token[1] != '\0')) {
204  return false; /* we can be sure the fixedbuf was used in this case */
205  }
206  if (RNA_property_collection_lookup_int(ptr, prop, intkey, r_nextptr)) {
207  found = true;
208  }
209  else {
210  r_nextptr->data = NULL;
211  }
212  }
213 
214  if (token != fixedbuf) {
215  MEM_freeN(token);
216  }
217  }
218  else {
219  if (RNA_property_collection_type_get(ptr, prop, r_nextptr)) {
220  found = true;
221  }
222  else {
223  /* ensure we quit on invalid values */
224  r_nextptr->data = NULL;
225  }
226  }
227 
228  return found;
229 }
230 
231 static bool rna_path_parse_array_index(const char **path,
232  PointerRNA *ptr,
233  PropertyRNA *prop,
234  int *r_index)
235 {
236  char fixedbuf[256];
237  int index_arr[RNA_MAX_ARRAY_DIMENSION] = {0};
239  const int dim = RNA_property_array_dimension(ptr, prop, len);
240  int i;
241 
242  *r_index = -1;
243 
244  /* end of path, ok */
245  if (!(**path)) {
246  return true;
247  }
248 
249  for (i = 0; i < dim; i++) {
250  int temp_index = -1;
251  char *token;
252 
253  /* multi index resolve */
254  if (**path == '[') {
255  bool quoted;
256  token = rna_path_token_in_brackets(path, fixedbuf, sizeof(fixedbuf), &quoted);
257 
258  if (token == NULL) {
259  /* invalid syntax blah[] */
260  return false;
261  }
262  /* check for "" to see if it is a string */
263  if (quoted) {
264  temp_index = RNA_property_array_item_index(prop, *token);
265  }
266  else {
267  /* otherwise do int lookup */
268  temp_index = atoi(token);
269 
270  if (temp_index == 0 && (token[0] != '0' || token[1] != '\0')) {
271  if (token != fixedbuf) {
272  MEM_freeN(token);
273  }
274 
275  return false;
276  }
277  }
278  }
279  else if (dim == 1) {
280  /* location.x || scale.X, single dimension arrays only */
281  token = rna_path_token(path, fixedbuf, sizeof(fixedbuf));
282  if (token == NULL) {
283  /* invalid syntax blah. */
284  return false;
285  }
286  temp_index = RNA_property_array_item_index(prop, *token);
287  }
288  else {
289  /* just to avoid uninitialized pointer use */
290  token = fixedbuf;
291  }
292 
293  if (token != fixedbuf) {
294  MEM_freeN(token);
295  }
296 
297  /* out of range */
298  if (temp_index < 0 || temp_index >= len[i]) {
299  return false;
300  }
301 
302  index_arr[i] = temp_index;
303  /* end multi index resolve */
304  }
305 
306  /* arrays always contain numbers so further values are not valid */
307  if (**path) {
308  return false;
309  }
310 
311  /* flatten index over all dimensions */
312  {
313  int totdim = 1;
314  int flat_index = 0;
315 
316  for (i = dim - 1; i >= 0; i--) {
317  flat_index += index_arr[i] * totdim;
318  totdim *= len[i];
319  }
320 
321  *r_index = flat_index;
322  }
323  return true;
324 }
325 
348 static bool rna_path_parse(const PointerRNA *ptr,
349  const char *path,
350  PointerRNA *r_ptr,
351  PropertyRNA **r_prop,
352  int *r_index,
353  PointerRNA *r_item_ptr,
354  ListBase *r_elements,
355  const bool eval_pointer)
356 {
357  BLI_assert(r_item_ptr == NULL || !eval_pointer);
358  PropertyRNA *prop;
359  PointerRNA curptr, nextptr;
360  PropertyElemRNA *prop_elem = NULL;
361  int index = -1;
362  char fixedbuf[256];
363  int type;
364  const bool do_item_ptr = r_item_ptr != NULL && !eval_pointer;
365 
366  if (do_item_ptr) {
367  RNA_POINTER_INVALIDATE(&nextptr);
368  }
369 
370  prop = NULL;
371  curptr = *ptr;
372 
373  if (path == NULL || *path == '\0') {
374  return false;
375  }
376 
377  while (*path) {
378  if (do_item_ptr) {
379  RNA_POINTER_INVALIDATE(&nextptr);
380  }
381 
382  const bool use_id_prop = (*path == '[');
383  /* Custom property lookup: e.g. `C.object["someprop"]`. */
384 
385  if (!curptr.data) {
386  return false;
387  }
388 
389  /* look up property name in current struct */
390  bool quoted = false;
391  char *token = use_id_prop ?
392  rna_path_token_in_brackets(&path, fixedbuf, sizeof(fixedbuf), &quoted) :
393  rna_path_token(&path, fixedbuf, sizeof(fixedbuf));
394  if (!token) {
395  return false;
396  }
397 
398  prop = NULL;
399  if (use_id_prop) { /* look up property name in current struct */
400  IDProperty *group = RNA_struct_idprops(&curptr, 0);
401  if (group && quoted) {
402  prop = (PropertyRNA *)IDP_GetPropertyFromGroup(group, token);
403  }
404  }
405  else {
406  prop = RNA_struct_find_property(&curptr, token);
407  }
408 
409  if (token != fixedbuf) {
410  MEM_freeN(token);
411  }
412 
413  if (!prop) {
414  return false;
415  }
416 
417  if (r_elements) {
418  prop_elem = MEM_cnew<PropertyElemRNA>(__func__);
419  prop_elem->ptr = curptr;
420  prop_elem->prop = prop;
421  prop_elem->index = -1; /* index will be added later, if needed. */
422  BLI_addtail(r_elements, prop_elem);
423  }
424 
425  type = RNA_property_type(prop);
426 
427  /* now look up the value of this property if it is a pointer or
428  * collection, otherwise return the property rna so that the
429  * caller can read the value of the property itself */
430  switch (type) {
431  case PROP_POINTER: {
432  /* resolve pointer if further path elements follow
433  * or explicitly requested
434  */
435  if (do_item_ptr || eval_pointer || *path != '\0') {
436  nextptr = RNA_property_pointer_get(&curptr, prop);
437  }
438 
439  if (eval_pointer || *path != '\0') {
440  curptr = nextptr;
441  prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
442  index = -1;
443  }
444  break;
445  }
446  case PROP_COLLECTION: {
447  /* Resolve pointer if further path elements follow.
448  * Note that if path is empty, rna_path_parse_collection_key will do nothing anyway,
449  * so do_item_ptr is of no use in that case.
450  */
451  if (*path) {
452  if (!rna_path_parse_collection_key(&path, &curptr, prop, &nextptr)) {
453  return false;
454  }
455 
456  if (eval_pointer || *path != '\0') {
457  curptr = nextptr;
458  prop = NULL; /* now we have a PointerRNA, the prop is our parent so forget it */
459  index = -1;
460  }
461  }
462  break;
463  }
464  default:
465  if (r_index || prop_elem) {
466  if (!rna_path_parse_array_index(&path, &curptr, prop, &index)) {
467  return false;
468  }
469 
470  if (prop_elem) {
471  prop_elem->index = index;
472  }
473  }
474  break;
475  }
476  }
477 
478  if (r_ptr) {
479  *r_ptr = curptr;
480  }
481  if (r_prop) {
482  *r_prop = prop;
483  }
484  if (r_index) {
485  *r_index = index;
486  }
487  if (r_item_ptr && do_item_ptr) {
488  *r_item_ptr = nextptr;
489  }
490 
491  if (prop_elem && (prop_elem->ptr.data != curptr.data || prop_elem->prop != prop ||
492  prop_elem->index != index)) {
493  prop_elem = MEM_cnew<PropertyElemRNA>(__func__);
494  prop_elem->ptr = curptr;
495  prop_elem->prop = prop;
496  prop_elem->index = index;
497  BLI_addtail(r_elements, prop_elem);
498  }
499 
500  return true;
501 }
502 
504  const char *path,
505  PointerRNA *r_ptr,
506  PropertyRNA **r_prop)
507 {
508  if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, NULL, true)) {
509  return false;
510  }
511 
512  return r_ptr->data != NULL;
513 }
514 
516  const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
517 {
518  if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, NULL, true)) {
519  return false;
520  }
521 
522  return r_ptr->data != NULL;
523 }
524 
526  const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
527 {
528  return rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, NULL, true);
529 }
530 
532  const char *path,
533  PointerRNA *r_ptr,
534  PropertyRNA **r_prop)
535 {
536  if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, NULL, NULL, false)) {
537  return false;
538  }
539 
540  return r_ptr->data != NULL && *r_prop != NULL;
541 }
542 
544  const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
545 {
546  if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, NULL, NULL, false)) {
547  return false;
548  }
549 
550  return r_ptr->data != NULL && *r_prop != NULL;
551 }
552 
554  const char *path,
555  PointerRNA *r_ptr,
556  PropertyRNA **r_prop,
557  PointerRNA *r_item_ptr)
558 {
559  if (!rna_path_parse(ptr, path, r_ptr, r_prop, NULL, r_item_ptr, NULL, false)) {
560  return false;
561  }
562 
563  return r_ptr->data != NULL && *r_prop != NULL;
564 }
565 
567  const char *path,
568  PointerRNA *r_ptr,
569  PropertyRNA **r_prop,
570  int *r_index,
571  PointerRNA *r_item_ptr)
572 {
573  if (!rna_path_parse(ptr, path, r_ptr, r_prop, r_index, r_item_ptr, NULL, false)) {
574  return false;
575  }
576 
577  return r_ptr->data != NULL && *r_prop != NULL;
578 }
579 bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, ListBase *r_elements)
580 {
581  return rna_path_parse(ptr, path, NULL, NULL, NULL, NULL, r_elements, false);
582 }
583 
584 char *RNA_path_append(const char *path,
585  const PointerRNA *UNUSED(ptr),
586  PropertyRNA *prop,
587  int intkey,
588  const char *strkey)
589 {
590  DynStr *dynstr;
591  char *result;
592 
593  dynstr = BLI_dynstr_new();
594 
595  /* add .identifier */
596  if (path) {
597  BLI_dynstr_append(dynstr, path);
598  if (*path) {
599  BLI_dynstr_append(dynstr, ".");
600  }
601  }
602 
604 
605  const bool has_key = (intkey > -1) || (strkey != nullptr);
606  if (has_key && (RNA_property_type(prop) == PROP_COLLECTION)) {
607  /* add ["strkey"] or [intkey] */
608  BLI_dynstr_append(dynstr, "[");
609 
610  if (strkey) {
611  const int strkey_esc_max_size = (strlen(strkey) * 2) + 1;
612  char *strkey_esc = static_cast<char *>(BLI_array_alloca(strkey_esc, strkey_esc_max_size));
613  BLI_str_escape(strkey_esc, strkey, strkey_esc_max_size);
614  BLI_dynstr_append(dynstr, "\"");
615  BLI_dynstr_append(dynstr, strkey_esc);
616  BLI_dynstr_append(dynstr, "\"");
617  }
618  else {
619  char appendstr[128];
620  BLI_snprintf(appendstr, sizeof(appendstr), "%d", intkey);
621  BLI_dynstr_append(dynstr, appendstr);
622  }
623 
624  BLI_dynstr_append(dynstr, "]");
625  }
626 
627  result = BLI_dynstr_get_cstring(dynstr);
628  BLI_dynstr_free(dynstr);
629 
630  return result;
631 }
632 
633 /* Having both path append & back seems like it could be useful,
634  * this function isn't used at the moment. */
635 static UNUSED_FUNCTION_WITH_RETURN_TYPE(char *, RNA_path_back)(const char *path)
636 {
637  char fixedbuf[256];
638  const char *previous, *current;
639  char *result;
640  int i;
641 
642  if (!path) {
643  return NULL;
644  }
645 
646  previous = NULL;
647  current = path;
648 
649  /* parse token by token until the end, then we back up to the previous
650  * position and strip of the next token to get the path one step back */
651  while (*current) {
652  char *token;
653 
654  token = rna_path_token(&current, fixedbuf, sizeof(fixedbuf));
655 
656  if (!token) {
657  return NULL;
658  }
659  if (token != fixedbuf) {
660  MEM_freeN(token);
661  }
662 
663  /* in case of collection we also need to strip off [] */
664  bool quoted;
665  token = rna_path_token_in_brackets(&current, fixedbuf, sizeof(fixedbuf), &quoted);
666  if (token && token != fixedbuf) {
667  MEM_freeN(token);
668  }
669 
670  if (!*current) {
671  break;
672  }
673 
674  previous = current;
675  }
676 
677  if (!previous) {
678  return NULL;
679  }
680 
681  /* copy and strip off last token */
682  i = previous - path;
683  result = BLI_strdup(path);
684 
685  if (i > 0 && result[i - 1] == '.') {
686  i--;
687  }
688  result[i] = 0;
689 
690  return result;
691 }
692 
693 const char *RNA_path_array_index_token_find(const char *rna_path, const PropertyRNA *array_prop)
694 {
695  if (array_prop != NULL) {
696  if (!ELEM(array_prop->type, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) {
697  BLI_assert(array_prop->arraydimension == 0);
698  return NULL;
699  }
700  if (array_prop->arraydimension == 0) {
701  return NULL;
702  }
703  }
704 
705  /* Valid 'array part' of a rna path can only have '[', ']' and digit characters.
706  * It may have more than one of those (e.g. `[12][1]`) in case of multi-dimensional arrays. */
707  if (UNLIKELY(rna_path[0] == '\0')) {
708  return NULL;
709  }
710  size_t rna_path_len = (size_t)strlen(rna_path) - 1;
711  if (rna_path[rna_path_len] != ']') {
712  return NULL;
713  }
714 
715  const char *last_valid_index_token_start = NULL;
716  while (rna_path_len--) {
717  switch (rna_path[rna_path_len]) {
718  case '[':
719  if (rna_path_len <= 0 || rna_path[rna_path_len - 1] != ']') {
720  return &rna_path[rna_path_len];
721  }
722  last_valid_index_token_start = &rna_path[rna_path_len];
723  rna_path_len--;
724  break;
725  case '0':
726  case '1':
727  case '2':
728  case '3':
729  case '4':
730  case '5':
731  case '6':
732  case '7':
733  case '8':
734  case '9':
735  break;
736  default:
737  return last_valid_index_token_start;
738  }
739  }
740  return last_valid_index_token_start;
741 }
742 
743 /* generic path search func
744  * if its needed this could also reference the IDProperty direct */
745 typedef struct IDP_Chain {
746  struct IDP_Chain *up; /* parent member, reverse and set to child for path conversion. */
747 
748  const char *name;
749  int index;
750 
752 
753 static char *rna_idp_path_create(IDP_Chain *child_link)
754 {
755  DynStr *dynstr = BLI_dynstr_new();
756  char *path;
757  bool is_first = true;
758 
759  int tot = 0;
760  IDP_Chain *link = child_link;
761 
762  /* reverse the list */
763  IDP_Chain *link_prev;
764  link_prev = NULL;
765  while (link) {
766  IDP_Chain *link_next = link->up;
767  link->up = link_prev;
768  link_prev = link;
769  link = link_next;
770  tot++;
771  }
772 
773  for (link = link_prev; link; link = link->up) {
774  /* pass */
775  if (link->index >= 0) {
776  BLI_dynstr_appendf(dynstr, is_first ? "%s[%d]" : ".%s[%d]", link->name, link->index);
777  }
778  else {
779  BLI_dynstr_appendf(dynstr, is_first ? "%s" : ".%s", link->name);
780  }
781 
782  is_first = false;
783  }
784 
785  path = BLI_dynstr_get_cstring(dynstr);
786  BLI_dynstr_free(dynstr);
787 
788  if (*path == '\0') {
789  MEM_freeN(path);
790  path = NULL;
791  }
792 
793  return path;
794 }
795 
797  IDProperty *haystack,
798  IDProperty *needle,
799  IDP_Chain *parent_link)
800 {
801  char *path = NULL;
802  IDP_Chain link;
803 
804  IDProperty *iter;
805  int i;
806 
807  BLI_assert(haystack->type == IDP_GROUP);
808 
809  link.up = parent_link;
810  /* Always set both name and index, else a stale value might get used. */
811  link.name = NULL;
812  link.index = -1;
813 
814  for (i = 0, iter = reinterpret_cast<IDProperty *>(haystack->data.group.first); iter;
815  iter = iter->next, i++) {
816  if (needle == iter) { /* found! */
817  link.name = iter->name;
818  link.index = -1;
819  path = rna_idp_path_create(&link);
820  break;
821  }
822 
823  /* Early out in case the IDProperty type cannot contain RNA properties. */
824  if (!ELEM(iter->type, IDP_GROUP, IDP_IDPARRAY)) {
825  continue;
826  }
827 
828  /* Ensure this is RNA. */
829  /* NOTE: `iter` might be a fully user-defined IDProperty (a.k.a. custom data), which name
830  * collides with an actual fully static RNA property of the same struct (which would then not
831  * be flagged with `PROP_IDPROPERTY`).
832  *
833  * That case must be ignored here, we only want to deal with runtime RNA properties stored in
834  * IDProps.
835  *
836  * See T84091. */
838  if (prop == NULL || (prop->flag & PROP_IDPROPERTY) == 0) {
839  continue;
840  }
841 
842  if (iter->type == IDP_GROUP) {
843  if (prop->type == PROP_POINTER) {
844  PointerRNA child_ptr = RNA_property_pointer_get(ptr, prop);
845  if (RNA_pointer_is_null(&child_ptr)) {
846  /* Pointer ID prop might be a 'leaf' in the IDProp group hierarchy, in which case a NULL
847  * value is perfectly valid. Just means it won't match the searched needle. */
848  continue;
849  }
850 
851  link.name = iter->name;
852  link.index = -1;
853  if ((path = rna_idp_path(&child_ptr, iter, needle, &link))) {
854  break;
855  }
856  }
857  }
858  else if (iter->type == IDP_IDPARRAY) {
859  if (prop->type == PROP_COLLECTION) {
860  IDProperty *array = IDP_IDPArray(iter);
861  if (needle >= array && needle < (iter->len + array)) { /* found! */
862  link.name = iter->name;
863  link.index = (int)(needle - array);
864  path = rna_idp_path_create(&link);
865  break;
866  }
867  int j;
868  link.name = iter->name;
869  for (j = 0; j < iter->len; j++, array++) {
870  PointerRNA child_ptr;
871  if (RNA_property_collection_lookup_int(ptr, prop, j, &child_ptr)) {
872  if (RNA_pointer_is_null(&child_ptr)) {
873  /* Array item ID prop might be a 'leaf' in the IDProp group hierarchy, in which case
874  * a NULL value is perfectly valid. Just means it won't match the searched needle. */
875  continue;
876  }
877  link.index = j;
878  if ((path = rna_idp_path(&child_ptr, array, needle, &link))) {
879  break;
880  }
881  }
882  }
883  if (path) {
884  break;
885  }
886  }
887  }
888  }
889 
890  return path;
891 }
892 
894 {
895  IDProperty *haystack = RNA_struct_idprops(ptr, false);
896 
897  if (haystack) { /* can fail when called on bones */
898  return rna_idp_path(ptr, haystack, needle, NULL);
899  }
900  return NULL;
901 }
902 
904 {
905  PointerRNA id_ptr;
906 
908 
909  /* TODO: Support Bones/PoseBones. no pointers stored to the bones from here, only the ID.
910  * See example in T25746.
911  * Unless this is added only way to find this is to also search
912  * all bones and pose bones of an armature or object.
913  */
915 
916  return RNA_path_from_struct_to_idproperty(&id_ptr, reinterpret_cast<IDProperty *>(ptr->data));
917 }
918 
919 ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path)
920 {
921  if (r_path) {
922  *r_path = "";
923  }
924 
925  if ((id == NULL) || (id->flag & LIB_EMBEDDED_DATA) == 0) {
926  return id;
927  }
928 
929  const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
930  if (r_path) {
931  switch (GS(id->name)) {
932  case ID_NT:
933  *r_path = "node_tree";
934  break;
935  case ID_GR:
936  *r_path = "collection";
937  break;
938  default:
939  BLI_assert_msg(0, "Missing handling of embedded id type.");
940  }
941  }
942 
943  if (id_type->owner_get == NULL) {
944  BLI_assert_msg(0, "Missing handling of embedded id type.");
945  return id;
946  }
947  return id_type->owner_get(bmain, id, nullptr);
948 }
949 
950 static char *rna_prepend_real_ID_path(Main *bmain, ID *id, char *path, ID **r_real_id)
951 {
952  if (r_real_id != NULL) {
953  *r_real_id = NULL;
954  }
955 
956  const char *prefix;
957  ID *real_id = RNA_find_real_ID_and_path(bmain, id, &prefix);
958 
959  if (r_real_id != NULL) {
960  *r_real_id = real_id;
961  }
962 
963  if (path != NULL) {
964  char *new_path = NULL;
965 
966  if (real_id) {
967  if (prefix[0]) {
968  new_path = BLI_sprintfN("%s%s%s", prefix, path[0] == '[' ? "" : ".", path);
969  }
970  else {
971  return path;
972  }
973  }
974 
975  MEM_freeN(path);
976  return new_path;
977  }
978  return prefix[0] != '\0' ? BLI_strdup(prefix) : NULL;
979 }
980 
982 {
983  char *ptrpath = NULL;
984 
985  if (!ptr->owner_id || !ptr->data) {
986  return NULL;
987  }
988 
989  if (!RNA_struct_is_ID(ptr->type)) {
990  if (ptr->type->path) {
991  /* if type has a path to some ID, use it */
992  ptrpath = ptr->type->path((PointerRNA *)ptr);
993  }
994  else if (ptr->type->nested && RNA_struct_is_ID(ptr->type->nested)) {
995  PointerRNA parentptr;
996  PropertyRNA *userprop;
997 
998  /* find the property in the struct we're nested in that references this struct, and
999  * use its identifier as the first part of the path used...
1000  */
1001  RNA_id_pointer_create(ptr->owner_id, &parentptr);
1002  userprop = rna_struct_find_nested(&parentptr, ptr->type);
1003 
1004  if (userprop) {
1005  ptrpath = BLI_strdup(RNA_property_identifier(userprop));
1006  }
1007  else {
1008  return NULL; /* can't do anything about this case yet... */
1009  }
1010  }
1011  else if (RNA_struct_is_a(ptr->type, &RNA_PropertyGroup)) {
1012  /* special case, easier to deal with here than in ptr->type->path() */
1014  }
1015  else {
1016  return NULL;
1017  }
1018  }
1019 
1020  return ptrpath;
1021 }
1022 
1023 char *RNA_path_from_real_ID_to_struct(Main *bmain, const PointerRNA *ptr, struct ID **r_real)
1024 {
1025  char *path = RNA_path_from_ID_to_struct(ptr);
1026 
1027  /* NULL path is valid in that case, when given struct is an ID one... */
1028  return rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real);
1029 }
1030 
1032  const int totdims,
1033  const int index_dim,
1034  int index,
1035  int r_index_multi[RNA_MAX_ARRAY_LENGTH])
1036 {
1037  int dimsize_step[RNA_MAX_ARRAY_LENGTH + 1];
1038  int i = totdims - 1;
1039  dimsize_step[i + 1] = 1;
1040  dimsize_step[i] = dimsize[i];
1041  while (--i != -1) {
1042  dimsize_step[i] = dimsize[i] * dimsize_step[i + 1];
1043  }
1044  while (++i != index_dim) {
1045  int index_round = index / dimsize_step[i + 1];
1046  r_index_multi[i] = index_round;
1047  index -= (index_round * dimsize_step[i + 1]);
1048  }
1049  BLI_assert(index == 0);
1050 }
1051 
1053  PropertyRNA *prop,
1054  int index_dim,
1055  int index,
1056  char *index_str,
1057  int index_str_len)
1058 {
1059  int dimsize[RNA_MAX_ARRAY_LENGTH];
1060  int totdims = RNA_property_array_dimension(ptr, prop, dimsize);
1061  int index_multi[RNA_MAX_ARRAY_LENGTH];
1062 
1063  rna_path_array_multi_from_flat_index(dimsize, totdims, index_dim, index, index_multi);
1064 
1065  for (int i = 0, offset = 0; (i < index_dim) && (offset < index_str_len); i++) {
1067  &index_str[offset], index_str_len - offset, "[%d]", index_multi[i]);
1068  }
1069 }
1070 
1072  PropertyRNA *prop,
1073  int index_dim,
1074  int index)
1075 {
1076  const bool is_rna = (prop->magic == RNA_MAGIC);
1077  const char *propname;
1078  char *ptrpath, *path;
1079 
1080  if (!ptr->owner_id || !ptr->data) {
1081  return NULL;
1082  }
1083 
1084  /* path from ID to the struct holding this property */
1085  ptrpath = RNA_path_from_ID_to_struct(ptr);
1086 
1087  propname = RNA_property_identifier(prop);
1088 
1089  /* support indexing w/ multi-dimensional arrays */
1090  char index_str[RNA_MAX_ARRAY_LENGTH * 12 + 1];
1091  if (index_dim == 0) {
1092  index_str[0] = '\0';
1093  }
1094  else {
1096  ptr, prop, index_dim, index, index_str, sizeof(index_str));
1097  }
1098 
1099  if (ptrpath) {
1100  if (is_rna) {
1101  path = BLI_sprintfN("%s.%s%s", ptrpath, propname, index_str);
1102  }
1103  else {
1104  char propname_esc[MAX_IDPROP_NAME * 2];
1105  BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
1106  path = BLI_sprintfN("%s[\"%s\"]%s", ptrpath, propname_esc, index_str);
1107  }
1108  MEM_freeN(ptrpath);
1109  }
1110  else if (RNA_struct_is_ID(ptr->type)) {
1111  if (is_rna) {
1112  path = BLI_sprintfN("%s%s", propname, index_str);
1113  }
1114  else {
1115  char propname_esc[MAX_IDPROP_NAME * 2];
1116  BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
1117  path = BLI_sprintfN("[\"%s\"]%s", propname_esc, index_str);
1118  }
1119  }
1120  else {
1121  path = NULL;
1122  }
1123 
1124  return path;
1125 }
1126 
1128 {
1129  return RNA_path_from_ID_to_property_index(ptr, prop, 0, -1);
1130 }
1131 
1133  const PointerRNA *ptr,
1134  PropertyRNA *prop,
1135  int index_dim,
1136  int index,
1137  ID **r_real_id)
1138 {
1139  char *path = RNA_path_from_ID_to_property_index(ptr, prop, index_dim, index);
1140 
1141  /* NULL path is always an error here, in that case do not return the 'fake ID from real ID' part
1142  * of the path either. */
1143  return path != NULL ? rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real_id) : NULL;
1144 }
1145 
1147  PropertyRNA *prop,
1148  const StructRNA *type)
1149 {
1150  /* Try to recursively find an "type"'d ancestor,
1151  * to handle situations where path from ID is not enough. */
1152  PointerRNA idptr;
1153  ListBase path_elems = {NULL};
1154  char *path = NULL;
1155  char *full_path = RNA_path_from_ID_to_property(ptr, prop);
1156 
1157  if (full_path == NULL) {
1158  return NULL;
1159  }
1160 
1162 
1163  if (RNA_path_resolve_elements(&idptr, full_path, &path_elems)) {
1164  LISTBASE_FOREACH_BACKWARD (PropertyElemRNA *, prop_elem, &path_elems) {
1165  if (RNA_struct_is_a(prop_elem->ptr.type, type)) {
1166  char *ref_path = RNA_path_from_ID_to_struct(&prop_elem->ptr);
1167  if (ref_path) {
1168  path = BLI_strdup(full_path + strlen(ref_path) + 1); /* +1 for the linking '.' */
1169  MEM_freeN(ref_path);
1170  }
1171  break;
1172  }
1173  }
1174 
1175  BLI_freelistN(&path_elems);
1176  }
1177 
1178  MEM_freeN(full_path);
1179  return path;
1180 }
1181 
1182 char *RNA_path_full_ID_py(Main *bmain, ID *id)
1183 {
1184  const char *path;
1185  ID *id_real = RNA_find_real_ID_and_path(bmain, id, &path);
1186 
1187  if (id_real) {
1188  id = id_real;
1189  }
1190  else {
1191  path = "";
1192  }
1193 
1194  char lib_filepath_esc[(sizeof(id->lib->filepath) * 2) + 4];
1195  if (ID_IS_LINKED(id)) {
1196  int ofs = 0;
1197  memcpy(lib_filepath_esc, ", \"", 3);
1198  ofs += 3;
1199  ofs += BLI_str_escape(lib_filepath_esc + ofs, id->lib->filepath, sizeof(lib_filepath_esc));
1200  memcpy(lib_filepath_esc + ofs, "\"", 2);
1201  }
1202  else {
1203  lib_filepath_esc[0] = '\0';
1204  }
1205 
1206  char id_esc[(sizeof(id->name) - 2) * 2];
1207  BLI_str_escape(id_esc, id->name + 2, sizeof(id_esc));
1208 
1209  return BLI_sprintfN("bpy.data.%s[\"%s\"%s]%s%s",
1211  id_esc,
1212  lib_filepath_esc,
1213  path[0] ? "." : "",
1214  path);
1215 }
1216 
1218 {
1219  char *id_path;
1220  char *data_path;
1221 
1222  char *ret;
1223 
1224  if (!ptr->owner_id) {
1225  return NULL;
1226  }
1227 
1228  /* never fails */
1229  id_path = RNA_path_full_ID_py(bmain, ptr->owner_id);
1230 
1231  data_path = RNA_path_from_ID_to_struct(ptr);
1232 
1233  /* XXX data_path may be NULL (see T36788),
1234  * do we want to get the 'bpy.data.foo["bar"].(null)' stuff? */
1235  ret = BLI_sprintfN("%s.%s", id_path, data_path);
1236 
1237  if (data_path) {
1238  MEM_freeN(data_path);
1239  }
1240  MEM_freeN(id_path);
1241 
1242  return ret;
1243 }
1244 
1246  Main *bmain, const PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback)
1247 {
1248  char *id_path;
1249  const char *data_delim;
1250  const char *data_path;
1251  bool data_path_free;
1252 
1253  char *ret;
1254 
1255  if (!ptr->owner_id) {
1256  return NULL;
1257  }
1258 
1259  /* never fails */
1260  id_path = RNA_path_full_ID_py(bmain, ptr->owner_id);
1261 
1262  data_path = RNA_path_from_ID_to_property(ptr, prop);
1263  if (data_path) {
1264  data_delim = (data_path[0] == '[') ? "" : ".";
1265  data_path_free = true;
1266  }
1267  else {
1268  if (use_fallback) {
1269  /* Fuzzy fallback. Be explicit in our ignorance. */
1270  data_path = RNA_property_identifier(prop);
1271  data_delim = " ... ";
1272  }
1273  else {
1274  data_delim = ".";
1275  }
1276  data_path_free = false;
1277  }
1278 
1279  if ((index == -1) || (RNA_property_array_check(prop) == false)) {
1280  ret = BLI_sprintfN("%s%s%s", id_path, data_delim, data_path);
1281  }
1282  else {
1283  ret = BLI_sprintfN("%s%s%s[%d]", id_path, data_delim, data_path, index);
1284  }
1285  MEM_freeN(id_path);
1286  if (data_path_free) {
1287  MEM_freeN((void *)data_path);
1288  }
1289 
1290  return ret;
1291 }
1292 
1294 {
1295  return RNA_path_full_property_py_ex(bmain, ptr, prop, index, false);
1296 }
1297 
1299 {
1300  char *data_path;
1301 
1302  char *ret;
1303 
1304  if (!ptr->owner_id) {
1305  return NULL;
1306  }
1307 
1308  data_path = RNA_path_from_ID_to_property(ptr, prop);
1309 
1310  if (data_path == NULL) {
1311  /* This may not be an ID at all, check for simple when pointer owns property.
1312  * TODO: more complex nested case. */
1313  if (!RNA_struct_is_ID(ptr->type)) {
1314  const char *prop_identifier = RNA_property_identifier(prop);
1315  if (RNA_struct_find_property(ptr, prop_identifier) == prop) {
1316  data_path = BLI_strdup(prop_identifier);
1317  }
1318  }
1319  }
1320 
1321  if ((index == -1) || (RNA_property_array_check(prop) == false)) {
1322  ret = BLI_strdup(data_path);
1323  }
1324  else {
1325  ret = BLI_sprintfN("%s[%d]", data_path, index);
1326  }
1327 
1328  if (data_path) {
1329  MEM_freeN(data_path);
1330  }
1331 
1332  return ret;
1333 }
1334 
1336 {
1337  const bool is_rna = (prop->magic == RNA_MAGIC);
1338  const char *propname = RNA_property_identifier(prop);
1339  char *ret;
1340 
1341  if ((index == -1) || (RNA_property_array_check(prop) == false)) {
1342  if (is_rna) {
1343  ret = BLI_strdup(propname);
1344  }
1345  else {
1346  char propname_esc[MAX_IDPROP_NAME * 2];
1347  BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
1348  ret = BLI_sprintfN("[\"%s\"]", propname_esc);
1349  }
1350  }
1351  else {
1352  if (is_rna) {
1353  ret = BLI_sprintfN("%s[%d]", propname, index);
1354  }
1355  else {
1356  char propname_esc[MAX_IDPROP_NAME * 2];
1357  BLI_str_escape(propname_esc, propname, sizeof(propname_esc));
1358  ret = BLI_sprintfN("[\"%s\"][%d]", propname_esc, index);
1359  }
1360  }
1361 
1362  return ret;
1363 }
#define IDP_IDPArray(prop)
Definition: BKE_idprop.h:272
struct IDProperty * IDP_GetPropertyFromGroup(const struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
const char * BKE_idtype_idcode_to_name_plural(short idcode)
Definition: idtype.c:149
const struct IDTypeInfo * BKE_idtype_get_info_from_id(const struct ID *id)
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:22
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:50
char * BLI_dynstr_get_cstring(const DynStr *ds) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: BLI_dynstr.c:256
void BLI_dynstr_free(DynStr *ds) ATTR_NONNULL()
Definition: BLI_dynstr.c:281
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
void BLI_dynstr_append(DynStr *__restrict ds, const char *cstr) ATTR_NONNULL()
Definition: BLI_dynstr.c:75
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
Definition: BLI_listbase.h:348
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:466
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, size_t src_maxncpy) ATTR_NONNULL()
Definition: string.c:327
size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
const char * BLI_str_escape_find_quote(const char *str) ATTR_NONNULL()
Definition: string.c:341
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
size_t size_t char size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL()
Definition: string.c:250
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
ID and Library types, which are fundamental for sdna.
@ IDP_IDPARRAY
Definition: DNA_ID.h:144
@ IDP_GROUP
Definition: DNA_ID.h:141
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define MAX_IDPROP_NAME
Definition: DNA_ID.h:131
@ LIB_EMBEDDED_DATA
Definition: DNA_ID.h:635
@ ID_NT
Definition: DNA_ID_enums.h:68
@ ID_GR
Definition: DNA_ID_enums.h:65
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define RNA_POINTER_INVALIDATE(ptr)
Definition: RNA_access.h:744
#define RNA_MAX_ARRAY_LENGTH
Definition: RNA_define.h:25
#define RNA_MAX_ARRAY_DIMENSION
Definition: RNA_define.h:28
@ PROP_FLOAT
Definition: RNA_types.h:61
@ PROP_BOOLEAN
Definition: RNA_types.h:59
@ PROP_INT
Definition: RNA_types.h:60
@ PROP_POINTER
Definition: RNA_types.h:64
@ PROP_COLLECTION
Definition: RNA_types.h:65
@ PROP_IDPROPERTY
Definition: RNA_types.h:288
int len
Definition: draw_manager.c:108
#define GS(x)
Definition: iris.c:225
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
return ret
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1080
bool RNA_struct_is_a(const StructRNA *type, const StructRNA *srna)
Definition: rna_access.c:695
void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
Definition: rna_access.c:112
bool RNA_struct_is_ID(const StructRNA *type)
Definition: rna_access.c:655
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1000
PropertyRNA * rna_struct_find_nested(PointerRNA *ptr, StructRNA *srna)
Definition: rna_access.c:742
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1010
PointerRNA RNA_property_pointer_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:3493
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr)
Definition: rna_access.c:4097
IDProperty * RNA_struct_idprops(PointerRNA *ptr, bool create)
Definition: rna_access.c:251
int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr)
Definition: rna_access.c:4184
int RNA_property_array_dimension(const PointerRNA *ptr, PropertyRNA *prop, int length[])
Definition: rna_access.c:1085
bool RNA_pointer_is_null(const PointerRNA *ptr)
Definition: rna_access.c:164
bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr)
Definition: rna_access.c:4210
int RNA_property_array_item_index(PropertyRNA *prop, char name)
Definition: rna_access.c:1136
StructRNA RNA_PropertyGroup
#define RNA_MAGIC
Definition: rna_internal.h:21
char * RNA_path_full_struct_py(Main *bmain, const PointerRNA *ptr)
Definition: rna_path.cc:1217
static bool rna_path_parse_array_index(const char **path, PointerRNA *ptr, PropertyRNA *prop, int *r_index)
Definition: rna_path.cc:231
static char * rna_path_token_in_brackets(const char **path, char *fixedbuf, int fixedlen, bool *r_quoted)
Definition: rna_path.cc:78
static bool rna_path_parse(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index, PointerRNA *r_item_ptr, ListBase *r_elements, const bool eval_pointer)
Definition: rna_path.cc:348
bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, ListBase *r_elements)
Definition: rna_path.cc:579
char * RNA_path_from_ID_to_struct(const PointerRNA *ptr)
Definition: rna_path.cc:981
static UNUSED_FUNCTION_WITH_RETURN_TYPE(char *, RNA_path_back)(const char *path)
Definition: rna_path.cc:635
char * RNA_path_append(const char *path, const PointerRNA *UNUSED(ptr), PropertyRNA *prop, int intkey, const char *strkey)
Definition: rna_path.cc:584
char * RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_path.cc:1298
bool RNA_path_resolve_full_maybe_null(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition: rna_path.cc:525
char * RNA_path_from_ID_to_property_index(const PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index)
Definition: rna_path.cc:1071
char * RNA_path_full_property_py(Main *bmain, const PointerRNA *ptr, PropertyRNA *prop, int index)
Definition: rna_path.cc:1293
char * RNA_path_from_struct_to_idproperty(PointerRNA *ptr, IDProperty *needle)
Definition: rna_path.cc:893
char * RNA_path_resolve_from_type_to_property(const PointerRNA *ptr, PropertyRNA *prop, const StructRNA *type)
Definition: rna_path.cc:1146
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
static char * rna_path_from_ID_to_idpgroup(const PointerRNA *ptr)
Definition: rna_path.cc:903
char * RNA_path_full_ID_py(Main *bmain, ID *id)
Definition: rna_path.cc:1182
static char * rna_idp_path_create(IDP_Chain *child_link)
Definition: rna_path.cc:753
bool RNA_path_resolve_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition: rna_path.cc:515
static char * rna_path_token(const char **path, char *fixedbuf, int fixedlen)
Definition: rna_path.cc:38
static bool rna_path_parse_collection_key(const char **path, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_nextptr)
Definition: rna_path.cc:164
char * RNA_path_from_ID_to_property(const PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_path.cc:1127
static char * rna_prepend_real_ID_path(Main *bmain, ID *id, char *path, ID **r_real_id)
Definition: rna_path.cc:950
char * RNA_path_property_py(const PointerRNA *UNUSED(ptr), PropertyRNA *prop, int index)
Definition: rna_path.cc:1335
struct IDP_Chain IDP_Chain
bool RNA_path_resolve_property(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_path.cc:531
static void rna_path_array_multi_string_from_flat_index(const PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, char *index_str, int index_str_len)
Definition: rna_path.cc:1052
bool RNA_path_resolve_property_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index)
Definition: rna_path.cc:543
char * RNA_path_from_real_ID_to_property_index(Main *bmain, const PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, ID **r_real_id)
Definition: rna_path.cc:1132
static char * rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *needle, IDP_Chain *parent_link)
Definition: rna_path.cc:796
bool RNA_path_resolve_property_and_item_pointer_full(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop, int *r_index, PointerRNA *r_item_ptr)
Definition: rna_path.cc:566
const char * RNA_path_array_index_token_find(const char *rna_path, const PropertyRNA *array_prop)
Definition: rna_path.cc:693
char * RNA_path_from_real_ID_to_struct(Main *bmain, const PointerRNA *ptr, struct ID **r_real)
Definition: rna_path.cc:1023
char * RNA_path_full_property_py_ex(Main *bmain, const PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback)
Definition: rna_path.cc:1245
bool RNA_path_resolve(const PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
Definition: rna_path.cc:503
static void rna_path_array_multi_from_flat_index(const int dimsize[RNA_MAX_ARRAY_LENGTH], const int totdims, const int index_dim, int index, int r_index_multi[RNA_MAX_ARRAY_LENGTH])
Definition: rna_path.cc:1031
struct IDP_Chain * up
Definition: rna_path.cc:746
const char * name
Definition: rna_path.cc:748
int index
Definition: rna_path.cc:749
ListBase group
Definition: DNA_ID.h:101
int len
Definition: DNA_ID.h:121
struct IDProperty * next
Definition: DNA_ID.h:107
char name[64]
Definition: DNA_ID.h:111
IDPropertyData data
Definition: DNA_ID.h:117
char type
Definition: DNA_ID.h:108
IDTypeEmbeddedOwnerGetFunction owner_get
Definition: BKE_idtype.h:189
Definition: DNA_ID.h:368
struct Library * lib
Definition: DNA_ID.h:372
short flag
Definition: DNA_ID.h:383
char name[66]
Definition: DNA_ID.h:378
char filepath[1024]
Definition: DNA_ID.h:461
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
struct StructRNA * type
Definition: RNA_types.h:37
void * data
Definition: RNA_types.h:38
struct ID * owner_id
Definition: RNA_types.h:36
PointerRNA ptr
Definition: RNA_path.h:158
PropertyRNA * prop
Definition: RNA_path.h:159
unsigned int arraydimension
PropertyType type
struct StructRNA * nested
StructPathFunc path
PointerRNA * ptr
Definition: wm_files.c:3480