Blender  V3.3
cachefile.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2016 Blender Foundation. All rights reserved. */
3 
8 #include <string.h>
9 
10 #include "DNA_anim_types.h"
11 #include "DNA_cachefile_types.h"
12 #include "DNA_constraint_types.h"
13 #include "DNA_object_types.h"
14 #include "DNA_scene_types.h"
15 
16 #include "BLI_fileops.h"
17 #include "BLI_ghash.h"
18 #include "BLI_listbase.h"
19 #include "BLI_path_util.h"
20 #include "BLI_string.h"
21 #include "BLI_threads.h"
22 #include "BLI_utildefines.h"
23 
24 #include "BLT_translation.h"
25 
26 #include "BKE_anim_data.h"
27 #include "BKE_bpath.h"
28 #include "BKE_cachefile.h"
29 #include "BKE_idtype.h"
30 #include "BKE_lib_id.h"
31 #include "BKE_main.h"
32 #include "BKE_modifier.h"
33 #include "BKE_scene.h"
34 
35 #include "DEG_depsgraph_query.h"
36 
37 #include "RE_engine.h"
38 
39 #include "BLO_read_write.h"
40 
41 #include "MEM_guardedalloc.h"
42 
43 #ifdef WITH_ALEMBIC
44 # include "ABC_alembic.h"
45 #endif
46 
47 #ifdef WITH_USD
48 # include "usd.h"
49 #endif
50 
51 static void cachefile_handle_free(CacheFile *cache_file);
52 
53 static void cache_file_init_data(ID *id)
54 {
55  CacheFile *cache_file = (CacheFile *)id;
56 
57  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(cache_file, id));
58 
59  cache_file->scale = 1.0f;
61  BLI_strncpy(cache_file->velocity_name, ".velocities", sizeof(cache_file->velocity_name));
62 }
63 
64 static void cache_file_copy_data(Main *UNUSED(bmain),
65  ID *id_dst,
66  const ID *id_src,
67  const int UNUSED(flag))
68 {
69  CacheFile *cache_file_dst = (CacheFile *)id_dst;
70  const CacheFile *cache_file_src = (const CacheFile *)id_src;
71 
72  cache_file_dst->handle = NULL;
73  cache_file_dst->handle_readers = NULL;
74  BLI_duplicatelist(&cache_file_dst->object_paths, &cache_file_src->object_paths);
75  BLI_duplicatelist(&cache_file_dst->layers, &cache_file_src->layers);
76 }
77 
78 static void cache_file_free_data(ID *id)
79 {
80  CacheFile *cache_file = (CacheFile *)id;
81  cachefile_handle_free(cache_file);
82  BLI_freelistN(&cache_file->object_paths);
83  BLI_freelistN(&cache_file->layers);
84 }
85 
86 static void cache_file_foreach_path(ID *id, BPathForeachPathData *bpath_data)
87 {
88  CacheFile *cache_file = (CacheFile *)id;
89  BKE_bpath_foreach_path_fixed_process(bpath_data, cache_file->filepath);
90 }
91 
92 static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_address)
93 {
94  CacheFile *cache_file = (CacheFile *)id;
95 
96  /* Clean up, important in undo case to reduce false detection of changed datablocks. */
97  BLI_listbase_clear(&cache_file->object_paths);
98  cache_file->handle = NULL;
99  memset(cache_file->handle_filepath, 0, sizeof(cache_file->handle_filepath));
100  cache_file->handle_readers = NULL;
101 
102  BLO_write_id_struct(writer, CacheFile, id_address, &cache_file->id);
103  BKE_id_blend_write(writer, &cache_file->id);
104 
105  if (cache_file->adt) {
106  BKE_animdata_blend_write(writer, cache_file->adt);
107  }
108 
109  /* write layers */
110  LISTBASE_FOREACH (CacheFileLayer *, layer, &cache_file->layers) {
111  BLO_write_struct(writer, CacheFileLayer, layer);
112  }
113 }
114 
116 {
117  CacheFile *cache_file = (CacheFile *)id;
118  BLI_listbase_clear(&cache_file->object_paths);
119  cache_file->handle = NULL;
120  cache_file->handle_filepath[0] = '\0';
121  cache_file->handle_readers = NULL;
122 
123  /* relink animdata */
124  BLO_read_data_address(reader, &cache_file->adt);
125  BKE_animdata_blend_read_data(reader, cache_file->adt);
126 
127  /* relink layers */
128  BLO_read_list(reader, &cache_file->layers);
129 }
130 
132  .id_code = ID_CF,
133  .id_filter = FILTER_ID_CF,
134  .main_listbase_index = INDEX_ID_CF,
135  .struct_size = sizeof(CacheFile),
136  .name = "CacheFile",
137  .name_plural = "cache_files",
138  .translation_context = BLT_I18NCONTEXT_ID_CACHEFILE,
140  .asset_type_info = NULL,
141 
143  .copy_data = cache_file_copy_data,
144  .free_data = cache_file_free_data,
145  .make_local = NULL,
146  .foreach_id = NULL,
147  .foreach_cache = NULL,
148  .foreach_path = cache_file_foreach_path,
149  .owner_get = NULL,
150 
151  .blend_write = cache_file_blend_write,
152  .blend_read_data = cache_file_blend_read_data,
153  .blend_read_lib = NULL,
154  .blend_read_expand = NULL,
155 
156  .blend_read_undo_preserve = NULL,
157 
158  .lib_override_apply_post = NULL,
159 };
160 
161 /* TODO: make this per cache file to avoid global locks. */
162 static SpinLock spin;
163 
165 {
167 }
168 
170 {
171  BLI_spin_end(&spin);
172 }
173 
175  struct CacheReader **reader,
176  Object *object,
177  const char *object_path)
178 {
179 #if defined(WITH_ALEMBIC) || defined(WITH_USD)
180 
181  BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
182 
183  if (cache_file->handle == NULL) {
184  return;
185  }
186 
187  switch (cache_file->type) {
189 # ifdef WITH_ALEMBIC
190  /* Open Alembic cache reader. */
191  *reader = CacheReader_open_alembic_object(cache_file->handle, *reader, object, object_path);
192 # endif
193  break;
194  case CACHEFILE_TYPE_USD:
195 # ifdef WITH_USD
196  /* Open USD cache reader. */
197  *reader = CacheReader_open_usd_object(cache_file->handle, *reader, object, object_path);
198 # endif
199  break;
201  break;
202  }
203 
204  /* Multiple modifiers and constraints can call this function concurrently. */
206  if (*reader) {
207  /* Register in set so we can free it when the cache file changes. */
208  if (cache_file->handle_readers == NULL) {
209  cache_file->handle_readers = BLI_gset_ptr_new("CacheFile.handle_readers");
210  }
211  BLI_gset_reinsert(cache_file->handle_readers, reader, NULL);
212  }
213  else if (cache_file->handle_readers) {
214  /* Remove in case CacheReader_open_alembic_object free the existing reader. */
215  BLI_gset_remove(cache_file->handle_readers, reader, NULL);
216  }
218 #else
219  UNUSED_VARS(cache_file, reader, object, object_path);
220 #endif
221 }
222 
223 void BKE_cachefile_reader_free(CacheFile *cache_file, struct CacheReader **reader)
224 {
225 #if defined(WITH_ALEMBIC) || defined(WITH_USD)
226  /* Multiple modifiers and constraints can call this function concurrently, and
227  * cachefile_handle_free() can also be called at the same time. */
229  if (*reader != NULL) {
230  if (cache_file) {
231  BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
232 
233  switch (cache_file->type) {
235 # ifdef WITH_ALEMBIC
236  ABC_CacheReader_free(*reader);
237 # endif
238  break;
239  case CACHEFILE_TYPE_USD:
240 # ifdef WITH_USD
241  USD_CacheReader_free(*reader);
242 # endif
243  break;
245  break;
246  }
247  }
248 
249  *reader = NULL;
250 
251  if (cache_file && cache_file->handle_readers) {
252  BLI_gset_remove(cache_file->handle_readers, reader, NULL);
253  }
254  }
256 #else
257  UNUSED_VARS(cache_file, reader);
258 #endif
259 }
260 
261 static void cachefile_handle_free(CacheFile *cache_file)
262 {
263 #if defined(WITH_ALEMBIC) || defined(WITH_USD)
264 
265  /* Free readers in all modifiers and constraints that use the handle, before
266  * we free the handle itself. */
268  if (cache_file->handle_readers) {
269  GSetIterator gs_iter;
270  GSET_ITER (gs_iter, cache_file->handle_readers) {
271  struct CacheReader **reader = BLI_gsetIterator_getKey(&gs_iter);
272  if (*reader != NULL) {
273  switch (cache_file->type) {
275 # ifdef WITH_ALEMBIC
276  ABC_CacheReader_free(*reader);
277 # endif
278  break;
279  case CACHEFILE_TYPE_USD:
280 # ifdef WITH_USD
281  USD_CacheReader_free(*reader);
282 # endif
283  break;
285  break;
286  }
287 
288  *reader = NULL;
289  }
290  }
291 
292  BLI_gset_free(cache_file->handle_readers, NULL);
293  cache_file->handle_readers = NULL;
294  }
296 
297  /* Free handle. */
298  if (cache_file->handle) {
299 
300  switch (cache_file->type) {
302 # ifdef WITH_ALEMBIC
303  ABC_free_handle(cache_file->handle);
304 # endif
305  break;
306  case CACHEFILE_TYPE_USD:
307 # ifdef WITH_USD
308  USD_free_handle(cache_file->handle);
309 # endif
310  break;
312  break;
313  }
314 
315  cache_file->handle = NULL;
316  }
317 
318  cache_file->handle_filepath[0] = '\0';
319 #else
320  UNUSED_VARS(cache_file);
321 #endif
322 }
323 
324 void *BKE_cachefile_add(Main *bmain, const char *name)
325 {
326  CacheFile *cache_file = BKE_id_new(bmain, ID_CF, name);
327 
328  return cache_file;
329 }
330 
332 {
333  /* To force reload, free the handle and tag depsgraph to load it again. */
334  CacheFile *cache_file_eval = (CacheFile *)DEG_get_evaluated_id(depsgraph, &cache_file->id);
335  if (cache_file_eval) {
336  cachefile_handle_free(cache_file_eval);
337  }
338 
340 }
341 
343 {
344  BLI_assert(cache_file->id.tag & LIB_TAG_COPIED_ON_WRITE);
345 
346  /* Compute filepath. */
347  char filepath[FILE_MAX];
348  if (!BKE_cachefile_filepath_get(bmain, depsgraph, cache_file, filepath)) {
349  return;
350  }
351 
352  /* Test if filepath change or if we can keep the existing handle. */
353  if (STREQ(cache_file->handle_filepath, filepath)) {
354  return;
355  }
356 
357  cachefile_handle_free(cache_file);
358  BLI_freelistN(&cache_file->object_paths);
359 
360 #ifdef WITH_ALEMBIC
361  if (BLI_path_extension_check_glob(filepath, "*abc")) {
362  cache_file->type = CACHEFILE_TYPE_ALEMBIC;
363  cache_file->handle = ABC_create_handle(
364  bmain, filepath, cache_file->layers.first, &cache_file->object_paths);
365  BLI_strncpy(cache_file->handle_filepath, filepath, FILE_MAX);
366  }
367 #endif
368 #ifdef WITH_USD
369  if (BLI_path_extension_check_glob(filepath, "*.usd;*.usda;*.usdc")) {
370  cache_file->type = CACHEFILE_TYPE_USD;
371  cache_file->handle = USD_create_handle(bmain, filepath, &cache_file->object_paths);
372  BLI_strncpy(cache_file->handle_filepath, filepath, FILE_MAX);
373  }
374 #endif
375 
376  if (DEG_is_active(depsgraph)) {
377  /* Flush object paths back to original data-block for UI. */
378  CacheFile *cache_file_orig = (CacheFile *)DEG_get_original_id(&cache_file->id);
379  BLI_freelistN(&cache_file_orig->object_paths);
380  BLI_duplicatelist(&cache_file_orig->object_paths, &cache_file->object_paths);
381  }
382 }
383 
385  const Depsgraph *depsgraph,
386  const CacheFile *cache_file,
387  char r_filepath[FILE_MAX])
388 {
389  BLI_strncpy(r_filepath, cache_file->filepath, FILE_MAX);
390  BLI_path_abs(r_filepath, ID_BLEND_PATH(bmain, &cache_file->id));
391 
392  int fframe;
393  int frame_len;
394 
395  if (cache_file->is_sequence && BLI_path_frame_get(r_filepath, &fframe, &frame_len)) {
397  const float ctime = BKE_scene_ctime_get(scene);
398  const double fps = (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base);
399  const int frame = (int)BKE_cachefile_time_offset(cache_file, (double)ctime, fps);
400 
401  char ext[32];
402  BLI_path_frame_strip(r_filepath, ext, sizeof(ext));
403  BLI_path_frame(r_filepath, frame, frame_len);
404  BLI_path_extension_ensure(r_filepath, FILE_MAX, ext);
405 
406  /* TODO(kevin): store sequence range? */
407  return BLI_exists(r_filepath);
408  }
409 
410  return true;
411 }
412 
413 double BKE_cachefile_time_offset(const CacheFile *cache_file, const double time, const double fps)
414 {
415  const double time_offset = (double)cache_file->frame_offset / fps;
416  const double frame = (cache_file->override_frame ? (double)cache_file->frame : time);
417  return cache_file->is_sequence ? frame : frame / fps - time_offset;
418 }
419 
421 {
422  RenderEngineType *render_engine_type = RE_engines_find(scene->r.engine);
423 
424  if (cache_file->type != CACHEFILE_TYPE_ALEMBIC ||
425  !RE_engine_supports_alembic_procedural(render_engine_type, scene)) {
426  return false;
427  }
428 
429  return cache_file->use_render_procedural;
430 }
431 
432 CacheFileLayer *BKE_cachefile_add_layer(CacheFile *cache_file, const char filename[1024])
433 {
434  for (CacheFileLayer *layer = cache_file->layers.first; layer; layer = layer->next) {
435  if (STREQ(layer->filepath, filename)) {
436  return NULL;
437  }
438  }
439 
440  const int num_layers = BLI_listbase_count(&cache_file->layers);
441 
442  CacheFileLayer *layer = MEM_callocN(sizeof(CacheFileLayer), "CacheFileLayer");
443  BLI_strncpy(layer->filepath, filename, sizeof(layer->filepath));
444 
445  BLI_addtail(&cache_file->layers, layer);
446 
447  cache_file->active_layer = (char)(num_layers + 1);
448 
449  return layer;
450 }
451 
453 {
454  return BLI_findlink(&cache_file->layers, cache_file->active_layer - 1);
455 }
456 
458 {
459  cache_file->active_layer = 0;
460  BLI_remlink(&cache_file->layers, layer);
461  MEM_freeN(layer);
462 }
struct CacheArchiveHandle * ABC_create_handle(struct Main *bmain, const char *filename, const struct CacheFileLayer *layers, struct ListBase *object_paths)
struct CacheReader * CacheReader_open_alembic_object(struct CacheArchiveHandle *handle, struct CacheReader *reader, struct Object *object, const char *object_path)
void ABC_CacheReader_free(struct CacheReader *reader)
void ABC_free_handle(struct CacheArchiveHandle *handle)
void BKE_animdata_blend_read_data(struct BlendDataReader *reader, struct AnimData *adt)
Definition: anim_data.c:1443
void BKE_animdata_blend_write(struct BlendWriter *writer, struct AnimData *adt)
Definition: anim_data.c:1421
bool BKE_bpath_foreach_path_fixed_process(struct BPathForeachPathData *bpath_data, char *path)
Definition: bpath.c:121
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition: BKE_idtype.h:39
void BKE_id_blend_write(struct BlendWriter *writer, struct ID *id)
Definition: lib_id.c:2008
void * BKE_id_new(struct Main *bmain, short type, const char *name)
Definition: lib_id.c:1159
float BKE_scene_ctime_get(const struct Scene *scene)
#define BLI_assert(a)
Definition: BLI_assert.h:46
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:314
bool BLI_gset_reinsert(GSet *gh, void *key, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:992
GSet * BLI_gset_ptr_new(const char *info)
#define GSET_ITER(gs_iter_, gset_)
Definition: BLI_ghash.h:471
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1037
BLI_INLINE void * BLI_gsetIterator_getKey(GSetIterator *gsi)
Definition: BLI_ghash.h:458
bool BLI_gset_remove(GSet *gs, const void *key, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1002
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
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
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL()
Definition: path_util.c:709
#define FILE_MAX
bool BLI_path_extension_ensure(char *path, size_t maxlen, const char *ext) ATTR_NONNULL()
Definition: path_util.c:1420
bool BLI_path_extension_check_glob(const char *str, const char *ext_fnmatch) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1341
bool BLI_path_frame_get(char *path, int *r_frame, int *r_digits_len) ATTR_NONNULL()
Definition: path_util.c:753
void BLI_path_frame_strip(char *path, char *r_ext, size_t ext_maxlen) ATTR_NONNULL()
Definition: path_util.c:805
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:110
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:419
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:452
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:433
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:467
#define UNUSED_VARS(...)
#define UNUSED(x)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define STREQ(a, b)
#define BLO_read_data_address(reader, ptr_p)
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
void BLO_read_list(BlendDataReader *reader, struct ListBase *list)
Definition: readfile.c:5172
#define BLT_I18NCONTEXT_ID_CACHEFILE
typedef double(DMatrix)[4][4]
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
bool DEG_is_active(const struct Depsgraph *depsgraph)
Definition: depsgraph.cc:312
void DEG_id_tag_update(struct ID *id, int flag)
struct ID * DEG_get_evaluated_id(const struct Depsgraph *depsgraph, struct ID *id)
struct ID * DEG_get_original_id(struct ID *id)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
#define FILTER_ID_CF
Definition: DNA_ID.h:927
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ INDEX_ID_CF
Definition: DNA_ID.h:1017
#define ID_BLEND_PATH(_bmain, _id)
Definition: DNA_ID.h:559
@ LIB_TAG_COPIED_ON_WRITE
Definition: DNA_ID.h:720
@ ID_CF
Definition: DNA_ID_enums.h:78
struct CacheFile CacheFile
@ CACHE_FILE_TYPE_INVALID
@ CACHEFILE_TYPE_ALEMBIC
@ CACHEFILE_TYPE_USD
@ CACHEFILE_VELOCITY_UNIT_SECOND
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
static float frame_len(const Frame *frame)
Definition: MOD_skin.c:379
bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file, Scene *scene)
Definition: cachefile.c:420
CacheFileLayer * BKE_cachefile_add_layer(CacheFile *cache_file, const char filename[1024])
Definition: cachefile.c:432
double BKE_cachefile_time_offset(const CacheFile *cache_file, const double time, const double fps)
Definition: cachefile.c:413
static void cachefile_handle_free(CacheFile *cache_file)
Definition: cachefile.c:261
CacheFileLayer * BKE_cachefile_get_active_layer(CacheFile *cache_file)
Definition: cachefile.c:452
static void cache_file_free_data(ID *id)
Definition: cachefile.c:78
void BKE_cachefiles_init(void)
Definition: cachefile.c:164
void BKE_cachefile_remove_layer(CacheFile *cache_file, CacheFileLayer *layer)
Definition: cachefile.c:457
static void cache_file_init_data(ID *id)
Definition: cachefile.c:53
static SpinLock spin
Definition: cachefile.c:162
static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_address)
Definition: cachefile.c:92
static void cache_file_foreach_path(ID *id, BPathForeachPathData *bpath_data)
Definition: cachefile.c:86
static void cache_file_blend_read_data(BlendDataReader *reader, ID *id)
Definition: cachefile.c:115
void BKE_cachefile_reader_free(CacheFile *cache_file, struct CacheReader **reader)
Definition: cachefile.c:223
void * BKE_cachefile_add(Main *bmain, const char *name)
Definition: cachefile.c:324
bool BKE_cachefile_filepath_get(const Main *bmain, const Depsgraph *depsgraph, const CacheFile *cache_file, char r_filepath[FILE_MAX])
Definition: cachefile.c:384
void BKE_cachefile_reload(Depsgraph *depsgraph, CacheFile *cache_file)
Definition: cachefile.c:331
void BKE_cachefile_eval(Main *bmain, Depsgraph *depsgraph, CacheFile *cache_file)
Definition: cachefile.c:342
void BKE_cachefile_reader_open(CacheFile *cache_file, struct CacheReader **reader, Object *object, const char *object_path)
Definition: cachefile.c:174
static void cache_file_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int UNUSED(flag))
Definition: cachefile.c:64
void BKE_cachefiles_exit(void)
Definition: cachefile.c:169
IDTypeInfo IDType_ID_CF
Definition: cachefile.c:131
double time
Scene scene
const Depsgraph * depsgraph
RenderEngineType * RE_engines_find(const char *idname)
Definition: engine.c:98
bool RE_engine_supports_alembic_procedural(const RenderEngineType *render_type, Scene *scene)
Definition: engine.c:121
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
struct CacheArchiveHandle * handle
struct AnimData * adt
ListBase object_paths
char handle_filepath[1024]
struct GSet * handle_readers
char use_render_procedural
char filepath[1024]
char velocity_name[64]
short id_code
Definition: BKE_idtype.h:114
Definition: DNA_ID.h:368
int tag
Definition: DNA_ID.h:387
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
float frs_sec_base
char engine[32]
struct RenderData r
CacheArchiveHandle * USD_create_handle(struct Main *, const char *filepath, ListBase *object_paths)
void USD_CacheReader_free(CacheReader *reader)
CacheReader * CacheReader_open_usd_object(CacheArchiveHandle *handle, CacheReader *reader, Object *object, const char *object_path)
void USD_free_handle(CacheArchiveHandle *handle)