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:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2016-08-06 07:20:37 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2016-08-06 11:58:13 +0300
commit61050f75b13ef706d3a80b86137436d3fb0bfa93 (patch)
treea8044c720b35ae0b1dd8d265178e7a412a50e8bf /source/blender/editors
parent4158737cb2d79898b9f1147eaa26eb486f4980a1 (diff)
Basic Alembic support
All in all, this patch adds an Alembic importer, an Alembic exporter, and a new CacheFile data block which, for now, wraps around an Alembic archive. This data block is made available through a new modifier ("Mesh Sequence Cache") as well as a new constraint ("Transform Cache") to somewhat properly support respectively geometric and transformation data streaming from alembic caches. A more in-depth documentation is to be found on the wiki, as well as a guide to compile alembic: https://wiki.blender.org/index.php/ User:Kevindietrich/AlembicBasicIo. Many thanks to everyone involved in this little project, and huge shout out to "cgstrive" for the thorough testings with Maya, 3ds Max, Houdini and Realflow as well as @fjuhec, @jensverwiebe and @jasperge for the custom builds and compile fixes. Reviewers: sergey, campbellbarton, mont29 Reviewed By: sergey, campbellbarton, mont29 Differential Revision: https://developer.blender.org/D2060
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c84
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c5
-rw-r--r--source/blender/editors/animation/anim_filter.c72
-rw-r--r--source/blender/editors/animation/keyframes_draw.c32
-rw-r--r--source/blender/editors/include/ED_anim_api.h2
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h3
-rw-r--r--source/blender/editors/include/UI_interface.h1
-rw-r--r--source/blender/editors/interface/interface_icons.c2
-rw-r--r--source/blender/editors/interface/interface_templates.c72
-rw-r--r--source/blender/editors/io/CMakeLists.txt14
-rw-r--r--source/blender/editors/io/io_alembic.c458
-rw-r--r--source/blender/editors/io/io_alembic.h37
-rw-r--r--source/blender/editors/io/io_cache.c162
-rw-r--r--source/blender/editors/io/io_cache.h37
-rw-r--r--source/blender/editors/io/io_ops.c16
-rw-r--r--source/blender/editors/object/object_constraint.c7
-rw-r--r--source/blender/editors/space_file/filelist.c7
-rw-r--r--source/blender/editors/space_file/filesel.c4
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c1
-rw-r--r--source/blender/editors/space_nla/nla_channels.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h2
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c11
-rw-r--r--source/blender/editors/space_time/space_time.c65
24 files changed, 1092 insertions, 5 deletions
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 752544f65e1..3085e383909 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -40,6 +40,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
+#include "DNA_cachefile_types.h"
#include "DNA_camera_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
@@ -1578,6 +1579,88 @@ static bAnimChannelType ACF_DSTEX =
/* Camera Expander ------------------------------------------- */
// TODO: just get this from RNA?
+static int acf_dscachefile_icon(bAnimListElem *ale)
+{
+ UNUSED_VARS(ale);
+ return ICON_FILE;
+}
+
+/* get the appropriate flag(s) for the setting when it is valid */
+static int acf_dscachefile_setting_flag(bAnimContext *ac, eAnimChannel_Settings setting, bool *neg)
+{
+ /* clear extra return data first */
+ *neg = false;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return CACHEFILE_DS_EXPAND;
+
+ case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
+ return ADT_NLA_EVAL_OFF;
+
+ case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */
+ *neg = true;
+ return ADT_CURVES_NOT_VISIBLE;
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ return ADT_UI_SELECTED;
+
+ default: /* unsupported */
+ return 0;
+ }
+
+ UNUSED_VARS(ac);
+}
+
+/* get pointer to the setting */
+static void *acf_dscachefile_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
+{
+ CacheFile *cache_file = (CacheFile *)ale->data;
+
+ /* clear extra return data first */
+ *type = 0;
+
+ switch (setting) {
+ case ACHANNEL_SETTING_EXPAND: /* expanded */
+ return GET_ACF_FLAG_PTR(cache_file->flag, type);
+
+ case ACHANNEL_SETTING_SELECT: /* selected */
+ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
+ case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
+ if (cache_file->adt) {
+ return GET_ACF_FLAG_PTR(cache_file->adt->flag, type);
+ }
+
+ return NULL;
+
+ default: /* unsupported */
+ return NULL;
+ }
+}
+
+/* CacheFile expander type define. */
+static bAnimChannelType ACF_DSCACHEFILE =
+{
+ "Cache File Expander", /* type name */
+ ACHANNEL_ROLE_EXPANDER, /* role */
+
+ acf_generic_dataexpand_color, /* backdrop color */
+ acf_generic_dataexpand_backdrop, /* backdrop */
+ acf_generic_indention_1, /* indent level */
+ acf_generic_basic_offset, /* offset */
+
+ acf_generic_idblock_name, /* name */
+ acf_generic_idfill_name_prop, /* name prop */
+ acf_dscachefile_icon, /* icon */
+
+ acf_generic_dataexpand_setting_valid, /* has setting */
+ acf_dscachefile_setting_flag, /* flag for setting */
+ acf_dscachefile_setting_ptr /* pointer for setting */
+};
+
+/* Camera Expander ------------------------------------------- */
+
+// TODO: just get this from RNA?
static int acf_dscam_icon(bAnimListElem *UNUSED(ale))
{
return ICON_CAMERA_DATA;
@@ -3388,6 +3471,7 @@ static void ANIM_init_channel_typeinfo_data(void)
animchannelTypeInfo[type++] = &ACF_DSMAT; /* Material Channel */
animchannelTypeInfo[type++] = &ACF_DSLAM; /* Lamp Channel */
animchannelTypeInfo[type++] = &ACF_DSCAM; /* Camera Channel */
+ animchannelTypeInfo[type++] = &ACF_DSCACHEFILE; /* CacheFile Channel */
animchannelTypeInfo[type++] = &ACF_DSCUR; /* Curve Channel */
animchannelTypeInfo[type++] = &ACF_DSSKEY; /* ShapeKey Channel */
animchannelTypeInfo[type++] = &ACF_DSWOR; /* World Channel */
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 1a59acb2aeb..cb65a9aecad 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -120,6 +120,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
@@ -175,6 +176,7 @@ void ANIM_set_active_channel(bAnimContext *ac, void *data, eAnimCont_Types datat
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
@@ -275,6 +277,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
@@ -370,6 +373,7 @@ void ANIM_deselect_anim_channels(bAnimContext *ac, void *data, eAnimCont_Types d
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
@@ -2716,6 +2720,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 88d96c531e0..5cd305f69f5 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -53,6 +53,7 @@
#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
+#include "DNA_cachefile_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_linestyle_types.h"
@@ -199,6 +200,16 @@ static bool actedit_get_context(bAnimContext *ac, SpaceAction *saction)
ac->mode = saction->mode;
return true;
+
+ case SACTCONT_CACHEFILE: /* Cache File */ /* XXX review how this mode is handled... */
+ /* update scene-pointer (no need to check for pinning yet, as not implemented) */
+ saction->ads.source = (ID *)ac->scene;
+
+ ac->datatype = ANIMCONT_CHANNEL;
+ ac->data = &saction->ads;
+
+ ac->mode = saction->mode;
+ return true;
case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */
{
@@ -660,6 +671,19 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
ale->adt = BKE_animdata_from_id(data);
break;
}
+ case ANIMTYPE_DSCACHEFILE:
+ {
+ CacheFile *cache_file = (CacheFile *)data;
+ AnimData *adt = cache_file->adt;
+
+ ale->flag = FILTER_CACHEFILE_OBJD(cache_file);
+
+ ale->key_data = (adt) ? adt->action : NULL;
+ ale->datatype = ALE_ACT;
+
+ ale->adt = BKE_animdata_from_id(data);
+ break;
+ }
case ANIMTYPE_DSCUR:
{
Curve *cu = (Curve *)data;
@@ -1751,6 +1775,42 @@ static size_t animdata_filter_ds_gpencil(bAnimContext *ac, ListBase *anim_data,
return items;
}
+/* Helper for Cache File data integrated with main DopeSheet */
+static size_t animdata_filter_ds_cachefile(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, CacheFile *cache_file, int filter_mode)
+{
+ ListBase tmp_data = {NULL, NULL};
+ size_t tmp_items = 0;
+ size_t items = 0;
+
+ /* add relevant animation channels for Cache File */
+ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_CACHEFILE_OBJD(cache_file))
+ {
+ /* add animation channels */
+ tmp_items += animfilter_block_data(ac, &tmp_data, ads, &cache_file->id, filter_mode);
+ }
+ END_ANIMFILTER_SUBCHANNELS;
+
+ /* did we find anything? */
+ if (tmp_items) {
+ /* include data-expand widget first */
+ if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
+ /* check if filtering by active status */
+ // XXX: active check here needs checking
+ if (ANIMCHANNEL_ACTIVEOK(cache_file)) {
+ ANIMCHANNEL_NEW_CHANNEL(cache_file, ANIMTYPE_DSCACHEFILE, cache_file);
+ }
+ }
+
+ /* now add the list of collected channels */
+ BLI_movelisttolist(anim_data, &tmp_data);
+ BLI_assert(BLI_listbase_is_empty(&tmp_data));
+ items += tmp_items;
+ }
+
+ /* return the number of items added to the list */
+ return items;
+}
+
/* Helper for Mask Editing - mask layers */
static size_t animdata_filter_mask_data(ListBase *anim_data, Mask *mask, const int filter_mode)
{
@@ -2839,6 +2899,12 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
filter_mode |= ANIMFILTER_SELEDIT;
}
+ /* Cache files level animations (frame duration and such). */
+ CacheFile *cache_file = G.main->cachefiles.first;
+ for (; cache_file; cache_file = cache_file->id.next) {
+ items += animdata_filter_ds_cachefile(ac, anim_data, ads, cache_file, filter_mode);
+ }
+
/* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode);
@@ -2950,7 +3016,11 @@ static size_t animdata_filter_animchan(bAnimContext *ac, ListBase *anim_data, bD
case ANIMTYPE_OBJECT:
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, channel->data, filter_mode);
break;
-
+
+ case ANIMTYPE_DSCACHEFILE:
+ items += animdata_filter_ds_cachefile(ac, anim_data, ads, channel->data, filter_mode);
+ break;
+
case ANIMTYPE_ANIMDATA:
items += animfilter_block_data(ac, anim_data, ads, channel->id, filter_mode);
break;
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 6e776953356..5f675e690b9 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -44,6 +44,7 @@
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
+#include "DNA_cachefile_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_gpencil_types.h"
@@ -965,6 +966,37 @@ void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *bl
ANIM_animdata_freelist(&anim_data);
}
+void cachefile_to_keylist(bDopeSheet *ads, CacheFile *cache_file, DLRBT_Tree *keys, DLRBT_Tree *blocks)
+{
+ if (cache_file == NULL) {
+ return;
+ }
+
+ /* create a dummy wrapper data to work with */
+ bAnimListElem dummychan = {NULL};
+ dummychan.type = ANIMTYPE_DSCACHEFILE;
+ dummychan.data = cache_file;
+ dummychan.id = &cache_file->id;
+ dummychan.adt = cache_file->adt;
+
+ bAnimContext ac = {NULL};
+ ac.ads = ads;
+ ac.data = &dummychan;
+ ac.datatype = ANIMCONT_CHANNEL;
+
+ /* get F-Curves to take keyframes from */
+ ListBase anim_data = { NULL, NULL };
+ int filter = ANIMFILTER_DATA_VISIBLE; // curves only
+ ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+
+ /* loop through each F-Curve, grabbing the keyframes */
+ for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
+ fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
+ }
+
+ ANIM_animdata_freelist(&anim_data);
+}
+
void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
{
BezTriple *bezt;
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 0940f594482..bfd89e90fce 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -156,6 +156,7 @@ typedef enum eAnim_ChannelType {
ANIMTYPE_DSMAT,
ANIMTYPE_DSLAM,
ANIMTYPE_DSCAM,
+ ANIMTYPE_DSCACHEFILE,
ANIMTYPE_DSCUR,
ANIMTYPE_DSSKEY,
ANIMTYPE_DSWOR,
@@ -275,6 +276,7 @@ typedef enum eAnimFilter_Flags {
#define FILTER_MAT_OBJD(ma) (CHECK_TYPE_INLINE(ma, Material *), ((ma->flag & MA_DS_EXPAND)))
#define FILTER_LAM_OBJD(la) (CHECK_TYPE_INLINE(la, Lamp *), ((la->flag & LA_DS_EXPAND)))
#define FILTER_CAM_OBJD(ca) (CHECK_TYPE_INLINE(ca, Camera *), ((ca->flag & CAM_DS_EXPAND)))
+#define FILTER_CACHEFILE_OBJD(cf) (CHECK_TYPE_INLINE(cf, CacheFile *), ((cf->flag & CACHEFILE_DS_EXPAND)))
#define FILTER_CUR_OBJD(cu) (CHECK_TYPE_INLINE(cu, Curve *), ((cu->flag & CU_DS_EXPAND)))
#define FILTER_PART_OBJD(part) (CHECK_TYPE_INLINE(part, ParticleSettings *), ((part->flag & PART_DS_EXPAND)))
#define FILTER_MBALL_OBJD(mb) (CHECK_TYPE_INLINE(mb, MetaBall *), ((mb->flag2 & MB_DS_EXPAND)))
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index b1f3f012e09..c478a8b17e5 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -34,6 +34,7 @@
struct bAnimContext;
struct AnimData;
+struct CacheFile;
struct FCurve;
struct bDopeSheet;
struct bAction;
@@ -141,6 +142,8 @@ void agroup_to_keylist(struct AnimData *adt, struct bActionGroup *agrp, struct D
void action_to_keylist(struct AnimData *adt, struct bAction *act, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* Object */
void ob_to_keylist(struct bDopeSheet *ads, struct Object *ob, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
+/* Cache File */
+void cachefile_to_keylist(struct bDopeSheet *ads, struct CacheFile *cache_file, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* Scene */
void scene_to_keylist(struct bDopeSheet *ads, struct Scene *sce, struct DLRBT_Tree *keys, struct DLRBT_Tree *blocks);
/* DopeSheet Summary */
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index f77e795adca..1f053c806b0 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -945,6 +945,7 @@ void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
+void uiTemplateCacheFile(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname);
/* Default UIList class name, keep in sync with its declaration in bl_ui/__init__.py */
#define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list"
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 4107414a240..22a450d2523 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1541,6 +1541,8 @@ int UI_idcode_icon_get(const int idcode)
return ICON_BRUSH_DATA;
case ID_CA:
return ICON_CAMERA_DATA;
+ case ID_CF:
+ return ICON_FILE;
case ID_CU:
return ICON_CURVE_DATA;
case ID_GD:
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 58cadf5587a..52283776816 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -32,6 +32,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_cachefile_types.h"
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -368,6 +369,7 @@ static const char *template_id_browse_tip(StructRNA *type)
case ID_MSK: return N_("Browse Mask to be linked");
case ID_PAL: return N_("Browse Palette Data to be linked");
case ID_PC: return N_("Browse Paint Curve Data to be linked");
+ case ID_CF: return N_("Browse Cache Files to be linked");
}
}
return N_("Browse ID data to be linked");
@@ -3848,3 +3850,73 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
UI_block_align_end(block);
}
+
+/********************************* Cache File *********************************/
+
+void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname)
+{
+ if (!ptr->data) {
+ return;
+ }
+
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ printf("%s: property not found: %s.%s\n",
+ __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ if (RNA_property_type(prop) != PROP_POINTER) {
+ printf("%s: expected pointer property for %s.%s\n",
+ __func__, RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ PointerRNA fileptr = RNA_property_pointer_get(ptr, prop);
+ CacheFile *file = fileptr.data;
+
+ uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr);
+
+ uiTemplateID(layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL);
+
+ if (!file) {
+ return;
+ }
+
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiBlock *block = uiLayoutGetBlock(row);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, IFACE_("File Path:"), 0, 19, 145, 19, NULL, 0, 0, 0, 0, "");
+
+ row = uiLayoutRow(layout, false);
+ uiLayout *split = uiLayoutSplit(row, 0.0f, false);
+ row = uiLayoutRow(split, true);
+
+ uiItemR(row, &fileptr, "filepath", 0, "", ICON_NONE);
+ uiItemO(row, "", ICON_FILE_REFRESH, "cachefile.reload");
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "is_sequence", 0, "Is Sequence", ICON_NONE);
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "override_frame", 0, "Override Frame", ICON_NONE);
+
+ row = uiLayoutRow(layout, false);
+ uiLayoutSetEnabled(row, RNA_boolean_get(&fileptr, "override_frame"));
+ uiItemR(row, &fileptr, "frame", 0, "Frame", ICON_NONE);
+
+ row = uiLayoutRow(layout, false);
+ uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "scale", 0, "Scale", ICON_NONE);
+
+ /* TODO: unused for now, so no need to expose. */
+#if 0
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "forward_axis", 0, "Forward Axis", ICON_NONE);
+
+ row = uiLayoutRow(layout, false);
+ uiItemR(row, &fileptr, "up_axis", 0, "Up Axis", ICON_NONE);
+#endif
+}
diff --git a/source/blender/editors/io/CMakeLists.txt b/source/blender/editors/io/CMakeLists.txt
index 828cb494eab..b3bbce939a5 100644
--- a/source/blender/editors/io/CMakeLists.txt
+++ b/source/blender/editors/io/CMakeLists.txt
@@ -28,6 +28,8 @@ set(INC
../../makesrna
../../windowmanager
../../collada
+ ../../alembic
+ ../../../../intern/guardedalloc
)
set(INC_SYS
@@ -35,9 +37,13 @@ set(INC_SYS
)
set(SRC
+ io_alembic.c
+ io_cache.c
io_collada.c
io_ops.c
+ io_alembic.h
+ io_cache.h
io_collada.h
io_ops.h
)
@@ -46,6 +52,14 @@ if(WITH_OPENCOLLADA)
add_definitions(-DWITH_COLLADA)
endif()
+if(WITH_ALEMBIC)
+ add_definitions(-DWITH_ALEMBIC)
+
+ if(WITH_ALEMBIC_HDF5)
+ add_definitions(-DWITH_ALEMBIC_HDF5)
+ endif()
+endif()
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
new file mode 100644
index 00000000000..7a7c42e501b
--- /dev/null
+++ b/source/blender/editors/io/io_alembic.c
@@ -0,0 +1,458 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifdef WITH_ALEMBIC
+
+/* needed for directory lookup */
+#ifndef WIN32
+# include <dirent.h>
+#else
+# include "BLI_winstuff.h"
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math_vector.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BLT_translation.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "io_alembic.h"
+
+#include "ABC_alembic.h"
+
+static int wm_alembic_export_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ char filepath[FILE_MAX];
+ BLI_strncpy(filepath, G.main->name, sizeof(filepath));
+ BLI_replace_extension(filepath, sizeof(filepath), ".abc");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+
+ UNUSED_VARS(event);
+}
+
+static int wm_alembic_export_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;
+ }
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ const struct AlembicExportParams params = {
+ .frame_start = RNA_int_get(op->ptr, "start"),
+ .frame_end = RNA_int_get(op->ptr, "end"),
+
+ .frame_step_xform = 1.0 / (double)RNA_int_get(op->ptr, "xsamples"),
+ .frame_step_shape = 1.0 / (double)RNA_int_get(op->ptr, "gsamples"),
+
+ .shutter_open = RNA_float_get(op->ptr, "sh_open"),
+ .shutter_close = RNA_float_get(op->ptr, "sh_close"),
+
+ .selected_only = RNA_boolean_get(op->ptr, "selected"),
+ .uvs = RNA_boolean_get(op->ptr, "uvs"),
+ .normals = RNA_boolean_get(op->ptr, "normals"),
+ .vcolors = RNA_boolean_get(op->ptr, "vcolors"),
+ .apply_subdiv = RNA_boolean_get(op->ptr, "apply_subdiv"),
+ .flatten_hierarchy = RNA_boolean_get(op->ptr, "flatten"),
+ .visible_layers_only = RNA_boolean_get(op->ptr, "visible_layers_only"),
+ .renderable_only = RNA_boolean_get(op->ptr, "renderable_only"),
+ .face_sets = RNA_boolean_get(op->ptr, "face_sets"),
+ .use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
+ .compression_type = RNA_enum_get(op->ptr, "compression_type"),
+ .packuv = RNA_boolean_get(op->ptr, "packuv"),
+
+ .global_scale = RNA_float_get(op->ptr, "global_scale"),
+ };
+
+ ABC_export(CTX_data_scene(C), C, filename, &params);
+
+ return OPERATOR_FINISHED;
+}
+
+static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
+{
+ uiLayout *box = uiLayoutBox(layout);
+ uiLayout *row;
+
+#ifdef WITH_ALEMBIC_HDF5
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Archive Options:"), ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "compression_type", 0, NULL, ICON_NONE);
+#endif
+
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "global_scale", 0, NULL, ICON_NONE);
+
+ /* Scene Options */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Scene Options:"), ICON_SCENE_DATA);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "start", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "end", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "xsamples", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "gsamples", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "sh_open", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "sh_close", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "selected", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "renderable_only", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "visible_layers_only", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "flatten", 0, NULL, ICON_NONE);
+
+ /* Object Data */
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Object Options:"), ICON_OBJECT_DATA);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "uvs", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "packuv", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "uvs"));
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "normals", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "vcolors", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "face_sets", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "subdiv_schema", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "apply_subdiv", 0, NULL, ICON_NONE);
+}
+
+static void wm_alembic_export_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ PointerRNA ptr;
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ ui_alembic_export_settings(op->layout, &ptr);
+}
+
+void WM_OT_alembic_export(wmOperatorType *ot)
+{
+ ot->name = "Export Alembic Archive";
+ ot->idname = "WM_OT_alembic_export";
+
+ ot->invoke = wm_alembic_export_invoke;
+ ot->exec = wm_alembic_export_exec;
+ ot->poll = WM_operator_winactive;
+ ot->ui = wm_alembic_export_draw;
+
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
+ FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+
+ RNA_def_int(ot->srna, "start", 1, INT_MIN, INT_MAX,
+ "Start Frame", "Start Frame", INT_MIN, INT_MAX);
+
+ RNA_def_int(ot->srna, "end", 1, INT_MIN, INT_MAX,
+ "End Frame", "End Frame", INT_MIN, INT_MAX);
+
+ RNA_def_int(ot->srna, "xsamples", 1, 1, 128,
+ "Transform Samples", "Number of times per frame transformations are sampled", 1, 128);
+
+ RNA_def_int(ot->srna, "gsamples", 1, 1, 128,
+ "Geometry Samples", "Number of times per frame object datas are sampled", 1, 128);
+
+ RNA_def_float(ot->srna, "sh_open", 0.0f, -1.0f, 1.0f,
+ "Shutter Open", "Time at which the shutter is open", -1.0f, 1.0f);
+
+ RNA_def_float(ot->srna, "sh_close", 1.0f, -1.0f, 1.0f,
+ "Shutter Close", "Time at which the shutter is closed", -1.0f, 1.0f);
+
+ RNA_def_boolean(ot->srna, "selected", 0,
+ "Selected Objects Only", "Export only selected objects");
+
+ RNA_def_boolean(ot->srna, "renderable_only", 1,
+ "Renderable Objects Only",
+ "Export only objects marked renderable in the outliner");
+
+ RNA_def_boolean(ot->srna, "visible_layers_only", 0,
+ "Visible Layers Only", "Export only objects in visible layers");
+
+ RNA_def_boolean(ot->srna, "flatten", 0,
+ "Flatten Hierarchy",
+ "Do not preserve objects' parent/children relationship");
+
+ RNA_def_boolean(ot->srna, "uvs", 1, "UVs", "Export UVs");
+
+ RNA_def_boolean(ot->srna, "packuv", 1, "Pack UV Islands",
+ "Export UVs with packed island");
+
+ RNA_def_boolean(ot->srna, "normals", 1, "Normals", "Export normals");
+
+ RNA_def_boolean(ot->srna, "vcolors", 0, "Vertex colors", "Export vertex colors");
+
+ RNA_def_boolean(ot->srna, "face_sets", 0, "Face Sets", "Export per face shading group assignments");
+
+ RNA_def_boolean(ot->srna, "subdiv_schema", 0,
+ "Use Subdivision Schema",
+ "Export meshes using Alembic's subdivision schema");
+
+ RNA_def_boolean(ot->srna, "apply_subdiv", 0,
+ "Apply Subsurf", "Export subdivision surfaces as meshes");
+
+ RNA_def_enum(ot->srna, "compression_type", rna_enum_abc_compression_items,
+ ABC_ARCHIVE_OGAWA, "Compression", "");
+
+ RNA_def_float(ot->srna, "global_scale", 1.0f, 0.0001f, 1000.0f, "Scale",
+ "Value by which to enlarge or shrink the objects with respect to the world's origin",
+ 0.0001f, 1000.0f);
+}
+
+/* ************************************************************************** */
+
+/* TODO(kevin): check on de-duplicating all this with code in image_ops.c */
+
+typedef struct CacheFrame {
+ struct CacheFrame *next, *prev;
+ int framenr;
+} CacheFrame;
+
+static int cmp_frame(const void *a, const void *b)
+{
+ const CacheFrame *frame_a = a;
+ const CacheFrame *frame_b = b;
+
+ if (frame_a->framenr < frame_b->framenr) return -1;
+ if (frame_a->framenr > frame_b->framenr) return 1;
+ return 0;
+}
+
+static int get_sequence_len(char *filename, int *ofs)
+{
+ int frame;
+ int numdigit;
+
+ if (!BLI_path_frame_get(filename, &frame, &numdigit)) {
+ return 1;
+ }
+
+ char path[FILE_MAX];
+ BLI_split_dir_part(filename, path, FILE_MAX);
+
+ DIR *dir = opendir(path);
+
+ const char *ext = ".abc";
+ const char *basename = BLI_path_basename(filename);
+ const int len = strlen(basename) - (numdigit + strlen(ext));
+
+ ListBase frames;
+ BLI_listbase_clear(&frames);
+
+ struct dirent *fname;
+ while ((fname = readdir(dir)) != NULL) {
+ /* do we have the right extension? */
+ if (!strstr(fname->d_name, ext)) {
+ continue;
+ }
+
+ if (!STREQLEN(basename, fname->d_name, len)) {
+ continue;
+ }
+
+ CacheFrame *cache_frame = MEM_callocN(sizeof(CacheFrame), "abc_frame");
+
+ BLI_path_frame_get(fname->d_name, &cache_frame->framenr, &numdigit);
+
+ BLI_addtail(&frames, cache_frame);
+ }
+
+ closedir(dir);
+
+ BLI_listbase_sort(&frames, cmp_frame);
+
+ CacheFrame *cache_frame = frames.first;
+
+ if (cache_frame) {
+ int frame_curr = cache_frame->framenr;
+ (*ofs) = frame_curr;
+
+ while (cache_frame && (cache_frame->framenr == frame_curr)) {
+ ++frame_curr;
+ cache_frame = cache_frame->next;
+ }
+
+ BLI_freelistN(&frames);
+
+ return frame_curr - (*ofs);
+ }
+
+ return 1;
+}
+
+/* ************************************************************************** */
+
+static void ui_alembic_import_settings(uiLayout *layout, PointerRNA *imfptr)
+{
+ uiLayout *box = uiLayoutBox(layout);
+ uiLayout *row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Manual Transform:"), ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "scale", 0, NULL, ICON_NONE);
+
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+ uiItemL(row, IFACE_("Options:"), ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "set_frame_range", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "is_sequence", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "validate_meshes", 0, NULL, ICON_NONE);
+}
+
+static void wm_alembic_import_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ PointerRNA ptr;
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ ui_alembic_import_settings(op->layout, &ptr);
+}
+
+static int wm_alembic_import_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;
+ }
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ const float scale = RNA_float_get(op->ptr, "scale");
+ const bool is_sequence = RNA_boolean_get(op->ptr, "is_sequence");
+ const bool set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range");
+ const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
+
+ int offset = 0;
+ int sequence_len = 1;
+
+ if (is_sequence) {
+ sequence_len = get_sequence_len(filename, &offset);
+ }
+
+ ABC_import(C, filename, scale, is_sequence, set_frame_range, sequence_len, offset, validate_meshes);
+
+ return OPERATOR_FINISHED;
+}
+
+void WM_OT_alembic_import(wmOperatorType *ot)
+{
+ ot->name = "Import Alembic Archive";
+ ot->idname = "WM_OT_alembic_import";
+
+ ot->invoke = WM_operator_filesel;
+ ot->exec = wm_alembic_import_exec;
+ ot->poll = WM_operator_winactive;
+ ot->ui = wm_alembic_import_draw;
+
+ WM_operator_properties_filesel(ot, FILE_TYPE_FOLDER | FILE_TYPE_ALEMBIC,
+ FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+
+ RNA_def_float(ot->srna, "scale", 1.0f, 0.0001f, 1000.0f, "Scale",
+ "Value by which to enlarge or shrink the objects with respect to the world's origin",
+ 0.0001f, 1000.0f);
+
+ RNA_def_boolean(ot->srna, "set_frame_range", true,
+ "Set Frame Range",
+ "If checked, update scene's start and end frame to match those of the Alembic archive");
+
+ RNA_def_boolean(ot->srna, "validate_meshes", 0,
+ "Validate Meshes", "Check imported mesh objects for invalid data (slow)");
+
+ RNA_def_boolean(ot->srna, "is_sequence", false, "Is Sequence",
+ "Set to true if the cache is split into separate files");
+}
+
+#endif
diff --git a/source/blender/editors/io/io_alembic.h b/source/blender/editors/io/io_alembic.h
new file mode 100644
index 00000000000..5eefabef4be
--- /dev/null
+++ b/source/blender/editors/io/io_alembic.h
@@ -0,0 +1,37 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef __IO_ALEMBIC_H__
+#define __IO_ALEMBIC_H__
+
+/** \file blender/editors/io/io_alembic.h
+ * \ingroup editor/io
+ */
+
+struct wmOperatorType;
+
+void WM_OT_alembic_export(struct wmOperatorType *ot);
+void WM_OT_alembic_import(struct wmOperatorType *ot);
+
+#endif /* __IO_ALEMBIC_H__ */
diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c
new file mode 100644
index 00000000000..d6e2c1ae204
--- /dev/null
+++ b/source/blender/editors/io/io_cache.c
@@ -0,0 +1,162 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_cachefile_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "BKE_cachefile.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_report.h"
+
+#include "RNA_access.h"
+
+#include "UI_interface.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "io_cache.h"
+
+static void cachefile_init(bContext *C, wmOperator *op)
+{
+ PropertyPointerRNA *pprop;
+
+ op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
+ UI_context_active_but_prop_get_templateID(C, &pprop->ptr, &pprop->prop);
+}
+
+static int cachefile_open_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
+ char filepath[FILE_MAX];
+ BLI_strncpy(filepath, G.main->name, sizeof(filepath));
+ BLI_replace_extension(filepath, sizeof(filepath), ".abc");
+ RNA_string_set(op->ptr, "filepath", filepath);
+ }
+
+ cachefile_init(C, op);
+
+ WM_event_add_fileselect(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+
+ UNUSED_VARS(event);
+}
+
+static void open_cancel(bContext *UNUSED(C), wmOperator *op)
+{
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+}
+
+static int cachefile_open_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;
+ }
+
+ char filename[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filename);
+
+ Main *bmain = CTX_data_main(C);
+
+ CacheFile *cache_file = BKE_libblock_alloc(bmain, ID_CF, BLI_path_basename(filename));
+ BLI_strncpy(cache_file->filepath, filename, FILE_MAX);
+ BKE_cachefile_reload(bmain, cache_file);
+
+ /* hook into UI */
+ PropertyPointerRNA *pprop = op->customdata;
+
+ if (pprop->prop) {
+ /* when creating new ID blocks, use is already 1, but RNA
+ * pointer se also increases user, so this compensates it */
+ id_us_min(&cache_file->id);
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&cache_file->id, &idptr);
+ RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
+ RNA_property_update(C, &pprop->ptr, pprop->prop);
+ }
+
+ MEM_freeN(op->customdata);
+
+ return OPERATOR_FINISHED;
+}
+
+void CACHEFILE_OT_open(wmOperatorType *ot)
+{
+ ot->name = "Open Cache File";
+ ot->idname = "CACHEFILE_OT_open";
+
+ ot->invoke = cachefile_open_invoke;
+ ot->exec = cachefile_open_exec;
+ ot->cancel = open_cancel;
+
+ WM_operator_properties_filesel(ot, FILE_TYPE_ALEMBIC | FILE_TYPE_FOLDER,
+ FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH,
+ FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
+}
+
+/* ***************************** Reload Operator **************************** */
+
+static int cachefile_reload_exec(bContext *C, wmOperator *op)
+{
+ CacheFile *cache_file = CTX_data_edit_cachefile(C);
+
+ if (!cache_file) {
+ return OPERATOR_CANCELLED;
+ }
+
+ Main *bmain = CTX_data_main(C);
+
+ BLI_listbase_clear(&cache_file->object_paths);
+ BKE_cachefile_reload(bmain, cache_file);
+
+ return OPERATOR_FINISHED;
+
+ UNUSED_VARS(op);
+}
+
+void CACHEFILE_OT_reload(wmOperatorType *ot)
+{
+ ot->name = "Refresh Archive";
+ ot->description = "Update objects paths list with new data from the archive";
+ ot->idname = "CACHEFILE_OT_reload";
+
+ /* api callbacks */
+ ot->exec = cachefile_reload_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/io/io_cache.h b/source/blender/editors/io/io_cache.h
new file mode 100644
index 00000000000..ea270c2aba1
--- /dev/null
+++ b/source/blender/editors/io/io_cache.h
@@ -0,0 +1,37 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
+
+#ifndef __IO_CACHE_H__
+#define __IO_CACHE_H__
+
+/** \file blender/editors/io/io_cache.h
+ * \ingroup editor/io
+ */
+
+struct wmOperatorType;
+
+void CACHEFILE_OT_open(struct wmOperatorType *ot);
+void CACHEFILE_OT_reload(struct wmOperatorType *ot);
+
+#endif /* __IO_CACHE_H__ */
diff --git a/source/blender/editors/io/io_ops.c b/source/blender/editors/io/io_ops.c
index a70a51a60be..d1e933517a9 100644
--- a/source/blender/editors/io/io_ops.c
+++ b/source/blender/editors/io/io_ops.c
@@ -30,11 +30,18 @@
#include "io_ops.h" /* own include */
+#include "WM_api.h"
+
#ifdef WITH_COLLADA
# include "io_collada.h"
-# include "WM_api.h"
#endif
+#ifdef WITH_ALEMBIC
+# include "io_alembic.h"
+#endif
+
+#include "io_cache.h"
+
void ED_operatortypes_io(void)
{
#ifdef WITH_COLLADA
@@ -42,4 +49,11 @@ void ED_operatortypes_io(void)
WM_operatortype_append(WM_OT_collada_export);
WM_operatortype_append(WM_OT_collada_import);
#endif
+#ifdef WITH_ALEMBIC
+ WM_operatortype_append(WM_OT_alembic_import);
+ WM_operatortype_append(WM_OT_alembic_export);
+#endif
+
+ WM_operatortype_append(CACHEFILE_OT_open);
+ WM_operatortype_append(CACHEFILE_OT_reload);
}
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index db8a4c1960f..59d78f13ccb 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -416,6 +416,13 @@ static void test_constraint(Object *owner, bPoseChannel *pchan, bConstraint *con
if ((data->flag & CAMERASOLVER_ACTIVECLIP) == 0 && (data->clip == NULL))
con->flag |= CONSTRAINT_DISABLE;
}
+ else if (con->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
+ bTransformCacheConstraint *data = con->data;
+
+ if ((data->cache_file == NULL) || (data->object_path[0] == '\0')) {
+ con->flag |= CONSTRAINT_DISABLE;
+ }
+ }
/* Check targets for constraints */
if (check_targets && cti && cti->get_constraint_targets) {
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index 5e9eb1f9207..b6e4991bf52 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -920,6 +920,8 @@ static int filelist_geticon_ex(
return ICON_FILE_BLANK;
else if (typeflag & FILE_TYPE_COLLADA)
return ICON_FILE_BLANK;
+ else if (typeflag & FILE_TYPE_ALEMBIC)
+ return ICON_FILE_BLANK;
else if (typeflag & FILE_TYPE_TEXT)
return ICON_FILE_TEXT;
else if (typeflag & FILE_TYPE_BLENDERLIB) {
@@ -1952,6 +1954,9 @@ int ED_path_extension_type(const char *path)
else if (BLI_testextensie(path, ".dae")) {
return FILE_TYPE_COLLADA;
}
+ else if (BLI_testextensie(path, ".abc")) {
+ return FILE_TYPE_ALEMBIC;
+ }
else if (BLI_testextensie_array(path, imb_ext_image) ||
(G.have_quicktime && BLI_testextensie_array(path, imb_ext_image_qt)))
{
@@ -2004,6 +2009,8 @@ int ED_file_extension_icon(const char *path)
return ICON_FILE_BLANK;
case FILE_TYPE_COLLADA:
return ICON_FILE_BLANK;
+ case FILE_TYPE_ALEMBIC:
+ return ICON_FILE_BLANK;
case FILE_TYPE_TEXT:
return ICON_FILE_TEXT;
default:
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index ab33d452d3c..1a558d40560 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -185,6 +185,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BTX : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_collada")))
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_COLLADA : 0;
+ if ((prop = RNA_struct_find_property(op->ptr, "filter_alembic")))
+ params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_ALEMBIC : 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) {
/* Protection against pyscripts not setting proper size limit... */
char *tmp = RNA_property_string_get_alloc(
@@ -213,7 +215,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
FILTER_ID_GR | FILTER_ID_IM | FILTER_ID_LA | FILTER_ID_LS | FILTER_ID_LT | FILTER_ID_MA |
FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB |
FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO |
- FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO;
+ FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF;
if (U.uiflag & USER_HIDE_DOT) {
params->flag |= FILE_HIDE_DOT;
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 9032d286933..3243579f7d0 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -131,6 +131,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 9e73e03a664..4f30c049d9d 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -170,6 +170,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
case ANIMTYPE_DSLAM:
case ANIMTYPE_DSCAM:
+ case ANIMTYPE_DSCACHEFILE:
case ANIMTYPE_DSCUR:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index b57462df53b..d4553b650c5 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -1173,6 +1173,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break;
case eModifierType_MeshCache:
UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ case eModifierType_MeshSequenceCache:
+ UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
case eModifierType_Wireframe:
UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break;
case eModifierType_LaplacianDeform:
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index d2666cd0b6d..ca037cb20cc 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -62,7 +62,7 @@ typedef struct TreeElement {
#define TREESTORE_ID_TYPE(_id) \
(ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
ELEM(GS((_id)->name), ID_KE, ID_WO, ID_SPK, ID_GR, ID_AR, ID_AC, ID_BR, ID_PA, ID_GD, ID_LS) || \
- ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO)) /* Only in 'blendfile' mode ... :/ */
+ ELEM(GS((_id)->name), ID_SCR, ID_WM, ID_TXT, ID_VF, ID_SO, ID_CF)) /* Only in 'blendfile' mode ... :/ */
/* TreeElement->flag */
#define TE_ACTIVE 1
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index b22e6595caf..96bab3d5c1e 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -38,6 +38,7 @@
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_camera_types.h"
+#include "DNA_cachefile_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_group_types.h"
#include "DNA_key_types.h"
@@ -746,6 +747,16 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor
outliner_add_element(soops, &te->subtree, ca, te, TSE_ANIM_DATA, 0);
break;
}
+ case ID_CF:
+ {
+ CacheFile *cache_file = (CacheFile *)id;
+
+ if (outliner_animdata_test(cache_file->adt)) {
+ outliner_add_element(soops, &te->subtree, cache_file, te, TSE_ANIM_DATA, 0);
+ }
+
+ break;
+ }
case ID_LA:
{
Lamp *la = (Lamp *)id;
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index 525d42a1965..021c4a54b0a 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -32,7 +32,10 @@
#include <string.h>
#include <stdio.h>
+#include "DNA_cachefile_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
@@ -42,7 +45,10 @@
#include "BLI_dlrbTree.h"
#include "BLI_utildefines.h"
+#include "BKE_constraint.h"
#include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_modifier.h"
#include "BKE_screen.h"
#include "BKE_pointcache.h"
@@ -320,6 +326,9 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
case ID_GD:
gpencil_to_keylist(&ads, (bGPdata *)id, &keys);
break;
+ case ID_CF:
+ cachefile_to_keylist(&ads, (CacheFile *)id, &keys, NULL);
+ break;
}
/* build linked-list for searching */
@@ -344,6 +353,56 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel)
BLI_dlrbTree_free(&keys);
}
+static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel)
+{
+ CacheFile *cache_file;
+
+ for (cache_file = bmain->cachefiles.first;
+ cache_file;
+ cache_file = cache_file->id.next)
+ {
+ cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN;
+ }
+
+ for (Base *base = scene->base.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
+
+ if (md) {
+ MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
+
+ cache_file = mcmd->cache_file;
+
+ if (!cache_file || (cache_file->draw_flag & CACHEFILE_KEYFRAME_DRAWN) != 0) {
+ continue;
+ }
+
+ cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN;
+
+ time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel);
+ }
+
+ for (bConstraint *con = ob->constraints.first; con; con = con->next) {
+ if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) {
+ continue;
+ }
+
+ bTransformCacheConstraint *data = con->data;
+
+ cache_file = data->cache_file;
+
+ if (!cache_file || (cache_file->draw_flag & CACHEFILE_KEYFRAME_DRAWN) != 0) {
+ continue;
+ }
+
+ cache_file->draw_flag |= CACHEFILE_KEYFRAME_DRAWN;
+
+ time_draw_idblock_keyframes(v2d, (ID *)cache_file, onlysel);
+ }
+ }
+}
+
/* draw keyframe lines for timeline */
static void time_draw_keyframes(const bContext *C, ARegion *ar)
{
@@ -354,7 +413,11 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
/* set this for all keyframe lines once and for all */
glLineWidth(1.0);
-
+
+ /* draw cache files keyframes (if available) */
+ UI_ThemeColor(TH_TIME_KEYFRAME);
+ time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel);
+
/* draw grease pencil keyframes (if available) */
UI_ThemeColor(TH_TIME_GP_KEYFRAME);
if (scene->gpd) {