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/blenfont/BLF_api.h1
-rw-r--r--source/blender/blenfont/intern/blf.c1
-rw-r--r--source/blender/blenkernel/BKE_constraint.h1
-rw-r--r--source/blender/blenkernel/BKE_sound.h2
-rw-r--r--source/blender/blenkernel/intern/action.c5
-rw-r--r--source/blender/blenkernel/intern/constraint.c58
-rw-r--r--source/blender/blenkernel/intern/fcurve.c115
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c86
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c135
-rw-r--r--source/blender/blenkernel/intern/sequencer.c3
-rw-r--r--source/blender/blenkernel/intern/sound.c5
-rw-r--r--source/blender/blenloader/intern/readfile.c36
-rw-r--r--source/blender/blenloader/intern/writefile.c3
-rw-r--r--source/blender/collada/AnimationExporter.cpp854
-rw-r--r--source/blender/collada/AnimationExporter.h144
-rw-r--r--source/blender/collada/AnimationImporter.cpp397
-rw-r--r--source/blender/collada/AnimationImporter.h23
-rw-r--r--source/blender/collada/ArmatureImporter.cpp123
-rw-r--r--source/blender/collada/ArmatureImporter.h7
-rw-r--r--source/blender/collada/CMakeLists.txt2
-rw-r--r--source/blender/collada/DocumentExporter.cpp631
-rw-r--r--source/blender/collada/DocumentImporter.cpp16
-rw-r--r--source/blender/collada/SkinInfo.cpp4
-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.c44
-rw-r--r--source/blender/editors/animation/keyframes_general.c4
-rw-r--r--source/blender/editors/animation/keyingsets.c9
-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/interface_style.c10
-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_buttons.c12
-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.c25
-rw-r--r--source/blender/editors/space_nla/nla_ops.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c7
-rw-r--r--source/blender/editors/space_text/text_draw.c9
-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_actuator_types.h3
-rw-r--r--source/blender/makesdna/DNA_anim_types.h23
-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/makesdna/DNA_sequence_types.h11
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_access.c2
-rw-r--r--source/blender/makesrna/intern/rna_actuator.c61
-rw-r--r--source/blender/makesrna/intern/rna_animation.c6
-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.c82
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c35
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c6
-rw-r--r--source/blender/windowmanager/intern/wm_files.c7
62 files changed, 2425 insertions, 832 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 57f8c83eda6..fba09ee9826 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -215,5 +215,6 @@ void BLF_dir_free(char **dirs, int count);
// XXX, bad design
extern int blf_mono_font;
extern int blf_mono_font_render; // dont mess drawing with render threads.
+extern int blf_default_font_render; // dont mess drawing with render threads.
#endif /* BLF_API_H */
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index c0e62b1c0c7..3bfb7c22082 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -74,6 +74,7 @@ static int global_font_dpi= 72;
// XXX, should these be made into global_font_'s too?
int blf_mono_font= -1;
int blf_mono_font_render= -1;
+int blf_default_font_render= -1;
static FontBLF *BLF_get(int fontid)
{
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/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index 04597fd666e..7402d501120 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -104,4 +104,6 @@ int sound_read_sound_buffer(struct bSound* sound, float* buffer, int length, flo
int sound_get_channels(struct bSound* sound);
+void* sound_get_factory(void* sound);
+
#endif
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index f7086c81756..08eed6d61ba 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -85,8 +85,6 @@ bAction *add_empty_action(const char name[])
bAction *act;
act= alloc_libblock(&G.main->action, ID_AC, name);
- act->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore
- act->id.us++;
return act;
}
@@ -200,9 +198,6 @@ bAction *copy_action (bAction *src)
}
}
- dst->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore
- dst->id.us++;
-
return dst;
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 7be4744a224..a321e718bbb 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -2641,7 +2641,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) {
@@ -2654,14 +2654,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;
}
@@ -2670,7 +2670,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;
}
}
@@ -4420,6 +4420,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 ----------- */
@@ -4464,27 +4492,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/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index d6a9d950015..1f45cc56117 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -42,6 +42,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_object_types.h"
#include "BLI_blenlib.h"
@@ -52,6 +53,7 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_global.h"
#include "BKE_object.h"
@@ -1151,25 +1153,50 @@ static float dvar_eval_locDiff (ChannelDriver *driver, DriverVar *dvar)
/* check if object or bone */
if (pchan) {
/* bone */
- if ((dtar->flag & DTAR_FLAG_LOCALSPACE) == 0) {
+ if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
+ if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
+ float mat[4][4];
+
+ /* extract transform just like how the constraints do it! */
+ copy_m4_m4(mat, pchan->pose_mat);
+ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+
+ /* ... and from that, we get our transform */
+ VECCOPY(tmp_loc, mat[3]);
+ }
+ else {
+ /* transform space (use transform values directly) */
+ VECCOPY(tmp_loc, pchan->loc);
+ }
+ }
+ else {
/* convert to worldspace */
VECCOPY(tmp_loc, pchan->pose_head);
mul_m4_v3(ob->obmat, tmp_loc);
}
- else {
- /* local (use transform values directly) */
- VECCOPY(tmp_loc, pchan->loc);
- }
}
else {
/* object */
- if ((dtar->flag & DTAR_FLAG_LOCALSPACE) == 0) {
- /* worldspace */
- VECCOPY(tmp_loc, ob->obmat[3]);
+ if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
+ if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
+ // XXX: this should practically be the same as transform space...
+ float mat[4][4];
+
+ /* extract transform just like how the constraints do it! */
+ copy_m4_m4(mat, ob->obmat);
+ constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+
+ /* ... and from that, we get our transform */
+ VECCOPY(tmp_loc, mat[3]);
+ }
+ else {
+ /* transform space (use transform values directly) */
+ VECCOPY(tmp_loc, ob->loc);
+ }
}
else {
- /* local (use transform values directly) */
- VECCOPY(tmp_loc, ob->loc);
+ /* worldspace */
+ VECCOPY(tmp_loc, ob->obmat[3]);
}
}
@@ -1197,7 +1224,7 @@ static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar)
Object *ob= (Object *)dtar_id_ensure_proxy_from(dtar->id);
bPoseChannel *pchan;
float mat[4][4];
- float eul[3] = {0.0f,0.0f,0.0f};
+ float oldEul[3] = {0.0f,0.0f,0.0f};
short useEulers=0, rotOrder=ROT_MODE_EUL;
/* check if this target has valid data */
@@ -1210,36 +1237,62 @@ static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar)
/* try to get posechannel */
pchan= get_pose_channel(ob->pose, dtar->pchan_name);
- /* check if object or bone, and get transform matrix accordingly */
+ /* check if object or bone, and get transform matrix accordingly
+ * - "useEulers" code is used to prevent the problems associated with non-uniqueness
+ * of euler decomposition from matrices [#20870]
+ * - localspace is for [#21384], where parent results are not wanted
+ * but local-consts is for all the common "corrective-shapes-for-limbs" situations
+ */
if (pchan) {
/* bone */
if (pchan->rotmode > 0) {
- VECCOPY(eul, pchan->eul);
+ VECCOPY(oldEul, pchan->eul);
rotOrder= pchan->rotmode;
useEulers = 1;
}
if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
- /* specially calculate local matrix, since chan_mat is not valid
- * since it stores delta transform of pose_mat so that deforms work
- */
- pchan_to_mat4(pchan, mat);
+ if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
+ /* just like how the constraints do it! */
+ copy_m4_m4(mat, pchan->pose_mat);
+ constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL);
+ }
+ else {
+ /* specially calculate local matrix, since chan_mat is not valid
+ * since it stores delta transform of pose_mat so that deforms work
+ * so it cannot be used here for "transform" space
+ */
+ pchan_to_mat4(pchan, mat);
+ }
}
- else
+ else {
+ /* worldspace matrix */
mul_m4_m4m4(mat, pchan->pose_mat, ob->obmat);
+ }
}
else {
/* object */
if (ob->rotmode > 0) {
- VECCOPY(eul, ob->rot);
+ VECCOPY(oldEul, ob->rot);
rotOrder= ob->rotmode;
useEulers = 1;
}
- if (dtar->flag & DTAR_FLAG_LOCALSPACE)
- object_to_mat4(ob, mat);
- else
+ if (dtar->flag & DTAR_FLAG_LOCALSPACE) {
+ if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) {
+ /* just like how the constraints do it! */
+ copy_m4_m4(mat, ob->obmat);
+ constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL);
+ }
+ else {
+ /* transforms to matrix */
+ object_to_mat4(ob, mat);
+ }
+ }
+ else {
+ /* worldspace matrix - just the good-old one */
copy_m4_m4(mat, ob->obmat);
+ }
}
/* check which transform */
@@ -1255,9 +1308,21 @@ static float dvar_eval_transChan (ChannelDriver *driver, DriverVar *dvar)
return scale[dtar->transChan - DTAR_TRANSCHAN_SCALEX];
}
else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) {
- /* extract euler rotation (if needed), and choose the right axis */
- if ((dtar->flag & DTAR_FLAG_LOCALSPACE)==0 || (useEulers == 0))
- mat4_to_eulO(eul, rotOrder, mat);
+ /* extract rotation as eulers (if needed)
+ * - definitely if rotation order isn't eulers already
+ * - if eulers, then we have 2 options:
+ * a) decompose transform matrix as required, then try to make eulers from
+ * there compatible with original values
+ * b) [NOT USED] directly use the original values (no decomposition)
+ * - only an option for "transform space", if quality is really bad with a)
+ */
+ float eul[3];
+
+ mat4_to_eulO(eul, rotOrder, mat);
+
+ if (useEulers) {
+ compatible_eul(eul, oldEul);
+ }
return eul[dtar->transChan - DTAR_TRANSCHAN_ROTX];
}
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 844f25e6d21..dcf81c19479 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -1013,6 +1013,7 @@ FModifier *add_fmodifier (ListBase *modifiers, int type)
fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
fcm->type = type;
fcm->flag = FMODIFIER_FLAG_EXPANDED;
+ fcm->influence = 1.0f;
BLI_addtail(modifiers, fcm);
/* tag modifier as "active" if no other modifiers exist in the stack yet */
@@ -1200,6 +1201,47 @@ short list_has_suitable_fmodifier (ListBase *modifiers, int mtype, short acttype
/* Evaluation API --------------------------- */
+/* helper function - calculate influence of FModifier */
+static float eval_fmodifier_influence (FModifier *fcm, float evaltime)
+{
+ float influence;
+
+ /* sanity check */
+ if (fcm == NULL)
+ return 0.0f;
+
+ /* should we use influence stored in modifier or not
+ * NOTE: this is really just a hack so that we don't need to version patch old files ;)
+ */
+ if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE)
+ influence = fcm->influence;
+ else
+ influence = 1.0f;
+
+ /* restricted range or full range? */
+ if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
+ if ((evaltime <= fcm->sfra) || (evaltime >= fcm->efra)) {
+ /* out of range */
+ return 0.0f;
+ }
+ else if ((evaltime > fcm->sfra) && (evaltime < fcm->sfra + fcm->blendin)) {
+ /* blend in range */
+ float a = fcm->sfra;
+ float b = fcm->sfra + fcm->blendin;
+ return influence * (evaltime - a) / (b - a);
+ }
+ else if ((evaltime < fcm->efra) && (evaltime > fcm->efra - fcm->blendout)) {
+ /* blend out range */
+ float a = fcm->efra;
+ float b = fcm->efra - fcm->blendout;
+ return influence * (evaltime - a) / (b - a);
+ }
+ }
+
+ /* just return the influence of the modifier */
+ return influence;
+}
+
/* evaluate time modifications imposed by some F-Curve Modifiers
* - this step acts as an optimisation to prevent the F-Curve stack being evaluated
* several times by modifiers requesting the time be modified, as the final result
@@ -1230,11 +1272,24 @@ 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 */
+ if (fmi->evaluate_modifier_time) {
+ if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0) {
+ float influence = eval_fmodifier_influence(fcm, evaltime);
+ float nval = fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
+
+ evaltime = interpf(nval, evaltime, influence);
+ }
+ }
}
}
@@ -1257,11 +1312,22 @@ 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 */
- // 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 (fmi == NULL)
+ continue;
+
+ /* only evaluate if there's a callback for this, and if F-Modifier can be evaluated on this frame */
+ 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) {
+ float influence = eval_fmodifier_influence(fcm, evaltime);
+ float nval = *cvalue;
+
+ fmi->evaluate_modifier(fcu, fcm, &nval, evaltime);
+ *cvalue = interpf(nval, *cvalue, influence);
+ }
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index fbb5a77fa04..688fdd8ff49 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -40,8 +40,11 @@
#include "BLI_dynlib.h"
#include "BLI_math.h" /* windows needs for M_PI */
+#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "BLF_api.h"
+
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "DNA_anim_types.h"
@@ -2805,6 +2808,130 @@ static struct ImBuf * do_solid_color(
}
/* **********************************************************************
+ TITLE CARD
+ ********************************************************************** */
+
+static void init_title_card(Sequence *seq)
+{
+ TitleCardVars *tv;
+
+ if(seq->effectdata)MEM_freeN(seq->effectdata);
+ seq->effectdata = MEM_callocN(sizeof(struct TitleCardVars), "titlecard");
+
+ tv = (TitleCardVars *)seq->effectdata;
+
+ BLI_strncpy(tv->titlestr, "Title goes here", sizeof(tv->titlestr));
+ tv->fgcol[0] = tv->fgcol[1] = tv->fgcol[2] = 1.0f; /* white */
+}
+
+static int num_inputs_titlecard(void)
+{
+ return 0;
+}
+
+static void free_title_card(Sequence *seq)
+{
+ if(seq->effectdata)MEM_freeN(seq->effectdata);
+ seq->effectdata = NULL;
+}
+
+static void copy_title_card(Sequence *dst, Sequence *src)
+{
+ dst->effectdata = MEM_dupallocN(src->effectdata);
+}
+
+static int early_out_titlecard(struct Sequence *UNUSED(seq),
+ float UNUSED(facf0), float UNUSED(facf1))
+{
+ return -1;
+}
+
+static struct ImBuf * do_title_card(
+ SeqRenderData context, Sequence *seq, float cfra,
+ float facf0, float facf1,
+ struct ImBuf *ibuf1, struct ImBuf *ibuf2,
+ struct ImBuf *ibuf3)
+{
+ TitleCardVars *tv = (TitleCardVars *)seq->effectdata;
+
+ SolidColorVars cv = {{0}};
+ struct ImBuf *out;
+
+ int titleFontId = blf_default_font_render; // XXX: bad design!
+
+ int width = context.rectx;
+ int height = context.recty;
+ float w, h;
+ int x, y;
+
+ /* use fake solid-color vars to get backdrop (and an out buffer at the same time) */
+ VECCOPY(cv.col, tv->bgcol);
+ seq->effectdata = &cv;
+
+ out = do_solid_color(context, seq, cfra,
+ facf0, facf1,
+ ibuf1, ibuf2, ibuf3);
+
+ seq->effectdata = tv;
+
+ /* draw text */
+ /* FIXME: imbuf out->rect is unsigned int NOT unsigned char, but without passing this pointer
+ * this drawing code doesn't work. This cast really masks some potential bugs though...
+ */
+ BLF_buffer(titleFontId, out->rect_float, (unsigned char *)out->rect, width, height, 4);
+
+ if (tv->titlestr[0]) {
+ /* automatic scale - these formulae have been derived experimentally:
+ * - base size is based on 40pt at 960 width
+ * - each 26 characters, size jumps down one step,
+ * but this decrease needs to be exponential to fit everything
+ */
+ float lfac = strlen(tv->titlestr) / 26.0f;
+ float size = (width * 0.06f) * (1.0f - 0.1f*lfac*lfac);
+
+ BLF_size(titleFontId, size, 72);
+ BLF_buffer_col(titleFontId, tv->fgcol[0], tv->fgcol[1], tv->fgcol[2], 1.0);
+
+ BLF_width_and_height(titleFontId, tv->titlestr, &w, &h);
+ x = width/2.0f - w/2.0f;
+ if (tv->subtitle[0])
+ y = height/2.0f + h;
+ else
+ y = height/2.0f;
+
+ BLF_position(titleFontId, x, y, 0.0);
+ BLF_draw_buffer(titleFontId, tv->titlestr);
+ }
+
+ if (tv->subtitle[0]) {
+ /* automatic scale - these formulae have been derived experimentally (as above):
+ * - base size is based on 20pt at 960 width
+ * - size steps aren't quite as refined here. Need a slower-growing curve!
+ */
+ float lfac = strlen(tv->subtitle) / 36.0f;
+ float size = (width * 0.03f) * (1.0f - 0.1f*lfac*lfac*log(lfac));
+
+ BLF_size(titleFontId, size, 72);
+ BLF_buffer_col(titleFontId, tv->fgcol[0], tv->fgcol[1], tv->fgcol[2], 1.0);
+
+ BLF_width_and_height(titleFontId, tv->subtitle, &w, &h);
+ x = width/2.0f - w/2.0f;
+ if (tv->titlestr[0])
+ y = height/2.0f - h;
+ else
+ y = height/2.0f;
+
+ BLF_position(titleFontId, x, y, 0.0);
+ BLF_draw_buffer(titleFontId, tv->subtitle);
+ }
+
+ /* cleanup the buffer. */
+ BLF_buffer(UIFONT_DEFAULT, NULL, NULL, 0, 0, 0);
+
+ return out;
+}
+
+/* **********************************************************************
MULTICAM
********************************************************************** */
@@ -3343,6 +3470,14 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
rval.early_out = early_out_adjustment;
rval.execute = do_adjustment;
break;
+ case SEQ_TITLECARD:
+ rval.init = init_title_card;
+ rval.num_inputs = num_inputs_titlecard;
+ rval.early_out = early_out_titlecard;
+ rval.free = free_title_card;
+ rval.copy = copy_title_card;
+ rval.execute = do_title_card;
+ break;
}
return rval;
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index b82ac69fc9e..550b81e8a0f 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -895,6 +895,7 @@ static const char *give_seqname_by_type(int type)
case SEQ_MULTICAM: return "Multicam";
case SEQ_ADJUSTMENT: return "Adjustment";
case SEQ_SPEED: return "Speed";
+ case SEQ_TITLECARD: return "Title Card";
default:
return NULL;
}
@@ -3020,7 +3021,7 @@ Sequence *seq_foreground_frame_get(Scene *scene, int frame)
if(seq->flag & SEQ_MUTE || seq->startdisp > frame || seq->enddisp <= frame)
continue;
/* only use elements you can see - not */
- if (ELEM5(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR)) {
+ if (ELEM6(seq->type, SEQ_IMAGE, SEQ_META, SEQ_SCENE, SEQ_MOVIE, SEQ_COLOR, SEQ_TITLECARD)) {
if (seq->machine > best_machine) {
best_seq = seq;
best_machine = seq->machine;
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index e0e456a371e..f42492ef713 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -502,3 +502,8 @@ int sound_get_channels(struct bSound* sound)
return info.specs.channels;
}
+
+void* sound_get_factory(void* sound)
+{
+ return ((struct bSound*) sound)->playback_handle;
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 222c4bcf6fc..b8a72616593 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -11663,8 +11663,42 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
+
+ {
+ /* convert fcurve actuator to action actuator */
+ Object *ob;
+ bActuator *act;
+ bIpoActuator *ia;
+ bActionActuator *aa;
+
+ for (ob= main->object.first; ob; ob= ob->id.next) {
+ for (act= ob->actuators.first; act; act= act->next) {
+ if (act->type == ACT_IPO) {
+ // Create the new actuator
+ ia= act->data;
+ aa= MEM_callocN(sizeof(bActionActuator), "fcurve -> action actuator do_version");
+
+ // Copy values
+ aa->type = ia->type;
+ aa->flag = ia->flag;
+ aa->sta = ia->sta;
+ aa->end = ia->end;
+ strcpy(aa->name, ia->name);
+ strcpy(aa->frameProp, ia->frameProp);
+ aa->act = ob->adt->action;
+
+ // Get rid of the old actuator
+ MEM_freeN(ia);
+
+ // Assign the new actuator
+ act->data = aa;
+ act->type= act->otype= ACT_ACTION;
+
+ }
+ }
+ }
+ }
}
-
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 240e8d00ab8..fb5c96cd854 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1892,6 +1892,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
case SEQ_TRANSFORM:
writestruct(wd, DATA, "TransformVars", 1, seq->effectdata);
break;
+ case SEQ_TITLECARD:
+ writestruct(wd, DATA, "TitleCardVars", 1, seq->effectdata);
+ break;
}
}
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp
new file mode 100644
index 00000000000..f0491af3a49
--- /dev/null
+++ b/source/blender/collada/AnimationExporter.cpp
@@ -0,0 +1,854 @@
+/*
+ * $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;
+ char * transformName = extract_transform_name( fcu->rna_path );
+
+
+ //if (ob->type == OB_ARMATURE) {
+ // if (!ob->data) return;
+ // bArmature *arm = (bArmature*)ob->data;
+ // while(fcu)
+ // {
+ // transformName = extract_transform_name( fcu->rna_path );
+ // // std::string ob_name = getObjectBoneName( ob , fcu);
+ // // for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next)
+ // // write_bone_animation(ob, bone);
+ // dae_animation(ob, fcu, ob_name, transformName);
+ // fcu = fcu->next;
+ // }
+ //}
+ //else {
+ while (fcu) {
+ transformName = extract_transform_name( fcu->rna_path );
+
+ if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) ||
+ (!strcmp(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL)||
+ (!strcmp(transformName, "rotation_quaternion")))
+ dae_animation(ob ,fcu, transformName );
+
+ fcu = fcu->next;
+ }
+ //}
+ }
+
+ float * AnimationExporter::get_eul_source_for_quat(Object *ob )
+ {
+ FCurve *fcu = (FCurve*)ob->adt->action->curves.first;
+ const int keys = fcu->totvert;
+ float *quat = (float*)MEM_callocN(sizeof(float) * fcu->totvert * 4, "quat output source values");
+ float *eul = (float*)MEM_callocN(sizeof(float) * fcu->totvert * 3, "quat output source values");
+ float temp_quat[4];
+ float temp_eul[3];
+ while(fcu)
+ {
+ char * transformName = extract_transform_name( fcu->rna_path );
+
+ if( !strcmp(transformName, "rotation_quaternion") )
+ {
+ for ( int i = 0 ; i < fcu->totvert ; i++)
+ {
+ *(quat + ( i * 4 ) + fcu->array_index) = fcu->bezt[i].vec[1][1];
+ }
+ }
+ fcu = fcu->next;
+ }
+
+ for ( int i = 0 ; i < fcu->totvert ; i++)
+ {
+ for ( int j = 0;j<4;j++)
+ temp_quat[j] = quat[(i*4)+j];
+
+ quat_to_eul(temp_eul,temp_quat);
+
+ for (int k = 0;k<3;k++)
+ eul[i*3 + k] = temp_eul[k];
+
+ }
+
+ return eul;
+
+ }
+ std::string AnimationExporter::getObjectBoneName( Object* ob,const FCurve* fcu )
+ {
+ //hard-way to derive the bone name from rna_path. Must find more compact method
+ std::string rna_path = std::string(fcu->rna_path);
+
+ char* boneName = strtok((char *)rna_path.c_str(), "\"");
+ boneName = strtok(NULL,"\"");
+
+ if( boneName != NULL )
+ return id_name(ob) + "_" + std::string(boneName);
+ else
+ return id_name(ob);
+ }
+
+ void AnimationExporter::dae_animation(Object* ob, FCurve *fcu/*, std::string ob_name*/ , char* transformName )
+ {
+
+ const char *axis_name = NULL;
+ char anim_id[200];
+
+ bool has_tangents = false;
+ bool quatRotation = false;
+
+ if ( !strcmp(transformName, "rotation_quaternion") )
+ {
+ quatRotation = true;
+ /*const char *axis_names[] = {"", "X", "Y", "Z"};
+ if (fcu->array_index < 4)
+ axis_name = axis_names[fcu->array_index];*/
+ }
+
+ else
+ {
+ const char *axis_names[] = {"X", "Y", "Z"};
+ if (fcu->array_index < 3)
+ axis_name = axis_names[fcu->array_index];
+ }
+ std::string ob_name = std::string("null");
+ if (ob->type == OB_ARMATURE)
+ {
+ ob_name = getObjectBoneName( ob , fcu);
+ BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s.%s", (char*)translate_id(ob_name).c_str(),
+ transformName, axis_name);
+ }
+ else
+ {
+ ob_name = id_name(ob);
+ BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char*)translate_id(ob_name).c_str(),
+ fcu->rna_path, axis_name);
+ }
+
+ // 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 ;
+
+ /*if(quatRotation)
+ {
+ float * eul = get_eul_source_for_quat(ob);
+ float * eul_axis =
+ for ( int i = 0 ; i< fcu->totvert ; i++)
+ eul_axis[i] = eul[i*3 + fcu->array_index];
+ output_id= create_source_from_array(COLLADASW::InputSemantic::OUTPUT, eul_axis , fcu->totvert, quatRotation, anim_id, axis_name);
+ }
+ else*/
+
+ 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 axises 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] = (bezt->vec[1][1]) * 180.0f/M_PI;
+ }
+ 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] = (bezt->vec[0][1]) * 180.0f/M_PI;
+ } 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] = (bezt->vec[0][1]) * 180.0f/M_PI;
+ } 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 *= 180.0f / M_PI;
+ 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;
+ bool is_rotation =false;
+ // when given rna_path, determine tm_type from it
+ if (rna_path) {
+ char *name = extract_transform_name(rna_path);
+
+ if (!strcmp(name, "rotation_euler"))
+ tm_type = 0;
+ else if (!strcmp(name, "rotation_quaternion"))
+ tm_type = 1;
+ else if (!strcmp(name, "scale"))
+ tm_type = 2;
+ else if (!strcmp(name, "location"))
+ tm_type = 3;
+ else
+ tm_type = -1;
+ }
+
+ switch (tm_type) {
+ case 0:
+ case 1:
+ tm_name = "rotation";
+ is_rotation = true;
+ break;
+ case 2:
+ tm_name = "scale";
+ break;
+ case 3:
+ tm_name = "location";
+ break;
+ default:
+ tm_name = "";
+ break;
+ }
+
+ if (tm_name.size()) {
+ if (is_rotation)
+ return tm_name + 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..e05fac4eed7
--- /dev/null
+++ b/source/blender/collada/AnimationExporter.h
@@ -0,0 +1,144 @@
+/*
+ * $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(Object* ob, FCurve *fcu, char* transformName);
+
+ 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);
+
+ float * get_eul_source_for_quat(Object *ob );
+
+ 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);
+
+ std::string getObjectBoneName ( Object *ob,const FCurve * fcu);
+}; \ No newline at end of file
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 336f127b11f..69beac653d2 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -89,12 +89,15 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
{
COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues();
COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues();
- // COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
- // COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
+
+ if( curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ) {
+ COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
+ COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
+ }
float fps = (float)FPS;
size_t dim = curve->getOutDimension();
unsigned int i;
-
+
std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()];
switch (dim) {
@@ -108,28 +111,42 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED);
// fcu->rna_path = BLI_strdupn(path, strlen(path));
fcu->array_index = 0;
- //fcu->totvert = curve->getKeyCount();
+ fcu->totvert = curve->getKeyCount();
// create beztriple for each key
for (unsigned int j = 0; j < curve->getKeyCount(); j++) {
BezTriple bez;
memset(&bez, 0, sizeof(BezTriple));
- // intangent
- // bez.vec[0][0] = get_float_value(intan, j * 6 + i + i) * fps;
- // bez.vec[0][1] = get_float_value(intan, j * 6 + i + i + 1);
-
+
// input, output
bez.vec[1][0] = bc_get_float_value(input, j) * fps;
bez.vec[1][1] = bc_get_float_value(output, j * dim + i);
- // outtangent
- // bez.vec[2][0] = get_float_value(outtan, j * 6 + i + i) * fps;
- // bez.vec[2][1] = get_float_value(outtan, j * 6 + i + i + 1);
- bez.ipo = U.ipo_new; /* use default interpolation mode here... */
+ if( curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER )
+ {
+ COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
+ COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
+
+ // intangent
+ bez.vec[0][0] = bc_get_float_value(intan, (j * 2 * dim ) + (2 * i)) * fps;
+ bez.vec[0][1] = bc_get_float_value(intan, (j * 2 * dim )+ (2 * i) + 1);
+
+ // outtangent
+ bez.vec[2][0] = bc_get_float_value(outtan, (j * 2 * dim ) + (2 * i)) * fps;
+ bez.vec[2][1] = bc_get_float_value(outtan, (j * 2 * dim )+ (2 * i) + 1);
+ bez.ipo = BEZT_IPO_BEZ;
+ //bez.h1 = bez.h2 = HD_AUTO;
+ }
+ else
+ {
+ bez.h1 = bez.h2 = HD_AUTO;
+ bez.ipo = BEZT_IPO_LIN;
+ }
+ // bez.ipo = U.ipo_new; /* use default interpolation mode here... */
bez.f1 = bez.f2 = bez.f3 = SELECT;
- bez.h1 = bez.h2 = HD_AUTO;
+
insert_bezt_fcurve(fcu, &bez, 0);
}
@@ -147,11 +164,15 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
unused_curves.push_back(*it);
}
+
void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
{
for (unsigned int i = 0; i < cu->totvert; i++) {
// TODO convert handles too
cu->bezt[i].vec[1][1] *= M_PI / 180.0f;
+ cu->bezt[i].vec[0][1] *= M_PI / 180.0f;
+ cu->bezt[i].vec[2][1] *= M_PI / 180.0f;
+ cu->bezt[i].vec[1][0];
}
}
@@ -277,10 +298,11 @@ bool AnimationImporter::write_animation(const COLLADAFW::Animation* anim)
bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList* animlist)
{
const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId();
-
+
animlist_map[animlist_id] = animlist;
-
+
#if 0
+
// should not happen
if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) {
return true;
@@ -291,17 +313,18 @@ bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList* ani
// what does this AnimationList animate?
Animation& animated = uid_animated_map[animlist_id];
Object *ob = animated.ob;
-
+
char rna_path[100];
char joint_path[100];
bool is_joint = false;
// if ob is NULL, it should be a JOINT
if (!ob) {
+
ob = armature_importer->get_armature_for_joint(animated.node);
if (!ob) {
- fprintf(stderr, "Cannot find armature for node %s\n", get_joint_name(animated.node));
+// fprintf(stderr, "Cannot find armature for node %s\n", get_joint_name(animated.node));
return true;
}
@@ -309,7 +332,7 @@ bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList* ani
is_joint = true;
}
-
+ printf("object for animlist: %s found\n", animlist->getUniqueId().toAscii().c_str());
const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
switch (animated.tm->getTransformationType()) {
@@ -512,66 +535,320 @@ virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act)
}
#endif
-// prerequisites:
-// animlist_map - map animlist id -> animlist
-// curve_map - map anim id -> curve(s)
-Object *AnimationImporter::translate_animation(COLLADAFW::Node *node,
- std::map<COLLADAFW::UniqueId, Object*>& object_map,
- std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
- COLLADAFW::Transformation::TransformationType tm_type,
- Object *par_job)
+
+//sets the rna_path and array index to curve
+void AnimationImporter::modify_fcurve(std::vector<FCurve*>* curves , char* rna_path , int array_index )
+{
+ std::vector<FCurve*>::iterator it;
+ int i;
+ for (it = curves->begin(), i = 0; it != curves->end(); it++, i++) {
+ FCurve *fcu = *it;
+ fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
+
+ if (array_index == -1) fcu->array_index = i;
+ else fcu->array_index = array_index;
+
+ unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
+ }
+}
+
+void AnimationImporter::find_frames( std::vector<float>* frames , std::vector<FCurve*>* curves)
{
- bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
+ std::vector<FCurve*>::iterator iter;
+ for (iter = curves->begin(); iter != curves->end(); iter++) {
+ FCurve *fcu = *iter;
+
+ for (unsigned int k = 0; k < fcu->totvert; k++) {
+ //get frame value from bezTriple
+ float fra = fcu->bezt[k].vec[1][0];
+ //if frame already not added add frame to frames
+ if (std::find(frames->begin(), frames->end(), fra) == frames->end())
+ frames->push_back(fra);
+
+ }
+ }
+}
+
+//creates the rna_paths and array indices of fcurves from animations using transformation and bound animation class of each animation.
+void AnimationImporter:: Assign_transform_animations(std::vector<float>* frames,
+ COLLADAFW::Transformation * transform ,
+ const COLLADAFW::AnimationList::AnimationBinding * binding,
+ std::vector<FCurve*>* curves, bool is_joint, char * joint_path)
+{
+ COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
- bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
+ bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
+
+ //to check if the no of curves are valid
+ bool xyz = ((tm_type == COLLADAFW::Transformation::TRANSLATE ||tm_type == COLLADAFW::Transformation::SCALE) && binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
+
+
+ if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) {
+ fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves->size());
+ return;
+ }
+
+ //find key frames of the animation and accumulates them to frames of the transformation.
+ find_frames (frames , curves );
+
+ char rna_path[100];
+ //char joint_path[100];
+
+
+ switch (tm_type) {
+ case COLLADAFW::Transformation::TRANSLATE:
+ case COLLADAFW::Transformation::SCALE:
+ {
+ bool loc = tm_type == COLLADAFW::Transformation::TRANSLATE;
+ if (is_joint)
+ BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale");
+ else
+ BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path));
+
+ switch (binding->animationClass) {
+ case COLLADAFW::AnimationList::POSITION_X:
+ modify_fcurve(curves, rna_path, 0 );
+ break;
+ case COLLADAFW::AnimationList::POSITION_Y:
+ modify_fcurve(curves, rna_path, 1 );
+ break;
+ case COLLADAFW::AnimationList::POSITION_Z:
+ modify_fcurve(curves, rna_path, 2 );
+ break;
+ case COLLADAFW::AnimationList::POSITION_XYZ:
+ modify_fcurve(curves, rna_path, -1 );
+ break;
+ default:
+ fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
+ binding->animationClass, loc ? "TRANSLATE" : "SCALE");
+ }
+ break;
+ }
+
+
+ case COLLADAFW::Transformation::ROTATE:
+ {
+ if (is_joint)
+ BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path);
+ else
+ BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path));
+ std::vector<FCurve*>::iterator iter;
+ for (iter = curves->begin(); iter != curves->end(); iter++) {
+ FCurve* fcu = *iter;
+
+ //if transform is rotation the fcurves values must be turned in to radian.
+ if (is_rotation)
+ fcurve_deg_to_rad(fcu);
+ }
+ COLLADAFW::Rotate* rot = (COLLADAFW::Rotate*)transform;
+ COLLADABU::Math::Vector3& axis = rot->getRotationAxis();
+
+ switch (binding->animationClass) {
+ case COLLADAFW::AnimationList::ANGLE:
+ if (COLLADABU::Math::Vector3::UNIT_X == axis) {
+ modify_fcurve(curves, rna_path, 0 );
+ }
+ else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
+ modify_fcurve(curves, rna_path, 1 );
+ }
+ else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
+ modify_fcurve(curves, rna_path, 2 );
+ }
+ break;
+ case COLLADAFW::AnimationList::AXISANGLE:
+ // TODO convert axis-angle to quat? or XYZ?
+ default:
+ fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n",
+ binding->animationClass);
+ }
+ break;
+ }
+
+ case COLLADAFW::Transformation::MATRIX:
+ case COLLADAFW::Transformation::SKEW:
+ case COLLADAFW::Transformation::LOOKAT:
+ fprintf(stderr, "Animation of MATRIX, SKEW and LOOKAT transformations is not supported yet.\n");
+ break;
+ }
+
+}
+void AnimationImporter::translate_Animations_NEW ( COLLADAFW::Node * node ,
+ std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
+ std::map<COLLADAFW::UniqueId, Object*>& object_map )
+{
+ bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
+
COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
- Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()];
+ Object *ob = is_joint ? armature_importer->get_armature_for_joint(root) : object_map[node->getUniqueId()];
+
const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
+
+ if ( ! is_object_animated(node) ) return ;
+
+ char joint_path[200];
+ if ( is_joint )
+ armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
+
+ bAction * act;
+ bActionGroup *grp = NULL;
+
+ if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID*)&ob->id, 1);
+ else act = ob->adt->action;
+ //Get the list of animation curves of the object
+
+ ListBase *AnimCurves = &(act->curves);
+
if (!ob) {
fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
- return NULL;
+ return;
}
- // frames at which to sample
- std::vector<float> frames;
+
+ /*float irest_dae[4][4];
+ float rest[4][4], irest[4][4];
+
+ if (is_joint) {
+ get_joint_rest_mat(irest_dae, root, node);
+ invert_m4(irest_dae);
+
+ Bone *bone = get_named_bone((bArmature*)ob->data, bone_name);
+ if (!bone) {
+ fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
+ return;
+ }
+
+ unit_m4(rest);
+ copy_m4_m4(rest, bone->arm_mat);
+ invert_m4_m4(irest, rest);
+ }*/
+
+ const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
+
+ //for each transformation in node
+ for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
+ COLLADAFW::Transformation *transform = nodeTransforms[i];
+ COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
+
+ bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
+ bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
+
+ const COLLADAFW::UniqueId& listid = transform->getAnimationList();
+
+ //might not be needed
+ std::vector<float> frames;
+
+ //check if transformation has animations
+ if (animlist_map.find(listid) == animlist_map.end()) continue ;
+ else
+ {
+ //transformation has animations
+ const COLLADAFW::AnimationList *animlist = animlist_map[listid];
+ const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
+ //all the curves belonging to the current binding
+ std::vector<FCurve*> animcurves;
+ for (unsigned int j = 0; j < bindings.getCount(); j++) {
+ animcurves = curve_map[bindings[j].animation];
+ //calculate rnapaths and array index of fcurves according to transformation and animation class
+ Assign_transform_animations(&frames,transform, &bindings[j], &animcurves, is_joint, joint_path );
+
+ std::vector<FCurve*>::iterator iter;
+ //Add the curves of the current animation to the object
+ for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
+ FCurve * fcu = *iter;
+ if (ob->type == OB_ARMATURE)
+ add_bone_fcurve( ob, node , fcu );
+ else
+ BLI_addtail(AnimCurves, fcu);
+ }
+ }
+ std::sort(frames.begin(), frames.end());
+ }
+ if (is_rotation || is_matrix) {
+ if (is_joint)
+ {
+ bPoseChannel *chan = get_pose_channel(ob->pose, bone_name);
+ chan->rotmode = ROT_MODE_EUL;
+ }
+ else
+ {
+ ob->rotmode = ROT_MODE_EUL;
+ }
+ }
+ }
+
+}
+
+//Check if object is animated by checking if animlist_map holds the animlist_id of node transforms
+bool AnimationImporter::is_object_animated ( const COLLADAFW::Node * node )
+{
+ bool exists = false;
+ const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
+
+ //for each transformation in node
+ for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
+ COLLADAFW::Transformation *transform = nodeTransforms[i];
+ const COLLADAFW::UniqueId& listid = transform->getAnimationList();
+
+ //check if transformation has animations
+ if (animlist_map.find(listid) == animlist_map.end()) continue ;
+ else
+ {
+ exists = true;
+ break;
+ }
+ }
+
+ return exists;
+}
+//XXX Is not used anymore.
+void AnimationImporter::find_frames_old(std::vector<float> * frames, COLLADAFW::Node * node , COLLADAFW::Transformation::TransformationType tm_type)
+{
+ bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
+ bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
// for each <rotate>, <translate>, etc. there is a separate Transformation
- const COLLADAFW::TransformationPointerArray& tms = node->getTransformations();
+ const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
unsigned int i;
-
// find frames at which to sample plus convert all rotation keys to radians
- for (i = 0; i < tms.getCount(); i++) {
- COLLADAFW::Transformation *tm = tms[i];
- COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
+ for (i = 0; i < nodeTransforms.getCount(); i++) {
+ COLLADAFW::Transformation *transform = nodeTransforms[i];
+ COLLADAFW::Transformation::TransformationType nodeTmType = transform->getTransformationType();
- if (type == tm_type) {
- const COLLADAFW::UniqueId& listid = tm->getAnimationList();
+ if (nodeTmType == tm_type) {
+ //get animation bindings for the current transformation
+ const COLLADAFW::UniqueId& listid = transform->getAnimationList();
+ //if transform is animated its animlist must exist.
if (animlist_map.find(listid) != animlist_map.end()) {
+
const COLLADAFW::AnimationList *animlist = animlist_map[listid];
const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
-
+
if (bindings.getCount()) {
+ //for each AnimationBinding get the fcurves which animate the transform
for (unsigned int j = 0; j < bindings.getCount(); j++) {
std::vector<FCurve*>& curves = curve_map[bindings[j].animation];
- bool xyz = ((type == COLLADAFW::Transformation::TRANSLATE || type == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
+ bool xyz = ((nodeTmType == COLLADAFW::Transformation::TRANSLATE || nodeTmType == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) {
std::vector<FCurve*>::iterator iter;
for (iter = curves.begin(); iter != curves.end(); iter++) {
FCurve *fcu = *iter;
-
+
+ //if transform is rotation the fcurves values must be turned in to radian.
if (is_rotation)
fcurve_deg_to_rad(fcu);
for (unsigned int k = 0; k < fcu->totvert; k++) {
+ //get frame value from bezTriple
float fra = fcu->bezt[k].vec[1][0];
- if (std::find(frames.begin(), frames.end(), fra) == frames.end())
- frames.push_back(fra);
+ //if frame already not added add frame to frames
+ if (std::find(frames->begin(), frames->end(), fra) == frames->end())
+ frames->push_back(fra);
}
}
}
@@ -583,7 +860,38 @@ Object *AnimationImporter::translate_animation(COLLADAFW::Node *node,
}
}
}
+}
+
+
+// prerequisites:
+// animlist_map - map animlist id -> animlist
+// curve_map - map anim id -> curve(s)
+Object *AnimationImporter::translate_animation(COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Object*>& object_map,
+ std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
+ COLLADAFW::Transformation::TransformationType tm_type,
+ Object *par_job)
+{
+
+ bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
+ bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
+ bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
+
+ COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
+ Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()];
+ const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
+ if (!ob) {
+ fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
+ return NULL;
+ }
+ // frames at which to sample
+ std::vector<float> frames;
+
+ find_frames_old(&frames, node , tm_type);
+
+ unsigned int i;
+
float irest_dae[4][4];
float rest[4][4], irest[4][4];
@@ -664,7 +972,6 @@ Object *AnimationImporter::translate_animation(COLLADAFW::Node *node,
BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
else
strcpy(rna_path, tm_str);
-
newcu[i] = create_fcurve(axis, rna_path);
#ifdef ARMATURE_TEST
diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h
index 05347a1fbc1..1e005b5c341 100644
--- a/source/blender/collada/AnimationImporter.h
+++ b/source/blender/collada/AnimationImporter.h
@@ -94,16 +94,35 @@ public:
#if 0
virtual void change_eul_to_quat(Object *ob, bAction *act);
#endif
+
+ void translate_Animations_NEW ( COLLADAFW::Node * Node ,
+ std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
+ std::map<COLLADAFW::UniqueId, Object*>& object_map );
+ bool is_object_animated ( const COLLADAFW::Node * node ) ;
+
+
+ void Assign_transform_animations(std::vector<float>* frames,
+ COLLADAFW::Transformation* transform ,
+ const COLLADAFW::AnimationList::AnimationBinding * binding,
+ std::vector<FCurve*>* curves, bool is_joint, char * joint_path);
+
+ /*void Assign_transform_animations(std::vector<float>* frames,
+ COLLADAFW::Transformation *transform ,
+ COLLADAFW::AnimationList::AnimationBinding * binding,
+ COLLADAFW::Node * node);*/
+ void modify_fcurve(std::vector<FCurve*>* curves , char* rna_path , int array_index );
// prerequisites:
// animlist_map - map animlist id -> animlist
// curve_map - map anim id -> curve(s)
- Object *translate_animation(COLLADAFW::Node *node,
+ Object * translate_animation(COLLADAFW::Node *node,
std::map<COLLADAFW::UniqueId, Object*>& object_map,
std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map,
COLLADAFW::Transformation::TransformationType tm_type,
Object *par_job = NULL);
-
+
+ void find_frames( std::vector<float>* frames , std::vector<FCurve*>* curves );
+ void find_frames_old( std::vector<float>* frames, COLLADAFW::Node * node, COLLADAFW::Transformation::TransformationType tm_type );
// internal, better make it private
// warning: evaluates only rotation
// prerequisites: animlist_map, curve_map
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index 8b8e89fd4f5..48e0d99535b 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -78,6 +78,67 @@ JointData *ArmatureImporter::get_joint_data(COLLADAFW::Node *node);
return &joint_index_to_joint_info_map[joint_index];
}
#endif
+void ArmatureImporter::create_unskinned_bone( COLLADAFW::Node *node, EditBone *parent, int totchild,
+ float parent_mat[][4], bArmature *arm)
+{
+ float mat[4][4];
+ float obmat[4][4];
+
+ // object-space
+ get_node_mat(obmat, node, NULL, NULL);
+
+ // get world-space
+ if (parent)
+ mul_m4_m4m4(mat, obmat, parent_mat);
+ else
+ copy_m4_m4(mat, obmat);
+
+ EditBone *bone = ED_armature_edit_bone_add(arm, (char*)bc_get_joint_name(node));
+ totbone++;
+
+ if (parent) bone->parent = parent;
+
+ // set head
+ copy_v3_v3(bone->head, mat[3]);
+
+ // set tail, don't set it to head because 0-length bones are not allowed
+ float vec[3] = {0.0f, 0.5f, 0.0f};
+ add_v3_v3v3(bone->tail, bone->head, vec);
+
+ // set parent tail
+ if (parent && totchild == 1) {
+ copy_v3_v3(parent->tail, bone->head);
+
+ // not setting BONE_CONNECTED because this would lock child bone location with respect to parent
+ // bone->flag |= BONE_CONNECTED;
+
+ // XXX increase this to prevent "very" small bones?
+ const float epsilon = 0.000001f;
+
+ // derive leaf bone length
+ float length = len_v3v3(parent->head, parent->tail);
+ if ((length < leaf_bone_length || totbone == 0) && length > epsilon) {
+ leaf_bone_length = length;
+ }
+
+ // treat zero-sized bone like a leaf bone
+ if (length <= epsilon) {
+ add_leaf_bone(parent_mat, parent);
+ }
+
+ }
+
+ COLLADAFW::NodePointerArray& children = node->getChildNodes();
+ for (unsigned int i = 0; i < children.getCount(); i++) {
+ create_unskinned_bone( children[i], bone, children.getCount(), mat, arm);
+ }
+
+ // in second case it's not a leaf bone, but we handle it the same way
+ if (!children.getCount() || children.getCount() > 1) {
+ add_leaf_bone(mat, bone);
+ }
+
+}
void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
float parent_mat[][4], bArmature *arm)
@@ -300,6 +361,47 @@ ArmatureJoints& ArmatureImporter::get_armature_joints(Object *ob_arm)
return armature_joints.back();
}
#endif
+void ArmatureImporter::create_armature_bones( )
+{
+ std::vector<COLLADAFW::Node*>::iterator ri;
+ //if there is an armature created for root_joint next root_joint
+ for (ri = root_joints.begin(); ri != root_joints.end(); ri++) {
+ if ( get_armature_for_joint(*ri) != NULL ) continue;
+
+ //add armature object for current joint
+ //Object *ob_arm = add_object(scene, OB_ARMATURE);
+
+ Object *ob_arm = joint_parent_map[(*ri)->getUniqueId()];
+ //ob_arm->type = OB_ARMATURE;
+ ED_armature_to_edit(ob_arm);
+
+ // min_angle = 360.0f; // minimum angle between bone head-tail and a row of bone matrix
+
+ // create unskinned bones
+ /*
+ TODO:
+ check if bones have already been created for a given joint
+ */
+ leaf_bone_length = FLT_MAX;
+ create_unskinned_bone(*ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature*)ob_arm->data);
+
+ fix_leaf_bones();
+
+ // exit armature edit mode
+
+
+ //if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && ob_arm->parent!=NULL)
+ // ob_arm->parent = joint_parent_map[(*ri)->getUniqueId()];
+
+ unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
+
+ ED_armature_from_edit(ob_arm);
+ ED_armature_edit_free(ob_arm);
+ DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB|OB_RECALC_DATA);
+ }
+
+
+}
void ArmatureImporter::create_armature_bones(SkinInfo& skin)
{
@@ -373,7 +475,7 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
if (shared)
ob_arm = skin.set_armature(shared);
else
- ob_arm = skin.create_armature(scene);
+ ob_arm = skin.create_armature(scene); //once for every armature
// enter armature edit mode
ED_armature_to_edit(ob_arm);
@@ -413,21 +515,24 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB|OB_RECALC_DATA);
// set_leaf_bone_shapes(ob_arm);
- // set_euler_rotmode();
+ // set_euler_rotmode();
}
// root - if this joint is the top joint in hierarchy, if a joint
// is a child of a node (not joint), root should be true since
// this is where we build armature bones from
-void ArmatureImporter::add_joint(COLLADAFW::Node *node, bool root, Object *parent)
+
+void ArmatureImporter::add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce)
{
joint_by_uid[node->getUniqueId()] = node;
if (root) {
root_joints.push_back(node);
- if (parent)
+ if (parent) {
+
joint_parent_map[node->getUniqueId()] = parent;
+ }
}
}
@@ -472,6 +577,9 @@ void ArmatureImporter::make_armatures(bContext *C)
// free memory stolen from SkinControllerData
skin.free();
}
+
+ create_armature_bones();
+
}
#if 0
@@ -566,7 +674,12 @@ Object *ArmatureImporter::get_armature_for_joint(COLLADAFW::Node *node)
if (skin.uses_joint_or_descendant(node))
return skin.get_armature();
}
-
+
+ std::map<COLLADAFW::UniqueId, Object*>::iterator arm;
+ for (arm = unskinned_armature_map.begin(); arm != unskinned_armature_map.end(); arm++) {
+ if(arm->first == node->getUniqueId() )
+ return arm->second;
+ }
return NULL;
}
diff --git a/source/blender/collada/ArmatureImporter.h b/source/blender/collada/ArmatureImporter.h
index d36bccf7e57..f9cb09dca19 100644
--- a/source/blender/collada/ArmatureImporter.h
+++ b/source/blender/collada/ArmatureImporter.h
@@ -89,6 +89,7 @@ private:
std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> joint_by_uid; // contains all joints
std::vector<COLLADAFW::Node*> root_joints;
std::map<COLLADAFW::UniqueId, Object*> joint_parent_map;
+ std::map<COLLADAFW::UniqueId, Object*> unskinned_armature_map;
MeshImporterBase *mesh_importer;
AnimationImporterBase *anim_importer;
@@ -105,6 +106,9 @@ private:
void create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
float parent_mat[][4], bArmature *arm);
+ void create_unskinned_bone(COLLADAFW::Node *node, EditBone *parent, int totchild,
+ float parent_mat[][4], bArmature *arm);
+
void add_leaf_bone(float mat[][4], EditBone *bone);
void fix_leaf_bones();
@@ -123,6 +127,7 @@ private:
#endif
void create_armature_bones(SkinInfo& skin);
+ void create_armature_bones( );
public:
@@ -132,7 +137,7 @@ public:
// root - if this joint is the top joint in hierarchy, if a joint
// is a child of a node (not joint), root should be true since
// this is where we build armature bones from
- void add_joint(COLLADAFW::Node *node, bool root, Object *parent);
+ void add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce);
#if 0
void add_root_joint(COLLADAFW::Node *node);
diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt
index 07da532146f..260dd1a7073 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/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp
index 78ee444bb4e..14ce9a9b417 100644
--- a/source/blender/collada/DocumentImporter.cpp
+++ b/source/blender/collada/DocumentImporter.cpp
@@ -250,12 +250,13 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
unsigned int i;
Object *ob;
- for (i = 0; i < 4; i++)
- ob = anim_importer.translate_animation(node, object_map, root_map, types[i]);
+ //for (i = 0; i < 4; i++)
+ //ob =
+ anim_importer.translate_Animations_NEW(node, root_map, object_map);
COLLADAFW::NodePointerArray &children = node->getChildNodes();
for (i = 0; i < children.getCount(); i++) {
- translate_anim_recursive(children[i], node, ob);
+ translate_anim_recursive(children[i], node, NULL);
}
}
@@ -382,7 +383,14 @@ void DocumentImporter::write_node (COLLADAFW::Node *node, COLLADAFW::Node *paren
bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
if (is_joint) {
- armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par);
+ if ( par ) {
+ Object * empty = par;
+ par = add_object(sce, OB_ARMATURE);
+ bc_set_parent(par,empty->parent, mContext);
+ //remove empty : todo
+ object_map[parent_node->getUniqueId()] = par;
+ }
+ armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
}
else {
COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index 83b9449c8f2..ce0d561c524 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -308,11 +308,15 @@ void SkinInfo::find_root_joints(const std::vector<COLLADAFW::Node*> &root_joints
std::vector<COLLADAFW::Node*>& result)
{
std::vector<COLLADAFW::Node*>::const_iterator it;
+ // for each root_joint
for (it = root_joints.begin(); it != root_joints.end(); it++) {
COLLADAFW::Node *root = *it;
std::vector<JointData>::iterator ji;
+ //for each joint_data in this skin
for (ji = joint_data.begin(); ji != joint_data.end(); ji++) {
+ //get joint node from joint map
COLLADAFW::Node *joint = joint_by_uid[(*ji).joint_uid];
+ //find if joint node is in the tree belonging to the root_joint
if (find_node_in_tree(joint, root)) {
if (std::find(result.begin(), result.end(), root) == result.end())
result.push_back(root);
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 9145cc2b79d..9eb9e3ecd9a 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 c6e55427034..1fb2317cdbb 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -1500,3 +1500,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..8197d6b25dd 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -604,7 +604,7 @@ static void draw_modifier__stepped(uiLayout *layout, ID *id, FModifier *fcm, sho
void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifiers, FModifier *fcm)
{
FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
- uiLayout *box, *row, *subrow;
+ uiLayout *box, *row, *subrow, *col;
uiBlock *block;
uiBut *but;
short width= 314;
@@ -622,7 +622,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie
block= uiLayoutGetBlock(row); // err...
/* left-align -------------------------------------------- */
- subrow= uiLayoutRow(row, 0);
+ subrow= uiLayoutRow(row, 1);
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
uiBlockSetEmboss(block, UI_EMBOSSN);
@@ -640,7 +640,7 @@ void ANIM_uiTemplate_fmodifier_draw (uiLayout *layout, ID *id, ListBase *modifie
uiItemL(subrow, "<Unknown Modifier>", ICON_NONE);
/* right-align ------------------------------------------- */
- subrow= uiLayoutRow(row, 0);
+ subrow= uiLayoutRow(row, 1);
uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
@@ -694,6 +694,44 @@ 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);
+
+ /* restricted range ----------------------------------------------------- */
+ col = uiLayoutColumn(box, 1);
+
+ /* top row: use restricted range */
+ row= uiLayoutRow(col, 1);
+ uiItemR(row, &ptr, "use_restricted_range", 0, NULL, ICON_NONE);
+
+ if (fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) {
+ /* second row: settings */
+ row = uiLayoutRow(col, 1);
+
+ uiItemR(row, &ptr, "frame_start", 0, "Start", ICON_NONE);
+ uiItemR(row, &ptr, "frame_end", 0, "End", ICON_NONE);
+
+ /* third row: blending influence */
+ row = uiLayoutRow(col, 1);
+
+ uiItemR(row, &ptr, "blend_in", 0, "In", ICON_NONE);
+ uiItemR(row, &ptr, "blend_out", 0, "Out", ICON_NONE);
+ }
+
+ /* influence -------------------------------------------------------------- */
+ col = uiLayoutColumn(box, 1);
+
+ /* top row: use influence */
+ uiItemR(col, &ptr, "use_influence", 0, NULL, ICON_NONE);
+
+ if (fcm->flag & FMODIFIER_FLAG_USEINFLUENCE) {
+ /* second row: influence value */
+ uiItemR(col, &ptr, "influence", 0, NULL, 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..69e7c4eb73a 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -224,6 +224,7 @@ static int add_empty_ks_path_exec (bContext *C, wmOperator *op)
ksp->groupmode= KSP_GROUP_KSNAME; // XXX?
ksp->idtype= ID_OB;
+ ksp->flag= KSP_FLAG_WHOLE_ARRAY;
return OPERATOR_FINISHED;
}
@@ -782,19 +783,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/interface_style.c b/source/blender/editors/interface/interface_style.c
index 2e4106b3c04..1352648b271 100644
--- a/source/blender/editors/interface/interface_style.c
+++ b/source/blender/editors/interface/interface_style.c
@@ -295,6 +295,7 @@ void uiStyleInit(void)
{
uiFont *font= U.uifonts.first;
uiStyle *style= U.uistyles.first;
+ int defaultFontId = -1;
/* recover from uninitialized dpi */
if(U.dpi == 0)
@@ -314,6 +315,7 @@ void uiStyleInit(void)
if(font->uifont_id==UIFONT_DEFAULT) {
font->blf_id= BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
+ defaultFontId = font->blf_id;
}
else {
font->blf_id= BLF_load(font->filename);
@@ -351,6 +353,14 @@ void uiStyleInit(void)
blf_mono_font_render= BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size);
BLF_size(blf_mono_font_render, 12, 72);
+
+ /* also another copy of default for rendering else we get threading problems */
+ if (defaultFontId != -1) {
+ if (blf_default_font_render == -1)
+ blf_default_font_render= BLF_load_mem_unique("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);
+
+ BLF_size(blf_default_font_render, 12, 72);
+ }
}
void uiStyleFontSet(uiFontStyle *fs)
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 3f825762d74..7cb274f04c6 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_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index fb1144b4fa8..3073ff13075 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -472,7 +472,7 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
- uiItemR(col, &dtar_ptr, "use_local_space_transform", 0, NULL, ICON_NONE);
+ uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE);
col= uiLayoutColumn(layout, 1);
uiTemplateAnyID(col, &dtar2_ptr, "id", "id_type", "Ob/Bone 2:");
@@ -484,7 +484,7 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
- uiItemR(col, &dtar2_ptr, "use_local_space_transform", 0, NULL, ICON_NONE);
+ uiItemR(col, &dtar2_ptr, "transform_space", 0, NULL, ICON_NONE);
}
/* settings for 'transform channel' driver variable type */
@@ -493,7 +493,7 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
DriverTarget *dtar= &dvar->targets[0];
Object *ob = (Object *)dtar->id;
PointerRNA dtar_ptr;
- uiLayout *col, *row;
+ uiLayout *col, *subcol;
/* initialise RNA pointer to the target */
RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
@@ -509,9 +509,9 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
- row= uiLayoutRow(layout, 1);
- uiItemR(row, &dtar_ptr, "transform_type", 0, "", ICON_NONE);
- uiItemR(row, &dtar_ptr, "use_local_space_transform", 0, NULL, ICON_NONE);
+ subcol= uiLayoutColumn(layout, 1);
+ uiItemR(subcol, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE);
+ uiItemR(subcol, &dtar_ptr, "transform_space", 0, "Space", ICON_NONE);
}
/* driver settings for active F-Curve (only for 'Drivers' mode) */
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 019ce2a714a..c1fc27eb9f3 100644
--- a/source/blender/editors/space_logic/logic_window.c
+++ b/source/blender/editors/space_logic/logic_window.c
@@ -3677,16 +3677,22 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
{
Object *ob = (Object *)ptr->id.data;
PointerRNA settings_ptr;
- uiLayout *row;
+ uiLayout *row, *subrow, *col;;
- 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);
uiItemR(row, ptr, "play_mode", 0, "", ICON_NONE);
+
+ subrow= uiLayoutRow(row, 1);
+ uiItemR(subrow, ptr, "use_force", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+ uiItemR(subrow, ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+
+ col = uiLayoutColumn(subrow, 0);
+ uiLayoutSetActive(col, (RNA_boolean_get(ptr, "use_additive") || RNA_boolean_get(ptr, "use_force")));
+ uiItemR(col, ptr, "use_local", UI_ITEM_R_TOGGLE, NULL, ICON_NONE);
+
+ row= uiLayoutRow(layout, 0);
uiItemR(row, ptr, "action", 0, "", ICON_NONE);
uiItemR(row, ptr, "use_continue_last_frame", 0, NULL, ICON_NONE);
@@ -3699,11 +3705,16 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
uiItemR(row, ptr, "frame_end", 0, NULL, ICON_NONE);
}
+ uiItemR(row, ptr, "apply_to_children", 0, NULL, ICON_NONE);
+
row= uiLayoutRow(layout, 0);
uiItemR(row, ptr, "frame_blend_in", 0, NULL, ICON_NONE);
uiItemR(row, ptr, "priority", 0, NULL, ICON_NONE);
row= uiLayoutRow(layout, 0);
+ uiItemR(row, ptr, "layer", 0, NULL, ICON_NONE);
+
+ row= uiLayoutRow(layout, 0);
uiItemPointerR(layout, ptr, "frame_property", &settings_ptr, "properties", NULL, ICON_NONE);
#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
@@ -3977,6 +3988,7 @@ static void draw_actuator_game(uiLayout *layout, PointerRNA *ptr)
uiItemR(layout, ptr, "filename", 0, NULL, ICON_NONE);
}
+/* The IPO/Fcurve actuator has been deprecated, so this is no longer used */
static void draw_actuator_ipo(uiLayout *layout, PointerRNA *ptr)
{
Object *ob;
@@ -4397,9 +4409,6 @@ static void draw_brick_actuator(uiLayout *layout, PointerRNA *ptr, bContext *C)
case ACT_GAME:
draw_actuator_game(box, ptr);
break;
- case ACT_IPO:
- draw_actuator_ipo(box, ptr);
- break;
case ACT_MESSAGE:
draw_actuator_message(box, ptr, C);
break;
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_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 119c5da309e..e1efd5b4622 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -127,6 +127,7 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
case SEQ_GLOW:
case SEQ_MULTICAM:
case SEQ_ADJUSTMENT:
+ case SEQ_TITLECARD:
UI_GetThemeColor3ubv(TH_SEQ_EFFECT, col);
/* slightly offset hue to distinguish different effects */
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index c8965c4d3db..46638007fb1 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -98,9 +98,10 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
{SEQ_GLOW, "GLOW", 0, "Glow", "Glow effect strip type"},
{SEQ_TRANSFORM, "TRANSFORM", 0, "Transform", "Transform effect strip type"},
{SEQ_COLOR, "COLOR", 0, "Color", "Color effect strip type"},
- {SEQ_SPEED, "SPEED", 0, "Speed", "Color effect strip type"},
+ {SEQ_SPEED, "SPEED", 0, "Speed", ""},
{SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TITLECARD, "TITLE_CARD", 0, "Title Card", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -408,6 +409,7 @@ int event_to_efftype(int event)
if(event==16) return SEQ_COLOR;
if(event==17) return SEQ_SPEED;
if(event==18) return SEQ_ADJUSTMENT;
+ if(event==19) return SEQ_TITLECARD;
return 0;
}
@@ -520,7 +522,8 @@ static void change_sequence(Scene *scene)
"|Transform%x15"
"|Color Generator%x16"
"|Speed Control%x17"
- "|Adjustment Layer%x18");
+ "|Adjustment Layer%x18"
+ "|Title Card%x19");
if(event > 0) {
if(event==1) {
SWAP(Sequence *,last_seq->seq1,last_seq->seq2);
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 625e5561389..28230b7a48b 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -907,9 +907,12 @@ static void text_update_drawcache(SpaceText *st, ARegion *ar)
void text_drawcache_tag_update(SpaceText *st, int full)
{
- DrawCache *drawcache= (DrawCache *)st->drawcache;
-
- if(drawcache) {
+ /* this happens if text editor ops are caled from python */
+ if (st == NULL)
+ return;
+
+ if(st->drawcache) {
+ DrawCache *drawcache= (DrawCache *)st->drawcache;
Text *txt= st->text;
if(drawcache->update_flag) {
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index 02a7ea890f5..29f40ec9dd0 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 181fb0f0aac..b8369d8cbff 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);
}
}
@@ -5783,8 +5804,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 669c3195dfd..34d206f9d6b 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_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index 887a0300ee2..071f66cddd6 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -56,8 +56,10 @@ typedef struct bActionActuator {
char frameProp[32]; /* Set this property to the actions current frame */
short blendin; /* Number of frames of blending */
short priority; /* Execution priority */
+ short layer; /* Animation layer */
short end_reset; /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */
short strideaxis; /* Displacement axis */
+ short pad[3];
float stridelength; /* Displacement incurred by cycle */ // not in use
} bActionActuator;
@@ -120,6 +122,7 @@ typedef struct bObjectActuator {
struct Object *reference;
} bObjectActuator;
+/* deprecated, handled by bActionActuator now */
typedef struct bIpoActuator {
short flag, type;
float sta, end;
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 4b649031f97..00a9786fc6f 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -62,6 +62,11 @@ 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 */
+ float blendin; /* number of frames from sfra before modifier takes full influence */
+ float blendout; /* number of frames from efra before modifier fades out */
} FModifier;
/* Types of F-Curve modifier
@@ -86,13 +91,17 @@ 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),
+ /* use influence control */
+ FMODIFIER_FLAG_USEINFLUENCE = (1<<5)
} eFModifier_Flags;
/* --- */
@@ -280,8 +289,12 @@ typedef enum eDriverTarget_Flag {
DTAR_FLAG_STRUCT_REF = (1<<0),
/* idtype can only be 'Object' */
DTAR_FLAG_ID_OB_ONLY = (1<<1),
- /* toggles localspace (where transforms are manually obtained) */
+
+ /* "localspace" flags */
+ /* base flag - basically "pre parent+constraints" */
DTAR_FLAG_LOCALSPACE = (1<<2),
+ /* include constraints transformed to space including parents */
+ DTAR_FLAG_LOCAL_CONSTS = (1<<3),
} eDriverTarget_Flag;
/* Transform Channels for Driver Targets */
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/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 3e7654bcf47..b9bea7a89b0 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -227,6 +227,14 @@ typedef struct SolidColorVars {
float pad;
} SolidColorVars;
+typedef struct TitleCardVars {
+ char titlestr[64];
+ char subtitle[128];
+
+ float fgcol[3];
+ float bgcol[3];
+} TitleCardVars;
+
typedef struct SpeedControlVars {
float * frameMap;
float globalSpeed;
@@ -314,7 +322,8 @@ typedef struct SpeedControlVars {
#define SEQ_SPEED 29
#define SEQ_MULTICAM 30
#define SEQ_ADJUSTMENT 31
-#define SEQ_EFFECT_MAX 31
+#define SEQ_TITLECARD 40
+#define SEQ_EFFECT_MAX 40
#define STRIPELEM_FAILED 0
#define STRIPELEM_OK 1
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index ae57cf3f80b..4757c112b09 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -435,6 +435,7 @@ extern UserDef U; /* from blenkernel blender.c */
#define USER_NONEGFRAMES (1 << 24)
#define USER_TXT_TABSTOSPACES_DISABLE (1 << 25)
#define USER_TOOLTIPS_PYTHON (1 << 26)
+#define USER_NO_RECENTLOAD_UPDATE (1 << 27)
/* helper macro for checking frame clamping */
#define FRAMENUMBER_MIN_CLAMP(cfra) \
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 882fbce9271..49bc10a0675 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -534,6 +534,7 @@ extern StructRNA RNA_ThemeWidgetColors;
extern StructRNA RNA_ThemeWidgetStateColors;
extern StructRNA RNA_TimelineMarker;
extern StructRNA RNA_Timer;
+extern StructRNA RNA_TitleCardSequence;
extern StructRNA RNA_ToolSettings;
extern StructRNA RNA_TouchSensor;
extern StructRNA RNA_TrackToConstraint;
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 8fbee8ea740..a632c5c646e 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -3188,7 +3188,7 @@ static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int
/* 2 kinds of lookups now, quoted or unquoted */
quote= *p;
- if(quote != '"')
+ if(quote != '"') /* " - this comment is hack for Aligorith's text editor's sanity */
quote= 0;
if(quote==0) {
diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c
index cddba59f979..5f532d7bb31 100644
--- a/source/blender/makesrna/intern/rna_actuator.c
+++ b/source/blender/makesrna/intern/rna_actuator.c
@@ -49,7 +49,6 @@ EnumPropertyItem actuator_type_items[] ={
{ACT_CAMERA, "CAMERA", 0, "Camera", ""},
{ACT_CONSTRAINT, "CONSTRAINT", 0, "Constraint", ""},
{ACT_EDIT_OBJECT, "EDIT_OBJECT", 0, "Edit Object", ""},
- {ACT_IPO, "FCURVE", 0, "F-Curve", ""},
{ACT_2DFILTER, "FILTER_2D", 0, "Filter 2D", ""},
{ACT_GAME, "GAME", 0, "Game", ""},
{ACT_MESSAGE, "MESSAGE", 0, "Message", ""},
@@ -77,8 +76,6 @@ static StructRNA* rna_Actuator_refine(struct PointerRNA *ptr)
return &RNA_ActionActuator;
case ACT_OBJECT:
return &RNA_ObjectActuator;
- case ACT_IPO:
- return &RNA_FCurveActuator;
case ACT_CAMERA:
return &RNA_CameraActuator;
case ACT_SOUND:
@@ -353,6 +350,29 @@ static void rna_FcurveActuator_force_set(struct PointerRNA *ptr, int value)
ia->flag &= ~ACT_IPOFORCE;
}
+static void rna_ActionActuator_add_set(struct PointerRNA *ptr, int value)
+{
+ bActuator *act = (bActuator *)ptr->data;
+ bActionActuator *aa = act->data;
+
+ if(value == 1){
+ aa->flag &= ~ACT_IPOFORCE;
+ aa->flag |= ACT_IPOADD;
+ }else
+ aa->flag &= ~ACT_IPOADD;
+}
+
+static void rna_ActionActuator_force_set(struct PointerRNA *ptr, int value)
+{
+ bActuator *act = (bActuator *)ptr->data;
+ bActionActuator *aa = act->data;
+
+ if(value == 1){
+ aa->flag &= ~ACT_IPOADD;
+ aa->flag |= ACT_IPOFORCE;
+ }else
+ aa->flag &= ~ACT_IPOFORCE;
+}
static void rna_ObjectActuator_type_set(struct PointerRNA *ptr, int value)
{
@@ -426,15 +446,14 @@ 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);
- RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_IPO);
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_2DFILTER);
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_GAME);
RNA_enum_items_add_value(&item, &totitem, actuator_type_items, ACT_MESSAGE);
@@ -616,11 +635,39 @@ static void rna_def_action_actuator(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Priority", "Execution priority - lower numbers will override actions with higher numbers. With 2 or more actions at once, the overriding channels must be lower in the stack");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+ prop= RNA_def_property(srna, "layer", PROP_INT, PROP_NONE);
+ RNA_def_property_range(prop, 0, 4); /* This should match BL_ActionManager::MAX_ACTION_LAYERS */
+ RNA_def_property_ui_text(prop, "Layer", "The animation layer to play the action on");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
prop= RNA_def_property(srna, "frame_property", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "frameProp");
RNA_def_property_ui_text(prop, "Frame Property", "Assign the action's current frame number to this property");
RNA_def_property_update(prop, NC_LOGIC, NULL);
+ /* booleans */
+ prop= RNA_def_property(srna, "use_additive", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_IPOADD);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_ActionActuator_add_set");
+ RNA_def_property_ui_text(prop, "Add", "Action is added to the current loc/rot/scale in global or local coordinate according to Local flag");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop= RNA_def_property(srna, "use_force", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_IPOFORCE);
+ RNA_def_property_boolean_funcs(prop, NULL, "rna_ActionActuator_force_set");
+ RNA_def_property_ui_text(prop, "Force", "Apply Action as a global or local force depending on the local option (dynamic objects only)");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop= RNA_def_property(srna, "use_local", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_IPOLOCAL);
+ RNA_def_property_ui_text(prop, "L", "Let the Action act in local coordinates, used in Force and Add mode");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
+ prop= RNA_def_property(srna, "apply_to_children", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_IPOCHILD);
+ RNA_def_property_ui_text(prop, "Child", "Update Action on all children Objects as well");
+ RNA_def_property_update(prop, NC_LOGIC, NULL);
+
#ifdef __NLA_ACTION_BY_MOTION_ACTUATOR
prop= RNA_def_property(srna, "stride_length", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "stridelength");
@@ -815,6 +862,7 @@ static void rna_def_object_actuator(BlenderRNA *brna)
RNA_def_property_update(prop, NC_LOGIC, NULL);
}
+/* The fcurve actuator has been replace with the action actuator, so this is no longer used */
static void rna_def_fcurve_actuator(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1957,7 +2005,6 @@ void RNA_def_actuator(BlenderRNA *brna)
rna_def_action_actuator(brna);
rna_def_object_actuator(brna);
- rna_def_fcurve_actuator(brna);
rna_def_camera_actuator(brna);
rna_def_sound_actuator(brna);
rna_def_property_actuator(brna);
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 7f817aa5b4b..d523a01dc2c 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -76,6 +76,10 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
ID *ownerId = (ID *)ptr->id.data;
AnimData *adt = (AnimData *)ptr->data;
+ /* manage usercount for current action */
+ if (adt->action)
+ id_us_min((ID*)adt->action);
+
/* assume that AnimData's action can in fact be edited... */
if ((value.data) && (ownerId)) {
bAction *act = (bAction *)value.data;
@@ -85,6 +89,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
if (ELEM(act->idroot, 0, GS(ownerId->name))) {
/* can set */
adt->action = act;
+ id_us_plus((ID*)adt->action);
}
else {
/* cannot set */
@@ -98,6 +103,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value)
act->id.name+2);
adt->action = act;
+ id_us_plus((ID*)adt->action);
}
}
else {
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..ab3665fb8ff 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -454,6 +454,30 @@ 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_blending_range(PointerRNA *ptr, float *min, float *max)
+{
+ FModifier *fcm= (FModifier*)ptr->data;
+
+ *min= 0.0f;
+ *max= fcm->efra - fcm->sfra;
+}
+
static void rna_FModifier_active_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
FModifier *fm, *fmo= (FModifier*)ptr->data;
@@ -1015,6 +1039,51 @@ 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);
+
+ prop= RNA_def_property(srna, "blend_in", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "blendin");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_blending_range");
+ RNA_def_property_ui_text(prop, "Blend In", "Number of frames from start frame for influence to take effect");
+ RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
+
+ prop= RNA_def_property(srna, "blend_out", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "blendout");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_FModifier_blending_range");
+ RNA_def_property_ui_text(prop, "Blend Out", "Number of frames from start frame for influence to fade out");
+ RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
+
+ /* influence */
+ prop= RNA_def_property(srna, "use_influence", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FMODIFIER_FLAG_USEINFLUENCE);
+ RNA_def_property_ui_text(prop, "Use Influence", "F-Curve Modifier's effects will be tempered by a default factor");
+ 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, "influence", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "influence");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Influence", "Amount of influence F-Curve Modifier will have when not fading in/out");
+ RNA_def_property_update(prop, NC_ANIMATION|ND_KEYFRAME_PROP, NULL);
}
/* *********************** */
@@ -1035,6 +1104,12 @@ static void rna_def_drivertarget(BlenderRNA *brna)
{DTAR_TRANSCHAN_SCALEY, "SCALE_Y", 0, "Y Scale", ""},
{DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""},
{0, NULL, 0, NULL, NULL}};
+
+ static EnumPropertyItem prop_local_space_items[] = {
+ {0, "WORLD_SPACE", 0, "World Space", "Transforms include effects of parenting/restpose and constraints"},
+ {DTAR_FLAG_LOCALSPACE, "TRANSFORM_SPACE", 0, "Transform Space", "Transforms don't include parenting/restpose or constraints"},
+ {DTAR_FLAG_LOCALSPACE|DTAR_FLAG_LOCAL_CONSTS, "LOCAL_SPACE", 0, "Local Space", "Transforms include effects of constraints but not parenting/restpose"},
+ {0, NULL, 0, NULL, NULL}};
srna= RNA_def_struct(brna, "DriverTarget", NULL);
RNA_def_struct_ui_text(srna, "Driver Target", "Source of input values for driver variables");
@@ -1075,9 +1150,10 @@ static void rna_def_drivertarget(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Type", "Driver variable type");
RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
- prop= RNA_def_property(srna, "use_local_space_transform", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", DTAR_FLAG_LOCALSPACE);
- RNA_def_property_ui_text(prop, "Local Space", "Use transforms in Local Space (as opposed to the worldspace default)");
+ prop= RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+ RNA_def_property_enum_items(prop, prop_local_space_items);
+ RNA_def_property_ui_text(prop, "Transform Space", "Space in which transforms are used");
RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
}
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 8c4e4d9e736..eb2d38e9778 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -418,6 +418,8 @@ static StructRNA* rna_Sequence_refine(struct PointerRNA *ptr)
return &RNA_ColorSequence;
case SEQ_SPEED:
return &RNA_SpeedControlSequence;
+ case SEQ_TITLECARD:
+ return &RNA_TitleCardSequence;
default:
return &RNA_Sequence;
}
@@ -886,6 +888,7 @@ static void rna_def_sequence(BlenderRNA *brna)
{SEQ_SPEED, "SPEED", 0, "Speed", ""},
{SEQ_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
{SEQ_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
+ {SEQ_TITLECARD, "TITLE_CARD", 0, "Title Card", ""},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem blend_mode_items[]= {
@@ -1666,6 +1669,37 @@ static void rna_def_speed_control(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
}
+static void rna_def_title_card(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "TitleCardSequence", "EffectSequence");
+ RNA_def_struct_ui_text(srna, "Title Card Sequence", "Sequence strip creating an image displaying some text on a plain color background");
+ RNA_def_struct_sdna_from(srna, "TitleCardVars", "effectdata");
+
+ /* texts */
+ prop= RNA_def_property(srna, "title", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "titlestr");
+ RNA_def_property_ui_text(prop, "Title", "Text for main heading");
+ RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
+
+ prop= RNA_def_property(srna, "subtitle", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Subtitle", "Additional text to be shown under the main heading");
+ RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
+
+ /* colors */
+ prop= RNA_def_property(srna, "color_background", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "bgcol");
+ RNA_def_property_ui_text(prop, "Background Color", "");
+ RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
+
+ prop= RNA_def_property(srna, "color_foreground", PROP_FLOAT, PROP_COLOR);
+ RNA_def_property_float_sdna(prop, NULL, "fgcol");
+ RNA_def_property_ui_text(prop, "Text Color", "");
+ RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update");
+}
+
void RNA_def_sequencer(BlenderRNA *brna)
{
rna_def_strip_element(brna);
@@ -1691,6 +1725,7 @@ void RNA_def_sequencer(BlenderRNA *brna)
rna_def_transform(brna);
rna_def_solid_color(brna);
rna_def_speed_control(brna);
+ rna_def_title_card(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 1bdb21d2d00..23060ba1aee 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -2902,7 +2902,11 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
prop= RNA_def_property(srna, "recent_files", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 30);
RNA_def_property_ui_text(prop, "Recent Files", "Maximum number of recently opened files to remember");
-
+
+ prop= RNA_def_property(srna, "use_update_recent_files_on_load", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", USER_NO_RECENTLOAD_UPDATE);
+ RNA_def_property_ui_text(prop, "Update Recent on Load", "When enabled, opening files will update the recent files list. Otherwise, updates only occur when saving");
+
prop= RNA_def_property(srna, "use_save_preview_images", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_SAVE_PREVIEWS);
RNA_def_property_ui_text(prop, "Save Preview Images", "Enables automatic saving of preview images in the .blend file");
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index c088d0d2d43..79ec0360ac6 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -376,7 +376,12 @@ void WM_read_file(bContext *C, const char *filepath, ReportList *reports)
if (retval != BKE_READ_FILE_FAIL) {
G.relbase_valid = 1;
- if(!G.background) /* assume automated tasks with background, dont write recent file list */
+
+ /* dont write recent file list if:
+ * 1) assuming automated tasks with background
+ * 2) user preference to not do this is enabled (i.e. developer testing mode)
+ */
+ if (!G.background && !(U.flag & USER_NO_RECENTLOAD_UPDATE))
write_history();
}