Blender V5.0
fcurve_cache.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <cstdlib>
12#include <cstring>
13
14#include "MEM_guardedalloc.h"
15
16#include "DNA_anim_types.h"
17
18#include "BLI_ghash.h"
19
20#include "BKE_fcurve.hh"
21
22/* -------------------------------------------------------------------- */
27
34
44
48static int fcurve_cmp_for_cache(const void *fcu_a_p, const void *fcu_b_p)
49{
50 const FCurve *fcu_a = *((const FCurve **)fcu_a_p);
51 const FCurve *fcu_b = *((const FCurve **)fcu_b_p);
52 const int cmp = strcmp(fcu_a->rna_path, fcu_b->rna_path);
53 if (cmp != 0) {
54 return cmp;
55 }
56 if (fcu_a->array_index < fcu_b->array_index) {
57 return -1;
58 }
59 if (fcu_a->array_index > fcu_b->array_index) {
60 return 1;
61 }
62 return 0;
63}
64
66{
67 const uint fcurve_array_len = fcurves.size();
68 FCurve **fcurve_array = MEM_malloc_arrayN<FCurve *>(fcurve_array_len, __func__);
69 for (const int i : fcurves.index_range()) {
70 fcurve_array[i] = fcurves[i];
71 }
72 qsort(fcurve_array, fcurve_array_len, sizeof(FCurve *), fcurve_cmp_for_cache);
73
74 /* Allow for the case no F-Curves share an RNA-path, otherwise this is over-allocated.
75 * Although in practice it's likely to only be 3-4x as large as is needed
76 * (e.g. with transform channels). */
78 __func__);
79
80 /* May over reserve, harmless. */
81 GHash *span_from_rna_path = BLI_ghash_str_new_ex(__func__, fcurve_array_len);
82 uint span_index = 0;
83 uint i = 0;
84 while (i < fcurve_array_len) {
85 uint i_end;
86 for (i_end = i + 1; i_end < fcurve_array_len; i_end++) {
87 /* As the indices are sorted, we know a decrease means a new RNA path is found. */
88 if (fcurve_array[i]->array_index > fcurve_array[i_end]->array_index) {
89 BLI_assert(!STREQ(fcurve_array[i]->rna_path, fcurve_array[i_end]->rna_path));
90 break;
91 }
92 if (!STREQ(fcurve_array[i]->rna_path, fcurve_array[i_end]->rna_path)) {
93 break;
94 }
95 }
96
97 FCurvePathCache_Span *span = &span_table[span_index++];
98 span->index = i;
99 span->len = i_end - i;
100 BLI_ghash_insert(span_from_rna_path, fcurve_array[i]->rna_path, span);
101 i = i_end;
102 }
103
105 fcache->fcurve_array = fcurve_array;
106 fcache->fcurve_array_len = fcurve_array_len;
107 fcache->span_table = span_table;
108 fcache->span_from_rna_path = span_from_rna_path;
109
110 return fcache;
111}
112
114{
115 MEM_freeN(fcache->fcurve_array);
116 MEM_freeN(fcache->span_table);
117 BLI_ghash_free(fcache->span_from_rna_path, nullptr, nullptr);
118 MEM_freeN(fcache);
119}
120
122 const char *rna_path,
123 const int array_index)
124{
125 const FCurvePathCache_Span *span = static_cast<const FCurvePathCache_Span *>(
126 BLI_ghash_lookup(fcache->span_from_rna_path, rna_path));
127 if (span == nullptr) {
128 return nullptr;
129 }
130
131 FCurve **fcurve = fcache->fcurve_array + span->index;
132 const uint len = span->len;
133 for (int i = 0; i < len; i++) {
134 if (fcurve[i]->array_index == array_index) {
135 return fcurve[i];
136 }
137 /* As these are sorted, early exit. */
138 if (fcurve[i]->array_index > array_index) {
139 break;
140 }
141 }
142 return nullptr;
143}
144
146 const char *rna_path,
147 FCurve **fcurve_result,
148 int fcurve_result_len)
149{
150 memset(fcurve_result, 0x0, sizeof(*fcurve_result) * fcurve_result_len);
151
152 const FCurvePathCache_Span *span = static_cast<const FCurvePathCache_Span *>(
153 BLI_ghash_lookup(fcache->span_from_rna_path, rna_path));
154 if (span == nullptr) {
155 return 0;
156 }
157
158 int found = 0;
159 FCurve **fcurve = fcache->fcurve_array + span->index;
160 const uint len = span->len;
161 for (int i = 0; i < len; i++) {
162 /* As these are sorted, early exit. */
163 if (uint(fcurve[i]->array_index) > uint(fcurve_result_len)) {
164 break;
165 }
166 fcurve_result[fcurve[i]->array_index] = fcurve[i];
167 found += 1;
168 }
169 return found;
170}
171
#define BLI_assert(a)
Definition BLI_assert.h:46
GHash * BLI_ghash_str_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
unsigned int uint
#define STREQ(a, b)
Read Guarded memory(de)allocation.
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
void BKE_fcurve_pathcache_destroy(FCurvePathCache *fcache)
FCurvePathCache * BKE_fcurve_pathcache_create(blender::Span< FCurve * > fcurves)
static int fcurve_cmp_for_cache(const void *fcu_a_p, const void *fcu_b_p)
FCurve * BKE_fcurve_pathcache_find(const FCurvePathCache *fcache, const char *rna_path, const int array_index)
int BKE_fcurve_pathcache_find_array(const FCurvePathCache *fcache, const char *rna_path, FCurve **fcurve_result, int fcurve_result_len)
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
GHash * span_from_rna_path
FCurve ** fcurve_array
FCurvePathCache_Span * span_table
char * rna_path
int array_index
i
Definition text_draw.cc:230
uint len