#include "BLI_dynstr.h"
#include "BLI_utildefines.h"
+#include "DNA_anim_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "ED_object.h"
#include "ED_armature.h"
+#include "ED_keyframing.h"
#include "ED_screen.h"
#include "UI_interface.h"
edit_constraint_properties(ot);
}
+/* --------------- Follow Path Constraint ------------------ */
+
+static int followpath_path_animate_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
+ bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL;
+
+ bAction *act = NULL;
+ FCurve *fcu = NULL;
+ int sfra = RNA_int_get(op->ptr, "frame_start");
+ int len = RNA_int_get(op->ptr, "length");
+ float standardRange = 1.0;
+
+ /* nearly impossible sanity check */
+ if (data == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Follow Path constraint not found");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* add F-Curve as appropriate */
+ if (data->tar) {
+ Curve *cu = (Curve *)data->tar->data;
+
+ if ( ELEM(NULL, cu->adt, cu->adt->action) ||
+ (list_find_fcurve(&cu->adt->action->curves, "eval_time", 0) == NULL))
+ {
+ /* create F-Curve for path animation */
+ act = verify_adt_action(&cu->id, 1);
+ fcu = verify_fcurve(act, NULL, NULL, "eval_time", 0, 1);
+
+ /* standard vertical range - 1:1 = 100 frames */
+ standardRange = 100.0f;
+ }
+ else {
+ /* path anim exists already - abort for now as this may well be what was intended */
+ BKE_report(op->reports, RPT_WARNING, "Path is already animated");
+ return OPERATOR_CANCELLED;
+ }
+ }
+ else {
+ /* animate constraint's "fixed offset" */
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ char *path;
+
+ /* get RNA pointer to constraint's "offset_factor" property - to build RNA path */
+ RNA_pointer_create(&ob->id, &RNA_FollowPathConstraint, con, &ptr);
+ prop = RNA_struct_find_property(&ptr, "offset_factor");
+
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+
+ /* create F-Curve for constraint */
+ act = verify_adt_action(&ob->id, 1);
+ fcu = verify_fcurve(act, NULL, NULL, path, 0, 1);
+
+ /* standard vertical range - 0.0 to 1.0 */
+ standardRange = 1.0f;
+
+ /* enable "Use Fixed Position" so that animating this has effect */
+ data->followflag |= FOLLOWPATH_STATIC;
+
+ /* path needs to be freed */
+ if (path)
+ MEM_freeN(path);
+ }
+
+ /* setup dummy 'generator' modifier here to get 1-1 correspondence still working
+ * and define basic slope of this curve based on the properties
+ */
+ if (!fcu->bezt && !fcu->fpt && !fcu->modifiers.first) {
+ FModifier *fcm = add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR);
+ FMod_Generator *gen = fcm->data;
+
+ /* Assume that we have the following equation:
+ * y = Ax + B
+ * 1 0 <-- coefficients array indices
+ */
+ float A = standardRange / (float)(len);
+ float B = (float)(-sfra) * A;
+
+ gen->coefficients[1] = A;
+ gen->coefficients[0] = B;
+ }
+
+ /* updates... */
+ WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob);
+ return OPERATOR_FINISHED;
+}
+
+static int followpath_path_animate_invoke(bContext *C, wmOperator *op, wmEvent *evt)
+{
+ /* hook up invoke properties for figuring out which constraint we're dealing with */
+ if (edit_constraint_invoke_properties(C, op)) {
+ return followpath_path_animate_exec(C, op);
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void CONSTRAINT_OT_followpath_path_animate(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Auto Animate Path";
+ ot->idname = "CONSTRAINT_OT_followpath_path_animate";
+ ot->description = "Add default animation for path used by constraint if it isn't animated already";
+
+ /* callbacks */
+ ot->invoke = followpath_path_animate_invoke;
+ ot->exec = followpath_path_animate_exec;
+ ot->poll = edit_constraint_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* props */
+ edit_constraint_properties(ot);
+ RNA_def_int(ot->srna, "frame_start", 1, MINAFRAME, MAXFRAME, "Start Frame",
+ "First frame of path animation", MINAFRAME, MAXFRAME);
+ RNA_def_int(ot->srna, "length", 100, 0, MAXFRAME, "Length",
+ "Number of frames that path animation should take", 0, MAXFRAME);
+}
+
/* ------------- Object Solver Constraint ------------------ */
static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)