Merge branch 'master' into blender2.8
# Conflicts: # source/blender/alembic/intern/abc_exporter.cc # source/blender/alembic/intern/abc_exporter.h
This commit is contained in:
@@ -176,11 +176,10 @@ def draw(layout, context, context_member, property_type, use_edit=True):
|
|||||||
if not is_rna:
|
if not is_rna:
|
||||||
props = row.operator("wm.properties_edit", text="Edit")
|
props = row.operator("wm.properties_edit", text="Edit")
|
||||||
assign_props(props, val_draw, key)
|
assign_props(props, val_draw, key)
|
||||||
else:
|
|
||||||
row.label(text="API Defined")
|
|
||||||
|
|
||||||
props = row.operator("wm.properties_remove", text="", icon='ZOOMOUT')
|
props = row.operator("wm.properties_remove", text="", icon='ZOOMOUT')
|
||||||
assign_props(props, val_draw, key)
|
assign_props(props, val_draw, key)
|
||||||
|
else:
|
||||||
|
row.label(text="API Defined")
|
||||||
|
|
||||||
|
|
||||||
class PropertyPanel:
|
class PropertyPanel:
|
||||||
|
|||||||
@@ -53,41 +53,57 @@ struct AlembicExportParams {
|
|||||||
double shutter_open;
|
double shutter_open;
|
||||||
double shutter_close;
|
double shutter_close;
|
||||||
|
|
||||||
/* bools */
|
bool selected_only;
|
||||||
unsigned int selected_only : 1;
|
bool uvs;
|
||||||
unsigned int uvs : 1;
|
bool normals;
|
||||||
unsigned int normals : 1;
|
bool vcolors;
|
||||||
unsigned int vcolors : 1;
|
bool apply_subdiv;
|
||||||
unsigned int apply_subdiv : 1;
|
bool flatten_hierarchy;
|
||||||
unsigned int flatten_hierarchy : 1;
|
bool visible_layers_only;
|
||||||
unsigned int visible_layers_only : 1;
|
bool renderable_only;
|
||||||
unsigned int renderable_only : 1;
|
bool face_sets;
|
||||||
unsigned int face_sets : 1;
|
bool use_subdiv_schema;
|
||||||
unsigned int use_subdiv_schema : 1;
|
bool packuv;
|
||||||
unsigned int packuv : 1;
|
bool triangulate;
|
||||||
unsigned int triangulate : 1;
|
bool export_hair;
|
||||||
|
bool export_particles;
|
||||||
|
|
||||||
unsigned int compression_type : 1;
|
unsigned int compression_type : 1;
|
||||||
|
|
||||||
|
/* See MOD_TRIANGULATE_NGON_xxx and MOD_TRIANGULATE_QUAD_xxx
|
||||||
|
* in DNA_modifier_types.h */
|
||||||
int quad_method;
|
int quad_method;
|
||||||
int ngon_method;
|
int ngon_method;
|
||||||
|
|
||||||
float global_scale;
|
float global_scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ABC_export(
|
/* The ABC_export and ABC_import functions both take a as_background_job
|
||||||
|
* parameter, and return a boolean.
|
||||||
|
*
|
||||||
|
* When as_background_job=true, returns false immediately after scheduling
|
||||||
|
* a background job.
|
||||||
|
*
|
||||||
|
* When as_background_job=false, performs the export synchronously, and returns
|
||||||
|
* true when the export was ok, and false if there were any errors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool ABC_export(
|
||||||
struct Scene *scene,
|
struct Scene *scene,
|
||||||
struct bContext *C,
|
struct bContext *C,
|
||||||
const char *filepath,
|
const char *filepath,
|
||||||
const struct AlembicExportParams *params);
|
const struct AlembicExportParams *params,
|
||||||
|
bool as_background_job);
|
||||||
|
|
||||||
void ABC_import(struct bContext *C,
|
bool ABC_import(struct bContext *C,
|
||||||
const char *filepath,
|
const char *filepath,
|
||||||
float scale,
|
float scale,
|
||||||
bool is_sequence,
|
bool is_sequence,
|
||||||
bool set_frame_range,
|
bool set_frame_range,
|
||||||
int sequence_len,
|
int sequence_len,
|
||||||
int offset,
|
int offset,
|
||||||
bool validate_meshes);
|
bool validate_meshes,
|
||||||
|
bool as_background_job);
|
||||||
|
|
||||||
AbcArchiveHandle *ABC_create_handle(const char *filename, struct ListBase *object_paths);
|
AbcArchiveHandle *ABC_create_handle(const char *filename, struct ListBase *object_paths);
|
||||||
|
|
||||||
|
|||||||
@@ -217,16 +217,17 @@ void AbcCurveReader::readObjectData(Main *bmain, float time)
|
|||||||
|
|
||||||
cu->flag |= CU_DEFORM_FILL | CU_3D;
|
cu->flag |= CU_DEFORM_FILL | CU_3D;
|
||||||
cu->actvert = CU_ACT_NONE;
|
cu->actvert = CU_ACT_NONE;
|
||||||
|
cu->resolu = 1;
|
||||||
|
|
||||||
const ISampleSelector sample_sel(time);
|
const ISampleSelector sample_sel(time);
|
||||||
|
|
||||||
ICompoundProperty user_props = m_curves_schema.getUserProperties();
|
ICompoundProperty user_props = m_curves_schema.getUserProperties();
|
||||||
|
if (user_props) {
|
||||||
const PropertyHeader *header = user_props.getPropertyHeader(ABC_CURVE_RESOLUTION_U_PROPNAME);
|
const PropertyHeader *header = user_props.getPropertyHeader(ABC_CURVE_RESOLUTION_U_PROPNAME);
|
||||||
if (header != NULL && header->isScalar() && IInt16Property::matches(*header)) {
|
if (header != NULL && header->isScalar() && IInt16Property::matches(*header)) {
|
||||||
IInt16Property resolu(user_props, header->getName());
|
IInt16Property resolu(user_props, header->getName());
|
||||||
cu->resolu = resolu.getValue(sample_sel);
|
cu->resolu = resolu.getValue(sample_sel);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
cu->resolu = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_object = BKE_object_add_only_object(bmain, OB_CURVE, m_object_name.c_str());
|
m_object = BKE_object_add_only_object(bmain, OB_CURVE, m_object_name.c_str());
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ ExportSettings::ExportSettings()
|
|||||||
, export_vcols(false)
|
, export_vcols(false)
|
||||||
, export_face_sets(false)
|
, export_face_sets(false)
|
||||||
, export_vweigths(false)
|
, export_vweigths(false)
|
||||||
|
, export_hair(true)
|
||||||
|
, export_particles(true)
|
||||||
, apply_subdiv(false)
|
, apply_subdiv(false)
|
||||||
, use_subdiv_schema(false)
|
, use_subdiv_schema(false)
|
||||||
, export_child_hairs(true)
|
, export_child_hairs(true)
|
||||||
@@ -528,6 +530,29 @@ void AbcExporter::exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Obje
|
|||||||
free_object_duplilist(lb);
|
free_object_duplilist(lb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AbcExporter::createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform)
|
||||||
|
{
|
||||||
|
if (!m_settings.export_hair && !m_settings.export_particles) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
|
||||||
|
|
||||||
|
for (; psys; psys = psys->next) {
|
||||||
|
if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_settings.export_hair && psys->part->type == PART_HAIR) {
|
||||||
|
m_settings.export_child_hairs = true;
|
||||||
|
m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
|
||||||
|
}
|
||||||
|
else if (m_settings.export_particles && psys->part->type == PART_EMITTER) {
|
||||||
|
m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent)
|
void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent)
|
||||||
{
|
{
|
||||||
Object *ob = ob_base->object;
|
Object *ob = ob_base->object;
|
||||||
@@ -552,21 +577,7 @@ void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
|
createParticleSystemsWriters(ob, xform);
|
||||||
|
|
||||||
for (; psys; psys = psys->next) {
|
|
||||||
if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (psys->part->type == PART_HAIR) {
|
|
||||||
m_settings.export_child_hairs = true;
|
|
||||||
m_shapes.push_back(new AbcHairWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
|
|
||||||
}
|
|
||||||
else if (psys->part->type == PART_EMITTER) {
|
|
||||||
m_shapes.push_back(new AbcPointsWriter(m_scene, ob, xform, m_shape_sampling_index, m_settings, psys));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (ob->type) {
|
switch (ob->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ struct ExportSettings {
|
|||||||
bool export_vcols;
|
bool export_vcols;
|
||||||
bool export_face_sets;
|
bool export_face_sets;
|
||||||
bool export_vweigths;
|
bool export_vweigths;
|
||||||
|
bool export_hair;
|
||||||
|
bool export_particles;
|
||||||
|
|
||||||
bool apply_subdiv;
|
bool apply_subdiv;
|
||||||
bool use_subdiv_schema;
|
bool use_subdiv_schema;
|
||||||
@@ -117,6 +119,7 @@ private:
|
|||||||
void exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent);
|
void exploreObject(EvaluationContext *eval_ctx, Base *ob_base, Object *dupliObParent);
|
||||||
void createShapeWriters(EvaluationContext *eval_ctx);
|
void createShapeWriters(EvaluationContext *eval_ctx);
|
||||||
void createShapeWriter(Base *ob_base, Object *dupliObParent);
|
void createShapeWriter(Base *ob_base, Object *dupliObParent);
|
||||||
|
void createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform);
|
||||||
|
|
||||||
AbcTransformWriter *getXForm(const std::string &name);
|
AbcTransformWriter *getXForm(const std::string &name);
|
||||||
|
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ struct ExportJobData {
|
|||||||
float *progress;
|
float *progress;
|
||||||
|
|
||||||
bool was_canceled;
|
bool was_canceled;
|
||||||
|
bool export_ok;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void export_startjob(void *customdata, short *stop, short *do_update, float *progress)
|
static void export_startjob(void *customdata, short *stop, short *do_update, float *progress)
|
||||||
@@ -272,6 +273,8 @@ static void export_startjob(void *customdata, short *stop, short *do_update, flo
|
|||||||
|
|
||||||
BKE_scene_update_for_newframe(data->bmain->eval_ctx, data->bmain, scene);
|
BKE_scene_update_for_newframe(data->bmain->eval_ctx, data->bmain, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data->export_ok = !data->was_canceled;
|
||||||
}
|
}
|
||||||
catch (const std::exception &e) {
|
catch (const std::exception &e) {
|
||||||
ABC_LOG(data->settings.logger) << "Abc Export error: " << e.what() << '\n';
|
ABC_LOG(data->settings.logger) << "Abc Export error: " << e.what() << '\n';
|
||||||
@@ -298,15 +301,17 @@ static void export_endjob(void *customdata)
|
|||||||
BKE_spacedata_draw_locks(false);
|
BKE_spacedata_draw_locks(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ABC_export(
|
bool ABC_export(
|
||||||
Scene *scene,
|
Scene *scene,
|
||||||
bContext *C,
|
bContext *C,
|
||||||
const char *filepath,
|
const char *filepath,
|
||||||
const struct AlembicExportParams *params)
|
const struct AlembicExportParams *params,
|
||||||
|
bool as_background_job)
|
||||||
{
|
{
|
||||||
ExportJobData *job = static_cast<ExportJobData *>(MEM_mallocN(sizeof(ExportJobData), "ExportJobData"));
|
ExportJobData *job = static_cast<ExportJobData *>(MEM_mallocN(sizeof(ExportJobData), "ExportJobData"));
|
||||||
job->scene = scene;
|
job->scene = scene;
|
||||||
job->bmain = CTX_data_main(C);
|
job->bmain = CTX_data_main(C);
|
||||||
|
job->export_ok = false;
|
||||||
BLI_strncpy(job->filename, filepath, 1024);
|
BLI_strncpy(job->filename, filepath, 1024);
|
||||||
|
|
||||||
/* Alright, alright, alright....
|
/* Alright, alright, alright....
|
||||||
@@ -348,6 +353,8 @@ void ABC_export(
|
|||||||
job->settings.export_normals = params->normals;
|
job->settings.export_normals = params->normals;
|
||||||
job->settings.export_uvs = params->uvs;
|
job->settings.export_uvs = params->uvs;
|
||||||
job->settings.export_vcols = params->vcolors;
|
job->settings.export_vcols = params->vcolors;
|
||||||
|
job->settings.export_hair = params->export_hair;
|
||||||
|
job->settings.export_particles = params->export_particles;
|
||||||
job->settings.apply_subdiv = params->apply_subdiv;
|
job->settings.apply_subdiv = params->apply_subdiv;
|
||||||
job->settings.flatten_hierarchy = params->flatten_hierarchy;
|
job->settings.flatten_hierarchy = params->flatten_hierarchy;
|
||||||
|
|
||||||
@@ -369,6 +376,7 @@ void ABC_export(
|
|||||||
std::swap(job->settings.frame_start, job->settings.frame_end);
|
std::swap(job->settings.frame_start, job->settings.frame_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (as_background_job) {
|
||||||
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
|
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
|
||||||
CTX_wm_window(C),
|
CTX_wm_window(C),
|
||||||
job->scene,
|
job->scene,
|
||||||
@@ -382,6 +390,17 @@ void ABC_export(
|
|||||||
WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob);
|
WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob);
|
||||||
|
|
||||||
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Fake a job context, so that we don't need NULL pointer checks while exporting. */
|
||||||
|
short stop = 0, do_update = 0;
|
||||||
|
float progress = 0.f;
|
||||||
|
|
||||||
|
export_startjob(job, &stop, &do_update, &progress);
|
||||||
|
export_endjob(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
return job->export_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ********************** Import file ********************** */
|
/* ********************** Import file ********************** */
|
||||||
@@ -610,6 +629,7 @@ struct ImportJobData {
|
|||||||
|
|
||||||
char error_code;
|
char error_code;
|
||||||
bool was_cancelled;
|
bool was_cancelled;
|
||||||
|
bool import_ok;
|
||||||
};
|
};
|
||||||
|
|
||||||
ABC_INLINE bool is_mesh_and_strands(const IObject &object)
|
ABC_INLINE bool is_mesh_and_strands(const IObject &object)
|
||||||
@@ -818,6 +838,7 @@ static void import_endjob(void *user_data)
|
|||||||
switch (data->error_code) {
|
switch (data->error_code) {
|
||||||
default:
|
default:
|
||||||
case ABC_NO_ERROR:
|
case ABC_NO_ERROR:
|
||||||
|
data->import_ok = !data->was_cancelled;
|
||||||
break;
|
break;
|
||||||
case ABC_ARCHIVE_FAIL:
|
case ABC_ARCHIVE_FAIL:
|
||||||
WM_report(RPT_ERROR, "Could not open Alembic archive for reading! See console for detail.");
|
WM_report(RPT_ERROR, "Could not open Alembic archive for reading! See console for detail.");
|
||||||
@@ -833,13 +854,16 @@ static void import_freejob(void *user_data)
|
|||||||
delete data;
|
delete data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence, bool set_frame_range, int sequence_len, int offset, bool validate_meshes)
|
bool ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence,
|
||||||
|
bool set_frame_range, int sequence_len, int offset,
|
||||||
|
bool validate_meshes, bool as_background_job)
|
||||||
{
|
{
|
||||||
/* Using new here since MEM_* funcs do not call ctor to properly initialize
|
/* Using new here since MEM_* funcs do not call ctor to properly initialize
|
||||||
* data. */
|
* data. */
|
||||||
ImportJobData *job = new ImportJobData();
|
ImportJobData *job = new ImportJobData();
|
||||||
job->bmain = CTX_data_main(C);
|
job->bmain = CTX_data_main(C);
|
||||||
job->scene = CTX_data_scene(C);
|
job->scene = CTX_data_scene(C);
|
||||||
|
job->import_ok = false;
|
||||||
BLI_strncpy(job->filename, filepath, 1024);
|
BLI_strncpy(job->filename, filepath, 1024);
|
||||||
|
|
||||||
job->settings.scale = scale;
|
job->settings.scale = scale;
|
||||||
@@ -853,6 +877,7 @@ void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
|
|||||||
|
|
||||||
G.is_break = false;
|
G.is_break = false;
|
||||||
|
|
||||||
|
if (as_background_job) {
|
||||||
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
|
wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
|
||||||
CTX_wm_window(C),
|
CTX_wm_window(C),
|
||||||
job->scene,
|
job->scene,
|
||||||
@@ -866,6 +891,17 @@ void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence
|
|||||||
WM_jobs_callbacks(wm_job, import_startjob, NULL, NULL, import_endjob);
|
WM_jobs_callbacks(wm_job, import_startjob, NULL, NULL, import_endjob);
|
||||||
|
|
||||||
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
WM_jobs_start(CTX_wm_manager(C), wm_job);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Fake a job context, so that we don't need NULL pointer checks while importing. */
|
||||||
|
short stop = 0, do_update = 0;
|
||||||
|
float progress = 0.f;
|
||||||
|
|
||||||
|
import_startjob(job, &stop, &do_update, &progress);
|
||||||
|
import_endjob(job);
|
||||||
|
}
|
||||||
|
|
||||||
|
return job->import_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
|
|||||||
.renderable_only = RNA_boolean_get(op->ptr, "renderable_only"),
|
.renderable_only = RNA_boolean_get(op->ptr, "renderable_only"),
|
||||||
.face_sets = RNA_boolean_get(op->ptr, "face_sets"),
|
.face_sets = RNA_boolean_get(op->ptr, "face_sets"),
|
||||||
.use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
|
.use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
|
||||||
|
.export_hair = RNA_boolean_get(op->ptr, "export_hair"),
|
||||||
|
.export_particles = RNA_boolean_get(op->ptr, "export_particles"),
|
||||||
.compression_type = RNA_enum_get(op->ptr, "compression_type"),
|
.compression_type = RNA_enum_get(op->ptr, "compression_type"),
|
||||||
.packuv = RNA_boolean_get(op->ptr, "packuv"),
|
.packuv = RNA_boolean_get(op->ptr, "packuv"),
|
||||||
.triangulate = RNA_boolean_get(op->ptr, "triangulate"),
|
.triangulate = RNA_boolean_get(op->ptr, "triangulate"),
|
||||||
@@ -131,15 +133,17 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
|
|||||||
.global_scale = RNA_float_get(op->ptr, "global_scale"),
|
.global_scale = RNA_float_get(op->ptr, "global_scale"),
|
||||||
};
|
};
|
||||||
|
|
||||||
ABC_export(CTX_data_scene(C), C, filename, ¶ms);
|
const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
|
||||||
|
bool ok = ABC_export(CTX_data_scene(C), C, filename, ¶ms, as_background_job);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
||||||
{
|
{
|
||||||
uiLayout *box;
|
uiLayout *box;
|
||||||
uiLayout *row;
|
uiLayout *row;
|
||||||
|
uiLayout *col;
|
||||||
|
|
||||||
#ifdef WITH_ALEMBIC_HDF5
|
#ifdef WITH_ALEMBIC_HDF5
|
||||||
box = uiLayoutBox(layout);
|
box = uiLayoutBox(layout);
|
||||||
@@ -231,6 +235,15 @@ static void ui_alembic_export_settings(uiLayout *layout, PointerRNA *imfptr)
|
|||||||
row = uiLayoutRow(box, false);
|
row = uiLayoutRow(box, false);
|
||||||
uiLayoutSetEnabled(row, triangulate);
|
uiLayoutSetEnabled(row, triangulate);
|
||||||
uiItemR(row, imfptr, "ngon_method", 0, NULL, ICON_NONE);
|
uiItemR(row, imfptr, "ngon_method", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
/* Object Data */
|
||||||
|
box = uiLayoutBox(layout);
|
||||||
|
row = uiLayoutRow(box, false);
|
||||||
|
uiItemL(row, IFACE_("Particle Systems:"), ICON_PARTICLE_DATA);
|
||||||
|
|
||||||
|
col = uiLayoutColumn(box, true);
|
||||||
|
uiItemR(col, imfptr, "export_hair", 0, NULL, ICON_NONE);
|
||||||
|
uiItemR(col, imfptr, "export_particles", 0, NULL, ICON_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wm_alembic_export_draw(bContext *C, wmOperator *op)
|
static void wm_alembic_export_draw(bContext *C, wmOperator *op)
|
||||||
@@ -348,6 +361,12 @@ void WM_OT_alembic_export(wmOperatorType *ot)
|
|||||||
RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_quad_method_items,
|
RNA_def_enum(ot->srna, "ngon_method", rna_enum_modifier_triangulate_quad_method_items,
|
||||||
MOD_TRIANGULATE_NGON_BEAUTY, "Polygon Method", "Method for splitting the polygons into triangles");
|
MOD_TRIANGULATE_NGON_BEAUTY, "Polygon Method", "Method for splitting the polygons into triangles");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "export_hair", 1, "Export Hair", "Exports hair particle systems as animated curves");
|
||||||
|
RNA_def_boolean(ot->srna, "export_particles", 1, "Export Particles", "Exports non-hair particle systems");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "as_background_job", true, "Run as Background Job",
|
||||||
|
"Enable this to run the import in the background, disable to block Blender while importing");
|
||||||
|
|
||||||
/* This dummy prop is used to check whether we need to init the start and
|
/* This dummy prop is used to check whether we need to init the start and
|
||||||
* end frame values to that of the scene's, otherwise they are reset at
|
* end frame values to that of the scene's, otherwise they are reset at
|
||||||
* every change, draw update. */
|
* every change, draw update. */
|
||||||
@@ -482,6 +501,7 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
|
|||||||
const bool is_sequence = RNA_boolean_get(op->ptr, "is_sequence");
|
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 set_frame_range = RNA_boolean_get(op->ptr, "set_frame_range");
|
||||||
const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
|
const bool validate_meshes = RNA_boolean_get(op->ptr, "validate_meshes");
|
||||||
|
const bool as_background_job = RNA_boolean_get(op->ptr, "as_background_job");
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
int sequence_len = 1;
|
int sequence_len = 1;
|
||||||
@@ -490,9 +510,11 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
|
|||||||
sequence_len = get_sequence_len(filename, &offset);
|
sequence_len = get_sequence_len(filename, &offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
ABC_import(C, filename, scale, is_sequence, set_frame_range, sequence_len, offset, validate_meshes);
|
bool ok = ABC_import(C, filename, scale, is_sequence, set_frame_range,
|
||||||
|
sequence_len, offset, validate_meshes,
|
||||||
|
as_background_job);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return as_background_job || ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WM_OT_alembic_import(wmOperatorType *ot)
|
void WM_OT_alembic_import(wmOperatorType *ot)
|
||||||
@@ -523,6 +545,9 @@ void WM_OT_alembic_import(wmOperatorType *ot)
|
|||||||
|
|
||||||
RNA_def_boolean(ot->srna, "is_sequence", false, "Is Sequence",
|
RNA_def_boolean(ot->srna, "is_sequence", false, "Is Sequence",
|
||||||
"Set to true if the cache is split into separate files");
|
"Set to true if the cache is split into separate files");
|
||||||
|
|
||||||
|
RNA_def_boolean(ot->srna, "as_background_job", true, "Run as Background Job",
|
||||||
|
"Enable this to run the export in the background, disable to block Blender while exporting");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -207,6 +207,8 @@ static void rna_Scene_alembic_export(
|
|||||||
int renderable_only,
|
int renderable_only,
|
||||||
int face_sets,
|
int face_sets,
|
||||||
int use_subdiv_schema,
|
int use_subdiv_schema,
|
||||||
|
int export_hair,
|
||||||
|
int export_particles,
|
||||||
int compression_type,
|
int compression_type,
|
||||||
int packuv,
|
int packuv,
|
||||||
float scale,
|
float scale,
|
||||||
@@ -240,6 +242,8 @@ static void rna_Scene_alembic_export(
|
|||||||
.renderable_only = renderable_only,
|
.renderable_only = renderable_only,
|
||||||
.face_sets = face_sets,
|
.face_sets = face_sets,
|
||||||
.use_subdiv_schema = use_subdiv_schema,
|
.use_subdiv_schema = use_subdiv_schema,
|
||||||
|
.export_hair = export_hair,
|
||||||
|
.export_particles = export_particles,
|
||||||
.compression_type = compression_type,
|
.compression_type = compression_type,
|
||||||
.packuv = packuv,
|
.packuv = packuv,
|
||||||
.triangulate = triangulate,
|
.triangulate = triangulate,
|
||||||
@@ -249,7 +253,7 @@ static void rna_Scene_alembic_export(
|
|||||||
.global_scale = scale,
|
.global_scale = scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
ABC_export(scene, C, filepath, ¶ms);
|
ABC_export(scene, C, filepath, ¶ms, true);
|
||||||
|
|
||||||
#ifdef WITH_PYTHON
|
#ifdef WITH_PYTHON
|
||||||
BPy_END_ALLOW_THREADS;
|
BPy_END_ALLOW_THREADS;
|
||||||
@@ -440,8 +444,9 @@ void RNA_api_scene(StructRNA *srna)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_ALEMBIC
|
#ifdef WITH_ALEMBIC
|
||||||
|
/* XXX Deprecated, will be removed in 2.8 in favour of calling the export operator. */
|
||||||
func = RNA_def_function(srna, "alembic_export", "rna_Scene_alembic_export");
|
func = RNA_def_function(srna, "alembic_export", "rna_Scene_alembic_export");
|
||||||
RNA_def_function_ui_description(func, "Export to Alembic file");
|
RNA_def_function_ui_description(func, "Export to Alembic file (deprecated, use the Alembic export operator)");
|
||||||
|
|
||||||
parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Alembic file");
|
parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Alembic file");
|
||||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||||
@@ -463,6 +468,8 @@ void RNA_api_scene(StructRNA *srna)
|
|||||||
RNA_def_boolean(func, "renderable_only" , 0, "Renderable objects only", "Export only objects marked renderable in the outliner");
|
RNA_def_boolean(func, "renderable_only" , 0, "Renderable objects only", "Export only objects marked renderable in the outliner");
|
||||||
RNA_def_boolean(func, "face_sets" , 0, "Facesets", "Export face sets");
|
RNA_def_boolean(func, "face_sets" , 0, "Facesets", "Export face sets");
|
||||||
RNA_def_boolean(func, "subdiv_schema", 0, "Use Alembic subdivision Schema", "Use Alembic subdivision Schema");
|
RNA_def_boolean(func, "subdiv_schema", 0, "Use Alembic subdivision Schema", "Use Alembic subdivision Schema");
|
||||||
|
RNA_def_boolean(func, "export_hair", 1, "Export Hair", "Exports hair particle systems as animated curves");
|
||||||
|
RNA_def_boolean(func, "export_particles", 1, "Export Particles", "Exports non-hair particle systems");
|
||||||
RNA_def_enum(func, "compression_type", rna_enum_abc_compression_items, 0, "Compression", "");
|
RNA_def_enum(func, "compression_type", rna_enum_abc_compression_items, 0, "Compression", "");
|
||||||
RNA_def_boolean(func, "packuv" , 0, "Export with packed UV islands", "Export with packed UV islands");
|
RNA_def_boolean(func, "packuv" , 0, "Export with packed UV islands", "Export with packed UV islands");
|
||||||
RNA_def_float(func, "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_float(func, "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);
|
||||||
|
|||||||
@@ -54,6 +54,10 @@ def with_tempdir(wrapped):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
class AbcPropError(Exception):
|
||||||
|
"""Raised when AbstractAlembicTest.abcprop() finds an error."""
|
||||||
|
|
||||||
|
|
||||||
class AbstractAlembicTest(unittest.TestCase):
|
class AbstractAlembicTest(unittest.TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
@@ -104,8 +108,7 @@ class AbstractAlembicTest(unittest.TestCase):
|
|||||||
def abcprop(self, filepath: pathlib.Path, proppath: str) -> dict:
|
def abcprop(self, filepath: pathlib.Path, proppath: str) -> dict:
|
||||||
"""Uses abcls to obtain compound property values from an Alembic object.
|
"""Uses abcls to obtain compound property values from an Alembic object.
|
||||||
|
|
||||||
A dict of subproperties is returned, where the values are just strings
|
A dict of subproperties is returned, where the values are Python values.
|
||||||
as returned by abcls.
|
|
||||||
|
|
||||||
The Python bindings for Alembic are old, and only compatible with Python 2.x,
|
The Python bindings for Alembic are old, and only compatible with Python 2.x,
|
||||||
so that's why we can't use them here, and have to rely on other tooling.
|
so that's why we can't use them here, and have to rely on other tooling.
|
||||||
@@ -122,7 +125,7 @@ class AbstractAlembicTest(unittest.TestCase):
|
|||||||
output = self.ansi_remove_re.sub(b'', coloured_output).decode('utf8')
|
output = self.ansi_remove_re.sub(b'', coloured_output).decode('utf8')
|
||||||
|
|
||||||
if proc.returncode:
|
if proc.returncode:
|
||||||
self.fail('Error %d running abcls:\n%s' % (proc.returncode, output))
|
raise AbcPropError('Error %d running abcls:\n%s' % (proc.returncode, output))
|
||||||
|
|
||||||
# Mapping from value type to callable that can convert a string to Python values.
|
# Mapping from value type to callable that can convert a string to Python values.
|
||||||
converters = {
|
converters = {
|
||||||
@@ -130,6 +133,7 @@ class AbstractAlembicTest(unittest.TestCase):
|
|||||||
'uint8_t': int,
|
'uint8_t': int,
|
||||||
'int16_t': int,
|
'int16_t': int,
|
||||||
'int32_t': int,
|
'int32_t': int,
|
||||||
|
'uint64_t': int,
|
||||||
'float64_t': float,
|
'float64_t': float,
|
||||||
'float32_t': float,
|
'float32_t': float,
|
||||||
}
|
}
|
||||||
@@ -302,6 +306,72 @@ class CurveExportTest(AbstractAlembicTest):
|
|||||||
self.assertEqual(abcprop['blender:resolution'], 10)
|
self.assertEqual(abcprop['blender:resolution'], 10)
|
||||||
|
|
||||||
|
|
||||||
|
class HairParticlesExportTest(AbstractAlembicTest):
|
||||||
|
"""Tests exporting with/without hair/particles.
|
||||||
|
|
||||||
|
Just a basic test to ensure that the enabling/disabling works, and that export
|
||||||
|
works at all. NOT testing the quality/contents of the exported file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _do_test(self, tempdir: pathlib.Path, export_hair: bool, export_particles: bool) -> pathlib.Path:
|
||||||
|
abc = tempdir / 'hair-particles.abc'
|
||||||
|
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
|
||||||
|
"renderable_only=True, visible_layers_only=True, flatten=False, " \
|
||||||
|
"export_hair=%r, export_particles=%r, as_background_job=False)" \
|
||||||
|
% (abc, export_hair, export_particles)
|
||||||
|
self.run_blender('hair-particles.blend', script)
|
||||||
|
return abc
|
||||||
|
|
||||||
|
@with_tempdir
|
||||||
|
def test_with_both(self, tempdir: pathlib.Path):
|
||||||
|
abc = self._do_test(tempdir, True, True)
|
||||||
|
|
||||||
|
abcprop = self.abcprop(abc, '/Suzanne/Hair system/.geom')
|
||||||
|
self.assertIn('nVertices', abcprop)
|
||||||
|
|
||||||
|
abcprop = self.abcprop(abc, '/Suzanne/Non-hair particle system/.geom')
|
||||||
|
self.assertIn('.velocities', abcprop)
|
||||||
|
|
||||||
|
abcprop = self.abcprop(abc, '/Suzanne/SuzanneShape/.geom')
|
||||||
|
self.assertIn('.faceIndices', abcprop)
|
||||||
|
|
||||||
|
@with_tempdir
|
||||||
|
def test_with_hair_only(self, tempdir: pathlib.Path):
|
||||||
|
abc = self._do_test(tempdir, True, False)
|
||||||
|
|
||||||
|
abcprop = self.abcprop(abc, '/Suzanne/Hair system/.geom')
|
||||||
|
self.assertIn('nVertices', abcprop)
|
||||||
|
|
||||||
|
self.assertRaises(AbcPropError, self.abcprop, abc,
|
||||||
|
'/Suzanne/Non-hair particle system/.geom')
|
||||||
|
|
||||||
|
abcprop = self.abcprop(abc, '/Suzanne/SuzanneShape/.geom')
|
||||||
|
self.assertIn('.faceIndices', abcprop)
|
||||||
|
|
||||||
|
@with_tempdir
|
||||||
|
def test_with_particles_only(self, tempdir: pathlib.Path):
|
||||||
|
abc = self._do_test(tempdir, False, True)
|
||||||
|
|
||||||
|
self.assertRaises(AbcPropError, self.abcprop, abc, '/Suzanne/Hair system/.geom')
|
||||||
|
|
||||||
|
abcprop = self.abcprop(abc, '/Suzanne/Non-hair particle system/.geom')
|
||||||
|
self.assertIn('.velocities', abcprop)
|
||||||
|
|
||||||
|
abcprop = self.abcprop(abc, '/Suzanne/SuzanneShape/.geom')
|
||||||
|
self.assertIn('.faceIndices', abcprop)
|
||||||
|
|
||||||
|
@with_tempdir
|
||||||
|
def test_with_neither(self, tempdir: pathlib.Path):
|
||||||
|
abc = self._do_test(tempdir, False, False)
|
||||||
|
|
||||||
|
self.assertRaises(AbcPropError, self.abcprop, abc, '/Suzanne/Hair system/.geom')
|
||||||
|
self.assertRaises(AbcPropError, self.abcprop, abc,
|
||||||
|
'/Suzanne/Non-hair particle system/.geom')
|
||||||
|
|
||||||
|
abcprop = self.abcprop(abc, '/Suzanne/SuzanneShape/.geom')
|
||||||
|
self.assertIn('.faceIndices', abcprop)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--blender', required=True)
|
parser.add_argument('--blender', required=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user