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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_constraint.h1
-rw-r--r--source/blender/blenkernel/intern/constraint.c58
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c35
-rw-r--r--source/blender/collada/AnimationExporter.cpp751
-rw-r--r--source/blender/collada/AnimationExporter.h140
-rw-r--r--source/blender/collada/CMakeLists.txt2
-rw-r--r--source/blender/collada/DocumentExporter.cpp631
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c34
-rw-r--r--source/blender/editors/animation/anim_markers.c11
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c18
-rw-r--r--source/blender/editors/animation/keyframes_general.c4
-rw-r--r--source/blender/editors/animation/keyingsets.c8
-rw-r--r--source/blender/editors/armature/poseobject.c10
-rw-r--r--source/blender/editors/include/ED_markers.h4
-rw-r--r--source/blender/editors/interface/resources.c2
-rw-r--r--source/blender/editors/object/object_constraint.c3
-rw-r--r--source/blender/editors/space_action/action_ops.c6
-rw-r--r--source/blender/editors/space_graph/graph_edit.c2
-rw-r--r--source/blender/editors/space_graph/graph_ops.c6
-rw-r--r--source/blender/editors/space_logic/logic_window.c4
-rw-r--r--source/blender/editors/space_nla/nla_ops.c4
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c105
-rw-r--r--source/blender/editors/transform/transform.c31
-rw-r--r--source/blender/editors/transform/transform_conversions.c10
-rw-r--r--source/blender/editors/transform/transform_ops.c2
-rw-r--r--source/blender/makesdna/DNA_anim_types.h13
-rw-r--r--source/blender/makesdna/DNA_armature_types.h3
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c4
-rw-r--r--source/blender/makesrna/intern/rna_armature.c1
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c7
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c35
32 files changed, 1239 insertions, 711 deletions
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 7c0e7050a9f..ddff45c5422 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -154,6 +154,7 @@ void constraints_clear_evalob(struct bConstraintOb *cob);
void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[][4], short from, short to);
void get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime);
+void get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index d3c14a9dd12..fe3286dcc2b 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -2648,7 +2648,7 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
/* if inside, then move to surface */
if (dist <= data->dist) {
clamp_surf= 1;
- sfac= data->dist / dist;
+ if (dist != 0.0f) sfac= data->dist / dist;
}
/* if soft-distance is enabled, start fading once owner is dist+softdist from the target */
else if (data->flag & LIMITDIST_USESOFT) {
@@ -2661,14 +2661,14 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
/* if outside, then move to surface */
if (dist >= data->dist) {
clamp_surf= 1;
- sfac= data->dist / dist;
+ if (dist != 0.0f) sfac= data->dist / dist;
}
/* if soft-distance is enabled, start fading once owner is dist-soft from the target */
else if (data->flag & LIMITDIST_USESOFT) {
// FIXME: there's a problem with "jumping" when this kicks in
if (dist >= (data->dist - data->soft)) {
sfac = (float)( data->soft*(1.0f - expf(-(dist - data->dist)/data->soft)) + data->dist );
- sfac /= dist;
+ if (dist != 0.0f) sfac /= dist;
clamp_surf= 1;
}
@@ -2677,7 +2677,7 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
else {
if (IS_EQF(dist, data->dist)==0) {
clamp_surf= 1;
- sfac= data->dist / dist;
+ if (dist != 0.0f) sfac= data->dist / dist;
}
}
@@ -4427,6 +4427,34 @@ void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n,
unit_m4(mat);
}
}
+
+/* Get the list of targets required for solving a constraint */
+void get_constraint_targets_for_solving (bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
+{
+ bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
+
+ if (cti && cti->get_constraint_targets) {
+ bConstraintTarget *ct;
+
+ /* get targets
+ * - constraints should use ct->matrix, not directly accessing values
+ * - ct->matrix members have not yet been calculated here!
+ */
+ cti->get_constraint_targets(con, targets);
+
+ /* set matrices
+ * - calculate if possible, otherwise just initialise as identity matrix
+ */
+ if (cti->get_target_matrix) {
+ for (ct= targets->first; ct; ct= ct->next)
+ cti->get_target_matrix(con, cob, ct, ctime);
+ }
+ else {
+ for (ct= targets->first; ct; ct= ct->next)
+ unit_m4(ct->matrix);
+ }
+ }
+}
/* ---------- Evaluation ----------- */
@@ -4471,27 +4499,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
/* prepare targets for constraint solving */
- if (cti->get_constraint_targets) {
- bConstraintTarget *ct;
-
- /* get targets
- * - constraints should use ct->matrix, not directly accessing values
- * - ct->matrix members have not yet been calculated here!
- */
- cti->get_constraint_targets(con, &targets);
-
- /* set matrices
- * - calculate if possible, otherwise just initialise as identity matrix
- */
- if (cti->get_target_matrix) {
- for (ct= targets.first; ct; ct= ct->next)
- cti->get_target_matrix(con, cob, ct, ctime);
- }
- else {
- for (ct= targets.first; ct; ct= ct->next)
- unit_m4(ct->matrix);
- }
- }
+ get_constraint_targets_for_solving(con, cob, &targets, ctime);
/* Solve the constraint and put result in cob->matrix */
cti->evaluate_constraint(con, cob, &targets);
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 844f25e6d21..4a1a0f9ac6b 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -1230,11 +1230,21 @@ float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue,
for (fcm= modifiers->last; fcm; fcm= fcm->prev) {
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
- /* only evaluate if there's a callback for this */
- // TODO: implement the 'influence' control feature...
- if (fmi && fmi->evaluate_modifier_time) {
- if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
- evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
+ if (fmi == NULL)
+ continue;
+
+ /* if modifier cannot be applied on this frame (whatever scale it is on, it won't affect the results)
+ * hence we shouldn't bother seeing what it would do given the chance
+ */
+ if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)==0 ||
+ ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime)) )
+ {
+ /* only evaluate if there's a callback for this */
+ // TODO: implement the 'influence' control feature...
+ if (fmi->evaluate_modifier_time) {
+ if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
+ evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
+ }
}
}
@@ -1257,11 +1267,18 @@ void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue,
for (fcm= modifiers->first; fcm; fcm= fcm->next) {
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
- /* only evaluate if there's a callback for this */
+ if (fmi == NULL)
+ continue;
+
+ /* only evaluate if there's a callback for this, and if F-Modifier can be evaluated on this frame */
// TODO: implement the 'influence' control feature...
- if (fmi && fmi->evaluate_modifier) {
- if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
- fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime);
+ if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)==0 ||
+ ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime)) )
+ {
+ if (fmi->evaluate_modifier) {
+ if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
+ fmi->evaluate_modifier(fcu, fcm, cvalue, evaltime);
+ }
}
}
}
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
new file mode 100644
index 00000000000..f28883ce91c
--- /dev/null
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -0,0 +1,751 @@
+/*
+ * $Id: DocumentExporter.cpp 36898 2011-05-25 17:14:31Z phabtar $
+ *
+ * ***** 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.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "GeometryExporter.h"
+#include "AnimationExporter.h"
+
+template<class Functor>
+void forEachObjectInScene(Scene *sce, Functor &f)
+{
+ Base *base= (Base*) sce->base.first;
+ while(base) {
+ Object *ob = base->object;
+
+ f(ob);
+
+ base= base->next;
+ }
+}
+
+void AnimationExporter::exportAnimations(Scene *sce)
+ {
+ if(hasAnimations(sce)) {
+ this->scene = sce;
+
+ openLibrary();
+
+ forEachObjectInScene(sce, *this);
+
+ closeLibrary();
+ }
+ }
+
+ // called for each exported object
+ void AnimationExporter::operator() (Object *ob)
+ {
+ if (!ob->adt || !ob->adt->action) return; //this is already checked in hasAnimations()
+
+ FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
+
+ if (ob->type == OB_ARMATURE) {
+ if (!ob->data) return;
+
+ bArmature *arm = (bArmature*)ob->data;
+ for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next)
+ write_bone_animation(ob, bone);
+ }
+ else {
+ while (fcu) {
+ // TODO "rotation_quaternion" is also possible for objects (although euler is default)
+ if ((!strcmp(fcu->rna_path, "location") || !strcmp(fcu->rna_path, "scale")) ||
+ (!strcmp(fcu->rna_path, "rotation_euler") && ob->rotmode == ROT_MODE_EUL))
+ dae_animation(fcu, id_name(ob));
+
+ fcu = fcu->next;
+ }
+ }
+ }
+
+ void AnimationExporter::dae_animation(FCurve *fcu, std::string ob_name)
+ {
+ const char *axis_names[] = {"X", "Y", "Z"};
+ const char *axis_name = NULL;
+ char anim_id[200];
+ bool has_tangents = false;
+
+ if (fcu->array_index < 3)
+ axis_name = axis_names[fcu->array_index];
+
+ BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
+ fcu->rna_path, axis_names[fcu->array_index]);
+
+ // check rna_path is one of: rotation, scale, location
+
+ openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
+
+ // create input source
+ std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
+
+ // create output source
+ std::string output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
+
+ // create interpolations source
+ std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents);
+
+ // handle tangents (if required)
+ std::string intangent_id;
+ std::string outtangent_id;
+
+ if (has_tangents) {
+ // create in_tangent source
+ intangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::IN_TANGENT, fcu, anim_id, axis_name);
+
+ // create out_tangent source
+ outtangent_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUT_TANGENT, fcu, anim_id, axis_name);
+ }
+
+
+ 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));
+
+ // this input is required
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+
+ if (has_tangents) {
+ sampler.addInput(COLLADASW::InputSemantic::IN_TANGENT, COLLADABU::URI(empty, intangent_id));
+ sampler.addInput(COLLADASW::InputSemantic::OUT_TANGENT, COLLADABU::URI(empty, outtangent_id));
+ }
+
+ addSampler(sampler);
+
+ std::string target = translate_id(ob_name)
+ + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
+ addChannel(COLLADABU::URI(empty, sampler_id), target);
+
+ closeAnimation();
+ }
+
+ void AnimationExporter::write_bone_animation(Object *ob_arm, Bone *bone)
+ {
+ if (!ob_arm->adt)
+ return;
+
+ //write bone animations for 3 transform types
+ //i=0 --> rotations
+ //i=1 --> scale
+ //i=2 --> location
+ for (int i = 0; i < 3; i++)
+ sample_and_write_bone_animation(ob_arm, bone, i);
+
+ for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next)
+ write_bone_animation(ob_arm, child);
+ }
+
+ void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
+ {
+ bArmature *arm = (bArmature*)ob_arm->data;
+ int flag = arm->flag;
+ std::vector<float> fra;
+ char prefix[256];
+
+ BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
+
+ bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
+ if (!pchan)
+ return;
+ //Fill frame array with key frame values framed at @param:transform_type
+ switch (transform_type) {
+ case 0:
+ find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
+ break;
+ case 1:
+ find_frames(ob_arm, fra, prefix, "scale");
+ break;
+ case 2:
+ find_frames(ob_arm, fra, prefix, "location");
+ break;
+ default:
+ return;
+ }
+
+ // exit rest position
+ if (flag & ARM_RESTPOS) {
+ arm->flag &= ~ARM_RESTPOS;
+ where_is_pose(scene, ob_arm);
+ }
+ //v array will hold all values which will be exported.
+ if (fra.size()) {
+ float *values = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
+ sample_animation(values, fra, transform_type, bone, ob_arm, pchan);
+
+ if (transform_type == 0) {
+ // write x, y, z curves separately if it is rotation
+ float *axisValues = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
+
+ for (int i = 0; i < 3; i++) {
+ for (unsigned int j = 0; j < fra.size(); j++)
+ axisValues[j] = values[j * 3 + i];
+
+ dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name);
+ }
+ MEM_freeN(axisValues);
+ }
+ else {
+ // write xyz at once if it is location or scale
+ dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name);
+ }
+
+ MEM_freeN(values);
+ }
+
+ // restore restpos
+ if (flag & ARM_RESTPOS)
+ arm->flag = flag;
+ where_is_pose(scene, ob_arm);
+ }
+
+ void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan)
+ {
+ bPoseChannel *parchan = NULL;
+ /*bPose *pose = ob_arm->pose;
+
+ pchan = get_pose_channel(pose, bone->name);*/
+
+ if (!pchan)
+ return;
+
+ parchan = pchan->parent;
+
+ enable_fcurves(ob_arm->adt->action, bone->name);
+
+ std::vector<float>::iterator it;
+ for (it = frames.begin(); it != frames.end(); it++) {
+ float mat[4][4], ipar[4][4];
+
+ float ctime = bsystem_time(scene, ob_arm, *it, 0.0f);
+
+ BKE_animsys_evaluate_animdata(&ob_arm->id, ob_arm->adt, *it, ADT_RECALC_ANIM);
+ where_is_pose_bone(scene, ob_arm, pchan, ctime, 1);
+
+ // compute bone local mat
+ if (bone->parent) {
+ invert_m4_m4(ipar, parchan->pose_mat);
+ mul_m4_m4m4(mat, pchan->pose_mat, ipar);
+ }
+ else
+ copy_m4_m4(mat, pchan->pose_mat);
+
+ switch (type) {
+ case 0:
+ mat4_to_eul(v, mat);
+ break;
+ case 1:
+ mat4_to_size(v, mat);
+ break;
+ case 2:
+ copy_v3_v3(v, mat[3]);
+ break;
+ }
+
+ v += 3;
+ }
+
+ enable_fcurves(ob_arm->adt->action, NULL);
+ }
+
+ // dae_bone_animation -> add_bone_animation
+ // (blend this into dae_bone_animation)
+ void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
+ {
+ const char *axis_names[] = {"X", "Y", "Z"};
+ const char *axis_name = NULL;
+ char anim_id[200];
+ bool is_rot = tm_type == 0;
+
+ if (!fra.size())
+ return;
+
+ char rna_path[200];
+ BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
+ tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
+
+ if (axis > -1)
+ axis_name = axis_names[axis];
+
+ std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
+
+ BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
+ (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str());
+
+ openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
+
+ // create input source
+ std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
+
+ // create output source
+ std::string output_id;
+ if (axis == -1)
+ output_id = create_xyz_source(values, fra.size(), anim_id);
+ else
+ output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, values, fra.size(), is_rot, anim_id, axis_name);
+
+ // create interpolations source
+ std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, axis_name);
+
+ 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
+
+ // this input is required
+ sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+
+ addSampler(sampler);
+
+ std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
+ addChannel(COLLADABU::URI(empty, sampler_id), target);
+
+ closeAnimation();
+ }
+
+ float AnimationExporter::convert_time(float frame)
+ {
+ return FRA2TIME(frame);
+ }
+
+ float AnimationExporter::convert_angle(float angle)
+ {
+ return COLLADABU::Math::Utils::radToDegF(angle);
+ }
+
+ std::string AnimationExporter::get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
+ {
+ switch(semantic) {
+ case COLLADASW::InputSemantic::INPUT:
+ return INPUT_SOURCE_ID_SUFFIX;
+ case COLLADASW::InputSemantic::OUTPUT:
+ return OUTPUT_SOURCE_ID_SUFFIX;
+ case COLLADASW::InputSemantic::INTERPOLATION:
+ return INTERPOLATION_SOURCE_ID_SUFFIX;
+ case COLLADASW::InputSemantic::IN_TANGENT:
+ return INTANGENT_SOURCE_ID_SUFFIX;
+ case COLLADASW::InputSemantic::OUT_TANGENT:
+ return OUTTANGENT_SOURCE_ID_SUFFIX;
+ default:
+ break;
+ }
+ return "";
+ }
+
+ void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
+ COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis)
+ {
+ switch(semantic) {
+ case COLLADASW::InputSemantic::INPUT:
+ param.push_back("TIME");
+ break;
+ case COLLADASW::InputSemantic::OUTPUT:
+ if (is_rot) {
+ param.push_back("ANGLE");
+ }
+ else {
+ if (axis) {
+ param.push_back(axis);
+ }
+ else { //assumes if axis isn't specified all axi are added
+ param.push_back("X");
+ param.push_back("Y");
+ param.push_back("Z");
+ }
+ }
+ break;
+ case COLLADASW::InputSemantic::IN_TANGENT:
+ case COLLADASW::InputSemantic::OUT_TANGENT:
+ param.push_back("X");
+ param.push_back("Y");
+ break;
+ default:
+ break;
+ }
+ }
+
+ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length)
+ {
+ switch (semantic) {
+ case COLLADASW::InputSemantic::INPUT:
+ *length = 1;
+ values[0] = convert_time(bezt->vec[1][0]);
+ break;
+ case COLLADASW::InputSemantic::OUTPUT:
+ *length = 1;
+ if (rotation) {
+ values[0] = convert_angle(bezt->vec[1][1]);
+ }
+ else {
+ values[0] = bezt->vec[1][1];
+ }
+ break;
+
+ case COLLADASW::InputSemantic::IN_TANGENT:
+ *length = 2;
+ values[0] = convert_time(bezt->vec[0][0]);
+ if (bezt->ipo != BEZT_IPO_BEZ) {
+ // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
+ values[0] = 0;
+ values[1] = 0;
+ } else if (rotation) {
+ values[1] = convert_angle(bezt->vec[0][1]);
+ } else {
+ values[1] = bezt->vec[0][1];
+ }
+ break;
+
+ case COLLADASW::InputSemantic::OUT_TANGENT:
+ *length = 2;
+ values[0] = convert_time(bezt->vec[2][0]);
+ if (bezt->ipo != BEZT_IPO_BEZ) {
+ // We're in a mixed interpolation scenario, set zero as it's irrelevant but value might contain unused data
+ values[0] = 0;
+ values[1] = 0;
+ } else if (rotation) {
+ values[1] = convert_angle(bezt->vec[2][1]);
+ } else {
+ values[1] = bezt->vec[2][1];
+ }
+ break;
+ break;
+ default:
+ *length = 0;
+ break;
+ }
+ }
+
+ 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);
+
+ //bool is_rotation = !strcmp(fcu->rna_path, "rotation");
+ bool is_rotation = false;
+
+ if (strstr(fcu->rna_path, "rotation")) is_rotation = true;
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(fcu->totvert);
+
+ switch (semantic) {
+ case COLLADASW::InputSemantic::INPUT:
+ case COLLADASW::InputSemantic::OUTPUT:
+ source.setAccessorStride(1);
+ break;
+ case COLLADASW::InputSemantic::IN_TANGENT:
+ case COLLADASW::InputSemantic::OUT_TANGENT:
+ source.setAccessorStride(2);
+ break;
+ }
+
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ add_source_parameters(param, semantic, is_rotation, axis_name);
+
+ source.prepareToAppendValues();
+
+ for (unsigned int i = 0; i < fcu->totvert; i++) {
+ float values[3]; // be careful!
+ int length = 0;
+
+ get_source_values(&fcu->bezt[i], semantic, is_rotation, values, &length);
+ for (int j = 0; j < length; j++)
+ source.appendValues(values[j]);
+ }
+
+ source.finish();
+
+ return source_id;
+ }
+ //Currently called 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);
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(tot);
+ source.setAccessorStride(1);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ add_source_parameters(param, semantic, is_rot, axis_name);
+
+ source.prepareToAppendValues();
+
+ for (int i = 0; i < tot; i++) {
+ float val = v[i];
+ ////if (semantic == COLLADASW::InputSemantic::INPUT)
+ // val = convert_time(val);
+ //else
+ if (is_rot)
+ val = convert_angle(val);
+ source.appendValues(val);
+ }
+
+ source.finish();
+
+ return source_id;
+ }
+// 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);
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(fra.size());
+ source.setAccessorStride(1);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ add_source_parameters(param, semantic, is_rot, axis_name);
+
+ source.prepareToAppendValues();
+
+ std::vector<float>::iterator it;
+ for (it = fra.begin(); it != fra.end(); it++) {
+ float val = *it;
+ //if (semantic == COLLADASW::InputSemantic::INPUT)
+ val = convert_time(val);
+ /*else if (is_rot)
+ val = convert_angle(val);*/
+ source.appendValues(val);
+ }
+
+ source.finish();
+
+ return source_id;
+ }
+
+ // 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;
+ std::string source_id = anim_id + get_semantic_suffix(semantic);
+
+ COLLADASW::FloatSourceF source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(tot);
+ source.setAccessorStride(3);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ add_source_parameters(param, semantic, false, NULL);
+
+ source.prepareToAppendValues();
+
+ for (int i = 0; i < tot; i++) {
+ source.appendValues(*v, *(v + 1), *(v + 2));
+ v += 3;
+ }
+
+ source.finish();
+
+ return source_id;
+ }
+
+ std::string AnimationExporter::create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents)
+ {
+ std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
+
+ COLLADASW::NameSource source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(fcu->totvert);
+ source.setAccessorStride(1);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("INTERPOLATION");
+
+ source.prepareToAppendValues();
+
+ *has_tangents = false;
+
+ for (unsigned int i = 0; i < fcu->totvert; i++) {
+ if (fcu->bezt[i].ipo==BEZT_IPO_BEZ) {
+ source.appendValues(BEZIER_NAME);
+ *has_tangents = true;
+ } else if (fcu->bezt[i].ipo==BEZT_IPO_CONST) {
+ source.appendValues(STEP_NAME);
+ } else { // BEZT_IPO_LIN
+ source.appendValues(LINEAR_NAME);
+ }
+ }
+ // unsupported? -- HERMITE, CARDINAL, BSPLINE, NURBS
+
+ source.finish();
+
+ return source_id;
+ }
+
+ std::string AnimationExporter::fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
+ {
+ std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
+
+ COLLADASW::NameSource source(mSW);
+ source.setId(source_id);
+ source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+ source.setAccessorCount(tot);
+ source.setAccessorStride(1);
+
+ COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+ param.push_back("INTERPOLATION");
+
+ source.prepareToAppendValues();
+
+ for (int i = 0; i < tot; i++) {
+ source.appendValues(LINEAR_NAME);
+ }
+
+ source.finish();
+
+ return source_id;
+ }
+
+ // 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;
+
+ // when given rna_path, determine tm_type from it
+ if (rna_path) {
+ char *name = extract_transform_name(rna_path);
+
+ if (strstr(name, "rotation"))
+ tm_type = 0;
+ else if (!strcmp(name, "scale"))
+ tm_type = 1;
+ else if (!strcmp(name, "location"))
+ tm_type = 2;
+ else
+ tm_type = -1;
+ }
+
+ switch (tm_type) {
+ case 0:
+ return std::string("rotation") + std::string(axis_name) + ".ANGLE";
+ case 1:
+ tm_name = "scale";
+ break;
+ case 2:
+ tm_name = "location";
+ break;
+ default:
+ tm_name = "";
+ break;
+ }
+
+ if (tm_name.size()) {
+ if (append_axis)
+ return tm_name + std::string(".") + std::string(axis_name);
+ else
+ return tm_name;
+ }
+
+ return std::string("");
+ }
+
+ char* AnimationExporter::extract_transform_name(char *rna_path)
+ {
+ char *dot = strrchr(rna_path, '.');
+ return dot ? (dot + 1) : rna_path;
+ }
+
+ void AnimationExporter::find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
+ {
+ FCurve *fcu= (FCurve*)ob->adt->action->curves.first;
+
+ for (; fcu; fcu = fcu->next) {
+ if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix)))
+ continue;
+
+ char *name = extract_transform_name(fcu->rna_path);
+ if (!strcmp(name, tm_name)) {
+ 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_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
+ {
+ if (rotmode > 0)
+ find_frames(ob, fra, prefix, "rotation_euler");
+ else if (rotmode == ROT_MODE_QUAT)
+ find_frames(ob, fra, prefix, "rotation_quaternion");
+ /*else if (rotmode == ROT_MODE_AXISANGLE)
+ ;*/
+ }
+
+ // 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;
+ char prefix[200];
+
+ if (bone_name)
+ BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
+
+ for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) {
+ if (bone_name) {
+ if (!strncmp(fcu->rna_path, prefix, strlen(prefix)))
+ fcu->flag &= ~FCURVE_DISABLED;
+ else
+ fcu->flag |= FCURVE_DISABLED;
+ }
+ else {
+ fcu->flag &= ~FCURVE_DISABLED;
+ }
+ }
+ }
+
+ bool AnimationExporter::hasAnimations(Scene *sce)
+ {
+ Base *base= (Base*) sce->base.first;
+ while(base) {
+ Object *ob = base->object;
+
+ FCurve *fcu = 0;
+ if(ob->adt && ob->adt->action)
+ fcu = (FCurve*)ob->adt->action->curves.first;
+
+ //The Scene has animations if object type is armature or object has f-curve
+ if ((ob->type == OB_ARMATURE && ob->data) || fcu) {
+ return true;
+ }
+ base= base->next;
+ }
+ return false;
+ }
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
new file mode 100644
index 00000000000..3968401331a
--- /dev/null
+++ b/source/blender/collada/AnimationExporter.h
@@ -0,0 +1,140 @@
+/*
+ * $Id: DocumentExporter.cpp 36898 2011-05-25 17:14:31Z phabtar $
+ *
+ * ***** 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.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+extern "C"
+{
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_anim_types.h"
+#include "DNA_action_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_armature_types.h"
+
+#include "BKE_DerivedMesh.h"
+#include "BKE_fcurve.h"
+#include "BKE_animsys.h"
+#ifdef NAN_BUILDINFO
+extern char build_rev[];
+#endif
+}
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_action.h" // pose functions
+#include "BKE_armature.h"
+#include "BKE_object.h"
+
+#include "BLI_math.h"
+#include "BLI_string.h"
+#include "BLI_listbase.h"
+
+#include "RNA_access.h"
+
+#include "COLLADASWSource.h"
+#include "COLLADASWInstanceGeometry.h"
+#include "COLLADASWInputList.h"
+#include "COLLADASWPrimitves.h"
+#include "COLLADASWVertices.h"
+#include "COLLADASWLibraryAnimations.h"
+#include "COLLADASWParamTemplate.h"
+#include "COLLADASWParamBase.h"
+#include "COLLADASWSampler.h"
+#include "COLLADASWConstants.h"
+#include "COLLADASWBaseInputElement.h"
+
+#include "collada_internal.h"
+
+#include <vector>
+#include <algorithm> // std::find
+
+class AnimationExporter: COLLADASW::LibraryAnimations
+{
+private:
+ Scene *scene;
+ COLLADASW::StreamWriter *sw;
+
+public:
+
+ AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) { this->sw = sw; }
+
+
+ void exportAnimations(Scene *sce);
+
+ // called for each exported object
+ void operator() (Object *ob);
+
+protected:
+
+ void dae_animation(FCurve *fcu, std::string ob_name);
+
+ void write_bone_animation(Object *ob_arm, Bone *bone);
+
+ void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type);
+
+ void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pChan);
+
+ // dae_bone_animation -> add_bone_animation
+ // (blend this into dae_bone_animation)
+ void dae_bone_animation(std::vector<float> &fra, float *v, int tm_type, int axis, std::string ob_name, std::string bone_name);
+
+ float convert_time(float frame);
+
+ float convert_angle(float angle);
+
+ std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic);
+
+ void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
+ COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis);
+
+ void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length);
+
+ 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_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name);
+
+ 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_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents);
+
+ std::string fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name);
+ // for rotation, axis name is always appended and the value of append_axis is ignored
+ std::string get_transform_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_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode);
+
+ // enable fcurves driving a specific bone, disable all the rest
+ // if bone_name = NULL enable all fcurves
+ void enable_fcurves(bAction *act, char *bone_name);
+
+ bool hasAnimations(Scene *sce);
+
+ char* extract_transform_name(char *rna_path);
+}; \ No newline at end of file
diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt
index a7e7c973f36..7c43c09bc12 100644
--- a/source/blender/collada/CMakeLists.txt
+++ b/source/blender/collada/CMakeLists.txt
@@ -62,6 +62,7 @@ endif()
set(SRC
AnimationImporter.cpp
+ AnimationExporter.cpp
ArmatureExporter.cpp
ArmatureImporter.cpp
CameraExporter.cpp
@@ -84,6 +85,7 @@ set(SRC
collada_utils.cpp
AnimationImporter.h
+ AnimationExporter.h
ArmatureExporter.h
ArmatureImporter.h
CameraExporter.h
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp
index 00daac60281..0bdf41f15eb 100644
--- a/source/blender/collada/DocumentExporter.cpp
+++ b/source/blender/collada/DocumentExporter.cpp
@@ -114,6 +114,7 @@ extern char build_rev[];
#include "TransformWriter.h"
#include "ArmatureExporter.h"
+#include "AnimationExporter.h"
#include "CameraExporter.h"
#include "EffectExporter.h"
#include "GeometryExporter.h"
@@ -298,636 +299,6 @@ public:
// TODO: it would be better to instantiate animations rather than create a new one per object
// COLLADA allows this through multiple <channel>s in <animation>.
// For this to work, we need to know objects that use a certain action.
-class AnimationExporter: COLLADASW::LibraryAnimations
-{
- Scene *scene;
- COLLADASW::StreamWriter *sw;
-
-public:
-
- AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) { this->sw = sw; }
-
-
-
- void exportAnimations(Scene *sce)
- {
- if(hasAnimations(sce)) {
- this->scene = sce;
-
- openLibrary();
-
- forEachObjectInScene(sce, *this);
-
- closeLibrary();
- }
- }
-
- // called for each exported object
- void operator() (Object *ob)
- {
- if (!ob->adt || !ob->adt->action) return;
-
- FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
-
- if (ob->type == OB_ARMATURE) {
- if (!ob->data) return;
-
- bArmature *arm = (bArmature*)ob->data;
- for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next)
- write_bone_animation(ob, bone);
- }
- else {
- while (fcu) {
- // TODO "rotation_quaternion" is also possible for objects (although euler is default)
- if ((!strcmp(fcu->rna_path, "location") || !strcmp(fcu->rna_path, "scale")) ||
- (!strcmp(fcu->rna_path, "rotation_euler") && ob->rotmode == ROT_MODE_EUL))
- dae_animation(fcu, id_name(ob));
-
- fcu = fcu->next;
- }
- }
- }
-
-protected:
-
- void dae_animation(FCurve *fcu, std::string ob_name)
- {
- const char *axis_names[] = {"X", "Y", "Z"};
- const char *axis_name = NULL;
- char anim_id[200];
-
- if (fcu->array_index < 3)
- axis_name = axis_names[fcu->array_index];
-
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
- fcu->rna_path, axis_names[fcu->array_index]);
-
- // check rna_path is one of: rotation, scale, location
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
-
- // create input source
- std::string input_id = create_source_from_fcurve(COLLADASW::InputSemantic::INPUT, fcu, anim_id, axis_name);
-
- // create output source
- std::string output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name);
-
- // create interpolations source
- std::string interpolation_id = create_interpolation_source(fcu->totvert, anim_id, axis_name);
-
- 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));
-
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
-
- addSampler(sampler);
-
- std::string target = translate_id(ob_name)
- + "/" + get_transform_sid(fcu->rna_path, -1, axis_name, true);
- addChannel(COLLADABU::URI(empty, sampler_id), target);
-
- closeAnimation();
- }
-
- void write_bone_animation(Object *ob_arm, Bone *bone)
- {
- if (!ob_arm->adt)
- return;
-
- for (int i = 0; i < 3; i++)
- sample_and_write_bone_animation(ob_arm, bone, i);
-
- for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next)
- write_bone_animation(ob_arm, child);
- }
-
- void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type)
- {
- bArmature *arm = (bArmature*)ob_arm->data;
- int flag = arm->flag;
- std::vector<float> fra;
- char prefix[256];
-
- BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name);
-
- bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name);
- if (!pchan)
- return;
-
- switch (transform_type) {
- case 0:
- find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode);
- break;
- case 1:
- find_frames(ob_arm, fra, prefix, "scale");
- break;
- case 2:
- find_frames(ob_arm, fra, prefix, "location");
- break;
- default:
- return;
- }
-
- // exit rest position
- if (flag & ARM_RESTPOS) {
- arm->flag &= ~ARM_RESTPOS;
- where_is_pose(scene, ob_arm);
- }
-
- if (fra.size()) {
- float *v = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames");
- sample_animation(v, fra, transform_type, bone, ob_arm);
-
- if (transform_type == 0) {
- // write x, y, z curves separately if it is rotation
- float *c = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames");
- for (int i = 0; i < 3; i++) {
- for (unsigned int j = 0; j < fra.size(); j++)
- c[j] = v[j * 3 + i];
-
- dae_bone_animation(fra, c, transform_type, i, id_name(ob_arm), bone->name);
- }
- MEM_freeN(c);
- }
- else {
- // write xyz at once if it is location or scale
- dae_bone_animation(fra, v, transform_type, -1, id_name(ob_arm), bone->name);
- }
-
- MEM_freeN(v);
- }
-
- // restore restpos
- if (flag & ARM_RESTPOS)
- arm->flag = flag;
- where_is_pose(scene, ob_arm);
- }
-
- void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm)
- {
- bPoseChannel *pchan, *parchan = NULL;
- bPose *pose = ob_arm->pose;
-
- pchan = get_pose_channel(pose, bone->name);
-
- if (!pchan)
- return;
-
- parchan = pchan->parent;
-
- enable_fcurves(ob_arm->adt->action, bone->name);
-
- std::vector<float>::iterator it;
- for (it = frames.begin(); it != frames.end(); it++) {
- float mat[4][4], ipar[4][4];
-
- float ctime = bsystem_time(scene, ob_arm, *it, 0.0f);
-
- BKE_animsys_evaluate_animdata(&ob_arm->id, ob_arm->adt, *it, ADT_RECALC_ANIM);
- where_is_pose_bone(scene, ob_arm, pchan, ctime, 1);
-
- // compute bone local mat
- if (bone->parent) {
- invert_m4_m4(ipar, parchan->pose_mat);
- mul_m4_m4m4(mat, pchan->pose_mat, ipar);
- }
- else
- copy_m4_m4(mat, pchan->pose_mat);
-
- switch (type) {
- case 0:
- mat4_to_eul(v, mat);
- break;
- case 1:
- mat4_to_size(v, mat);
- break;
- case 2:
- copy_v3_v3(v, mat[3]);
- break;
- }
-
- v += 3;
- }
-
- enable_fcurves(ob_arm->adt->action, NULL);
- }
-
- // dae_bone_animation -> add_bone_animation
- // (blend this into dae_bone_animation)
- void dae_bone_animation(std::vector<float> &fra, float *v, int tm_type, int axis, std::string ob_name, std::string bone_name)
- {
- const char *axis_names[] = {"X", "Y", "Z"};
- const char *axis_name = NULL;
- char anim_id[200];
- bool is_rot = tm_type == 0;
-
- if (!fra.size())
- return;
-
- char rna_path[200];
- BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(),
- tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location"));
-
- if (axis > -1)
- axis_name = axis_names[axis];
-
- std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name, false);
-
- BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
- (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str());
-
- openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
-
- // create input source
- std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, is_rot, anim_id, axis_name);
-
- // create output source
- std::string output_id;
- if (axis == -1)
- output_id = create_xyz_source(v, fra.size(), anim_id);
- else
- output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, v, fra.size(), is_rot, anim_id, axis_name);
-
- // create interpolations source
- std::string interpolation_id = create_interpolation_source(fra.size(), anim_id, axis_name);
-
- 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
-
- // this input is required
- sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
-
- addSampler(sampler);
-
- std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid;
- addChannel(COLLADABU::URI(empty, sampler_id), target);
-
- closeAnimation();
- }
-
- float convert_time(float frame)
- {
- return FRA2TIME(frame);
- }
-
- float convert_angle(float angle)
- {
- return COLLADABU::Math::Utils::radToDegF(angle);
- }
-
- std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic)
- {
- switch(semantic) {
- case COLLADASW::InputSemantic::INPUT:
- return INPUT_SOURCE_ID_SUFFIX;
- case COLLADASW::InputSemantic::OUTPUT:
- return OUTPUT_SOURCE_ID_SUFFIX;
- case COLLADASW::InputSemantic::INTERPOLATION:
- return INTERPOLATION_SOURCE_ID_SUFFIX;
- case COLLADASW::InputSemantic::IN_TANGENT:
- return INTANGENT_SOURCE_ID_SUFFIX;
- case COLLADASW::InputSemantic::OUT_TANGENT:
- return OUTTANGENT_SOURCE_ID_SUFFIX;
- default:
- break;
- }
- return "";
- }
-
- void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param,
- COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis)
- {
- switch(semantic) {
- case COLLADASW::InputSemantic::INPUT:
- param.push_back("TIME");
- break;
- case COLLADASW::InputSemantic::OUTPUT:
- if (is_rot) {
- param.push_back("ANGLE");
- }
- else {
- if (axis) {
- param.push_back(axis);
- }
- else {
- param.push_back("X");
- param.push_back("Y");
- param.push_back("Z");
- }
- }
- break;
- case COLLADASW::InputSemantic::IN_TANGENT:
- case COLLADASW::InputSemantic::OUT_TANGENT:
- param.push_back("X");
- param.push_back("Y");
- break;
- default:
- break;
- }
- }
-
- void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length)
- {
- switch (semantic) {
- case COLLADASW::InputSemantic::INPUT:
- *length = 1;
- values[0] = convert_time(bezt->vec[1][0]);
- break;
- case COLLADASW::InputSemantic::OUTPUT:
- *length = 1;
- if (rotation) {
- values[0] = convert_angle(bezt->vec[1][1]);
- }
- else {
- values[0] = bezt->vec[1][1];
- }
- break;
- case COLLADASW::InputSemantic::IN_TANGENT:
- case COLLADASW::InputSemantic::OUT_TANGENT:
- // XXX
- *length = 2;
- break;
- default:
- *length = 0;
- break;
- }
- }
-
- std::string 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);
-
- //bool is_rotation = !strcmp(fcu->rna_path, "rotation");
- bool is_rotation = false;
-
- if (strstr(fcu->rna_path, "rotation")) is_rotation = true;
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fcu->totvert);
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, is_rotation, axis_name);
-
- source.prepareToAppendValues();
-
- for (unsigned int i = 0; i < fcu->totvert; i++) {
- float values[3]; // be careful!
- int length = 0;
-
- get_source_values(&fcu->bezt[i], semantic, is_rotation, values, &length);
- for (int j = 0; j < length; j++)
- source.appendValues(values[j]);
- }
-
- source.finish();
-
- return source_id;
- }
-
- std::string 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);
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(tot);
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, is_rot, axis_name);
-
- source.prepareToAppendValues();
-
- for (int i = 0; i < tot; i++) {
- float val = v[i];
- if (semantic == COLLADASW::InputSemantic::INPUT)
- val = convert_time(val);
- else if (is_rot)
- val = convert_angle(val);
- source.appendValues(val);
- }
-
- source.finish();
-
- return source_id;
- }
-
- 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 source_id = anim_id + get_semantic_suffix(semantic);
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(fra.size());
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, is_rot, axis_name);
-
- source.prepareToAppendValues();
-
- std::vector<float>::iterator it;
- for (it = fra.begin(); it != fra.end(); it++) {
- float val = *it;
- if (semantic == COLLADASW::InputSemantic::INPUT)
- val = convert_time(val);
- else if (is_rot)
- val = convert_angle(val);
- source.appendValues(val);
- }
-
- source.finish();
-
- return source_id;
- }
-
- // only used for sources with OUTPUT semantic
- std::string create_xyz_source(float *v, int tot, const std::string& anim_id)
- {
- COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
- std::string source_id = anim_id + get_semantic_suffix(semantic);
-
- COLLADASW::FloatSourceF source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(tot);
- source.setAccessorStride(3);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- add_source_parameters(param, semantic, false, NULL);
-
- source.prepareToAppendValues();
-
- for (int i = 0; i < tot; i++) {
- source.appendValues(*v, *(v + 1), *(v + 2));
- v += 3;
- }
-
- source.finish();
-
- return source_id;
- }
-
- std::string create_interpolation_source(int tot, const std::string& anim_id, const char *axis_name)
- {
- std::string source_id = anim_id + get_semantic_suffix(COLLADASW::InputSemantic::INTERPOLATION);
-
- COLLADASW::NameSource source(mSW);
- source.setId(source_id);
- source.setArrayId(source_id + ARRAY_ID_SUFFIX);
- source.setAccessorCount(tot);
- source.setAccessorStride(1);
-
- COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
- param.push_back("INTERPOLATION");
-
- source.prepareToAppendValues();
-
- for (int i = 0; i < tot; i++) {
- source.appendValues(LINEAR_NAME);
- }
-
- source.finish();
-
- return source_id;
- }
-
- // for rotation, axis name is always appended and the value of append_axis is ignored
- std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis)
- {
- std::string tm_name;
-
- // when given rna_path, determine tm_type from it
- if (rna_path) {
- char *name = extract_transform_name(rna_path);
-
- if (strstr(name, "rotation"))
- tm_type = 0;
- else if (!strcmp(name, "scale"))
- tm_type = 1;
- else if (!strcmp(name, "location"))
- tm_type = 2;
- else
- tm_type = -1;
- }
-
- switch (tm_type) {
- case 0:
- return std::string("rotation") + std::string(axis_name) + ".ANGLE";
- case 1:
- tm_name = "scale";
- break;
- case 2:
- tm_name = "location";
- break;
- default:
- tm_name = "";
- break;
- }
-
- if (tm_name.size()) {
- if (append_axis)
- return tm_name + std::string(".") + std::string(axis_name);
- else
- return tm_name;
- }
-
- return std::string("");
- }
-
- char *extract_transform_name(char *rna_path)
- {
- char *dot = strrchr(rna_path, '.');
- return dot ? (dot + 1) : rna_path;
- }
-
- void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name)
- {
- FCurve *fcu= (FCurve*)ob->adt->action->curves.first;
-
- for (; fcu; fcu = fcu->next) {
- if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix)))
- continue;
-
- char *name = extract_transform_name(fcu->rna_path);
- if (!strcmp(name, tm_name)) {
- 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 find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode)
- {
- if (rotmode > 0)
- find_frames(ob, fra, prefix, "rotation_euler");
- else if (rotmode == ROT_MODE_QUAT)
- find_frames(ob, fra, prefix, "rotation_quaternion");
- /*else if (rotmode == ROT_MODE_AXISANGLE)
- ;*/
- }
-
- // enable fcurves driving a specific bone, disable all the rest
- // if bone_name = NULL enable all fcurves
- void enable_fcurves(bAction *act, char *bone_name)
- {
- FCurve *fcu;
- char prefix[200];
-
- if (bone_name)
- BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name);
-
- for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) {
- if (bone_name) {
- if (!strncmp(fcu->rna_path, prefix, strlen(prefix)))
- fcu->flag &= ~FCURVE_DISABLED;
- else
- fcu->flag |= FCURVE_DISABLED;
- }
- else {
- fcu->flag &= ~FCURVE_DISABLED;
- }
- }
- }
-
- bool hasAnimations(Scene *sce)
- {
- Base *base= (Base*) sce->base.first;
- while(base) {
- Object *ob = base->object;
-
- FCurve *fcu = 0;
- if(ob->adt && ob->adt->action)
- fcu = (FCurve*)ob->adt->action->curves.first;
-
- if ((ob->type == OB_ARMATURE && ob->data) || fcu) {
- return true;
- }
- base= base->next;
- }
- return false;
- }
-};
void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename)
{
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index f755df79986..438c6e7e95e 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -38,7 +38,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-
+#include "BKE_library.h"
#include "DNA_anim_types.h"
#include "DNA_object_types.h"
@@ -515,12 +515,34 @@ void ANIM_fcurve_delete_from_animdata (bAnimContext *ac, AnimData *adt, FCurve *
* - Drivers
* - TODO... some others?
*/
- if (fcu->grp)
- action_groups_remove_channel(adt->action, fcu);
- else if ((ac) && (ac->datatype == ANIMCONT_DRIVERS))
+ if ((ac) && (ac->datatype == ANIMCONT_DRIVERS)) {
+ /* driver F-Curve */
BLI_remlink(&adt->drivers, fcu);
- else if (adt->action)
- BLI_remlink(&adt->action->curves, fcu);
+ }
+ else if (adt->action) {
+ /* remove from group or action, whichever one "owns" the F-Curve */
+ if (fcu->grp)
+ action_groups_remove_channel(adt->action, fcu);
+ else
+ BLI_remlink(&adt->action->curves, fcu);
+
+ /* if action has no more F-Curves as a result of this, unlink it from
+ * AnimData if it did not come from a NLA Strip being tweaked.
+ *
+ * This is done so that we don't have dangling Object+Action entries in
+ * channel list that are empty, and linger around long after the data they
+ * are for has disappeared (and probably won't come back).
+ */
+ // XXX: does everybody always want this?
+ /* XXX: there's a problem where many actions could build up in the file if multiple
+ * full add/delete cycles are performed on the same objects, but assume that this is rare
+ */
+ if ((adt->action->curves.first == NULL) && (adt->flag & ADT_NLA_EDIT_ON)==0)
+ {
+ id_us_min(&adt->action->id);
+ adt->action = NULL;
+ }
+ }
/* free the F-Curve itself */
free_fcurve(fcu);
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index c802ba621f1..f61c1ff7962 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -1495,3 +1495,14 @@ void ED_marker_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "MARKER_OT_camera_bind", BKEY, KM_PRESS, KM_CTRL, 0);
#endif
}
+
+/* to be called from animation editor keymaps, see note below */
+void ED_marker_keymap_animedit_conflictfree(wmKeyMap *keymap)
+{
+ /* duplicate of some marker-hotkeys but without the bounds checking
+ * since these are handy to be able to do unrestricted and won't conflict
+ * with primary function hotkeys (Usability tweak [#27469])
+ */
+ WM_keymap_add_item(keymap, "MARKER_OT_add", MKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "MARKER_OT_rename", MKEY, KM_PRESS, KM_CTRL, 0);
+}
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index 954928fc486..3018fa697b8 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -694,6 +694,24 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie
default: /* unknown type */
break;
}
+
+ /* one last panel below this: FModifier range */
+ // TODO: experiment with placement of this
+ {
+ box = uiLayoutBox(layout);
+
+ /* top row: use restricted range */
+ row= uiLayoutRow(box, 0);
+ uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE);
+
+ if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
+ /* second row: settings */
+ row = uiLayoutRow(box, 1);
+
+ uiItemR(row, &ptr, "frame_start", 0, "Start", ICON_NONE);
+ uiItemR(row, &ptr, "frame_end", 0, "End", ICON_NONE);
+ }
+ }
}
}
diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c
index f111339b963..e2afda04d30 100644
--- a/source/blender/editors/animation/keyframes_general.c
+++ b/source/blender/editors/animation/keyframes_general.c
@@ -111,7 +111,7 @@ void delete_fcurve_keys(FCurve *fcu)
{
int i;
- if(fcu->bezt==NULL) /* ignore baked curves */
+ if (fcu->bezt==NULL) /* ignore baked curves */
return;
/* Delete selected BezTriples */
@@ -124,7 +124,7 @@ void delete_fcurve_keys(FCurve *fcu)
}
/* Free the array of BezTriples if there are not keyframes */
- if(fcu->totvert == 0)
+ if (fcu->totvert == 0)
clear_fcurve_keys(fcu);
}
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index c525c9af626..610022660bd 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -782,19 +782,19 @@ void ANIM_keying_sets_menu_setup (bContext *C, const char title[], const char op
* - these are listed in the order in which they were defined for the active scene
*/
if (scene->keyingsets.first) {
- for (ks= scene->keyingsets.first; ks; ks= ks->next) {
+ for (ks= scene->keyingsets.first; ks; ks=ks->next, i++) {
if (ANIM_keyingset_context_ok_poll(C, ks))
- uiItemIntO(layout, ks->name, ICON_NONE, op_name, "type", i++);
+ uiItemIntO(layout, ks->name, ICON_NONE, op_name, "type", i);
}
uiItemS(layout);
}
/* builtin Keying Sets */
i= -1;
- for (ks= builtin_keyingsets.first; ks; ks= ks->next) {
+ for (ks= builtin_keyingsets.first; ks; ks=ks->next, i--) {
/* only show KeyingSet if context is suitable */
if (ANIM_keyingset_context_ok_poll(C, ks))
- uiItemEnumO_value(layout, ks->name, ICON_NONE, op_name, "type", i--);
+ uiItemEnumO_value(layout, ks->name, ICON_NONE, op_name, "type", i);
}
uiPupMenuEnd(C, pup);
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index 8176aa5893b..fa5fecbd9d0 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -1002,6 +1002,14 @@ static int pose_paste_exec (bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ /* if selOnly option is enabled, if user hasn't selected any bones,
+ * just go back to default behaviour to be more in line with other pose tools
+ */
+ if (selOnly) {
+ if (CTX_DATA_COUNT(C, selected_pose_bones) == 0)
+ selOnly = 0;
+ }
+
/* Safely merge all of the channels in the buffer pose into any existing pose */
for (chan= g_posebuf->chanbase.first; chan; chan=chan->next) {
if (chan->flag & POSE_KEY) {
@@ -1169,7 +1177,7 @@ void POSE_OT_paste (wmOperatorType *ot)
/* properties */
RNA_def_boolean(ot->srna, "flipped", 0, "Flipped on X-Axis", "Paste the stored pose flipped on to current pose");
- RNA_def_boolean(ot->srna, "selected_mask", 0, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose");
+ RNA_def_boolean(ot->srna, "selected_mask", 1, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose");
}
/* ********************************************** */
diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h
index f804e052301..a8e91add348 100644
--- a/source/blender/editors/include/ED_markers.h
+++ b/source/blender/editors/include/ED_markers.h
@@ -34,6 +34,7 @@
#define ED_MARKERS_H
struct wmKeyConfig;
+struct wmKeyMap;
struct bContext;
struct bAnimContext;
struct Scene;
@@ -72,6 +73,9 @@ void ED_operatortypes_marker(void);
/* called in screen_ops.c:ED_keymap_screen() */
void ED_marker_keymap(struct wmKeyConfig *keyconf);
+/* called in animation editors - keymap defines */
+void ED_marker_keymap_animedit_conflictfree(struct wmKeyMap *keymap);
+
/* debugging only */
void debug_markers_print_list(struct ListBase *markers);
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 1a2a2906f1a..3564dad474a 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -663,7 +663,7 @@ void ui_theme_init_default(void)
SETCOL(btheme->tipo.handle_vertex, 0, 0, 0, 255);
SETCOL(btheme->tipo.handle_vertex_select, 255, 133, 0, 255);
- btheme->tipo.handle_vertex_size= 3;
+ btheme->tipo.handle_vertex_size= 4;
SETCOL(btheme->tipo.ds_channel, 82, 96, 110, 255);
SETCOL(btheme->tipo.ds_subchannel, 124, 137, 150, 255);
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 450bd70a568..a3df25824a4 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -567,7 +567,8 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
}
con = constraints_findByName(list, constraint_name);
- printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>");
+ //if (G.f & G_DEBUG)
+ //printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>");
if (con && (type != 0) && (con->type != type))
con = NULL;
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index 6c3f80cda41..2ccad308676 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -40,6 +40,7 @@
#include "BLI_blenlib.h"
#include "ED_anim_api.h"
+#include "ED_markers.h"
#include "ED_transform.h"
#include "action_intern.h"
@@ -162,7 +163,7 @@ static void action_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap)
/* menu + set setting */
WM_keymap_add_item(keymap, "ACTION_OT_handle_type", VKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "ACTION_OT_interpolation_type", TKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "ACTION_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "ACTION_OT_keyframe_type", RKEY, KM_PRESS, 0, 0);
@@ -193,6 +194,9 @@ static void action_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap)
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_ACTION);
+
+ /* special markers hotkeys for anim editors: see note in definition of this function */
+ ED_marker_keymap_animedit_conflictfree(keymap);
}
/* --------------- */
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 962cadba1f3..0da03832d15 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -2248,7 +2248,7 @@ void GRAPH_OT_fmodifier_paste (wmOperatorType *ot)
/* api callbacks */
ot->exec= graph_fmodifier_paste_exec;
- ot->poll= graphop_editable_keyframes_poll;
+ ot->poll= graphop_active_fcurve_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c
index 03cc8bb9e80..0d7cdf94bc7 100644
--- a/source/blender/editors/space_graph/graph_ops.c
+++ b/source/blender/editors/space_graph/graph_ops.c
@@ -46,6 +46,7 @@
#include "UI_view2d.h"
#include "ED_anim_api.h"
+#include "ED_markers.h"
#include "ED_screen.h"
#include "ED_transform.h"
@@ -361,7 +362,7 @@ static void graphedit_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap)
WM_keymap_add_item(keymap, "GRAPH_OT_handle_type", VKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, KM_SHIFT, 0);
+ WM_keymap_add_item(keymap, "GRAPH_OT_interpolation_type", TKEY, KM_PRESS, 0, 0);
/* destructive */
WM_keymap_add_item(keymap, "GRAPH_OT_clean", OKEY, KM_PRESS, 0, 0);
@@ -399,6 +400,9 @@ static void graphedit_keymap_keyframes (wmKeyConfig *keyconf, wmKeyMap *keymap)
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_IPO);
+
+ /* special markers hotkeys for anim editors: see note in definition of this function */
+ ED_marker_keymap_animedit_conflictfree(keymap);
}
/* --------------- */
diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c
index bce492f5a04..0a9a91a53af 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -3679,10 +3679,6 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
PointerRNA settings_ptr;
uiLayout *row;
- if(ob->type != OB_ARMATURE){
- uiItemL(layout, "Actuator only available for armatures", ICON_NONE);
- return;
- }
RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr);
row= uiLayoutRow(layout, 0);
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index 85dcf14adac..ea8e8961f02 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -45,6 +45,7 @@
#include "BKE_screen.h"
#include "ED_anim_api.h"
+#include "ED_markers.h"
#include "ED_screen.h"
#include "ED_transform.h"
@@ -262,6 +263,9 @@ static void nla_keymap_main (wmKeyConfig *keyconf, wmKeyMap *keymap)
/* transform system */
transform_keymap_for_space(keyconf, keymap, SPACE_NLA);
+
+ /* special markers hotkeys for anim editors: see note in definition of this function */
+ ED_marker_keymap_animedit_conflictfree(keymap);
}
/* --------------- */
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 7c66cec5730..f42fd461510 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -1217,6 +1217,87 @@ static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsign
}
}
+static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments)
+{
+ if ((segments > 1) && (pchan)) {
+ float dlen= length/(float)segments;
+ Mat4 *bbone = bbones;
+ int a;
+
+ for (a=0; a<segments; a++, bbone++) {
+ glPushMatrix();
+ glMultMatrixf(bbone->mat);
+
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.0f, 0.0f);
+ glVertex3f(0.0f, dlen, 0.0f);
+ glEnd(); // GL_LINES
+
+ glPopMatrix();
+ }
+ }
+ else {
+ glPushMatrix();
+
+ glBegin(GL_LINES);
+ glVertex3f(0.0f, 0.0f, 0.0f);
+ glVertex3f(0.0f, length, 0.0f);
+ glEnd();
+
+ glPopMatrix();
+ }
+}
+
+static void draw_wire_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
+{
+ Mat4 *bbones = NULL;
+ int segments = 0;
+ float length;
+
+ if (pchan) {
+ segments= pchan->bone->segments;
+ length= pchan->bone->length;
+
+ if (segments > 1)
+ bbones = b_bone_spline_setup(pchan, 0);
+ }
+ else
+ length= ebone->length;
+
+ /* draw points only if... */
+ if (armflag & ARM_EDITMODE) {
+ /* move to unitspace */
+ glPushMatrix();
+ glScalef(length, length, length);
+ draw_bone_points(dt, armflag, boneflag, id);
+ glPopMatrix();
+ length *= 0.95f; // make vertices visible
+ }
+
+ /* this chunk not in object mode */
+ if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
+ if (id != -1)
+ glLoadName((GLuint) id|BONESEL_BONE);
+
+ draw_wire_bone_segments(pchan, bbones, length, segments);
+
+ /* further we send no names */
+ if (id != -1)
+ glLoadName(id & 0xFFFF); /* object tag, for bordersel optim */
+ }
+
+ /* colors for modes */
+ if (armflag & ARM_POSEMODE) {
+ set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ }
+ else if (armflag & ARM_EDITMODE) {
+ set_ebone_glColor(boneflag);
+ }
+
+ /* draw normal */
+ draw_wire_bone_segments(pchan, bbones, length, segments);
+}
+
static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, float length)
{
@@ -1656,7 +1737,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
glPushMatrix();
- if(use_custom && pchan->custom_tx) {
+ if (use_custom && pchan->custom_tx) {
glMultMatrixf(pchan->custom_tx->pose_mat);
}
else {
@@ -1684,6 +1765,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
else if (arm->drawtype==ARM_LINE)
; /* nothing in solid */
+ else if (arm->drawtype==ARM_WIRE)
+ ; /* nothing in solid */
else if (arm->drawtype==ARM_ENVELOPE)
draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
else if (arm->drawtype==ARM_B_BONE)
@@ -1702,7 +1785,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
* stick bones and/or wire custom-shapes are drawn in next loop
*/
- if ((arm->drawtype != ARM_LINE) && (draw_wire == 0)) {
+ if (ELEM(arm->drawtype,ARM_LINE,ARM_WIRE)==0 && (draw_wire == 0)) {
/* object tag, for bordersel optim */
glLoadName(index & 0xFFFF);
index= -1;
@@ -1773,8 +1856,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
if (index != -1)
index+= 0x10000; // pose bones count in higher 2 bytes only
}
- /* stick bones have not been drawn yet so dont clear object selection in this case */
- if ((arm->drawtype != ARM_LINE) && draw_wire) {
+ /* stick or wire bones have not been drawn yet so dont clear object selection in this case */
+ if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)==0 && draw_wire) {
/* object tag, for bordersel optim */
glLoadName(index & 0xFFFF);
index= -1;
@@ -1784,7 +1867,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
/* wire draw over solid only in posemode */
if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || (arm->drawtype==ARM_LINE)) {
/* draw line check first. we do selection indices */
- if (arm->drawtype==ARM_LINE) {
+ if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) {
if (arm->flag & ARM_POSEMODE)
index= base->selcol;
}
@@ -1879,6 +1962,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
}
else if (arm->drawtype==ARM_LINE)
draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
+ else if (arm->drawtype==ARM_WIRE)
+ draw_wire_bone(dt, arm->flag, flag, constflag, index, pchan, NULL);
else if (arm->drawtype==ARM_B_BONE)
draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
else
@@ -2013,7 +2098,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
}
/* if solid we draw it first */
- if ((dt > OB_WIRE) && (arm->drawtype!=ARM_LINE)) {
+ if ((dt > OB_WIRE) && (arm->drawtype != ARM_LINE)) {
for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) {
if (eBone->layer & arm->layer) {
if ((eBone->flag & BONE_HIDDEN_A)==0) {
@@ -2034,6 +2119,8 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
else if(arm->drawtype==ARM_B_BONE)
draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
+ else if (arm->drawtype==ARM_WIRE)
+ draw_wire_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
else {
draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
}
@@ -2047,7 +2134,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
/* if wire over solid, set offset */
index= -1;
glLoadName(-1);
- if (arm->drawtype==ARM_LINE) {
+ if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) {
if(G.f & G_PICKSEL)
index= 0;
}
@@ -2081,6 +2168,8 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
if (arm->drawtype == ARM_LINE)
draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
+ else if (arm->drawtype==ARM_WIRE)
+ draw_wire_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
else if (arm->drawtype == ARM_B_BONE)
draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
else
@@ -2109,7 +2198,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
/* restore */
if(index!=-1) glLoadName(-1);
- if (arm->drawtype==ARM_LINE);
+ if ELEM(arm->drawtype,ARM_LINE,ARM_WIRE);
else if (dt>OB_WIRE) bglPolygonOffset(rv3d->dist, 0.0f);
/* finally names and axes */
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 27ca345e132..0ce21c2efee 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1982,12 +1982,15 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu
/* ******************* TRANSFORM LIMITS ********************** */
-static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
+static void constraintTransLim(TransInfo *t, TransData *td)
{
if (td->con) {
- bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
+ bConstraintTypeInfo *ctiLoc= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
+ bConstraintTypeInfo *ctiDist= get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT);
+
bConstraintOb cob= {NULL};
bConstraint *con;
+ float ctime = (float)(t->scene->r.cfra);
/* Make a temporary bConstraintOb for using these limit constraints
* - they only care that cob->matrix is correctly set ;-)
@@ -1998,6 +2001,8 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
/* Evaluate valid constraints */
for (con= td->con; con; con= con->next) {
+ bConstraintTypeInfo *cti = NULL;
+ ListBase targets = {NULL, NULL};
float tmat[4][4];
/* only consider constraint if enabled */
@@ -2010,7 +2015,17 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
if ((data->flag2 & LIMIT_TRANSFORM)==0)
continue;
+ cti = ctiLoc;
+ }
+ else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) {
+ bDistLimitConstraint *data= con->data;
+ if ((data->flag & LIMITDIST_TRANSFORM)==0)
+ continue;
+ cti = ctiDist;
+ }
+
+ if (cti) {
/* do space conversions */
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
/* just multiply by td->mtx (this should be ok) */
@@ -2022,8 +2037,11 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
continue;
}
+ /* get constraint targets if needed */
+ get_constraint_targets_for_solving(con, &cob, &targets, ctime);
+
/* do constraint */
- cti->evaluate_constraint(con, &cob, NULL);
+ cti->evaluate_constraint(con, &cob, &targets);
/* convert spaces again */
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
@@ -2031,6 +2049,9 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
copy_m4_m4(tmat, cob.matrix);
mul_m4_m3m4(cob.matrix, td->smtx, tmat);
}
+
+ /* free targets list */
+ BLI_freelistN(&targets);
}
}
@@ -5780,8 +5801,8 @@ int TimeSlide(TransInfo *t, const int mval[2])
char str[200];
/* calculate mouse co-ordinates */
- UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]);
- UI_view2d_region_to_view(v2d, t->imval[0], t->imval[0], &sval[0], &sval[1]);
+ UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]);
+ UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &sval[0], &sval[1]);
/* t->values[0] stores cval[0], which is the current mouse-pointer location (in frames) */
// XXX Need to be able to repeat this
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index c7699f7249c..29fc514f01f 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -3131,12 +3131,18 @@ static void createTransActionData(bContext *C, TransInfo *t)
float min=999999999.0f, max=-999999999.0f;
int i;
- td= (t->data + 1);
- for (i=1; i < count; i+=3, td+=3) {
+ td= t->data;
+ for (i=0; i < count; i++, td++) {
if (min > *(td->val)) min= *(td->val);
if (max < *(td->val)) max= *(td->val);
}
+ if (min == max) {
+ /* just use the current frame ranges */
+ min = (float)PSFRA;
+ max = (float)PEFRA;
+ }
+
/* minx/maxx values used by TimeSlide are stored as a
* calloced 2-float array in t->customData. This gets freed
* in postTrans (T_FREE_CUSTOMDATA).
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index 7bdf6c909d9..4b0a734a98e 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -897,7 +897,7 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac
km= WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", SKEY, KM_PRESS, 0, 0);
RNA_enum_set(km->ptr, "mode", TFM_TIME_SCALE);
- km= WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", TKEY, KM_PRESS, 0, 0);
+ km= WM_keymap_add_item(keymap, "TRANSFORM_OT_transform", TKEY, KM_PRESS, KM_SHIFT, 0);
RNA_enum_set(km->ptr, "mode", TFM_TIME_SLIDE);
break;
case SPACE_IPO:
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 4b649031f97..88a3fe81825 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -62,6 +62,9 @@ typedef struct FModifier {
short flag; /* settings for the modifier */
float influence; /* the amount that the modifier should influence the value */
+
+ float sfra; /* start frame of restricted frame-range */
+ float efra; /* end frame of restricted frame-range */
} FModifier;
/* Types of F-Curve modifier
@@ -86,13 +89,15 @@ typedef enum eFModifier_Types {
/* F-Curve Modifier Settings */
typedef enum eFModifier_Flags {
/* modifier is not able to be evaluated for some reason, and should be skipped (internal) */
- FMODIFIER_FLAG_DISABLED = (1<<0),
+ FMODIFIER_FLAG_DISABLED = (1<<0),
/* modifier's data is expanded (in UI) */
- FMODIFIER_FLAG_EXPANDED = (1<<1),
+ FMODIFIER_FLAG_EXPANDED = (1<<1),
/* modifier is active one (in UI) for editing purposes */
- FMODIFIER_FLAG_ACTIVE = (1<<2),
+ FMODIFIER_FLAG_ACTIVE = (1<<2),
/* user wants modifier to be skipped */
- FMODIFIER_FLAG_MUTED = (1<<3)
+ FMODIFIER_FLAG_MUTED = (1<<3),
+ /* restrict range that F-Modifier can be considered over */
+ FMODIFIER_FLAG_RANGERESTRICT = (1<<4)
} eFModifier_Flags;
/* --- */
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 3547101612f..808db1f4843 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -136,7 +136,8 @@ typedef enum eArmature_Drawtype {
ARM_OCTA = 0,
ARM_LINE,
ARM_B_BONE,
- ARM_ENVELOPE
+ ARM_ENVELOPE,
+ ARM_WIRE
} eArmature_Drawtype;
/* armature->deformflag */
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 1d752fce4ef..c2c0c6f1611 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -677,7 +677,10 @@ typedef enum eRotLimit_Flags {
/* distance limit constraint */
/* bDistLimitConstraint->flag */
typedef enum eDistLimit_Flag {
- LIMITDIST_USESOFT = (1<<0)
+ /* "soft" cushion effect when reaching the limit sphere */ // NOT IMPLEMENTED!
+ LIMITDIST_USESOFT = (1<<0),
+ /* as for all Limit constraints - allow to be used during transform? */
+ LIMITDIST_TRANSFORM = (1<<1)
} eDistLimit_Flag;
/* bDistLimitConstraint->mode */
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index c7cf511d5c7..e16d13fafaa 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -426,11 +426,11 @@ EnumPropertyItem *rna_Actuator_type_itemf(bContext *C, PointerRNA *ptr, Property
if (ob != NULL) {
if (ob->type==OB_ARMATURE) {
- RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_ACTION);
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_ARMATURE);
}
}
-
+
+ RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_ACTION);
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_CAMERA);
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_CONSTRAINT);
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_EDIT_OBJECT);
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 2060f75f9de..41d169a8870 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -814,6 +814,7 @@ static void rna_def_armature(BlenderRNA *brna)
{ARM_LINE, "STICK", 0, "Stick", "Display bones as simple 2D lines with dots"},
{ARM_B_BONE, "BBONE", 0, "B-Bone", "Display bones as boxes, showing subdivision and B-Splines"},
{ARM_ENVELOPE, "ENVELOPE", 0, "Envelope", "Display bones as extruded spheres, showing deformation influence volume"},
+ {ARM_WIRE, "WIRE", 0, "Wire", "Display bones as thin wires, showing subdivision and B-Splines"},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem prop_ghost_type_items[] = {
{ARM_GHOST_CUR, "CURRENT_FRAME", 0, "Around Frame", "Display Ghosts of poses within a fixed number of frames around the current frame"},
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index a75ff601d08..4e178e77fd9 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -85,7 +85,7 @@ static EnumPropertyItem target_space_pchan_items[] = {
static EnumPropertyItem owner_space_pchan_items[] = {
{0, "WORLD", 0, "World Space", "The constraint is applied relative to the world coordinate system"},
{2, "POSE", 0, "Pose Space", "The constraint is applied in Pose Space, the object transformation is ignored"},
- {3, "LOCAL_WITH_PARENT", 0, "The constraint is applied relative to the local coordinate system of the object, with the parent transformation added"},
+ {3, "LOCAL_WITH_PARENT", 0, "Local With Parent", "The constraint is applied relative to the local coordinate system of the object, with the parent transformation added"},
{1, "LOCAL", 0, "Local Space", "The constraint is applied relative to the local coordinate sytem of the object"},
{0, NULL, 0, NULL, NULL}};
@@ -1787,6 +1787,11 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna)
RNA_def_property_enum_items(prop, constraint_distance_items);
RNA_def_property_ui_text(prop, "Limit Mode", "Distances in relation to sphere of influence to allow");
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop= RNA_def_property(srna, "use_transform_limit", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMITDIST_TRANSFORM);
+ RNA_def_property_ui_text(prop, "For Transform", "Transforms are affected by this constraint as well");
+ RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
}
static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index a46f84a22d2..ba0563f554a 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -454,6 +454,22 @@ static void rna_FModifier_active_set(PointerRNA *ptr, int UNUSED(value))
fm->flag |= FMODIFIER_FLAG_ACTIVE;
}
+static void rna_FModifier_start_frame_range(PointerRNA *ptr, float *min, float *max)
+{
+ FModifier *fcm= (FModifier*)ptr->data;
+
+ *min= MINAFRAMEF;
+ *max= (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)? fcm->efra : MAXFRAMEF;
+}
+
+static void rna_FModifier_end_frame_range(PointerRNA *ptr, float *min, float *max)
+{
+ FModifier *fcm= (FModifier*)ptr->data;
+
+ *min= (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT)? fcm->sfra : MINAFRAMEF;
+ *max= MAXFRAMEF;
+}
+
static void rna_FModifier_active_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
FModifier *fm, *fmo= (FModifier*)ptr->data;
@@ -1015,6 +1031,25 @@ static void rna_def_fmodifier(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, NULL, "rna_FModifier_active_set");
RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, "rna_FModifier_active_update");
RNA_def_property_ui_icon(prop, ICON_RADIOBUT_OFF, 1);
+
+ /* restricted range */
+ prop= RNA_def_property(srna, "use_restricted_range", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_RANGERESTRICT);
+ RNA_def_property_ui_text(prop, "Restrict Frame Range", "F-Curve Modifier is only applied for the specified frame range to help mask off effects in order to chain them");
+ RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
+ RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1); // XXX: depends on UI implementation
+
+ prop= RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "sfra");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_start_frame_range");
+ RNA_def_property_ui_text(prop, "Start Frame", "Frame that modifier's influence starts (if Restrict Frame Range is in use)");
+ RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
+
+ prop= RNA_def_property(srna, "frame_end", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "efra");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_end_frame_range");
+ RNA_def_property_ui_text(prop, "End Frame", "Frame that modifier's influence ends (if Restrict Frame Range is in use)");
+ RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
}
/* *********************** */