Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h10
-rw-r--r--source/blender/blenkernel/intern/cachefile.c47
-rw-r--r--source/blender/editors/include/UI_interface.h7
-rw-r--r--source/blender/editors/interface/interface_intern.h3
-rw-r--r--source/blender/editors/interface/interface_template_list.cc1
-rw-r--r--source/blender/editors/interface/interface_templates.c61
-rw-r--r--source/blender/editors/io/io_cache.c168
-rw-r--r--source/blender/editors/io/io_cache.h4
-rw-r--r--source/blender/editors/io/io_ops.c5
-rw-r--r--source/blender/io/alembic/ABC_alembic.h2
-rw-r--r--source/blender/io/alembic/intern/abc_reader_archive.cc49
-rw-r--r--source/blender/io/alembic/intern/abc_reader_archive.h10
-rw-r--r--source/blender/io/alembic/intern/alembic_capi.cc22
-rw-r--r--source/blender/makesdna/DNA_cachefile_types.h19
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_cachefile.c167
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c18
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c22
18 files changed, 607 insertions, 9 deletions
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index 0ab814c2d94..c6821d88d2a 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -28,6 +28,7 @@ extern "C" {
#endif
struct CacheFile;
+struct CacheFileLayer;
struct CacheReader;
struct Depsgraph;
struct Main;
@@ -69,6 +70,15 @@ bool BKE_cache_file_uses_render_procedural(const struct CacheFile *cache_file,
struct Scene *scene,
int dag_eval_mode);
+/* Add a layer to the cache_file. Return NULL if the filename is already that of an existing layer
+ * or if the number of layers exceeds the maximum allowed layer count. */
+struct CacheFileLayer *BKE_cachefile_add_layer(struct CacheFile *cache_file,
+ const char filename[1024]);
+
+struct CacheFileLayer *BKE_cachefile_get_active_layer(struct CacheFile *cache_file);
+
+void BKE_cachefile_remove_layer(struct CacheFile *cache_file, struct CacheFileLayer *layer);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index 8833f3eabe9..75df2e98fcd 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -54,6 +54,8 @@
#include "BLO_read_write.h"
+#include "MEM_guardedalloc.h"
+
#ifdef WITH_ALEMBIC
# include "ABC_alembic.h"
#endif
@@ -86,6 +88,7 @@ static void cache_file_copy_data(Main *UNUSED(bmain),
cache_file_dst->handle = NULL;
cache_file_dst->handle_readers = NULL;
BLI_duplicatelist(&cache_file_dst->object_paths, &cache_file_src->object_paths);
+ BLI_duplicatelist(&cache_file_dst->layers, &cache_file_src->layers);
}
static void cache_file_free_data(ID *id)
@@ -93,6 +96,7 @@ static void cache_file_free_data(ID *id)
CacheFile *cache_file = (CacheFile *)id;
cachefile_handle_free(cache_file);
BLI_freelistN(&cache_file->object_paths);
+ BLI_freelistN(&cache_file->layers);
}
static void cache_file_foreach_path(ID *id, BPathForeachPathData *bpath_data)
@@ -117,6 +121,11 @@ static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_a
if (cache_file->adt) {
BKE_animdata_blend_write(writer, cache_file->adt);
}
+
+ /* write layers */
+ LISTBASE_FOREACH (CacheFileLayer *, layer, &cache_file->layers) {
+ BLO_write_struct(writer, CacheFileLayer, layer);
+ }
}
static void cache_file_blend_read_data(BlendDataReader *reader, ID *id)
@@ -130,6 +139,9 @@ static void cache_file_blend_read_data(BlendDataReader *reader, ID *id)
/* relink animdata */
BLO_read_data_address(reader, &cache_file->adt);
BKE_animdata_blend_read_data(reader, cache_file->adt);
+
+ /* relink layers */
+ BLO_read_list(reader, &cache_file->layers);
}
IDTypeInfo IDType_ID_CF = {
@@ -364,7 +376,8 @@ void BKE_cachefile_eval(Main *bmain, Depsgraph *depsgraph, CacheFile *cache_file
#ifdef WITH_ALEMBIC
if (BLI_path_extension_check_glob(filepath, "*abc")) {
cache_file->type = CACHEFILE_TYPE_ALEMBIC;
- cache_file->handle = ABC_create_handle(bmain, filepath, &cache_file->object_paths);
+ cache_file->handle = ABC_create_handle(
+ bmain, filepath, cache_file->layers.first, &cache_file->object_paths);
BLI_strncpy(cache_file->handle_filepath, filepath, FILE_MAX);
}
#endif
@@ -435,3 +448,35 @@ bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file,
const bool is_final_render = (eEvaluationMode)dag_eval_mode == DAG_EVAL_RENDER;
return cache_file->use_render_procedural && !is_final_render;
}
+
+CacheFileLayer *BKE_cachefile_add_layer(CacheFile *cache_file, const char filename[1024])
+{
+ for (CacheFileLayer *layer = cache_file->layers.first; layer; layer = layer->next) {
+ if (STREQ(layer->filepath, filename)) {
+ return NULL;
+ }
+ }
+
+ const int num_layers = BLI_listbase_count(&cache_file->layers);
+
+ CacheFileLayer *layer = MEM_callocN(sizeof(CacheFileLayer), "CacheFileLayer");
+ BLI_strncpy(layer->filepath, filename, sizeof(layer->filepath));
+
+ BLI_addtail(&cache_file->layers, layer);
+
+ cache_file->active_layer = (char)(num_layers + 1);
+
+ return layer;
+}
+
+CacheFileLayer *BKE_cachefile_get_active_layer(CacheFile *cache_file)
+{
+ return BLI_findlink(&cache_file->layers, cache_file->active_layer - 1);
+}
+
+void BKE_cachefile_remove_layer(CacheFile *cache_file, CacheFileLayer *layer)
+{
+ cache_file->active_layer = 0;
+ BLI_remlink(&cache_file->layers, layer);
+ MEM_freeN(layer);
+}
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 9ce07cd2e07..3796fa51499 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -2426,6 +2426,13 @@ void uiTemplateCacheFileProcedural(uiLayout *layout,
*/
void uiTemplateCacheFileTimeSettings(uiLayout *layout, struct PointerRNA *fileptr);
+/**
+ * Draw the override layers related properties of the CacheFile.
+ */
+void uiTemplateCacheFileLayers(uiLayout *layout,
+ const struct bContext *C,
+ struct PointerRNA *fileptr);
+
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
enum uiTemplateListFlags {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 923f741e3ae..2d1138b46a7 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -1528,6 +1528,9 @@ uiTreeViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_bl
uiButTreeRow *ui_block_view_find_treerow_in_old_block(const uiBlock *new_block,
const uiTreeViewItemHandle *new_item_handle);
+/* interface_templates.c */
+struct uiListType *UI_UL_cache_file_layers(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/interface/interface_template_list.cc b/source/blender/editors/interface/interface_template_list.cc
index 13e539b5095..817599605a9 100644
--- a/source/blender/editors/interface/interface_template_list.cc
+++ b/source/blender/editors/interface/interface_template_list.cc
@@ -1322,6 +1322,7 @@ PointerRNA *UI_list_custom_drag_operator_set(uiList *ui_list,
void ED_uilisttypes_ui()
{
WM_uilisttype_add(UI_UL_asset_view());
+ WM_uilisttype_add(UI_UL_cache_file_layers());
}
/** \} */
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 00e9a75848a..8330f8c0db7 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -6474,6 +6474,67 @@ void uiTemplateCacheFileTimeSettings(uiLayout *layout, PointerRNA *fileptr)
uiLayoutSetActive(row, !RNA_boolean_get(fileptr, "is_sequence"));
}
+static void cache_file_layer_item(uiList *UNUSED(ui_list),
+ bContext *UNUSED(C),
+ uiLayout *layout,
+ PointerRNA *UNUSED(dataptr),
+ PointerRNA *itemptr,
+ int UNUSED(icon),
+ PointerRNA *UNUSED(active_dataptr),
+ const char *UNUSED(active_propname),
+ int UNUSED(index),
+ int UNUSED(flt_flag))
+{
+ uiLayout *row = uiLayoutRow(layout, true);
+ uiItemR(row, itemptr, "hide_layer", UI_ITEM_R_NO_BG, "", ICON_NONE);
+ uiItemR(row, itemptr, "filepath", UI_ITEM_R_NO_BG, "", ICON_NONE);
+}
+
+uiListType *UI_UL_cache_file_layers()
+{
+ uiListType *list_type = (uiListType *)MEM_callocN(sizeof(*list_type), __func__);
+
+ BLI_strncpy(list_type->idname, "UI_UL_cache_file_layers", sizeof(list_type->idname));
+ list_type->draw_item = cache_file_layer_item;
+
+ return list_type;
+}
+
+void uiTemplateCacheFileLayers(uiLayout *layout, const bContext *C, PointerRNA *fileptr)
+{
+ /* Ensure that the context has a CacheFile as this may not be set inside of modifiers panels. */
+ uiLayoutSetContextPointer(layout, "edit_cachefile", fileptr);
+
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiLayout *col = uiLayoutColumn(row, true);
+
+ uiTemplateList(col,
+ (bContext *)C,
+ "UI_UL_cache_file_layers",
+ "cache_file_layers",
+ fileptr,
+ "layers",
+ fileptr,
+ "active_index",
+ "",
+ 1,
+ 5,
+ UILST_LAYOUT_DEFAULT,
+ 1,
+ UI_TEMPLATE_LIST_FLAG_NONE);
+
+ col = uiLayoutColumn(row, true);
+ uiItemO(col, "", ICON_ADD, "cachefile.layer_add");
+ uiItemO(col, "", ICON_REMOVE, "cachefile.layer_remove");
+
+ CacheFile *file = fileptr->data;
+ if (BLI_listbase_count(&file->layers) > 1) {
+ uiItemS_ex(col, 1.0f);
+ uiItemO(col, "", ICON_TRIA_UP, "cachefile.layer_move");
+ uiItemO(col, "", ICON_TRIA_DOWN, "cachefile.layer_move");
+ }
+}
+
bool uiTemplateCacheFilePointer(PointerRNA *ptr, const char *propname, PointerRNA *r_file_ptr)
{
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
index bf20c1f6438..4f71a804986 100644
--- a/source/blender/editors/io/io_cache.c
+++ b/source/blender/editors/io/io_cache.c
@@ -26,6 +26,7 @@
#include "DNA_cachefile_types.h"
#include "DNA_space_types.h"
+#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
@@ -36,6 +37,7 @@
#include "BKE_report.h"
#include "RNA_access.h"
+#include "RNA_define.h"
#include "DEG_depsgraph.h"
@@ -46,6 +48,12 @@
#include "io_cache.h"
+static void reload_cachefile(bContext *C, CacheFile *cache_file)
+{
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ BKE_cachefile_reload(depsgraph, cache_file);
+}
+
static void cachefile_init(bContext *C, wmOperator *op)
{
PropertyPointerRNA *pprop;
@@ -146,8 +154,7 @@ static int cachefile_reload_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- BKE_cachefile_reload(depsgraph, cache_file);
+ reload_cachefile(C, cache_file);
return OPERATOR_FINISHED;
}
@@ -164,3 +171,160 @@ void CACHEFILE_OT_reload(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/* ***************************** Add Layer Operator **************************** */
+
+static int cachefile_layer_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ char filepath[FILE_MAX];
+ Main *bmain = CTX_data_main(C);
+
+ BLI_strncpy(filepath, BKE_main_blendfile_path(bmain), sizeof(filepath));
+ BLI_path_extension_replace(filepath, sizeof(filepath), ".abc");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
+
+ /* There is no more CacheFile set when returning from the file selector, so store it here. */
+ op->customdata = CTX_data_edit_cachefile(C);
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+
+ UNUSED_VARS(event);
+}
+
+static int cachefile_layer_add_exec(bContext *C, wmOperator *op)
+{
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ BKE_report(op->reports, RPT_ERROR, "No filename given");
+ return OPERATOR_CANCELLED;
+ }
+
+ CacheFile *cache_file = op->customdata;
+
+ if (!cache_file) {
+ return OPERATOR_CANCELLED;
+ }
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ CacheFileLayer *layer = BKE_cachefile_add_layer(cache_file, filename);
+
+ if (!layer) {
+ WM_report(RPT_ERROR, "Could not add a layer to the cache file");
+ return OPERATOR_CANCELLED;
+ }
+
+ reload_cachefile(C, cache_file);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void CACHEFILE_OT_layer_add(wmOperatorType *ot)
+{
+ ot->name = "Add layer";
+ ot->description = "Add an override layer to the archive";
+ ot->idname = "CACHEFILE_OT_layer_add";
+
+ /* api callbacks */
+ ot->invoke = cachefile_layer_open_invoke;
+ ot->exec = cachefile_layer_add_exec;
+
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_ALEMBIC | FILE_TYPE_FOLDER,
+ FILE_BLENDER,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_DEFAULT);
+}
+
+/* ***************************** Remove Layer Operator **************************** */
+
+static int cachefile_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ CacheFile *cache_file = CTX_data_edit_cachefile(C);
+
+ if (!cache_file) {
+ return OPERATOR_CANCELLED;
+ }
+
+ CacheFileLayer *layer = BKE_cachefile_get_active_layer(cache_file);
+ BKE_cachefile_remove_layer(cache_file, layer);
+
+ reload_cachefile(C, cache_file);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void CACHEFILE_OT_layer_remove(wmOperatorType *ot)
+{
+ ot->name = "Add layer";
+ ot->description = "Remove an override layer to the archive";
+ ot->idname = "CACHEFILE_OT_layer_remove";
+
+ /* api callbacks */
+ ot->exec = cachefile_layer_remove_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ***************************** Move Layer Operator **************************** */
+
+static int cachefile_layer_move_exec(bContext *C, wmOperator *op)
+{
+ CacheFile *cache_file = CTX_data_edit_cachefile(C);
+
+ if (!cache_file) {
+ return OPERATOR_CANCELLED;
+ }
+
+ CacheFileLayer *layer = BKE_cachefile_get_active_layer(cache_file);
+
+ if (!layer) {
+ return OPERATOR_CANCELLED;
+ }
+
+ const int dir = RNA_enum_get(op->ptr, "direction");
+
+ if (BLI_listbase_link_move(&cache_file->layers, layer, dir)) {
+ cache_file->active_layer = BLI_findindex(&cache_file->layers, layer) + 1;
+ /* Only reload if something moved, might be expensive. */
+ reload_cachefile(C, cache_file);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void CACHEFILE_OT_layer_move(wmOperatorType *ot)
+{
+ static const EnumPropertyItem layer_slot_move[] = {
+ {-1, "UP", 0, "Up", ""},
+ {1, "DOWN", 0, "Down", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ ot->name = "Move layer";
+ ot->description =
+ "Move layer in the list, layers further down the list will overwrite data from the layers "
+ "higher up";
+ ot->idname = "CACHEFILE_OT_layer_move";
+
+ /* api callbacks */
+ ot->exec = cachefile_layer_move_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_enum(ot->srna,
+ "direction",
+ layer_slot_move,
+ 0,
+ "Direction",
+ "Direction to move the active vertex group towards");
+}
diff --git a/source/blender/editors/io/io_cache.h b/source/blender/editors/io/io_cache.h
index be6e31842af..297e065434f 100644
--- a/source/blender/editors/io/io_cache.h
+++ b/source/blender/editors/io/io_cache.h
@@ -27,3 +27,7 @@ struct wmOperatorType;
void CACHEFILE_OT_open(struct wmOperatorType *ot);
void CACHEFILE_OT_reload(struct wmOperatorType *ot);
+
+void CACHEFILE_OT_layer_add(struct wmOperatorType *ot);
+void CACHEFILE_OT_layer_remove(struct wmOperatorType *ot);
+void CACHEFILE_OT_layer_move(struct wmOperatorType *ot);
diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c
index 5dff0b69c2a..d9bbd7d8692 100644
--- a/source/blender/editors/io/io_ops.c
+++ b/source/blender/editors/io/io_ops.c
@@ -69,5 +69,10 @@ void ED_operatortypes_io(void)
WM_operatortype_append(CACHEFILE_OT_open);
WM_operatortype_append(CACHEFILE_OT_reload);
+
+ WM_operatortype_append(CACHEFILE_OT_layer_add);
+ WM_operatortype_append(CACHEFILE_OT_layer_remove);
+ WM_operatortype_append(CACHEFILE_OT_layer_move);
+
WM_operatortype_append(WM_OT_obj_export);
}
diff --git a/source/blender/io/alembic/ABC_alembic.h b/source/blender/io/alembic/ABC_alembic.h
index c1f3add377b..18b0c91b67c 100644
--- a/source/blender/io/alembic/ABC_alembic.h
+++ b/source/blender/io/alembic/ABC_alembic.h
@@ -26,6 +26,7 @@ extern "C" {
#endif
struct CacheArchiveHandle;
+struct CacheFileLayer;
struct CacheReader;
struct ListBase;
struct Main;
@@ -102,6 +103,7 @@ bool ABC_import(struct bContext *C,
struct CacheArchiveHandle *ABC_create_handle(struct Main *bmain,
const char *filename,
+ const struct CacheFileLayer *layers,
struct ListBase *object_paths);
void ABC_free_handle(struct CacheArchiveHandle *handle);
diff --git a/source/blender/io/alembic/intern/abc_reader_archive.cc b/source/blender/io/alembic/intern/abc_reader_archive.cc
index 4951dc0e035..94def041285 100644
--- a/source/blender/io/alembic/intern/abc_reader_archive.cc
+++ b/source/blender/io/alembic/intern/abc_reader_archive.cc
@@ -23,6 +23,8 @@
#include "abc_reader_archive.h"
+#include "Alembic/AbcCoreLayer/Read.h"
+
#include "BKE_main.h"
#include "BLI_path_util.h"
@@ -76,6 +78,46 @@ static IArchive open_archive(const std::string &filename,
return IArchive();
}
+ArchiveReader *ArchiveReader::get(struct Main *bmain, const std::vector<const char *> &filenames)
+{
+ std::vector<ArchiveReader *> readers;
+
+ for (const char *filename : filenames) {
+ auto reader = new ArchiveReader(bmain, filename);
+
+ if (!reader->valid()) {
+ delete reader;
+ continue;
+ }
+
+ readers.push_back(reader);
+ }
+
+ if (readers.size() == 0) {
+ return nullptr;
+ }
+
+ if (readers.size() == 1) {
+ return readers[0];
+ }
+
+ return new ArchiveReader(readers);
+}
+
+ArchiveReader::ArchiveReader(const std::vector<ArchiveReader *> &readers) : m_readers(readers)
+{
+ Alembic::AbcCoreLayer::ArchiveReaderPtrs archives;
+
+ for (auto &reader : readers) {
+ archives.push_back(reader->m_archive.getPtr());
+ }
+
+ Alembic::AbcCoreLayer::ReadArchive layer;
+ Alembic::AbcCoreAbstract::ArchiveReaderPtr arPtr = layer(archives);
+
+ m_archive = IArchive(arPtr, kWrapExisting, ErrorHandler::kThrowPolicy);
+}
+
ArchiveReader::ArchiveReader(struct Main *bmain, const char *filename)
{
char abs_filename[FILE_MAX];
@@ -96,6 +138,13 @@ ArchiveReader::ArchiveReader(struct Main *bmain, const char *filename)
m_archive = open_archive(abs_filename, m_streams);
}
+ArchiveReader::~ArchiveReader()
+{
+ for (ArchiveReader *reader : m_readers) {
+ delete reader;
+ }
+}
+
bool ArchiveReader::valid() const
{
return m_archive.valid();
diff --git a/source/blender/io/alembic/intern/abc_reader_archive.h b/source/blender/io/alembic/intern/abc_reader_archive.h
index 67000194aa1..937e3a190cf 100644
--- a/source/blender/io/alembic/intern/abc_reader_archive.h
+++ b/source/blender/io/alembic/intern/abc_reader_archive.h
@@ -41,9 +41,17 @@ class ArchiveReader {
std::ifstream m_infile;
std::vector<std::istream *> m_streams;
- public:
+ std::vector<ArchiveReader *> m_readers;
+
+ ArchiveReader(const std::vector<ArchiveReader *> &readers);
+
ArchiveReader(struct Main *bmain, const char *filename);
+ public:
+ static ArchiveReader *get(struct Main *bmain, const std::vector<const char *> &filenames);
+
+ ~ArchiveReader();
+
bool valid() const;
Alembic::Abc::IObject getTop();
diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc
index d7b176eea50..58fc4dd599d 100644
--- a/source/blender/io/alembic/intern/alembic_capi.cc
+++ b/source/blender/io/alembic/intern/alembic_capi.cc
@@ -159,11 +159,25 @@ static bool gather_objects_paths(const IObject &object, ListBase *object_paths)
CacheArchiveHandle *ABC_create_handle(struct Main *bmain,
const char *filename,
+ const CacheFileLayer *layers,
ListBase *object_paths)
{
- ArchiveReader *archive = new ArchiveReader(bmain, filename);
+ std::vector<const char *> filenames;
+ filenames.push_back(filename);
- if (!archive->valid()) {
+ while (layers) {
+ if ((layers->flag & CACHEFILE_LAYER_HIDDEN) == 0) {
+ filenames.push_back(layers->filepath);
+ }
+ layers = layers->next;
+ }
+
+ /* We need to reverse the order as overriding archives should come first. */
+ std::reverse(filenames.begin(), filenames.end());
+
+ ArchiveReader *archive = ArchiveReader::get(bmain, filenames);
+
+ if (!archive || !archive->valid()) {
delete archive;
return nullptr;
}
@@ -447,9 +461,9 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
WM_set_locked_interface(data->wm, true);
- ArchiveReader *archive = new ArchiveReader(data->bmain, data->filename);
+ ArchiveReader *archive = ArchiveReader::get(data->bmain, {data->filename});
- if (!archive->valid()) {
+ if (!archive || !archive->valid()) {
data->error_code = ABC_ARCHIVE_FAIL;
delete archive;
return;
diff --git a/source/blender/makesdna/DNA_cachefile_types.h b/source/blender/makesdna/DNA_cachefile_types.h
index 0f4c53a6e7e..65e1dd6c096 100644
--- a/source/blender/makesdna/DNA_cachefile_types.h
+++ b/source/blender/makesdna/DNA_cachefile_types.h
@@ -59,6 +59,18 @@ typedef struct CacheObjectPath {
char path[4096];
} CacheObjectPath;
+/* CacheFileLayer::flag */
+enum { CACHEFILE_LAYER_HIDDEN = (1 << 0) };
+
+typedef struct CacheFileLayer {
+ struct CacheFileLayer *next, *prev;
+
+ /** 1024 = FILE_MAX. */
+ char filepath[1024];
+ int flag;
+ int _pad;
+} CacheFileLayer;
+
/* CacheFile::velocity_unit
* Determines what temporal unit is used to interpret velocity vectors for motion blur effects. */
enum {
@@ -73,6 +85,8 @@ typedef struct CacheFile {
/** Paths of the objects inside of the archive referenced by this CacheFile. */
ListBase object_paths;
+ ListBase layers;
+
/** 1024 = FILE_MAX. */
char filepath[1024];
@@ -109,7 +123,10 @@ typedef struct CacheFile {
/** Size in megabytes for the prefetch cache used by the Cycles Procedural. */
int prefetch_cache_size;
- char _pad2[7];
+ /** Index of the currently selected layer in the UI, starts at 1. */
+ int active_layer;
+
+ char _pad2[3];
char velocity_unit;
/* Name of the velocity property in the archive. */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index b32d98e3cb1..1ade964854d 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -105,6 +105,7 @@ extern StructRNA RNA_BuildModifier;
extern StructRNA RNA_ByteColorAttribute;
extern StructRNA RNA_ByteColorAttributeValue;
extern StructRNA RNA_CacheFile;
+extern StructRNA RNA_CacheFileLayer;
extern StructRNA RNA_Camera;
extern StructRNA RNA_CameraDOFSettings;
extern StructRNA RNA_CastModifier;
diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c
index 74d924b8937..2f8fc004d85 100644
--- a/source/blender/makesrna/intern/rna_cachefile.c
+++ b/source/blender/makesrna/intern/rna_cachefile.c
@@ -32,6 +32,7 @@
#ifdef RNA_RUNTIME
+# include "BLI_math.h"
# include "BLI_string.h"
# include "BKE_cachefile.h"
@@ -54,6 +55,14 @@ static void rna_CacheFile_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
+static void rna_CacheFileLayer_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ CacheFile *cache_file = (CacheFile *)ptr->owner_id;
+
+ DEG_id_tag_update(&cache_file->id, ID_RECALC_COPY_ON_WRITE);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+}
+
static void rna_CacheFile_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_CacheFile_update(bmain, scene, ptr);
@@ -66,6 +75,91 @@ static void rna_CacheFile_object_paths_begin(CollectionPropertyIterator *iter, P
rna_iterator_listbase_begin(iter, &cache_file->object_paths, NULL);
}
+static PointerRNA rna_CacheFile_active_layer_get(PointerRNA *ptr)
+{
+ CacheFile *cache_file = (CacheFile *)ptr->owner_id;
+ return rna_pointer_inherit_refine(
+ ptr, &RNA_CacheFileLayer, BKE_cachefile_get_active_layer(cache_file));
+}
+
+static void rna_CacheFile_active_layer_set(PointerRNA *ptr,
+ PointerRNA value,
+ struct ReportList *reports)
+{
+ CacheFile *cache_file = (CacheFile *)ptr->owner_id;
+ int index = BLI_findindex(&cache_file->layers, value.data);
+ if (index == -1) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "Layer '%s' not found in object '%s'",
+ ((CacheFileLayer *)value.data)->filepath,
+ cache_file->id.name + 2);
+ return;
+ }
+
+ cache_file->active_layer = index + 1;
+}
+
+static int rna_CacheFile_active_layer_index_get(PointerRNA *ptr)
+{
+ CacheFile *cache_file = (CacheFile *)ptr->owner_id;
+ return cache_file->active_layer - 1;
+}
+
+static void rna_CacheFile_active_layer_index_set(PointerRNA *ptr, int value)
+{
+ CacheFile *cache_file = (CacheFile *)ptr->owner_id;
+ cache_file->active_layer = value + 1;
+}
+
+static void rna_CacheFile_active_layer_index_range(
+ PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
+{
+ CacheFile *cache_file = (CacheFile *)ptr->owner_id;
+
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&cache_file->layers) - 1);
+}
+
+static void rna_CacheFileLayer_hidden_flag_set(PointerRNA *ptr, const bool value)
+{
+ CacheFileLayer *layer = (CacheFileLayer *)ptr->data;
+
+ if (value) {
+ layer->flag |= CACHEFILE_LAYER_HIDDEN;
+ }
+ else {
+ layer->flag &= ~CACHEFILE_LAYER_HIDDEN;
+ }
+}
+
+static CacheFileLayer *rna_CacheFile_layer_new(CacheFile *cache_file,
+ bContext *C,
+ ReportList *reports,
+ const char *filepath)
+{
+ CacheFileLayer *layer = BKE_cachefile_add_layer(cache_file, filepath);
+ if (layer == NULL) {
+ BKE_reportf(
+ reports, RPT_ERROR, "Cannot add a layer to CacheFile '%s'", cache_file->id.name + 2);
+ return NULL;
+ }
+
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ BKE_cachefile_reload(depsgraph, cache_file);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+ return layer;
+}
+
+static void rna_CacheFile_layer_remove(CacheFile *cache_file, bContext *C, PointerRNA *layer_ptr)
+{
+ CacheFileLayer *layer = layer_ptr->data;
+ BKE_cachefile_remove_layer(cache_file, layer);
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ BKE_cachefile_reload(depsgraph, cache_file);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
+}
+
#else
/* cachefile.object_paths */
@@ -94,6 +188,61 @@ static void rna_def_cachefile_object_paths(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_struct_ui_text(srna, "Object Paths", "Collection of object paths");
}
+static void rna_def_cachefile_layer(BlenderRNA *brna)
+{
+ StructRNA *srna = RNA_def_struct(brna, "CacheFileLayer", NULL);
+ RNA_def_struct_sdna(srna, "CacheFileLayer");
+ RNA_def_struct_ui_text(
+ srna,
+ "Cache Layer",
+ "Layer of the cache, used to load or override data from the first the first layer");
+
+ PropertyRNA *prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
+ RNA_def_property_ui_text(prop, "File Path", "Path to the archive");
+ RNA_def_property_update(prop, 0, "rna_CacheFileLayer_update");
+
+ prop = RNA_def_property(srna, "hide_layer", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", CACHEFILE_LAYER_HIDDEN);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_CacheFileLayer_hidden_flag_set");
+ RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
+ RNA_def_property_ui_text(prop, "Hide Layer", "Do not load data from this layer");
+ RNA_def_property_update(prop, 0, "rna_CacheFileLayer_update");
+}
+
+static void rna_def_cachefile_layers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ RNA_def_property_srna(cprop, "CacheFileLayers");
+ StructRNA *srna = RNA_def_struct(brna, "CacheFileLayers", NULL);
+ RNA_def_struct_sdna(srna, "CacheFile");
+ RNA_def_struct_ui_text(srna, "Cache Layers", "Collection of cache layers");
+
+ PropertyRNA *prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "CacheFileLayer");
+ RNA_def_property_pointer_funcs(
+ prop, "rna_CacheFile_active_layer_get", "rna_CacheFile_active_layer_set", NULL, NULL);
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Active Layer", "Active layer of the CacheFile");
+
+ /* Add a layer. */
+ FunctionRNA *func = RNA_def_function(srna, "new", "rna_CacheFile_layer_new");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Add a new layer");
+ PropertyRNA *parm = RNA_def_string(
+ func, "filepath", "File Path", 0, "", "File path to the archive used as a layer");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* Return type. */
+ parm = RNA_def_pointer(func, "layer", "CacheFileLayer", "", "Newly created layer");
+ RNA_def_function_return(func, parm);
+
+ /* Remove a layer. */
+ func = RNA_def_function(srna, "remove", "rna_CacheFile_layer_remove");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ RNA_def_function_ui_description(func, "Remove an existing layer from the cache file");
+ parm = RNA_def_pointer(func, "layer", "CacheFileLayer", "", "Layer to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
+}
+
static void rna_def_cachefile(BlenderRNA *brna)
{
StructRNA *srna = RNA_def_struct(brna, "CacheFile", "ID");
@@ -234,6 +383,23 @@ static void rna_def_cachefile(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_CacheFile_update");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ /* ----------------- Alembic Layers ----------------- */
+
+ prop = RNA_def_property(srna, "layers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "layers", NULL);
+ RNA_def_property_struct_type(prop, "CacheFileLayer");
+ RNA_def_property_override_clear_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
+ RNA_def_property_ui_text(prop, "Cache Layers", "Layers of the cache");
+ rna_def_cachefile_layers(brna, prop);
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_int_sdna(prop, NULL, "active_layer");
+ RNA_def_property_int_funcs(prop,
+ "rna_CacheFile_active_layer_index_get",
+ "rna_CacheFile_active_layer_index_set",
+ "rna_CacheFile_active_layer_index_range");
+
RNA_define_lib_overridable(false);
rna_def_cachefile_object_paths(brna, prop);
@@ -245,6 +411,7 @@ void RNA_def_cachefile(BlenderRNA *brna)
{
rna_def_cachefile(brna);
rna_def_alembic_object_path(brna);
+ rna_def_cachefile_layer(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index a406e867d6c..5bf778d1962 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -619,6 +619,19 @@ static void rna_uiTemplateCacheFileTimeSettings(uiLayout *layout,
uiTemplateCacheFileTimeSettings(layout, &fileptr);
}
+static void rna_uiTemplateCacheFileLayers(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname)
+{
+ PointerRNA fileptr;
+ if (!uiTemplateCacheFilePointer(ptr, propname, &fileptr)) {
+ return;
+ }
+
+ uiTemplateCacheFileLayers(layout, C, &fileptr);
+}
+
static void rna_uiTemplatePathBuilder(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
@@ -1847,6 +1860,11 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_function_ui_description(func, "Show cache files time settings");
api_ui_item_rna_common(func);
+ func = RNA_def_function(srna, "template_cache_file_layers", "rna_uiTemplateCacheFileLayers");
+ RNA_def_function_ui_description(func, "Show cache files override layers properties");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+
func = RNA_def_function(srna, "template_recent_files", "uiTemplateRecentFiles");
RNA_def_function_ui_description(func, "Show list of recently saved .blend files");
RNA_def_int(func, "rows", 5, 1, INT_MAX, "", "Maximum number of items to show", 1, INT_MAX);
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 00f39e58b4d..e1459ccba6d 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -392,6 +392,22 @@ static void render_procedural_panel_draw(const bContext *C, Panel *panel)
uiTemplateCacheFileProcedural(layout, C, &fileptr);
}
+static void override_layers_panel_draw(const bContext *C, Panel *panel)
+{
+ uiLayout *layout = panel->layout;
+
+ PointerRNA ob_ptr;
+ PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
+
+ PointerRNA fileptr;
+ if (!uiTemplateCacheFilePointer(ptr, "cache_file", &fileptr)) {
+ return;
+ }
+
+ uiLayoutSetPropSep(layout, true);
+ uiTemplateCacheFileLayers(layout, C, &fileptr);
+}
+
static void panelRegister(ARegionType *region_type)
{
PanelType *panel_type = modifier_panel_register(
@@ -405,6 +421,12 @@ static void panelRegister(ARegionType *region_type)
panel_type);
modifier_subpanel_register(
region_type, "velocity", "Velocity", NULL, velocity_panel_draw, panel_type);
+ modifier_subpanel_register(region_type,
+ "override_layers",
+ "Override Layers",
+ NULL,
+ override_layers_panel_draw,
+ panel_type);
}
static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)