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:
authorBastien Montagne <montagne29@wanadoo.fr>2018-02-27 14:17:23 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2018-02-27 14:17:23 +0300
commitf9b2e4a16b1beb62afdcb6e910d7d4bc39950b20 (patch)
tree9b117c15199402a141d1eea61ff65662d2c4ecd5 /source/blender
parentfdd7b788ace22d5bdf4fc48fcc6ea5b90fd2a615 (diff)
parent6aadd61bd892d3908ed815171553a3c52144ec6c (diff)
Merge branch 'master' into soc-2017-normal-tools
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/blenkernel/intern/node.c1
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c54
-rw-r--r--source/blender/blenkernel/intern/smoke.c6
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c2
-rw-r--r--source/blender/blenlib/intern/storage.c2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c18
-rw-r--r--source/blender/collada/AnimationExporter.cpp616
-rw-r--r--source/blender/collada/AnimationExporter.h30
-rw-r--r--source/blender/collada/AnimationImporter.cpp1
-rw-r--r--source/blender/collada/ControllerExporter.cpp2
-rw-r--r--source/blender/collada/DocumentExporter.cpp28
-rw-r--r--source/blender/collada/DocumentExporter.h2
-rw-r--r--source/blender/collada/ExportSettings.h2
-rw-r--r--source/blender/collada/SceneExporter.cpp7
-rw-r--r--source/blender/collada/SceneExporter.h3
-rw-r--r--source/blender/collada/collada.cpp9
-rw-r--r--source/blender/collada/collada.h7
-rw-r--r--source/blender/collada/collada_utils.cpp35
-rw-r--r--source/blender/collada/collada_utils.h11
-rw-r--r--source/blender/editors/animation/anim_filter.c2
-rw-r--r--source/blender/editors/interface/interface_widgets.c1
-rw-r--r--source/blender/editors/io/io_collada.c41
-rw-r--r--source/blender/editors/space_graph/graph_utils.c4
-rw-r--r--source/blender/editors/space_node/drawnode.c25
-rw-r--r--source/blender/editors/space_node/node_draw.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c53
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c85
-rw-r--r--source/blender/gpu/GPU_select.h1
-rw-r--r--source/blender/gpu/intern/gpu_select.c23
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c21
-rw-r--r--source/blender/gpu/intern/gpu_select_private.h1
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp24
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c117
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c52
-rw-r--r--source/blender/nodes/CMakeLists.txt1
-rw-r--r--source/blender/nodes/NOD_shader.h1
-rw-r--r--source/blender/nodes/NOD_static_types.h1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_principled.c85
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_scatter.c2
-rw-r--r--source/blender/windowmanager/intern/wm_files.c4
45 files changed, 982 insertions, 420 deletions
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index c99da724794..6cd93e19e95 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 279
-#define BLENDER_SUBVERSION 2
+#define BLENDER_SUBVERSION 3
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 8a736c9952d..05ba3ac1df4 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -792,6 +792,7 @@ struct ShadeResult;
#define SH_NODE_BEVEL 197
#define SH_NODE_DISPLACEMENT 198
#define SH_NODE_VECTOR_DISPLACEMENT 199
+#define SH_NODE_VOLUME_PRINCIPLED 200
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 00f5f0f84b6..5d4b1ae8170 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3616,6 +3616,7 @@ static void registerShaderNodes(void)
register_node_type_sh_holdout();
register_node_type_sh_volume_absorption();
register_node_type_sh_volume_scatter();
+ register_node_type_sh_volume_principled();
register_node_type_sh_subsurface_scattering();
register_node_type_sh_mix_shader();
register_node_type_sh_add_shader();
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 81a5874ef4c..0561af8507d 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -1104,7 +1104,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* This is to address tricky issues with vertex-emitting when user tries (and expects) exact 1-1 vert/part
* distribution (see T47983 and its two example files). It allows us to consider pos as
* 'midpoint between v and v+1' (or 'p and p+1', depending whether we have more vertices than particles or not),
- * and avoid stumbling over float imprecisions in element_sum.
+ * and avoid stumbling over float impression in element_sum.
* Note: moved face and volume distribution to this as well (instead of starting at zero),
* for the same reasons, see T52682. */
pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index dc1c0da4401..5b36b0f9f84 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -972,20 +972,20 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
- wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, NULL);
+ wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, sds->clipping, NULL);
clip_grid = wt_density_grid;
if (fluid_fields & SM_ACTIVE_FIRE) {
- OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
}
if (fluid_fields & SM_ACTIVE_COLORS) {
- OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, wt_density_grid);
+ OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, sds->clipping, wt_density_grid);
}
- OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, wt_density_grid);
+ OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, sds->clipping, wt_density_grid);
}
if (sds->fluid) {
@@ -999,33 +999,33 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx);
OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt);
- const char *name = (!sds->wt) ? "density" : "density low";
- density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, NULL);
+ const char *name = (!sds->wt) ? "density" : "density_low";
+ density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, sds->clipping, NULL);
clip_grid = sds->wt ? clip_grid : density_grid;
- OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, NULL);
+ OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, sds->clipping, NULL);
if (fluid_fields & SM_ACTIVE_HEAT) {
- OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, clip_grid);
- OpenVDB_export_grid_fl(writer, "heat old", heatold, sds->res, sds->fluidmat, clip_grid);
+ OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, sds->clipping, clip_grid);
+ OpenVDB_export_grid_fl(writer, "heat_old", heatold, sds->res, sds->fluidmat, sds->clipping, clip_grid);
}
if (fluid_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame low";
- OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, density_grid);
- name = (!sds->wt) ? "fuel" : "fuel low";
- OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, density_grid);
- name = (!sds->wt) ? "react" : "react low";
- OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, density_grid);
+ name = (!sds->wt) ? "flame" : "flame_low";
+ OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, sds->clipping, density_grid);
+ name = (!sds->wt) ? "fuel" : "fuel_low";
+ OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, sds->clipping, density_grid);
+ name = (!sds->wt) ? "react" : "react_low";
+ OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, sds->clipping, density_grid);
}
if (fluid_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color low";
- OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, density_grid);
+ name = (!sds->wt) ? "color" : "color_low";
+ OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, sds->clipping, density_grid);
}
- OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, clip_grid);
- OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, NULL);
+ OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, sds->clipping, clip_grid);
+ OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, sds->clipping, NULL);
}
return 1;
@@ -1104,25 +1104,25 @@ static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_
OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res);
- const char *name = (!sds->wt) ? "density" : "density low";
+ const char *name = (!sds->wt) ? "density" : "density_low";
OpenVDB_import_grid_fl(reader, name, &dens, sds->res);
if (cache_fields & SM_ACTIVE_HEAT) {
OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res);
- OpenVDB_import_grid_fl(reader, "heat old", &heatold, sds->res);
+ OpenVDB_import_grid_fl(reader, "heat_old", &heatold, sds->res);
}
if (cache_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame low";
+ name = (!sds->wt) ? "flame" : "flame_low";
OpenVDB_import_grid_fl(reader, name, &flame, sds->res);
- name = (!sds->wt) ? "fuel" : "fuel low";
+ name = (!sds->wt) ? "fuel" : "fuel_low";
OpenVDB_import_grid_fl(reader, name, &fuel, sds->res);
- name = (!sds->wt) ? "react" : "react low";
+ name = (!sds->wt) ? "react" : "react_low";
OpenVDB_import_grid_fl(reader, name, &react, sds->res);
}
if (cache_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color low";
+ name = (!sds->wt) ? "color" : "color_low";
OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res);
}
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 3adba9fbce8..bf473603c0e 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -523,8 +523,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->burning_rate = 0.75f;
smd->domain->flame_smoke = 1.0f;
smd->domain->flame_vorticity = 0.5f;
- smd->domain->flame_ignition = 1.25f;
- smd->domain->flame_max_temp = 1.75f;
+ smd->domain->flame_ignition = 1.5f;
+ smd->domain->flame_max_temp = 3.0f;
/* color */
smd->domain->flame_smoke_color[0] = 0.7f;
smd->domain->flame_smoke_color[1] = 0.7f;
@@ -551,6 +551,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->coba = NULL;
smd->domain->coba_field = FLUID_FIELD_DENSITY;
+
+ smd->domain->clipping = 1e-3f;
}
else if (smd->type & MOD_SMOKE_TYPE_FLOW)
{
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index dd7def16ca8..106dd125575 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -189,7 +189,7 @@ void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
options->image1_mask = NULL;
}
-/* Peform tracking from a reference_marker to destination_ibuf.
+/* Perform tracking from a reference_marker to destination_ibuf.
* Uses marker as an initial position guess.
*
* Returns truth if tracker returned success, puts result
diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c
index c08329ef34f..f69b35ce5a9 100644
--- a/source/blender/blenlib/intern/storage.c
+++ b/source/blender/blenlib/intern/storage.c
@@ -185,7 +185,7 @@ size_t BLI_file_size(const char *path)
}
/**
- * Returns the st_mode from statting the specified path name, or 0 if it couldn't be statted
+ * Returns the st_mode from stat-ing the specified path name, or 0 if stat fails
* (most likely doesn't exist or no access).
*/
int BLI_exists(const char *name)
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index d27c1ce16d3..f1c40aae399 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1735,6 +1735,24 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
+ if (!MAIN_VERSION_ATLEAST(main, 279, 3)) {
+ if (!DNA_struct_elem_find(fd->filesdna, "SmokeDomainSettings", "float", "clipping")) {
+ Object *ob;
+ ModifierData *md;
+
+ for (ob = main->object.first; ob; ob = ob->id.next) {
+ for (md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_Smoke) {
+ SmokeModifierData *smd = (SmokeModifierData *)md;
+ if (smd->domain) {
+ smd->domain->clipping = 1e-3f;
+ }
+ }
+ }
+ }
+ }
+ }
+
{
/* Fix for invalid state of screen due to bug in older versions. */
for (bScreen *sc = main->screen.first; sc; sc = sc->id.next) {
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
index bd5cb05a1fa..3eefe84b214 100644
--- a/source/blender/collada/AnimationExporter.cpp
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -49,40 +49,270 @@ bool AnimationExporter::exportAnimations(Scene *sce)
return has_animations;
}
-// called for each exported object
+bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count)
+{
+ for (int i = 0; i < values.size(); i += channel_count) {
+ for (int j = 0; j < channel_count; j++) {
+ if (!bc_in_range(values[j], values[i+j], 0.000001))
+ return false;
+ }
+ }
+ return true;
+}
+/*
+ * This function creates a complete LINEAR Collada <Animation> Entry with all needed
+ * <source>, <sampler>, and <channel> entries.
+ * This is is used for creating sampled Transformation Animations for either:
+ *
+ * 1-axis animation:
+ * times contains the time points in seconds from within the timeline
+ * values contains the data (list of single floats)
+ * channel_count = 1
+ * axis_name = ['X' | 'Y' | 'Z']
+ * is_rot indicates if the animation is a rotation
+ *
+ * 3-axis animation:
+ * times contains the time points in seconds from within the timeline
+ * values contains the data (list of floats where each 3 entries are one vector)
+ * channel_count = 3
+ * axis_name = "" (actually not used)
+ * is_rot = false (see xxx below)
+ *
+ * xxx: I tried to create a 3 axis rotation animation
+ * like for translation or scale. But i could not
+ * figure out how to setup the channel for this case.
+ * So for now rotations are exported as 3 separate 1-axis collada animations
+ * See export_sampled_animation() further down.
+ */
+void AnimationExporter::create_sampled_animation(int channel_count,
+ std::vector<float> &times,
+ std::vector<float> &values,
+ std::string ob_name,
+ std::string label,
+ std::string axis_name,
+ bool is_rot)
+{
+ char anim_id[200];
+
+ if (is_flat_line(values, channel_count))
+ return;
+
+ BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str());
+
+ openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
+
+ /* create input source */
+ std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, times, false, anim_id, "");
+
+ /* create output source */
+ std::string output_id;
+ if (channel_count == 1)
+ output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str());
+ else if (channel_count == 3)
+ output_id = create_xyz_source(&values[0], times.size(), anim_id);
+ else if (channel_count == 16)
+ output_id = create_4x4_source(times, values, anim_id);
+
+ std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
+ COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
+ std::string empty;
+ sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
+
+ /* TODO create in/out tangents source (LINEAR) */
+ std::string interpolation_id = fake_interpolation_source(times.size(), anim_id, "");
+
+ /* Create Sampler */
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+ addSampler(sampler);
+
+ /* Create channel */
+ std::string target = translate_id(ob_name) + "/" + label + axis_name + ((is_rot) ? ".ANGLE" : "");
+ addChannel(COLLADABU::URI(empty, sampler_id), target);
+
+ closeAnimation();
+
+}
+
+/*
+ * Export all animation FCurves of an Object.
+ *
+ * Note: This uses the keyframes as sample points,
+ * and exports "baked keyframes" while keeping the tangent infromation
+ * of the FCurves intact. This works for simple cases, but breaks
+ * especially when negative scales are involved in the animation.
+ *
+ * If it is necessary to conserve the Animation precisely then
+ * use export_sampled_animation_set() instead.
+ */
+void AnimationExporter::export_keyframed_animation_set(Object *ob)
+{
+ FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
+ if (!fcu) {
+ return; /* object has no animation */
+ }
+
+ if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
+
+ std::vector<float> ctimes;
+ find_keyframes(ob, ctimes);
+ if (ctimes.size() > 0)
+ export_sampled_matrix_animation(ob, ctimes);
+ }
+ else {
+ char *transformName;
+ while (fcu) {
+ //for armature animations as objects
+ if (ob->type == OB_ARMATURE)
+ transformName = fcu->rna_path;
+ else
+ transformName = extract_transform_name(fcu->rna_path);
+
+ if (
+ STREQ(transformName, "location") ||
+ STREQ(transformName, "scale") ||
+ (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
+ STREQ(transformName, "rotation_quaternion"))
+ {
+ create_keyframed_animation(ob, fcu, transformName, false);
+ }
+ fcu = fcu->next;
+ }
+ }
+}
+
+/*
+ * Export the sampled animation of an Object.
+ *
+ * Note: This steps over all animation frames (step size is given in export_settings.sample_size)
+ * and then evaluates the transformation,
+ * and exports "baked samples" This works always, however currently the interpolation type is set
+ * to LINEAR for now. (maybe later this can be changed to BEZIER)
+ *
+ * Note: If it is necessary to keep the FCurves intact, then use export_keyframed_animation_set() instead.
+ * However be aware that exporting keyframed animation may modify the animation slightly.
+ * Also keyframed animation exports tend to break when negative scales are involved.
+ */
+void AnimationExporter::export_sampled_animation_set(Object *ob)
+{
+ std::vector<float>ctimes;
+ find_sampleframes(ob, ctimes);
+ if (ctimes.size() > 0) {
+ if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX)
+ export_sampled_matrix_animation(ob, ctimes);
+ else
+ export_sampled_transrotloc_animation(ob, ctimes);
+ }
+}
+
+void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes)
+{
+ UnitConverter converter;
+
+ std::vector<float> values;
+
+ for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) {
+ float fmat[4][4];
+ float outmat[4][4];
+
+ bc_update_scene(scene, *ctime);
+ BKE_object_matrix_local_get(ob, fmat);
+
+ converter.mat4_to_dae(outmat, fmat);
+
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(outmat, 6);
+
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ values.push_back(outmat[j][i]);
+ }
+
+ std::string ob_name = id_name(ob);
+
+ create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false);
+}
+
+void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes)
+{
+ static int LOC = 0;
+ static int EULX = 1;
+ static int EULY = 2;
+ static int EULZ = 3;
+ static int SCALE = 4;
+
+ std::vector<float> baked_curves[5];
+
+ for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) {
+ float fmat[4][4];
+ float floc[3];
+ float fquat[4];
+ float fsize[3];
+ float feul[3];
+
+ bc_update_scene(scene, *ctime);
+
+ BKE_object_matrix_local_get(ob, fmat);
+ mat4_decompose(floc, fquat, fsize, fmat);
+ quat_to_eul(feul, fquat);
+
+ baked_curves[LOC].push_back(floc[0]);
+ baked_curves[LOC].push_back(floc[1]);
+ baked_curves[LOC].push_back(floc[2]);
+
+ baked_curves[EULX].push_back(feul[0]);
+ baked_curves[EULY].push_back(feul[1]);
+ baked_curves[EULZ].push_back(feul[2]);
+
+ baked_curves[SCALE].push_back(fsize[0]);
+ baked_curves[SCALE].push_back(fsize[1]);
+ baked_curves[SCALE].push_back(fsize[2]);
+
+ }
+
+ std::string ob_name = id_name(ob);
+
+ create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale", "", false);
+ create_sampled_animation(3, ctimes, baked_curves[LOC], ob_name, "location", "", false);
+
+ /* Not sure how to export rotation as a 3channel animation,
+ * so separate into 3 single animations for now:
+ */
+
+ create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true);
+ create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true);
+ create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true);
+
+ fprintf(stdout, "Animation Export: Baked %d frames for %s (sampling rate: %d)\n",
+ (int)baked_curves[0].size(),
+ ob->id.name,
+ this->export_settings->sampling_rate);
+}
+
+/* called for each exported object */
void AnimationExporter::operator()(Object *ob)
{
- FCurve *fcu;
char *transformName;
+
/* bool isMatAnim = false; */ /* UNUSED */
//Export transform animations
if (ob->adt && ob->adt->action) {
- fcu = (FCurve *)ob->adt->action->curves.first;
- //transform matrix export for bones are temporarily disabled here.
if (ob->type == OB_ARMATURE) {
+ /* Export skeletal animation (if any)*/
bArmature *arm = (bArmature *)ob->data;
for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next)
write_bone_animation_matrix(ob, bone);
}
- while (fcu) {
- //for armature animations as objects
- if (ob->type == OB_ARMATURE)
- transformName = fcu->rna_path;
- else
- transformName = extract_transform_name(fcu->rna_path);
-
- if ((STREQ(transformName, "location") || STREQ(transformName, "scale")) ||
- (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) ||
- (STREQ(transformName, "rotation_quaternion")))
- {
- dae_animation(ob, fcu, transformName, false);
- }
- fcu = fcu->next;
+ /* Armatures can have object animation and skeletal animation*/
+ if (this->export_settings->sampling_rate < 1) {
+ export_keyframed_animation_set(ob);
+ }
+ else {
+ export_sampled_animation_set(ob);
}
-
}
export_object_constraint_animation(ob);
@@ -92,14 +322,14 @@ void AnimationExporter::operator()(Object *ob)
//Export Lamp parameter animations
if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
- fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
+ FCurve *fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
if ((STREQ(transformName, "color")) || (STREQ(transformName, "spot_size")) ||
(STREQ(transformName, "spot_blend")) || (STREQ(transformName, "distance")))
{
- dae_animation(ob, fcu, transformName, true);
+ create_keyframed_animation(ob, fcu, transformName, true);
}
fcu = fcu->next;
}
@@ -107,7 +337,7 @@ void AnimationExporter::operator()(Object *ob)
//Export Camera parameter animations
if ( (ob->type == OB_CAMERA) && ((Camera *)ob->data)->adt && ((Camera *)ob->data)->adt->action) {
- fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
+ FCurve *fcu = (FCurve *)(((Camera *)ob->data)->adt->action->curves.first);
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
@@ -116,7 +346,7 @@ void AnimationExporter::operator()(Object *ob)
(STREQ(transformName, "clip_end")) ||
(STREQ(transformName, "clip_start")))
{
- dae_animation(ob, fcu, transformName, true);
+ create_keyframed_animation(ob, fcu, transformName, true);
}
fcu = fcu->next;
}
@@ -128,7 +358,7 @@ void AnimationExporter::operator()(Object *ob)
if (!ma) continue;
if (ma->adt && ma->adt->action) {
/* isMatAnim = true; */
- fcu = (FCurve *)ma->adt->action->curves.first;
+ FCurve *fcu = (FCurve *)ma->adt->action->curves.first;
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
@@ -136,7 +366,7 @@ void AnimationExporter::operator()(Object *ob)
(STREQ(transformName, "diffuse_color")) || (STREQ(transformName, "alpha")) ||
(STREQ(transformName, "ior")))
{
- dae_animation(ob, fcu, transformName, true, ma);
+ create_keyframed_animation(ob, fcu, transformName, true, ma);
}
fcu = fcu->next;
}
@@ -167,7 +397,7 @@ void AnimationExporter::export_morph_animation(Object *ob)
while (fcu) {
transformName = extract_transform_name(fcu->rna_path);
- dae_animation(ob, fcu, transformName, true);
+ create_keyframed_animation(ob, fcu, transformName, true);
fcu = fcu->next;
}
@@ -200,7 +430,7 @@ void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<fl
obtar = ct->tar;
if (obtar)
- find_frames(obtar, frames);
+ find_keyframes(obtar, frames);
}
if (cti->flush_constraint_targets)
@@ -265,8 +495,8 @@ std::string AnimationExporter::getAnimationPathId(const FCurve *fcu)
return translate_id(rna_path);
}
-//convert f-curves to animation curves and write
-void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
+/* convert f-curves to animation curves and write */
+void AnimationExporter::create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma)
{
const char *axis_name = NULL;
char anim_id[200];
@@ -274,6 +504,8 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
bool has_tangents = false;
bool quatRotation = false;
+ Object *obj = NULL;
+
if (STREQ(transformName, "rotation_quaternion") ) {
fprintf(stderr, "quaternion rotation curves are not supported. rotation curve will not be exported\n");
quatRotation = true;
@@ -291,15 +523,26 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
axis_name = axis_names[fcu->array_index];
}
- //axis names for transforms
- else if (STREQ(transformName, "location") ||
- STREQ(transformName, "scale") ||
- STREQ(transformName, "rotation_euler") ||
- STREQ(transformName, "rotation_quaternion"))
+ /*
+ * Note: Handle transformation animations separately (to apply matrix inverse to fcurves)
+ * We will use the object to evaluate the animation on all keyframes and calculate the
+ * resulting object matrix. We need this to incorporate the
+ * effects of the parent inverse matrix (when it contains a rotation component)
+ *
+ * TODO: try to combine exported fcurves into 3 channel animations like done
+ * in export_sampled_animation(). For now each channel is exported as separate <Animation>.
+ */
+
+ else if (
+ STREQ(transformName, "scale") ||
+ STREQ(transformName, "location") ||
+ STREQ(transformName, "rotation_euler"))
{
const char *axis_names[] = {"X", "Y", "Z"};
- if (fcu->array_index < 3)
+ if (fcu->array_index < 3) {
axis_name = axis_names[fcu->array_index];
+ obj = ob;
+ }
}
else {
/* no axis name. single parameter */
@@ -308,7 +551,7 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
std::string ob_name = std::string("null");
- //Create anim Id
+ /* Create anim Id */
if (ob->type == OB_ARMATURE) {
ob_name = getObjectBoneName(ob, fcu);
BLI_snprintf(
@@ -357,7 +600,7 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id);
}
else {
- output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
+ output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name, obj);
}
// create interpolations source
@@ -369,10 +612,10 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
if (has_tangents) {
// create in_tangent source
- intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name);
+ intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name, obj);
// create out_tangent source
- outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name);
+ outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name, obj);
}
std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
@@ -475,8 +718,11 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B
if (!pchan)
return;
- //every inserted keyframe of bones.
- find_frames(ob_arm, fra);
+
+ if (this->export_settings->sampling_rate < 1)
+ find_keyframes(ob_arm, fra);
+ else
+ find_sampleframes(ob_arm, fra);
if (flag & ARM_RESTPOS) {
arm->flag &= ~ARM_RESTPOS;
@@ -755,14 +1001,60 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman
}
}
+// old function to keep compatibility for calls where offset and object are not needed
std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name)
{
- std::string source_id = anim_id + get_semantic_suffix(semantic);
+ return create_source_from_fcurve(semantic, fcu, anim_id, axis_name, NULL);
+}
- //bool is_angle = STREQ(fcu->rna_path, "rotation");
- bool is_angle = false;
+void AnimationExporter::evaluate_anim_with_constraints(Object *ob, float ctime)
+{
+ BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
+ ListBase *conlist = get_active_constraints(ob);
+ bConstraint *con;
+ for (con = (bConstraint *)conlist->first; con; con = con->next) {
+ ListBase targets = { NULL, NULL };
+
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+
+ if (cti && cti->get_constraint_targets) {
+ bConstraintTarget *ct;
+ Object *obtar;
+ cti->get_constraint_targets(con, &targets);
+ for (ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
+ obtar = ct->tar;
- if (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path,"spot_size")) is_angle = true;
+ if (obtar) {
+ BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
+ BKE_object_where_is_calc_time(scene, obtar, ctime);
+ }
+ }
+
+ if (cti->flush_constraint_targets)
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
+ }
+ BKE_object_where_is_calc_time(scene, ob, ctime);
+}
+
+/*
+ * ob is needed to aply parent inverse information to fcurve.
+ * TODO: Here we have to step over all keyframes for each object and for each fcurve.
+ * Instead of processing each fcurve one by one,
+ * step over the animation from keyframe to keyframe,
+ * then create adjusted fcurves (and entries) for all affected objects.
+ * Then we would need to step through the scene only once.
+ */
+std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob)
+{
+ std::string source_id = anim_id + get_semantic_suffix(semantic);
+
+ bool is_angle = (strstr(fcu->rna_path, "rotation") || strstr(fcu->rna_path, "spot_size"));
+ bool is_euler = strstr(fcu->rna_path, "rotation_euler");
+ bool is_translation = strstr(fcu->rna_path, "location");
+ bool is_scale = strstr(fcu->rna_path, "scale");
+ bool is_tangent = false;
+ int offset_index = 0;
COLLADASW::FloatSourceF source(mSW);
source.setId(source_id);
@@ -773,27 +1065,76 @@ std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemanti
case COLLADASW::InputSemantic::INPUT:
case COLLADASW::InputSemantic::OUTPUT:
source.setAccessorStride(1);
+ offset_index = 0;
break;
case COLLADASW::InputSemantic::IN_TANGENT:
case COLLADASW::InputSemantic::OUT_TANGENT:
source.setAccessorStride(2);
+ offset_index = 1;
+ is_tangent = true;
break;
default:
break;
}
-
COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
add_source_parameters(param, semantic, is_angle, axis_name, false);
source.prepareToAppendValues();
- for (unsigned int i = 0; i < fcu->totvert; i++) {
+ for (unsigned int frame_index = 0; frame_index < fcu->totvert; frame_index++) {
+ float fixed_val = 0;
+ if (ob) {
+ float fmat[4][4];
+ float frame = fcu->bezt[frame_index].vec[1][0];
+ float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
+
+ evaluate_anim_with_constraints(ob, ctime); // set object transforms to fcurve's i'th keyframe
+
+ BKE_object_matrix_local_get(ob, fmat);
+ float floc[3];
+ float fquat[4];
+ float fsize[3];
+ mat4_decompose(floc, fquat, fsize, fmat);
+
+ if (is_euler) {
+ float eul[3];
+ quat_to_eul(eul, fquat);
+ fixed_val = RAD2DEGF(eul[fcu->array_index]);
+ }
+ else if (is_translation) {
+ fixed_val = floc[fcu->array_index];
+ }
+ else if (is_scale) {
+ fixed_val = fsize[fcu->array_index];
+ }
+ }
+
float values[3]; // be careful!
+ float offset = 0;
int length = 0;
- get_source_values(&fcu->bezt[i], semantic, is_angle, values, &length);
- for (int j = 0; j < length; j++)
- source.appendValues(values[j]);
+ get_source_values(&fcu->bezt[frame_index], semantic, is_angle, values, &length);
+ if (is_tangent) {
+ float bases[3];
+ int len = 0;
+ get_source_values(&fcu->bezt[frame_index], COLLADASW::InputSemantic::OUTPUT, is_angle, bases, &len);
+ offset = values[offset_index] - bases[0];
+ }
+
+ for (int j = 0; j < length; j++) {
+ float val;
+ if (j == offset_index) {
+ if (ob) {
+ val = fixed_val + offset;
+ }
+ else {
+ val = values[j] + offset;
+ }
+ } else {
+ val = values[j];
+ }
+ source.appendValues(val);
+ }
}
source.finish();
@@ -837,9 +1178,9 @@ std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLA
return source_id;
}
-
-
-//Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified )
+/*
+ * only to get OUTPUT source values ( if rotation and hence the axis is also specified )
+ */
std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name)
{
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -869,7 +1210,10 @@ std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic
return source_id;
}
-// only used for sources with INPUT semantic
+
+/*
+ * only used for sources with INPUT semantic
+ */
std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name)
{
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -900,9 +1244,47 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti
return source_id;
}
+std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id)
+{
+ COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
+ std::string source_id = anim_id + get_semantic_suffix(semantic);
+
+ COLLADASW::Float4x4Source source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(ctimes.size());
+ source.setAccessorStride(16);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ add_source_parameters(param, semantic, false, NULL, true);
+
+ source.prepareToAppendValues();
+
+ std::vector<float>::iterator it;
+
+ for (it = values.begin(); it != values.end(); it+=16) {
+ float mat[4][4];
+
+ bc_copy_m4_farray(mat, &*it);
+
+ UnitConverter converter;
+ double outmat[4][4];
+ converter.mat4_to_dae_double(outmat, mat);
+
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(outmat, 6);
+
+ source.appendValues(outmat);
+ }
+
+ source.finish();
+ return source_id;
+}
std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id)
{
+ bool is_bone_animation = ob->type == OB_ARMATURE && bone;
+
COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -920,7 +1302,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
bPoseChannel *parchan = NULL;
bPoseChannel *pchan = NULL;
- if (ob->type == OB_ARMATURE && bone) {
+ if (is_bone_animation) {
bPose *pose = ob->pose;
pchan = BKE_pose_channel_find_name(pose, bone->name);
if (!pchan)
@@ -935,13 +1317,11 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
int j = 0;
for (it = frames.begin(); it != frames.end(); it++) {
float mat[4][4], ipar[4][4];
+ float frame = *it;
- float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
- CFRA = BKE_scene_frame_get_from_ctime(scene, *it);
- //BKE_scene_update_for_newframe(G.main->eval_ctx, G.main,scene,scene->lay);
- BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
-
- if (bone) {
+ float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
+ bc_update_scene(scene, ctime);
+ if (is_bone_animation) {
if (pchan->flag & POSE_CHAIN) {
enable_fcurves(ob->adt->action, NULL);
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
@@ -959,9 +1339,10 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
else
copy_m4_m4(mat, pchan->pose_mat);
- // OPEN_SIM_COMPATIBILITY
- // AFAIK animation to second life is via BVH, but no
- // reason to not have the collada-animation be correct
+ /* OPEN_SIM_COMPATIBILITY
+ * AFAIK animation to second life is via BVH, but no
+ * reason to not have the collada-animation be correct
+ */
if (export_settings->open_sim) {
float temp[4][4];
copy_m4_m4(temp, bone->arm_mat);
@@ -980,7 +1361,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
}
else {
- calc_ob_mat_at_time(ob, ctime, mat);
+ copy_m4_m4(mat, ob->obmat);
}
UnitConverter converter;
@@ -1008,7 +1389,9 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
}
-// only used for sources with OUTPUT semantic ( locations and scale)
+/*
+ * only used for sources with OUTPUT semantic ( locations and scale)
+ */
std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
{
COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
@@ -1192,8 +1575,10 @@ std::string AnimationExporter::get_camera_param_sid(char *rna_path, int tm_type,
return std::string("");
}
-// Assign sid of the animated parameter or transform
-// for rotation, axis name is always appended and the value of append_axis is ignored
+/*
+ * Assign sid of the animated parameter or transform for rotation,
+ * axis name is always appended and the value of append_axis is ignored
+ */
std::string AnimationExporter::get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
{
std::string tm_name;
@@ -1277,29 +1662,10 @@ char *AnimationExporter::extract_transform_name(char *rna_path)
return dot ? (dot + 1) : rna_path;
}
-//find keyframes of all the objects animations
-void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra)
-{
- if (ob->adt && ob->adt->action) {
- FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
-
- for (; fcu; fcu = fcu->next) {
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- float f = fcu->bezt[i].vec[1][0];
- if (std::find(fra.begin(), fra.end(), f) == fra.end())
- fra.push_back(f);
- }
- }
-
- // keep the keys in ascending order
- std::sort(fra.begin(), fra.end());
- }
-}
-
-
-
-// enable fcurves driving a specific bone, disable all the rest
-// if bone_name = NULL enable all fcurves
+/*
+ * enable fcurves driving a specific bone, disable all the rest
+ * if bone_name = NULL enable all fcurves
+ */
void AnimationExporter::enable_fcurves(bAction *act, char *bone_name)
{
FCurve *fcu;
@@ -1364,14 +1730,53 @@ bool AnimationExporter::hasAnimations(Scene *sce)
void AnimationExporter::find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
{
if (rotmode > 0)
- find_frames(ob, fra, prefix, "rotation_euler");
+ find_keyframes(ob, fra, prefix, "rotation_euler");
else if (rotmode == ROT_MODE_QUAT)
- find_frames(ob, fra, prefix, "rotation_quaternion");
+ find_keyframes(ob, fra, prefix, "rotation_quaternion");
/*else if (rotmode == ROT_MODE_AXISANGLE)
;*/
}
-void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
+/* Take care to always have the first frame and the last frame in the animation
+ * regardless of the sampling_rate setting
+ */
+void AnimationExporter::find_sampleframes(Object *ob, std::vector<float> &fra)
+{
+ int frame = scene->r.sfra;
+ do {
+ float ctime = BKE_scene_frame_get_from_ctime(scene, frame);
+ fra.push_back(ctime);
+ if (frame == scene->r.efra)
+ break;
+ frame += this->export_settings->sampling_rate;
+ if (frame > scene->r.efra)
+ frame = scene->r.efra; // make sure the last frame is always exported
+
+ } while (true);
+}
+
+/*
+ * find keyframes of all the objects animations
+ */
+void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra)
+{
+ if (ob->adt && ob->adt->action) {
+ FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
+
+ for (; fcu; fcu = fcu->next) {
+ for (unsigned int i = 0; i < fcu->totvert; i++) {
+ float f = fcu->bezt[i].vec[1][0];
+ if (std::find(fra.begin(), fra.end(), f) == fra.end())
+ fra.push_back(f);
+ }
+ }
+
+ // keep the keys in ascending order
+ std::sort(fra.begin(), fra.end());
+ }
+}
+
+void AnimationExporter::find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
{
if (ob->adt && ob->adt->action) {
FCurve *fcu = (FCurve *)ob->adt->action->curves.first;
@@ -1429,10 +1834,10 @@ void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bo
find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
break;
case 1:
- find_frames(ob_arm, fra, prefix, "scale");
+ find_keyframes(ob_arm, fra, prefix, "scale");
break;
case 2:
- find_frames(ob_arm, fra, prefix, "location");
+ find_keyframes(ob_arm, fra, prefix, "location");
break;
default:
return;
@@ -1539,8 +1944,23 @@ bool AnimationExporter::validateConstraints(bConstraint *con)
return valid;
}
-void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4])
+#if 0
+/*
+ * Needed for sampled animations.
+ * This function calculates the object matrix at a given time,
+ * also taking constraints into account.
+ *
+ * XXX: Why looking at the constraints here is necessary?
+ * Maybe this can be done better?
+ */
+void AnimationExporter::calc_obmat_at_time(Object *ob, float ctime )
{
+ BKE_scene_frame_set(scene, ctime);
+
+ Main *bmain = bc_get_main();
+ EvaluationContext *ev_context = bc_get_evaluation_context();
+ BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
+
ListBase *conlist = get_active_constraints(ob);
bConstraint *con;
for (con = (bConstraint *)conlist->first; con; con = con->next) {
@@ -1566,6 +1986,6 @@ void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[
}
}
BKE_object_where_is_calc_time(scene, ob, ctime);
- copy_m4_m4(mat, ob->obmat);
}
+#endif
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
index 4736361ad13..52b46353528 100644
--- a/source/blender/collada/AnimationExporter.h
+++ b/source/blender/collada/AnimationExporter.h
@@ -90,9 +90,11 @@ private:
public:
AnimationExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings):
- COLLADASW::LibraryAnimations(sw), export_settings(export_settings)
- { this->sw = sw; }
-
+ COLLADASW::LibraryAnimations(sw),
+ export_settings(export_settings)
+ {
+ this->sw = sw;
+ }
bool exportAnimations(Scene *sce);
@@ -102,7 +104,6 @@ public:
protected:
const ExportSettings *export_settings;
- void dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL);
void export_object_constraint_animation(Object *ob);
@@ -143,7 +144,18 @@ protected:
float* get_eul_source_for_quat(Object *ob );
+ bool is_flat_line(std::vector<float> &values, int channel_count);
+ void export_keyframed_animation_set(Object *ob);
+ void create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL);
+ void export_sampled_animation_set(Object *ob);
+ void export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes);
+ void export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes);
+ void create_sampled_animation(int channel_count, std::vector<float> &times, std::vector<float> &values, std::string, std::string label, std::string axis_name, bool is_rot);
+
+ void evaluate_anim_with_constraints(Object *ob, float ctime);
+
std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name);
+ std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name, Object *ob);
std::string create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id);
@@ -152,7 +164,7 @@ protected:
std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name);
std::string create_xyz_source(float *v, int tot, const std::string& anim_id);
-
+ std::string create_4x4_source(std::vector<float> &times, std::vector<float> &values, const std::string& anim_id);
std::string create_4x4_source(std::vector<float> &frames, Object * ob_arm, Bone *bone, const std::string& anim_id);
std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents);
@@ -164,8 +176,10 @@ protected:
std::string get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
std::string get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
- void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name);
- void find_frames(Object *ob, std::vector<float> &fra);
+ void find_keyframes(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name);
+ void find_keyframes(Object *ob, std::vector<float> &fra);
+ void find_sampleframes(Object *ob, std::vector<float> &fra);
+
void make_anim_frames_from_targets(Object *ob, std::vector<float> &frames );
@@ -186,6 +200,6 @@ protected:
bool validateConstraints(bConstraint *con);
- void calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]);
+ //void calc_obmat_at_time(Object *ob, float ctime);
};
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 95543b2dc18..bc91b94afd9 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -817,7 +817,6 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a
}
float rot[4], loc[3], scale[3];
- transpose_m4(mat);
bc_rotate_from_reference_quat(rot, qref, mat);
copy_qt_qt(qref, rot);
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index 5cd5e6d271a..4afe71f47ba 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -282,7 +282,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
}
if (oob_counter > 0) {
- fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %lu.\n",
+ fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n",
oob_counter, joint_index_by_def_index.size());
}
}
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index 957fec50e4b..2b5d5692871 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -181,7 +181,7 @@ static COLLADABU::NativeString make_temp_filepath(const char *name, const char *
// COLLADA allows this through multiple <channel>s in <animation>.
// For this to work, we need to know objects that use a certain action.
-int DocumentExporter::exportCurrentScene(Scene *sce)
+int DocumentExporter::exportCurrentScene(EvaluationContext *eval_ctx, Scene *sce)
{
PointerRNA sceneptr, unit_settings;
PropertyRNA *system; /* unused , *scale; */
@@ -302,29 +302,11 @@ int DocumentExporter::exportCurrentScene(Scene *sce)
SceneExporter se(writer, &arm_exporter, this->export_settings);
- // <library_animations>
- AnimationExporter ae(writer, this->export_settings);
-
-#if 0
- bool has_animations = ae.exportAnimations(sce);
- /* The following code seems to be an obsolete workaround
- Comment out until it proofs correct that we no longer need it.
- */
- if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) {
- // channels adressing <matrix> objects is not (yet) supported
- // So we force usage of <location>, <translation> and <scale>
- fprintf(stdout,
- "For animated Ojects we must use decomposed <matrix> elements,\n" \
- "Forcing usage of TransLocRot transformation type.");
- se.setExportTransformationType(BC_TRANSFORMATION_TYPE_TRANSROTLOC);
+ if (this->export_settings->include_animations) {
+ // <library_animations>
+ AnimationExporter ae(writer, this->export_settings);
+ ae.exportAnimations(sce);
}
- else {
- se.setExportTransformationType(this->export_settings->export_transformation_type);
- }
-#else
- ae.exportAnimations(sce);
- se.setExportTransformationType(this->export_settings->export_transformation_type);
-#endif
se.exportScene(sce);
// <scene>
diff --git a/source/blender/collada/DocumentExporter.h b/source/blender/collada/DocumentExporter.h
index 6e3c1ecd7cd..b2d8214212c 100644
--- a/source/blender/collada/DocumentExporter.h
+++ b/source/blender/collada/DocumentExporter.h
@@ -39,7 +39,7 @@ class DocumentExporter
{
public:
DocumentExporter(const ExportSettings *export_settings);
- int exportCurrentScene(Scene *sce);
+ int exportCurrentScene(EvaluationContext *eval_ctx, Scene *sce);
void exportScenes(const char *filename);
private:
const ExportSettings *export_settings;
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index 6d90edd2f67..73a101108a9 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -39,6 +39,8 @@ public:
bool include_armatures;
bool include_shapekeys;
bool deform_bones_only;
+ bool include_animations;
+ int sampling_rate;
bool active_uv_only;
BC_export_texture_type export_texture_type;
diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp
index 73945539931..5a0badf8d3a 100644
--- a/source/blender/collada/SceneExporter.cpp
+++ b/source/blender/collada/SceneExporter.cpp
@@ -38,11 +38,6 @@ SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm,
{
}
-void SceneExporter::setExportTransformationType(BC_export_transformation_type transformation_type)
-{
- this->transformation_type = transformation_type;
-}
-
void SceneExporter::exportScene(Scene *sce)
{
// <library_visual_scenes> <visual_scene>
@@ -138,7 +133,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
// for skinned mesh we write obmat in <bind_shape_matrix>
TransformWriter::add_node_transform_identity(colladaNode);
else {
- TransformWriter::add_node_transform_ob(colladaNode, ob, this->transformation_type);
+ TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings->export_transformation_type);
}
// <instance_geometry>
diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h
index c7c15dba2cb..b896b9abd8d 100644
--- a/source/blender/collada/SceneExporter.h
+++ b/source/blender/collada/SceneExporter.h
@@ -97,11 +97,8 @@ class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter,
public:
SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings);
void exportScene(Scene *sce);
- void setExportTransformationType(BC_export_transformation_type transformation_type);
private:
- BC_export_transformation_type transformation_type;
- // required for writeNodes() for bone-parented objects
friend class ArmatureExporter;
void exportHierarchy(Scene *sce);
void writeNodes(Object *ob, Scene *sce);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index 024bc4a4a5c..7f723aae710 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -67,7 +67,8 @@ int collada_import(bContext *C,
return 0;
}
-int collada_export(Scene *sce,
+int collada_export(EvaluationContext *eval_ctx,
+ Scene *sce,
const char *filepath,
int apply_modifiers,
@@ -78,6 +79,8 @@ int collada_export(Scene *sce,
int include_armatures,
int include_shapekeys,
int deform_bones_only,
+ int include_animations,
+ int sampling_rate,
int active_uv_only,
BC_export_texture_type export_texture_type,
@@ -103,6 +106,8 @@ int collada_export(Scene *sce,
export_settings.include_armatures = include_armatures != 0;
export_settings.include_shapekeys = include_shapekeys != 0;
export_settings.deform_bones_only = deform_bones_only != 0;
+ export_settings.include_animations = include_animations;
+ export_settings.sampling_rate = sampling_rate;
export_settings.active_uv_only = active_uv_only != 0;
export_settings.export_texture_type = export_texture_type;
@@ -139,7 +144,7 @@ int collada_export(Scene *sce,
}
DocumentExporter exporter(&export_settings);
- int status = exporter.exportCurrentScene(sce);
+ int status = exporter.exportCurrentScene(eval_ctx, sce);
BLI_linklist_free(export_settings.export_set, NULL);
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index d31f5a8ba62..09b46c1de58 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -32,6 +32,7 @@
extern "C" {
#endif
+#include "BKE_depsgraph.h"
#include "BLI_linklist.h"
#include "BLI_path_util.h"
#include "RNA_types.h"
@@ -51,6 +52,7 @@ typedef enum BC_export_texture_type {
BC_TEXTURE_TYPE_UV
} BC_export_texture_type;
+struct EvaluationContext;
struct bContext;
struct Scene;
@@ -67,7 +69,8 @@ int collada_import(struct bContext *C,
int keep_bind_info);
-int collada_export(struct Scene *sce,
+int collada_export(struct EvaluationContext *eval_ctx,
+ struct Scene *sce,
const char *filepath,
int apply_modifiers,
BC_export_mesh_type export_mesh_type,
@@ -77,6 +80,8 @@ int collada_export(struct Scene *sce,
int include_armatures,
int include_shapekeys,
int deform_bones_only,
+ int include_animations,
+ int sampling_rate,
int active_uv_only,
BC_export_texture_type export_texture_type,
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 415daccfa3d..fcd92e220c0 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -53,6 +53,7 @@ extern "C" {
#include "BKE_mesh.h"
#include "BKE_scene.h"
#include "BKE_DerivedMesh.h"
+#include "BKE_main.h"
#include "ED_armature.h"
@@ -132,6 +133,25 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space)
return true;
}
+Main *bc_get_main()
+{
+ return G.main;
+}
+
+EvaluationContext *bc_get_evaluation_context()
+{
+ Main *bmain = G.main;
+ return bmain->eval_ctx;
+}
+
+void bc_update_scene(Scene *scene, float ctime)
+{
+ BKE_scene_frame_set(scene, ctime);
+ Main *bmain = bc_get_main();
+ EvaluationContext *ev_context = bc_get_evaluation_context();
+ BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay);
+}
+
Object *bc_add_object(Scene *scene, int type, const char *name)
{
Object *ob = BKE_object_add_only_object(G.main, type, name);
@@ -871,6 +891,21 @@ void bc_sanitize_mat(double mat[4][4], int precision)
mat[i][j] = double_round(mat[i][j], precision);
}
+void bc_copy_m4_farray(float r[4][4], float *a)
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ r[i][j] = *a++;
+}
+
+void bc_copy_farray_m4(float *r, float a[4][4])
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ *r++ = a[i][j];
+
+}
+
/*
* Returns name of Active UV Layer or empty String if no active UV Layer defined.
* Assuming the Object is of type MESH
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index e9066d7db46..0069b4d4871 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -63,6 +63,10 @@ extern "C" {
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureArrayMap;
+extern Main *bc_get_main();
+extern EvaluationContext *bc_get_evaluation_context();
+extern void bc_update_scene(Scene *scene, float ctime);
+
extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index);
extern int bc_test_parent_loop(Object *par, Object *ob);
extern int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space = true);
@@ -99,6 +103,13 @@ extern bool bc_is_leaf_bone(Bone *bone);
extern EditBone *bc_get_edit_bone(bArmature * armature, char *name);
extern int bc_set_layer(int bitfield, int layer, bool enable);
extern int bc_set_layer(int bitfield, int layer);
+
+inline bool bc_in_range(float a, float b, float range) {
+ return fabsf(a - b) < range;
+}
+void bc_copy_m4_farray(float r[4][4], float *a);
+void bc_copy_farray_m4(float *r, float a[4][4]);
+
extern void bc_sanitize_mat(float mat[4][4], int precision);
extern void bc_sanitize_mat(double mat[4][4], int precision);
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 0d51dc8dc76..aa31458aa5b 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -114,7 +114,7 @@ static void animedit_get_yscale_factor(bAnimContext *ac)
/* grab scale factor directly from action editor setting
* NOTE: This theme setting doesn't have an ID, as it cannot be accessed normally
- * since it is a float, and the theem settings methods can only handle chars.
+ * since it is a float, and the theme settings methods can only handle chars.
*/
ac->yscale_fac = btheme->tact.keyframe_scale_fac;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index b25e1130c60..9a1d47e0154 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1555,6 +1555,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
rcti temp = *rect;
temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1;
widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, false);
+ rect->xmax = temp.xmin;
}
/* If there's an icon too (made with uiDefIconTextBut) then draw the icon
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index 39065606201..8826dc2971d 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -36,6 +36,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
@@ -87,6 +88,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int include_shapekeys;
int deform_bones_only;
+ int include_animations;
+ int sample_animations;
+ int sampling_rate;
+
int export_texture_type;
int use_texture_copies;
int active_uv_only;
@@ -136,6 +141,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
include_children = RNA_boolean_get(op->ptr, "include_children");
include_armatures = RNA_boolean_get(op->ptr, "include_armatures");
include_shapekeys = RNA_boolean_get(op->ptr, "include_shapekeys");
+
+ include_animations = RNA_boolean_get(op->ptr, "include_animations");
+ sample_animations = RNA_boolean_get(op->ptr, "sample_animations");
+ sampling_rate = (sample_animations)? RNA_int_get(op->ptr, "sampling_rate") : 0;
+
deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only");
export_texture_type = RNA_enum_get(op->ptr, "export_texture_type_selection");
@@ -155,8 +165,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
/* get editmode results */
ED_object_editmode_load(CTX_data_edit_object(C));
+ EvaluationContext *eval_ctx = G.main->eval_ctx;
+ Scene *scene = CTX_data_scene(C);
- export_count = collada_export(CTX_data_scene(C),
+ export_count = collada_export(eval_ctx,
+ scene,
filepath,
apply_modifiers,
export_mesh_type,
@@ -165,6 +178,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
include_armatures,
include_shapekeys,
deform_bones_only,
+ include_animations,
+ sampling_rate,
active_uv_only,
export_texture_type,
@@ -200,6 +215,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
{
uiLayout *box, *row, *col, *split;
+ bool include_animations = RNA_boolean_get(imfptr, "include_animations");
/* Export Options: */
box = uiLayoutBox(layout);
@@ -229,6 +245,16 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "include_animations", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ if (include_animations) {
+ uiItemR(row, imfptr, "sample_animations", 0, NULL, ICON_NONE);
+ row = uiLayoutColumn(box, false);
+ uiItemR(row, imfptr, "sampling_rate", 0, NULL, ICON_NONE);
+ uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "sample_animations"));
+ }
+
/* Texture options */
box = uiLayoutBox(layout);
row = uiLayoutRow(box, false);
@@ -251,6 +277,7 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "deform_bones_only", 0, NULL, ICON_NONE);
+
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "open_sim", 0, NULL, ICON_NONE);
@@ -270,7 +297,6 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
uiItemL(split, IFACE_("Transformation Type"), ICON_NONE);
uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE);
-
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
@@ -366,7 +392,16 @@ void WM_OT_collada_export(wmOperatorType *ot)
"Export all Shape Keys from Mesh Objects");
RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only",
- "Only export deforming bones with armatures");
+ "Only export deforming bones with armatures");
+
+ RNA_def_boolean(func, "include_animations", false,
+ "Include Animations", "Export Animations if available.\nExporting Animations will enforce the decomposition of node transforms\ninto <translation> <rotation> and <scale> components");
+
+ RNA_def_boolean(func, "sample_animations", 0,
+ "Sample Animations", "Auto-generate keyframes with a frame distance set by 'Sampling Rate'.\nWhen disabled, export only the keyframes defined in the animation f-curves (may be less accurate)");
+
+ RNA_def_int(func, "sampling_rate", 1, 1, INT_MAX,
+ "Sampling Rate", "The distance between 2 keyframes. 1 means: Every frame is keyed", 1, INT_MAX);
RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
"Export only the selected UV Map");
diff --git a/source/blender/editors/space_graph/graph_utils.c b/source/blender/editors/space_graph/graph_utils.c
index 0e56dc817e4..907f346c931 100644
--- a/source/blender/editors/space_graph/graph_utils.c
+++ b/source/blender/editors/space_graph/graph_utils.c
@@ -171,8 +171,8 @@ int graphop_editable_keyframes_poll(bContext *C)
/* editable curves must fulfill the following criteria:
* - it has bezier keyframes
- * - it must not be protected from editing (this is already checked for with the foredit flag
- * - F-Curve modifiers do not interfere with the result too much
+ * - it must not be protected from editing (this is already checked for with the edit flag
+ * - F-Curve modifiers do not interfere with the result too much
* (i.e. the modifier-control drawing check returns false)
*/
if (fcu->bezt == NULL)
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 9d873795eaf..5665a5cff2d 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -3048,7 +3048,7 @@ static const float std_node_socket_colors[][4] = {
{0.70, 0.65, 0.19, 1.0}, /* SOCK_BOOLEAN */
{0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */
{0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */
- {1.0, 1.0, 1.0, 1.0}, /* SOCK_STRING */
+ {0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */
};
/* common color callbacks for standard types */
@@ -3135,20 +3135,11 @@ static void std_node_socket_draw(bContext *C, uiLayout *layout, PointerRNA *ptr,
uiTemplateComponentMenu(layout, ptr, "default_value", text);
break;
case SOCK_RGBA:
- {
- uiLayout *row = uiLayoutRow(layout, false);
- uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
- /* draw the socket name right of the actual button */
- uiItemR(row, ptr, "default_value", 0, "", 0);
- uiItemL(row, text, 0);
- break;
- }
case SOCK_STRING:
{
- uiLayout *row = uiLayoutRow(layout, true);
- /* draw the socket name right of the actual button */
- uiItemR(row, ptr, "default_value", 0, "", 0);
+ uiLayout *row = uiLayoutSplit(layout, 0.5f, false);
uiItemL(row, text, 0);
+ uiItemR(row, ptr, "default_value", 0, "", 0);
break;
}
default:
@@ -3182,11 +3173,6 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
break;
}
- case SOCK_BOOLEAN:
- {
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- break;
- }
case SOCK_VECTOR:
{
uiLayout *row;
@@ -3196,11 +3182,8 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout
uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0);
break;
}
+ case SOCK_BOOLEAN:
case SOCK_RGBA:
- {
- uiItemR(layout, ptr, "default_value", 0, NULL, 0);
- break;
- }
case SOCK_STRING:
{
uiItemR(layout, ptr, "default_value", 0, NULL, 0);
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index d7119302611..e56a3a549fc 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -354,6 +354,8 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
dy -= NODE_DYS / 2;
/* output sockets */
+ bool add_output_space = false;
+
for (nsock = node->outputs.first; nsock; nsock = nsock->next) {
if (nodeSocketIsHidden(nsock))
continue;
@@ -386,6 +388,12 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
dy = buty;
if (nsock->next)
dy -= NODE_SOCKDY;
+
+ add_output_space = true;
+ }
+
+ if (add_output_space) {
+ dy -= NODE_DY / 4;
}
node->prvr.xmin = locx + NODE_DYS;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index f999fab88ac..94c7ff5a051 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -1555,8 +1555,10 @@ ImBuf *ED_view3d_backbuf_read(ViewContext *vc, int xmin, int ymin, int xmax, int
}
}
-/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-unsigned int ED_view3d_backbuf_sample_rect(
+/**
+ * Smart function to sample a rectangle spiral ling outside, nice for backbuf selection
+ */
+uint ED_view3d_backbuf_sample_rect(
ViewContext *vc, const int mval[2], int size,
unsigned int min, unsigned int max, float *r_dist)
{
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 82c239eb320..68c35115584 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -916,61 +916,8 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot)
WM_operator_properties_gesture_lasso_select(ot);
}
-
-/* ************************************************* */
-
-#if 0
-/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo)
-{
- Base *base;
- unsigned int *bufmin, *bufmax;
- int a, b, rc, tel, len, dirvec[4][2], maxob;
- unsigned int retval = 0;
-
- base = LASTBASE;
- if (base == 0) return 0;
- maxob = base->selcol;
-
- len = (size - 1) / 2;
- rc = 0;
-
- dirvec[0][0] = 1;
- dirvec[0][1] = 0;
- dirvec[1][0] = 0;
- dirvec[1][1] = -size;
- dirvec[2][0] = -1;
- dirvec[2][1] = 0;
- dirvec[3][0] = 0;
- dirvec[3][1] = size;
-
- bufmin = buf;
- bufmax = buf + size * size;
- buf += len * size + len;
-
- for (tel = 1; tel <= size; tel++) {
-
- for (a = 0; a < 2; a++) {
- for (b = 0; b < tel; b++) {
-
- if (*buf && *buf <= maxob && *buf != dontdo) return *buf;
- if (*buf == dontdo) retval = dontdo; /* if only color dontdo is available, still return dontdo */
-
- buf += (dirvec[rc][0] + dirvec[rc][1]);
-
- if (buf < bufmin || buf >= bufmax) return retval;
- }
- rc++;
- rc &= 3;
- }
- }
- return retval;
-}
-#endif
-
/* ************************** mouse select ************************* */
-
/* The max number of menu items in an object select menu */
typedef struct SelMenuItemF {
char idname[MAX_ID_NAME - 2];
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 928a0fc7d1e..bf5a06f0a1c 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -336,6 +336,21 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist
/*************** visibility and selection utilities **************/
+static void uvedit_vertex_select_tagged(BMEditMesh *em, Scene *scene, bool select, int cd_loop_uv_offset)
+{
+ BMFace *efa;
+ BMLoop *l;
+ BMIter iter, liter;
+
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ }
+ }
+ }
+}
+
bool uvedit_face_visible_nolocal(Scene *scene, BMFace *efa)
{
ToolSettings *ts = scene->toolsettings;
@@ -1366,9 +1381,7 @@ static int uv_select_more_less(bContext *C, const bool select)
if (ts->uv_selectmode == UV_SELECT_FACE) {
/* clear tags */
- BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- }
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
/* mark loops to be selected */
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
@@ -1570,9 +1583,7 @@ static void uv_weld_align(bContext *C, int tool)
BMIter iter, liter, eiter;
/* clear tag */
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(eve, BM_ELEM_TAG);
- }
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
/* tag verts with a selected UV */
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
@@ -2692,12 +2703,8 @@ static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
/* Tag all verts as untouched, then touch the ones that have a face center
* in the loop and select all MLoopUV's that use a touched vert. */
- BMVert *eve;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(eve, BM_ELEM_TAG);
- }
-
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2783,11 +2790,7 @@ static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object
if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) {
/* Tag all verts as untouched, then touch the ones that have a face center
* in the loop and select all MLoopUV's that use a touched vert. */
- BMVert *eve;
-
- BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(eve, BM_ELEM_TAG);
- }
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2911,7 +2914,8 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
else {
/* other selection modes */
changed = true;
-
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (!uvedit_face_visible_test(scene, ima, efa, tf))
@@ -2924,15 +2928,21 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
/* UV_SYNC_SELECTION - can't do pinned selection */
if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
}
}
else if (pinned) {
if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) {
uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
}
}
}
}
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
}
if (changed) {
@@ -2982,19 +2992,6 @@ static int uv_inside_circle(const float uv[2], const float offset[2], const floa
return ((x * x + y * y) < 1.0f);
}
-static bool uv_select_inside_ellipse(BMEditMesh *em, Scene *scene, const bool select,
- const float offset[2], const float ellipse[2], BMLoop *l, MLoopUV *luv,
- const int cd_loop_uv_offset)
-{
- if (uv_inside_circle(luv->uv, offset, ellipse)) {
- uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
- return true;
- }
- else {
- return false;
- }
-}
-
static int uv_circle_select_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C);
@@ -3054,12 +3051,22 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
}
}
else {
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- changed |= uv_select_inside_ellipse(em, scene, select, offset, ellipse, l, luv, cd_loop_uv_offset);
+ if (uv_inside_circle(luv->uv, offset, ellipse)) {
+ changed = true;
+ uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
+ }
}
}
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
}
if (changed) {
@@ -3152,6 +3159,8 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
}
}
else { /* Vert Sel */
+ BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
@@ -3166,11 +3175,16 @@ static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short mo
{
uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset);
changed = true;
+ BM_elem_flag_enable(l->v, BM_ELEM_TAG);
}
}
}
}
}
+
+ if (sima->sticky == SI_STICKY_VERTEX) {
+ uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
+ }
}
if (changed) {
@@ -4168,17 +4182,14 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *loop;
BMIter iter, liter;
- bool clear = RNA_boolean_get(op->ptr, "clear");
+ bool flag_set = !RNA_boolean_get(op->ptr, "clear");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) {
- if (clear)
- BM_elem_flag_disable(loop->e, BM_ELEM_SEAM);
- else
- BM_elem_flag_enable(loop->e, BM_ELEM_SEAM);
+ BM_elem_flag_set(loop->e, BM_ELEM_SEAM, flag_set);
}
}
}
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index cf5b8bf7d8f..53f480bccd7 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -47,6 +47,7 @@ enum {
void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const struct rcti *input, char mode, int oldhits);
bool GPU_select_load_id(unsigned int id);
+void GPU_select_finalize(void);
unsigned int GPU_select_end(void);
bool GPU_select_query_check_active(void);
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 632b0cfee1b..e2837d96b0f 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -150,6 +150,29 @@ bool GPU_select_load_id(unsigned int id)
}
/**
+ * Needed when GL context of #GPU_select_end
+ * can't be used to finalize selection operations
+ * (because of context changes).
+ */
+void GPU_select_finalize(void)
+{
+ if (!g_select_state.select_is_active)
+ return;
+
+ switch (g_select_state.algorithm) {
+ case ALGO_GL_LEGACY:
+ case ALGO_GL_QUERY:
+ {
+ break;
+ }
+ default: /* ALGO_GL_PICK */
+ {
+ gpu_select_pick_finalize();
+ }
+ }
+}
+
+/**
* Cleanup and flush selection results to buffer.
* Return number of hits and hits in buffer.
* if \a dopass is true, we will do a second pass with occlusion queries to get the closest hit.
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
index 0a77420fa25..bd6b43ee42f 100644
--- a/source/blender/gpu/intern/gpu_select_pick.c
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -255,6 +255,7 @@ typedef struct GPUPickState {
/* Set after first draw */
bool is_init;
+ bool is_finalized;
unsigned int prev_id;
} gl;
@@ -366,6 +367,7 @@ void gpu_select_pick_begin(
#endif
ps->gl.is_init = false;
+ ps->gl.is_finalized = false;
ps->gl.prev_id = 0;
}
else {
@@ -526,6 +528,20 @@ bool gpu_select_pick_load_id(unsigned int id)
return true;
}
+ /**
+ * (Optional), call before 'gpu_select_pick_end' if GL context is not kept.
+ * is not compatible with regular select case.
+ * */
+void gpu_select_pick_finalize(void)
+{
+ GPUPickState *ps = &g_pick_state;
+ if (ps->gl.is_init) {
+ /* force finishing last pass */
+ gpu_select_pick_load_id(ps->gl.prev_id);
+ }
+ ps->gl.is_finalized = true;
+}
+
unsigned int gpu_select_pick_end(void)
{
GPUPickState *ps = &g_pick_state;
@@ -535,9 +551,8 @@ unsigned int gpu_select_pick_end(void)
#endif
if (ps->is_cached == false) {
- if (ps->gl.is_init) {
- /* force finishing last pass */
- gpu_select_pick_load_id(ps->gl.prev_id);
+ if (ps->gl.is_finalized == false) {
+ gpu_select_pick_finalize();
}
glPopAttrib();
diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h
index 8935bd7b253..8368aaa9edc 100644
--- a/source/blender/gpu/intern/gpu_select_private.h
+++ b/source/blender/gpu/intern/gpu_select_private.h
@@ -35,6 +35,7 @@
/* gpu_select_pick */
void gpu_select_pick_begin(unsigned int (*buffer)[4], unsigned int bufsize, const rcti *input, char mode);
bool gpu_select_pick_load_id(unsigned int id);
+void gpu_select_pick_finalize(void);
unsigned int gpu_select_pick_end(void);
void gpu_select_pick_cache_begin(void);
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index 539b9fa45b4..4cb1c13a44a 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -1290,7 +1290,7 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
return 1;
}
- /* last token is single character channel identifier */
+ /* last token is channel identifier */
len = imb_exr_split_token(name, end, &token);
if (len == 0) {
printf("multilayer read: bad channel name: %s\n", name);
@@ -1319,10 +1319,30 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa
ok = true;
}
}
+ else if (BLI_strcaseeq(token, "red")) {
+ echan->chan_id = 'R';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "green")) {
+ echan->chan_id = 'G';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "blue")) {
+ echan->chan_id = 'B';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "alpha")) {
+ echan->chan_id = 'A';
+ ok = true;
+ }
+ else if (BLI_strcaseeq(token, "depth")) {
+ echan->chan_id = 'Z';
+ ok = true;
+ }
if (ok == false) {
BLI_strncpy(tokenbuf, token, std::min(len + 1, EXR_TOT_MAXNAME));
- printf("multilayer read: channel token too long: %s\n", tokenbuf);
+ printf("multilayer read: unknown channel token: %s\n", tokenbuf);
return 0;
}
}
diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h
index 9932e16e988..c1565bde882 100644
--- a/source/blender/makesdna/DNA_smoke_types.h
+++ b/source/blender/makesdna/DNA_smoke_types.h
@@ -217,6 +217,9 @@ typedef struct SmokeDomainSettings {
char use_coba;
char coba_field; /* simulation field used for the color mapping */
char pad2;
+
+ float clipping;
+ float pad3;
} SmokeDomainSettings;
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index 0f22f8d3b0f..3043e636b31 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -262,63 +262,6 @@ static void rna_Scene_alembic_export(
#endif
-#ifdef WITH_COLLADA
-/* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
-#include "../../collada/collada.h"
-
-/* Note: This definition must match to the generated function call */
-static void rna_Scene_collada_export(
- Scene *scene,
- const char *filepath,
- int apply_modifiers,
-
- int export_mesh_type,
- int selected,
- int include_children,
- int include_armatures,
- int include_shapekeys,
- int deform_bones_only,
- int active_uv_only,
- int export_texture_type,
- int use_texture_copies,
- int triangulate,
- int use_object_instantiation,
- int use_blender_profile,
- int sort_by_name,
- int export_transformation_type,
- int open_sim,
- int limit_precision,
- int keep_bind_info)
-{
- collada_export(scene,
- filepath,
-
- apply_modifiers,
- export_mesh_type,
-
- selected,
- include_children,
- include_armatures,
- include_shapekeys,
- deform_bones_only,
-
- active_uv_only,
- export_texture_type,
- use_texture_copies,
-
- triangulate,
- use_object_instantiation,
- use_blender_profile,
- sort_by_name,
-
- export_transformation_type,
- open_sim,
- limit_precision,
- keep_bind_info);
-}
-
-#endif
-
#else
void RNA_api_scene(StructRNA *srna)
@@ -374,66 +317,6 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_function_output(func, parm);
-#ifdef WITH_COLLADA
- /* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
- func = RNA_def_function(srna, "collada_export", "rna_Scene_collada_export");
- parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Collada file");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */
-
- RNA_def_boolean(func, "apply_modifiers", false,
- "Apply Modifiers", "Apply modifiers to exported mesh (non destructive))");
-
- RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX,
- "Resolution", "Modifier resolution for export", INT_MIN, INT_MAX);
-
- RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements");
-
- RNA_def_boolean(func, "include_children", false,
- "Include Children", "Export all children of selected objects (even if not selected)");
-
- RNA_def_boolean(func, "include_armatures", false,
- "Include Armatures", "Export related armatures (even if not selected)");
-
- RNA_def_boolean(func, "include_shapekeys", true, "Include Shape Keys", "Export all Shape Keys from Mesh Objects");
-
- RNA_def_boolean(func, "deform_bones_only", false,
- "Deform Bones only", "Only export deforming bones with armatures");
-
- RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map");
-
- RNA_def_int(func, "export_texture_type", 0, INT_MIN, INT_MAX,
- "Texture Type", "Type for exported Textures (UV or MAT)", INT_MIN, INT_MAX);
-
- RNA_def_boolean(func, "use_texture_copies", true,
- "Copy", "Copy textures to same folder where the .dae file is exported");
-
- RNA_def_boolean(func, "triangulate", true, "Triangulate", "Export Polygons (Quads & NGons) as Triangles");
-
- RNA_def_boolean(func, "use_object_instantiation", true,
- "Use Object Instances", "Instantiate multiple Objects from same Data");
-
- RNA_def_boolean(func, "use_blender_profile", true, "Use Blender Profile",
- "Export additional Blender specific information (for material, shaders, bones, etc.)");
-
- RNA_def_boolean(func, "sort_by_name", false, "Sort by Object name", "Sort exported data by Object name");
-
- RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
- "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
-
- RNA_def_boolean(func, "open_sim", false,
- "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds");
-
- RNA_def_boolean(func, "limit_precision", false,
- "Limit Precision",
- "Reduce the precision of the exported data to 6 digits");
-
- RNA_def_boolean(func, "keep_bind_info", false,
- "Keep Bind Info",
- "Store bind pose information in custom bone properties for later use during Collada export");
-
-#endif
-
#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");
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 08665f3007a..54daba706c7 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -362,6 +362,42 @@ static void rna_SmokeModifier_heat_grid_get(PointerRNA *ptr, float *values)
#endif
}
+static void rna_SmokeModifier_temperature_grid_get(PointerRNA *ptr, float *values)
+{
+#ifdef WITH_SMOKE
+ SmokeDomainSettings *sds = (SmokeDomainSettings *)ptr->data;
+ int length[RNA_MAX_ARRAY_DIMENSION];
+ int size = rna_SmokeModifier_grid_get_length(ptr, length);
+ float *flame;
+
+ BLI_rw_mutex_lock(sds->fluid_mutex, THREAD_LOCK_READ);
+
+ if (sds->flags & MOD_SMOKE_HIGHRES && sds->wt) {
+ flame = smoke_turbulence_get_flame(sds->wt);
+ }
+ else {
+ flame = smoke_get_flame(sds->fluid);
+ }
+
+ if (flame) {
+ /* Output is such that 0..1 maps to 0..1000K */
+ float offset = sds->flame_ignition;
+ float scale = sds->flame_max_temp - sds->flame_ignition;
+
+ for (int i = 0; i < size; i++) {
+ values[i] = (flame[i] > 0.01f) ? offset + flame[i] * scale : 0.0f;
+ }
+ }
+ else {
+ memset(values, 0, size * sizeof(float));
+ }
+
+ BLI_rw_mutex_unlock(sds->fluid_mutex);
+#else
+ UNUSED_VARS(ptr, values);
+#endif
+}
+
static void rna_SmokeFlow_density_vgroup_get(PointerRNA *ptr, char *value)
{
SmokeFlowSettings *flow = (SmokeFlowSettings *)ptr->data;
@@ -677,6 +713,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_float_funcs(prop, "rna_SmokeModifier_heat_grid_get", NULL, NULL);
RNA_def_property_ui_text(prop, "Heat Grid", "Smoke heat grid");
+ prop = RNA_def_property(srna, "temperature_grid", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_array(prop, 32);
+ RNA_def_property_flag(prop, PROP_DYNAMIC);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_dynamic_array_funcs(prop, "rna_SmokeModifier_grid_get_length");
+ RNA_def_property_float_funcs(prop, "rna_SmokeModifier_temperature_grid_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Temperature Grid", "Smoke temperature grid, range 0..1 represents 0..1000K");
+
prop = RNA_def_property(srna, "cell_size", PROP_FLOAT, PROP_XYZ); /* can change each frame when using adaptive domain */
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "cell_size", "Cell Size");
@@ -854,6 +898,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "ColorRamp");
RNA_def_property_ui_text(prop, "Color Ramp", "");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ prop = RNA_def_property(srna, "clipping", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "clipping");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3);
+ RNA_def_property_ui_text(prop, "Clipping",
+ "Value under which voxels are considered empty space to optimize caching or rendering");
+ RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, NULL);
}
static void rna_def_smoke_flow_settings(BlenderRNA *brna)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 1acd1c4ea46..5247599bdf7 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -210,6 +210,7 @@ set(SRC
shader/nodes/node_shader_tex_wave.c
shader/nodes/node_shader_volume_scatter.c
shader/nodes/node_shader_volume_absorption.c
+ shader/nodes/node_shader_volume_principled.c
shader/nodes/node_shader_uvAlongStroke.c
shader/nodes/node_shader_uvmap.c
shader/node_shader_tree.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 6ed71e02823..b00307ed7fb 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -114,6 +114,7 @@ void register_node_type_sh_emission(void);
void register_node_type_sh_holdout(void);
void register_node_type_sh_volume_absorption(void);
void register_node_type_sh_volume_scatter(void);
+void register_node_type_sh_volume_principled(void);
void register_node_type_sh_bsdf_hair(void);
void register_node_type_sh_subsurface_scattering(void);
void register_node_type_sh_mix_shader(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 2db23c2122d..bc90e33ed03 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -92,6 +92,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_HAIR, def_hair, "BS
DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","")
DefNode( ShaderNode, SH_NODE_VOLUME_ABSORPTION, 0, "VOLUME_ABSORPTION", VolumeAbsorption, "Volume Absorption", "" )
DefNode( ShaderNode, SH_NODE_VOLUME_SCATTER, 0, "VOLUME_SCATTER", VolumeScatter, "Volume Scatter", "" )
+DefNode( ShaderNode, SH_NODE_VOLUME_PRINCIPLED, 0, "PRINCIPLED_VOLUME", VolumePrincipled, "Principled Volume", "" )
DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" )
DefNode( ShaderNode, SH_NODE_NEW_GEOMETRY, 0, "NEW_GEOMETRY", NewGeometry, "Geometry", "" )
DefNode( ShaderNode, SH_NODE_LIGHT_PATH, 0, "LIGHT_PATH", LightPath, "Light Path", "" )
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_principled.c b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
new file mode 100644
index 00000000000..f9a481e6c7e
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_principled.c
@@ -0,0 +1,85 @@
+/*
+ * ***** 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) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_volume_principled_in[] = {
+ { SOCK_RGBA, 1, N_("Color"), 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
+ { SOCK_STRING, 1, N_("Color Attribute"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+ { SOCK_STRING, 1, N_("Density Attribute"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Anisotropy"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, N_("Absorption Color"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Emission Strength"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1000.0f},
+ { SOCK_RGBA, 1, N_("Emission Color"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Blackbody Intensity"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+ { SOCK_RGBA, 1, N_("Blackbody Tint"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Temperature"), 1000.0f, 0.0f, 0.0f, 0.0f, 0.0f, 6500.0f},
+ { SOCK_STRING, 1, N_("Temperature Attribute"),0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketTemplate sh_node_volume_principled_out[] = {
+ { SOCK_SHADER, 0, N_("Volume")},
+ { -1, 0, "" }
+};
+
+static void node_shader_init_volume_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) {
+ if (STREQ(sock->name, "Density Attribute")) {
+ strcpy(((bNodeSocketValueString *)sock->default_value)->value, "density");
+ }
+ else if (STREQ(sock->name, "Temperature Attribute")) {
+ strcpy(((bNodeSocketValueString *)sock->default_value)->value, "temperature");
+ }
+ }
+}
+
+static int node_shader_gpu_volume_principled(GPUMaterial *UNUSED(mat), bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *UNUSED(in), GPUNodeStack *UNUSED(out))
+{
+ return false;
+}
+
+/* node type definition */
+void register_node_type_sh_volume_principled(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_VOLUME_PRINCIPLED, "Principled Volume", NODE_CLASS_SHADER, 0);
+ node_type_compatibility(&ntype, NODE_NEW_SHADING);
+ node_type_socket_templates(&ntype, sh_node_volume_principled_in, sh_node_volume_principled_out);
+ node_type_size_preset(&ntype, NODE_SIZE_LARGE);
+ node_type_init(&ntype, node_shader_init_volume_principled);
+ node_type_storage(&ntype, "", NULL, NULL);
+ node_type_gpu(&ntype, node_shader_gpu_volume_principled);
+
+ nodeRegisterType(&ntype);
+}
+
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
index 0c5647b4ba8..ed56df257b7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_scatter.c
@@ -32,7 +32,7 @@
static bNodeSocketTemplate sh_node_volume_scatter_in[] = {
{ SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
{ SOCK_FLOAT, 1, N_("Density"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
- { SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},
+ { SOCK_FLOAT, 1, N_("Anisotropy"),0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f, PROP_FACTOR},
{ -1, 0, "" }
};
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 2d72bcf4d58..71d6ec673e6 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -2144,11 +2144,13 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U
char path[FILE_MAX];
RNA_string_get(op->ptr, "filepath", path);
- if (BLI_exists(path)) {
+ if (RNA_boolean_get(op->ptr, "check_existing") && BLI_exists(path)) {
ret = WM_operator_confirm_message_ex(C, op, IFACE_("Save Over?"), ICON_QUESTION, path);
}
else {
ret = wm_save_as_mainfile_exec(C, op);
+ /* Without this there is no feedback the file was saved. */
+ BKE_reportf(op->reports, RPT_INFO, "Saved \"%s\"", BLI_path_basename(path));
}
}
else {