Blender  V2.93
fcurve_cache.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 
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_anim_types.h"
29 
30 #include "BLI_ghash.h"
31 #include "BLI_listbase.h"
32 
33 #include "BKE_fcurve.h"
34 
35 /* -------------------------------------------------------------------- */
46 };
47 
56 };
57 
61 static int fcurve_cmp_for_cache(const void *fcu_a_p, const void *fcu_b_p)
62 {
63  const FCurve *fcu_a = *((const FCurve **)fcu_a_p);
64  const FCurve *fcu_b = *((const FCurve **)fcu_b_p);
65  const int cmp = strcmp(fcu_a->rna_path, fcu_b->rna_path);
66  if (cmp != 0) {
67  return cmp;
68  }
69  if (fcu_a->array_index < fcu_b->array_index) {
70  return -1;
71  }
72  if (fcu_a->array_index > fcu_b->array_index) {
73  return 1;
74  }
75  return 0;
76 }
77 
79 {
82  uint i;
83  LISTBASE_FOREACH_INDEX (FCurve *, fcu, list, i) {
84  fcurve_array[i] = fcu;
85  }
87 
88  /* Allow for the case no F-curves share an RNA-path, otherwise this is over-allocated.
89  * Although in practice it's likely to only be 3-4x as large as is needed
90  * (with transform channels for e.g.). */
91  struct FCurvePathCache_Span *span_table = MEM_mallocN(sizeof(*span_table) * fcurve_array_len,
92  __func__);
93 
94  /* May over reserve, harmless. */
95  GHash *span_from_rna_path = BLI_ghash_str_new_ex(__func__, fcurve_array_len);
96  uint span_index = 0;
97  i = 0;
98  while (i < fcurve_array_len) {
99  uint i_end;
100  for (i_end = i + 1; i_end < fcurve_array_len; i_end++) {
101  /* As the indices are sorted, we know a decrease means a new RNA path is found. */
102  if (fcurve_array[i]->array_index > fcurve_array[i_end]->array_index) {
103  BLI_assert(!STREQ(fcurve_array[i]->rna_path, fcurve_array[i_end]->rna_path));
104  break;
105  }
106  if (!STREQ(fcurve_array[i]->rna_path, fcurve_array[i_end]->rna_path)) {
107  break;
108  }
109  }
110 
111  struct FCurvePathCache_Span *span = &span_table[span_index++];
112  span->index = i;
113  span->len = i_end - i;
114  BLI_ghash_insert(span_from_rna_path, fcurve_array[i]->rna_path, span);
115  i = i_end;
116  }
117 
118  struct FCurvePathCache *fcache = MEM_callocN(sizeof(struct FCurvePathCache), __func__);
119  fcache->fcurve_array = fcurve_array;
121  fcache->span_table = span_table;
123 
124  return fcache;
125 }
126 
128 {
129  MEM_freeN(fcache->fcurve_array);
130  MEM_freeN(fcache->span_table);
132  MEM_freeN(fcache);
133 }
134 
136  const char *rna_path,
137  const int array_index)
138 {
139  const struct FCurvePathCache_Span *span = BLI_ghash_lookup(fcache->span_from_rna_path, rna_path);
140  if (span == NULL) {
141  return NULL;
142  }
143 
144  FCurve **fcurve = fcache->fcurve_array + span->index;
145  const uint len = span->len;
146  for (int i = 0; i < len; i++) {
147  if (fcurve[i]->array_index == array_index) {
148  return fcurve[i];
149  }
150  /* As these are sorted, early exit. */
151  if (fcurve[i]->array_index > array_index) {
152  break;
153  }
154  }
155  return NULL;
156 }
157 
164  const char *rna_path,
165  FCurve **fcurve_result,
166  int fcurve_result_len)
167 {
168  memset(fcurve_result, 0x0, sizeof(*fcurve_result) * fcurve_result_len);
169 
170  const struct FCurvePathCache_Span *span = BLI_ghash_lookup(fcache->span_from_rna_path, rna_path);
171  if (span == NULL) {
172  return 0;
173  }
174 
175  int found = 0;
176  FCurve **fcurve = fcache->fcurve_array + span->index;
177  const uint len = span->len;
178  for (int i = 0; i < len; i++) {
179  /* As these are sorted, early exit. */
180  if ((uint)fcurve[i]->array_index > (uint)fcurve_result_len) {
181  break;
182  }
183  fcurve_result[fcurve[i]->array_index] = fcurve[i];
184  found += 1;
185  }
186  return found;
187 }
188 
#define BLI_assert(a)
Definition: BLI_assert.h:58
GHash * BLI_ghash_str_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition: BLI_ghash.c:756
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition: BLI_ghash.c:1008
void * BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:803
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:180
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
unsigned int uint
Definition: BLI_sys_types.h:83
#define STREQ(a, b)
Read Guarded memory(de)allocation.
struct FCurvePathCache * BKE_fcurve_pathcache_create(ListBase *list)
Definition: fcurve_cache.c:78
FCurve * BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache, const char *rna_path, const int array_index)
Definition: fcurve_cache.c:135
int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache, const char *rna_path, FCurve **fcurve_result, int fcurve_result_len)
Definition: fcurve_cache.c:163
static int fcurve_cmp_for_cache(const void *fcu_a_p, const void *fcu_b_p)
Definition: fcurve_cache.c:61
void BKE_fcurve_pathcache_destroy(struct FCurvePathCache *fcache)
Definition: fcurve_cache.c:127
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
GHash * span_from_rna_path
Definition: fcurve_cache.c:55
struct FCurvePathCache_Span * span_table
Definition: fcurve_cache.c:53
FCurve ** fcurve_array
Definition: fcurve_cache.c:50
char * rna_path
int array_index
uint len