Blender  V3.3
asset_indexer.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <fstream>
8 #include <iomanip>
9 #include <optional>
10 
11 #include "ED_asset_indexer.h"
12 
13 #include "DNA_asset_types.h"
14 #include "DNA_userdef_types.h"
15 
16 #include "BLI_fileops.h"
17 #include "BLI_hash.hh"
18 #include "BLI_linklist.h"
19 #include "BLI_path_util.h"
20 #include "BLI_serialize.hh"
21 #include "BLI_set.hh"
22 #include "BLI_string_ref.hh"
23 #include "BLI_uuid.h"
24 
25 #include "BKE_appdir.h"
26 #include "BKE_asset.h"
27 #include "BKE_asset_catalog.hh"
28 #include "BKE_idprop.hh"
29 #include "BKE_preferences.h"
30 
31 #include "CLG_log.h"
32 
33 static CLG_LogRef LOG = {"ed.asset"};
34 
36 
37 using namespace blender::io::serialize;
38 using namespace blender::bke;
39 using namespace blender::bke::idprop;
40 
71 constexpr StringRef ATTRIBUTE_VERSION("version");
72 constexpr StringRef ATTRIBUTE_ENTRIES("entries");
74 constexpr StringRef ATTRIBUTE_ENTRIES_CATALOG_ID("catalog_id");
75 constexpr StringRef ATTRIBUTE_ENTRIES_CATALOG_NAME("catalog_name");
76 constexpr StringRef ATTRIBUTE_ENTRIES_DESCRIPTION("description");
77 constexpr StringRef ATTRIBUTE_ENTRIES_AUTHOR("author");
79 constexpr StringRef ATTRIBUTE_ENTRIES_PROPERTIES("properties");
80 
82 class AbstractFile {
83  public:
84  virtual ~AbstractFile() = default;
85 
86  virtual const char *get_file_path() const = 0;
87 
88  bool exists() const
89  {
90  return BLI_exists(get_file_path());
91  }
92 
93  size_t get_file_size() const
94  {
95  return BLI_file_size(get_file_path());
96  }
97 };
98 
102 class BlendFile : public AbstractFile {
103  StringRefNull file_path_;
104 
105  public:
106  BlendFile(StringRefNull file_path) : file_path_(file_path)
107  {
108  }
109 
110  uint64_t hash() const
111  {
113  return hasher(file_path_);
114  }
115 
116  std::string get_filename() const
117  {
118  char filename[FILE_MAX];
119  BLI_split_file_part(get_file_path(), filename, sizeof(filename));
120  return std::string(filename);
121  }
122 
123  const char *get_file_path() const override
124  {
125  return file_path_.c_str();
126  }
127 };
128 
133  private:
138 
139  StringRefNull get_name_with_idcode() const
140  {
141  return lookup.lookup(ATTRIBUTE_ENTRIES_NAME)->as_string_value()->value();
142  }
143 
144  public:
145  AssetEntryReader(const DictionaryValue &entry) : lookup(entry.create_lookup())
146  {
147  }
148 
150  {
151  const StringRefNull name_with_idcode = get_name_with_idcode();
152  return GS(name_with_idcode.c_str());
153  }
154 
156  {
157  const StringRefNull name_with_idcode = get_name_with_idcode();
158  return name_with_idcode.substr(2);
159  }
160 
161  bool has_description() const
162  {
163  return lookup.contains(ATTRIBUTE_ENTRIES_DESCRIPTION);
164  }
165 
167  {
168  return lookup.lookup(ATTRIBUTE_ENTRIES_DESCRIPTION)->as_string_value()->value();
169  }
170 
171  bool has_author() const
172  {
173  return lookup.contains(ATTRIBUTE_ENTRIES_AUTHOR);
174  }
175 
177  {
178  return lookup.lookup(ATTRIBUTE_ENTRIES_AUTHOR)->as_string_value()->value();
179  }
180 
182  {
183  return lookup.lookup(ATTRIBUTE_ENTRIES_CATALOG_NAME)->as_string_value()->value();
184  }
185 
187  {
188  const std::string &catalog_id =
189  lookup.lookup(ATTRIBUTE_ENTRIES_CATALOG_ID)->as_string_value()->value();
190  CatalogID catalog_uuid(catalog_id);
191  return catalog_uuid;
192  }
193 
194  void add_tags_to_meta_data(AssetMetaData *asset_data) const
195  {
196  const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(ATTRIBUTE_ENTRIES_TAGS);
197  if (value_ptr == nullptr) {
198  return;
199  }
200 
201  const ArrayValue *array_value = (*value_ptr)->as_array_value();
202  const ArrayValue::Items &elements = array_value->elements();
203  for (const ArrayValue::Item &item : elements) {
204  const StringRefNull tag_name = item->as_string_value()->value();
205  BKE_asset_metadata_tag_add(asset_data, tag_name.c_str());
206  }
207  }
208 
210  {
211  BLI_assert(asset_data->properties == nullptr);
212  const DictionaryValue::LookupValue *value_ptr = lookup.lookup_ptr(
214  if (value_ptr == nullptr) {
215  return;
216  }
217 
218  const Value &value = *(value_ptr->get());
219  IDProperty *properties = convert_from_serialize_value(value);
220  asset_data->properties = properties;
221  }
222 };
223 
225  private:
226  DictionaryValue::Items &attributes;
227 
228  public:
229  AssetEntryWriter(DictionaryValue &entry) : attributes(entry.elements())
230  {
231  }
232 
238  void add_id_name(const short idcode, const StringRefNull name)
239  {
240  char idcode_prefix[2];
241  /* Similar to `BKE_libblock_alloc`. */
242  *((short *)idcode_prefix) = idcode;
243  std::string name_with_idcode = std::string(idcode_prefix, sizeof(idcode_prefix)) + name;
244 
245  attributes.append_as(std::pair(ATTRIBUTE_ENTRIES_NAME, new StringValue(name_with_idcode)));
246  }
247 
248  void add_catalog_id(const CatalogID &catalog_id)
249  {
250  char catalog_id_str[UUID_STRING_LEN];
251  BLI_uuid_format(catalog_id_str, catalog_id);
252  attributes.append_as(std::pair(ATTRIBUTE_ENTRIES_CATALOG_ID, new StringValue(catalog_id_str)));
253  }
254 
255  void add_catalog_name(const StringRefNull catalog_name)
256  {
257  attributes.append_as(std::pair(ATTRIBUTE_ENTRIES_CATALOG_NAME, new StringValue(catalog_name)));
258  }
259 
260  void add_description(const StringRefNull description)
261  {
262  attributes.append_as(std::pair(ATTRIBUTE_ENTRIES_DESCRIPTION, new StringValue(description)));
263  }
264 
265  void add_author(const StringRefNull author)
266  {
267  attributes.append_as(std::pair(ATTRIBUTE_ENTRIES_AUTHOR, new StringValue(author)));
268  }
269 
270  void add_tags(const ListBase /* AssetTag */ *asset_tags)
271  {
272  ArrayValue *tags = new ArrayValue();
273  attributes.append_as(std::pair(ATTRIBUTE_ENTRIES_TAGS, tags));
274  ArrayValue::Items &tag_items = tags->elements();
275 
276  LISTBASE_FOREACH (AssetTag *, tag, asset_tags) {
277  tag_items.append_as(new StringValue(tag->name));
278  }
279  }
280 
281  void add_properties(const IDProperty *properties)
282  {
283  std::unique_ptr<Value> value = convert_to_serialize_values(properties);
284  if (value == nullptr) {
285  return;
286  }
287  attributes.append_as(std::pair(ATTRIBUTE_ENTRIES_PROPERTIES, value.release()));
288  }
289 };
290 
292  const FileIndexerEntry *indexer_entry)
293 {
294  const BLODataBlockInfo &datablock_info = indexer_entry->datablock_info;
295 
296  result.add_id_name(indexer_entry->idcode, datablock_info.name);
297 
298  const AssetMetaData &asset_data = *datablock_info.asset_data;
299  result.add_catalog_id(asset_data.catalog_id);
300  result.add_catalog_name(asset_data.catalog_simple_name);
301 
302  if (asset_data.description != nullptr) {
303  result.add_description(asset_data.description);
304  }
305  if (asset_data.author != nullptr) {
306  result.add_author(asset_data.author);
307  }
308 
309  if (!BLI_listbase_is_empty(&asset_data.tags)) {
310  result.add_tags(&asset_data.tags);
311  }
312 
313  if (asset_data.properties != nullptr) {
314  result.add_properties(asset_data.properties);
315  }
316 
317  /* TODO: asset_data.IDProperties */
318 }
319 
321  const FileIndexerEntries &indexer_entries)
322 {
323  ArrayValue *entries = new ArrayValue();
324  ArrayValue::Items &items = entries->elements();
325 
326  for (LinkNode *ln = indexer_entries.entries; ln; ln = ln->next) {
327  const FileIndexerEntry *indexer_entry = static_cast<const FileIndexerEntry *>(ln->link);
328  /* We also get non asset types (brushes, workspaces), when browsing using the asset browser. */
329  if (indexer_entry->datablock_info.asset_data == nullptr) {
330  continue;
331  }
332  DictionaryValue *entry_value = new DictionaryValue();
333  AssetEntryWriter entry(*entry_value);
334  init_value_from_file_indexer_entry(entry, indexer_entry);
335  items.append_as(entry_value);
336  }
337 
338  /* When no entries to index, we should not store the entries attribute as this would make the
339  * size bigger than the #MIN_FILE_SIZE_WITH_ENTRIES. */
340  if (items.is_empty()) {
341  delete entries;
342  return;
343  }
344 
345  DictionaryValue::Items &attributes = result.elements();
346  attributes.append_as(std::pair(ATTRIBUTE_ENTRIES, entries));
347 }
348 
350  const AssetEntryReader &entry)
351 {
352  indexer_entry.idcode = entry.get_idcode();
353 
354  const std::string &name = entry.get_name();
355  BLI_strncpy(
356  indexer_entry.datablock_info.name, name.c_str(), sizeof(indexer_entry.datablock_info.name));
357 
359  indexer_entry.datablock_info.asset_data = asset_data;
360 
361  if (entry.has_description()) {
362  const std::string &description = entry.get_description();
363  char *description_c_str = static_cast<char *>(MEM_mallocN(description.length() + 1, __func__));
364  BLI_strncpy(description_c_str, description.c_str(), description.length() + 1);
365  asset_data->description = description_c_str;
366  }
367  if (entry.has_author()) {
368  const std::string &author = entry.get_author();
369  char *author_c_str = static_cast<char *>(MEM_mallocN(author.length() + 1, __func__));
370  BLI_strncpy(author_c_str, author.c_str(), author.length() + 1);
371  asset_data->author = author_c_str;
372  }
373 
374  const std::string &catalog_name = entry.get_catalog_name();
375  BLI_strncpy(asset_data->catalog_simple_name,
376  catalog_name.c_str(),
377  sizeof(asset_data->catalog_simple_name));
378 
379  asset_data->catalog_id = entry.get_catalog_id();
380 
381  entry.add_tags_to_meta_data(asset_data);
382  entry.add_properties_to_meta_data(asset_data);
383 }
384 
386  const DictionaryValue &value)
387 {
388  const DictionaryValue::Lookup attributes = value.create_lookup();
389  const DictionaryValue::LookupValue *entries_value = attributes.lookup_ptr(ATTRIBUTE_ENTRIES);
390  BLI_assert(entries_value != nullptr);
391 
392  if (entries_value == nullptr) {
393  return 0;
394  }
395 
396  int num_entries_read = 0;
397  const ArrayValue::Items elements = (*entries_value)->as_array_value()->elements();
398  for (ArrayValue::Item element : elements) {
399  const AssetEntryReader asset_entry(*element->as_dictionary_value());
400 
401  FileIndexerEntry *entry = static_cast<FileIndexerEntry *>(
402  MEM_callocN(sizeof(FileIndexerEntry), __func__));
403  init_indexer_entry_from_value(*entry, asset_entry);
404 
405  BLI_linklist_prepend(&indexer_entries.entries, entry);
406  num_entries_read += 1;
407  }
408 
409  return num_entries_read;
410 }
411 
426 
432  std::string indices_base_path;
433 
434  std::string library_path;
435 
436  public:
437  AssetLibraryIndex(const StringRef library_path) : library_path(library_path)
438  {
439  init_indices_base_path();
440  }
441 
442  uint64_t hash() const
443  {
445  return hasher(get_library_file_path());
446  }
447 
449  {
450  return library_path;
451  }
452 
459  {
460  char index_path[FILE_MAX];
461  BKE_appdir_folder_caches(index_path, sizeof(index_path));
462 
463  BLI_path_append(index_path, sizeof(index_path), "asset-library-indices");
464 
465  std::stringstream ss;
466  ss << std::setfill('0') << std::setw(16) << std::hex << hash() << "/";
467  BLI_path_append(index_path, sizeof(index_path), ss.str().c_str());
468 
469  indices_base_path = std::string(index_path);
470  }
471 
477  std::string index_file_path(const BlendFile &asset_file) const
478  {
479  std::stringstream ss;
480  ss << indices_base_path;
481  ss << std::setfill('0') << std::setw(16) << std::hex << asset_file.hash() << "_"
482  << asset_file.get_filename() << ".index.json";
483  return ss.str();
484  }
485 
490  {
491  const char *index_path = indices_base_path.c_str();
492  if (!BLI_is_dir(index_path)) {
493  return;
494  }
495  struct direntry *dir_entries = nullptr;
496  const int dir_entries_num = BLI_filelist_dir_contents(index_path, &dir_entries);
497  for (int i = 0; i < dir_entries_num; i++) {
498  struct direntry *entry = &dir_entries[i];
499  if (BLI_str_endswith(entry->relname, ".index.json")) {
500  unused_file_indices.add_as(std::string(entry->path));
501  }
502  }
503 
504  BLI_filelist_free(dir_entries, dir_entries_num);
505  }
506 
507  void mark_as_used(const std::string &filename)
508  {
509  unused_file_indices.remove(filename);
510  }
511 
513  {
514  int num_files_deleted = 0;
515  for (const std::string &unused_index : unused_file_indices) {
516  const char *file_path = unused_index.c_str();
517  CLOG_INFO(&LOG, 2, "Remove unused index file [%s].", file_path);
518  BLI_delete(file_path, false, false);
519  num_files_deleted++;
520  }
521 
522  return num_files_deleted;
523  }
524 };
525 
536 struct AssetIndex {
544  static const int CURRENT_VERSION = 1;
545 
549  const int UNKNOWN_VERSION = -1;
550 
558  std::unique_ptr<Value> contents;
559 
564  AssetIndex(const FileIndexerEntries &indexer_entries)
565  {
566  std::unique_ptr<DictionaryValue> root = std::make_unique<DictionaryValue>();
567  DictionaryValue::Items &root_attributes = root->elements();
568  root_attributes.append_as(std::pair(ATTRIBUTE_VERSION, new IntValue(CURRENT_VERSION)));
569  init_value_from_file_indexer_entries(*root, indexer_entries);
570 
571  contents = std::move(root);
572  }
573 
578  AssetIndex(std::unique_ptr<Value> &value) : contents(std::move(value))
579  {
580  }
581 
582  int get_version() const
583  {
584  const DictionaryValue *root = contents->as_dictionary_value();
585  if (root == nullptr) {
586  return UNKNOWN_VERSION;
587  }
588  const DictionaryValue::Lookup attributes = root->create_lookup();
589  const DictionaryValue::LookupValue *version_value = attributes.lookup_ptr(ATTRIBUTE_VERSION);
590  if (version_value == nullptr) {
591  return UNKNOWN_VERSION;
592  }
593  return (*version_value)->as_int_value()->value();
594  }
595 
596  bool is_latest_version() const
597  {
598  return get_version() == CURRENT_VERSION;
599  }
600 
606  int extract_into(FileIndexerEntries &indexer_entries) const
607  {
608  const DictionaryValue *root = contents->as_dictionary_value();
609  const int num_entries_read = init_indexer_entries_from_value(indexer_entries, *root);
610  return num_entries_read;
611  }
612 };
613 
614 class AssetIndexFile : public AbstractFile {
615  public:
621  const size_t MIN_FILE_SIZE_WITH_ENTRIES = 32;
622  std::string filename;
623 
624  AssetIndexFile(AssetLibraryIndex &library_index, BlendFile &asset_filename)
625  : library_index(library_index), filename(library_index.index_file_path(asset_filename))
626  {
627  }
628 
630  {
631  library_index.mark_as_used(filename);
632  }
633 
634  const char *get_file_path() const override
635  {
636  return filename.c_str();
637  }
638 
642  bool is_older_than(BlendFile &asset_file) const
643  {
644  return BLI_file_older(get_file_path(), asset_file.get_file_path());
645  }
646 
650  bool constains_entries() const
651  {
652  const size_t file_size = get_file_size();
653  return file_size >= MIN_FILE_SIZE_WITH_ENTRIES;
654  }
655 
656  std::unique_ptr<AssetIndex> read_contents() const
657  {
658  JsonFormatter formatter;
659  std::ifstream is;
660  is.open(filename);
661  std::unique_ptr<Value> read_data = formatter.deserialize(is);
662  is.close();
663 
664  return std::make_unique<AssetIndex>(read_data);
665  }
666 
668  {
669  /* `BLI_make_existing_file` only ensures parent path, otherwise than expected from the name of
670  * the function. */
671  return BLI_make_existing_file(get_file_path());
672  }
673 
674  void write_contents(AssetIndex &content)
675  {
676  JsonFormatter formatter;
677  if (!ensure_parent_path_exists()) {
678  CLOG_ERROR(&LOG, "Index not created: couldn't create folder [%s].", get_file_path());
679  return;
680  }
681 
682  std::ofstream os;
683  os.open(filename, std::ios::out | std::ios::trunc);
684  formatter.serialize(os, *content.contents);
685  os.close();
686  }
687 };
688 
689 static eFileIndexerResult read_index(const char *filename,
690  FileIndexerEntries *entries,
691  int *r_read_entries_len,
692  void *user_data)
693 {
694  AssetLibraryIndex &library_index = *static_cast<AssetLibraryIndex *>(user_data);
695  BlendFile asset_file(filename);
696  AssetIndexFile asset_index_file(library_index, asset_file);
697 
698  if (!asset_index_file.exists()) {
700  }
701 
702  /* Mark index as used, even when it will be recreated. When not done it would remove the index
703  * when the indexing has finished (see `AssetLibraryIndex.remove_unused_index_files`), thereby
704  * removing the newly created index.
705  */
706  asset_index_file.mark_as_used();
707 
708  if (asset_index_file.is_older_than(asset_file)) {
709  CLOG_INFO(
710  &LOG,
711  3,
712  "Asset index file [%s] needs to be refreshed as it is older than the asset file [%s].",
713  asset_index_file.filename.c_str(),
714  filename);
716  }
717 
718  if (!asset_index_file.constains_entries()) {
719  CLOG_INFO(&LOG,
720  3,
721  "Asset file index is to small to contain any entries. [%s]",
722  asset_index_file.filename.c_str());
723  *r_read_entries_len = 0;
725  }
726 
727  std::unique_ptr<AssetIndex> contents = asset_index_file.read_contents();
728  if (!contents->is_latest_version()) {
729  CLOG_INFO(&LOG,
730  3,
731  "Asset file index is ignored; expected version %d but file is version %d [%s].",
733  contents->get_version(),
734  asset_index_file.filename.c_str());
736  }
737 
738  const int read_entries_len = contents->extract_into(*entries);
739  CLOG_INFO(&LOG, 1, "Read %d entries from asset index for [%s].", read_entries_len, filename);
740  *r_read_entries_len = read_entries_len;
741 
743 }
744 
745 static void update_index(const char *filename, FileIndexerEntries *entries, void *user_data)
746 {
747  AssetLibraryIndex &library_index = *static_cast<AssetLibraryIndex *>(user_data);
748  BlendFile asset_file(filename);
749  AssetIndexFile asset_index_file(library_index, asset_file);
750  CLOG_INFO(&LOG,
751  1,
752  "Update asset index for [%s] store index in [%s].",
753  asset_file.get_file_path(),
754  asset_index_file.get_file_path());
755 
756  AssetIndex content(*entries);
757  asset_index_file.write_contents(content);
758 }
759 
760 static void *init_user_data(const char *root_directory, size_t root_directory_maxlen)
761 {
762  AssetLibraryIndex *library_index = MEM_new<AssetLibraryIndex>(
763  __func__, StringRef(root_directory, BLI_strnlen(root_directory, root_directory_maxlen)));
764  library_index->init_unused_index_files();
765  return library_index;
766 }
767 
768 static void free_user_data(void *user_data)
769 {
770  MEM_delete((AssetLibraryIndex *)user_data);
771 }
772 
773 static void filelist_finished(void *user_data)
774 {
775  AssetLibraryIndex &library_index = *static_cast<AssetLibraryIndex *>(user_data);
776  const int num_indices_removed = library_index.remove_unused_index_files();
777  if (num_indices_removed > 0) {
778  CLOG_INFO(&LOG, 1, "Removed %d unused indices.", num_indices_removed);
779  }
780 }
781 
783 {
784  FileIndexerType indexer = {nullptr};
785  indexer.read_index = read_index;
786  indexer.update_index = update_index;
787  indexer.init_user_data = init_user_data;
788  indexer.free_user_data = free_user_data;
790  return indexer;
791 }
792 
793 } // namespace blender::ed::asset::index
794 
795 extern "C" {
797 }
bool BKE_appdir_folder_caches(char *r_path, size_t path_len)
Definition: appdir.c:203
struct AssetMetaData * BKE_asset_metadata_create(void)
Definition: asset.cc:28
struct AssetTag * BKE_asset_metadata_tag_add(struct AssetMetaData *asset_data, const char *name)
Definition: asset.cc:60
#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_file_older(const char *file1, const char *file2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:569
int BLI_delete(const char *file, bool dir, bool recursive) ATTR_NONNULL()
Definition: fileops.c:934
unsigned int BLI_filelist_dir_contents(const char *dir, struct direntry **r_filelist)
Definition: BLI_filelist.c:218
size_t BLI_file_size(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:187
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:397
void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries)
Definition: BLI_filelist.c:420
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
bool BLI_make_existing_file(const char *name)
Definition: path_util.c:1197
#define FILE_MAX
void BLI_path_append(char *__restrict dst, size_t maxlen, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1514
void BLI_split_file_part(const char *string, char *file, size_t filelen)
Definition: path_util.c:1495
size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:899
bool BLI_str_endswith(const char *__restrict str, const char *__restrict end) ATTR_NONNULL()
Definition: string.c:887
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
void BLI_uuid_format(char *buffer, bUUID uuid) ATTR_NONNULL()
Definition: uuid.cc:86
#define CLOG_ERROR(clg_ref,...)
Definition: CLG_log.h:190
#define CLOG_INFO(clg_ref, level,...)
Definition: CLG_log.h:187
ID_Type
Definition: DNA_ID_enums.h:44
#define UUID_STRING_LEN
eFileIndexerResult
@ FILE_INDEXER_ENTRIES_LOADED
@ FILE_INDEXER_NEEDS_UPDATE
const FileIndexerType file_indexer_asset
static CLG_LogRef LOG
ATTR_WARN_UNUSED_RESULT const void * element
const Value * lookup_ptr(const Key &key) const
Definition: BLI_map.hh:463
bool add_as(ForwardKey &&key)
Definition: BLI_set.hh:261
bool remove(const Key &key)
Definition: BLI_set.hh:371
constexpr StringRef substr(int64_t start, int64_t size) const
constexpr const char * c_str() const
virtual const char * get_file_path() const =0
std::unique_ptr< AssetIndex > read_contents() const
bool is_older_than(BlendFile &asset_file) const
AssetIndexFile(AssetLibraryIndex &library_index, BlendFile &asset_filename)
const char * get_file_path() const override
void write_contents(AssetIndex &content)
Reference to a blend file that can be indexed.
const char * get_file_path() const override
BlendFile(StringRefNull file_path)
const Container & elements() const
std::shared_ptr< Value > LookupValue
std::unique_ptr< Value > deserialize(std::istream &is) override
Definition: serialize.cc:212
void serialize(std::ostream &os, const Value &value) override
Definition: serialize.cc:200
const ArrayValue * as_array_value() const
Definition: serialize.cc:41
const IntValue * as_int_value() const
Definition: serialize.cc:17
const DictionaryValue * as_dictionary_value() const
Definition: serialize.cc:49
void * user_data
#define GS(x)
Definition: iris.c:225
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
GAttributeReader lookup(const void *owner, const AttributeIDRef &attribute_id)
std::unique_ptr< io::serialize::ArrayValue > convert_to_serialize_values(const IDProperty *properties)
Convert the given properties to Value objects for serialization.
IDProperty * convert_from_serialize_value(const blender::io::serialize::Value &value)
Convert the given value to an IDProperty.
static void free_user_data(void *user_data)
constexpr StringRef ATTRIBUTE_ENTRIES_CATALOG_NAME("catalog_name")
constexpr StringRef ATTRIBUTE_ENTRIES_TAGS("tags")
constexpr StringRef ATTRIBUTE_ENTRIES_NAME("name")
constexpr StringRef ATTRIBUTE_ENTRIES_CATALOG_ID("catalog_id")
static int init_indexer_entries_from_value(FileIndexerEntries &indexer_entries, const DictionaryValue &value)
static void * init_user_data(const char *root_directory, size_t root_directory_maxlen)
constexpr StringRef ATTRIBUTE_ENTRIES_DESCRIPTION("description")
constexpr StringRef ATTRIBUTE_ENTRIES_PROPERTIES("properties")
static void filelist_finished(void *user_data)
static void init_value_from_file_indexer_entry(AssetEntryWriter &result, const FileIndexerEntry *indexer_entry)
static void init_indexer_entry_from_value(FileIndexerEntry &indexer_entry, const AssetEntryReader &entry)
static eFileIndexerResult read_index(const char *filename, FileIndexerEntries *entries, int *r_read_entries_len, void *user_data)
constexpr StringRef ATTRIBUTE_VERSION("version")
Indexer for asset libraries.
constexpr StringRef ATTRIBUTE_ENTRIES("entries")
static void init_value_from_file_indexer_entries(DictionaryValue &result, const FileIndexerEntries &indexer_entries)
constexpr StringRef ATTRIBUTE_ENTRIES_AUTHOR("author")
constexpr FileIndexerType asset_indexer()
static void update_index(const char *filename, FileIndexerEntries *entries, void *user_data)
PrimitiveValue< int64_t, eValueType::Int > IntValue
ContainerValue< Vector< std::shared_ptr< Value > >, eValueType::Array > ArrayValue
static const pxr::TfToken out("out", pxr::TfToken::Immortal)
#define hash
Definition: noise.c:153
unsigned __int64 uint64_t
Definition: stdint.h:90
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
char catalog_simple_name[64]
struct IDProperty * properties
struct bUUID catalog_id
User defined tag. Currently only used by assets, could be used more often at some point....
struct AssetMetaData * asset_data
Definition: BLO_readfile.h:184
struct LinkNode * entries
struct BLODataBlockInfo datablock_info
FileIndexerUpdateIndexFunc update_index
FileIndexerFinishedFunc filelist_finished
FileIndexerReadIndexFunc read_index
FileIndexerFreeUserDataFunc free_user_data
FileIndexerInitUserDataFunc init_user_data
struct LinkNode * next
Definition: BLI_linklist.h:23
Universally Unique Identifier according to RFC4122.
Single entry inside a #AssetIndexFile for reading.
void add_properties_to_meta_data(AssetMetaData *asset_data) const
void add_tags_to_meta_data(AssetMetaData *asset_data) const
AssetEntryReader(const DictionaryValue &entry)
void add_author(const StringRefNull author)
void add_tags(const ListBase *asset_tags)
void add_catalog_id(const CatalogID &catalog_id)
void add_catalog_name(const StringRefNull catalog_name)
void add_id_name(const short idcode, const StringRefNull name)
add id + name to the attributes.
void add_properties(const IDProperty *properties)
void add_description(const StringRefNull description)
AssetIndex(std::unique_ptr< Value > &value)
int extract_into(FileIndexerEntries &indexer_entries) const
AssetIndex(const FileIndexerEntries &indexer_entries)
static const int CURRENT_VERSION
Version to store in new index files.
std::unique_ptr< Value > contents
References the asset library directory.
void mark_as_used(const std::string &filename)
AssetLibraryIndex(const StringRef library_path)
std::string index_file_path(const BlendFile &asset_file) const
void init_indices_base_path()
Initializes #AssetLibraryIndex.indices_base_path.
std::string indices_base_path
Absolute path where the indices of library are stored.
const char * relname
const char * path
static const char hex[17]
Definition: thumbs.c:156