Page MenuHome

envmod_orderred.diff

envmod_orderred.diff

Index: rna_fcurve.c
===================================================================
--- rna_fcurve.c (revision 54202)
+++ rna_fcurve.c (working copy)
@@ -108,6 +108,8 @@
#include "BKE_depsgraph.h"
#include "BKE_animsys.h"
+#include "DNA_anim_types.h"
+
static void rna_ChannelDriver_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
{
ID *id = ptr->id.data;
@@ -633,6 +635,178 @@
calc_fcurve_range(fcu, range, range + 1, FALSE, FALSE);
}
+/* --------------- */
+
+#define BINARYSEARCH_FRAMEEQ_THRESH 0.0001f
+
+/* Binary search algorithm for finding where to insert Envelope Data Point.
+ * Returns the index to insert at (data already at that index will be offset if replace is 0)
+ */
+static int binarysearch_fcm_envelopedata_index(FCM_EnvelopeData array[], float frame, int arraylen, short *exists)
+{
+ int start = 0, end = arraylen;
+ int loopbreaker = 0, maxloop = arraylen * 2;
+
+ /* initialize exists-flag first */
+ *exists = 0;
+
+ /* sneaky optimizations (don't go through searching process if...):
+ * - keyframe to be added is to be added out of current bounds
+ * - keyframe to be added would replace one of the existing ones on bounds
+ */
+ if ((arraylen <= 0) || (array == NULL)) {
+ printf("Warning: binarysearch_fcm_envelopedata_index() encountered invalid array\n");
+ return 0;
+ }
+ else {
+ /* check whether to add before/after/on */
+ float framenum;
+
+ /* 'First' Point (when only one point, this case is used) */
+ framenum = array[0].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists = 1;
+ return 0;
+ }
+ else if (frame < framenum)
+ return 0;
+
+ /* 'Last' Point */
+ framenum = array[(arraylen - 1)].time;
+ if (IS_EQT(frame, framenum, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists = 1;
+ return (arraylen - 1);
+ }
+ else if (frame > framenum)
+ return arraylen;
+ }
+
+
+ /* most of the time, this loop is just to find where to put it
+ * - 'loopbreaker' is just here to prevent infinite loops
+ */
+ for (loopbreaker = 0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) {
+ /* compute and get midpoint */
+ int mid = start + ((end - start) / 2); /* we calculate the midpoint this way to avoid int overflows... */
+ float midfra = array[mid].time;
+
+ /* check if exactly equal to midpoint */
+ if (IS_EQT(frame, midfra, BINARYSEARCH_FRAMEEQ_THRESH)) {
+ *exists = 1;
+ return mid;
+ }
+
+ /* repeat in upper/lower half */
+ if (frame > midfra)
+ start = mid + 1;
+ else if (frame < midfra)
+ end = mid - 1;
+ }
+
+ /* print error if loop-limit exceeded */
+ if (loopbreaker == (maxloop - 1)) {
+ printf("Error: binarysearch_fcm_envelopedata_index() was taking too long\n");
+
+ // include debug info
+ printf("\tround = %d: start = %d, end = %d, arraylen = %d\n", loopbreaker, start, end, arraylen);
+ }
+
+ /* not found, so return where to place it */
+ return start;
+}
+
+/* callback to add new envelope data point */
+// TODO: should we have a separate file for things like this?
+
+static FCM_EnvelopeData *rna_FModifierEnvelope_points_add(FModifier *fmod, ReportList *reports, float frame)
+{
+ FCM_EnvelopeData fed;
+ FMod_Envelope *env = (FMod_Envelope *)fmod->data;
+ FCM_EnvelopeData *fedn;
+ /* init template data */
+ fed.min = -1.0f;
+ fed.max = 1.0f;
+ fed.time = frame; // XXX make this int for ease of use?
+ fed.f1 = fed.f2 = 0;
+ if (env->data) {
+ /* add point to end of control points ^/
+ /* XXX deal with this later if needs to be ordered */
+ short exists = -1;
+ int i = binarysearch_fcm_envelopedata_index(env->data, frame, env->totvert, &exists);
+ if (exists) {
+ char c[40];
+ sprintf(c, "Already a control point at frame %d", (int) frame);
+ BKE_report(reports, RPT_ERROR, c);
+ return NULL;
+ }
+ /* add new */
+ fedn = MEM_callocN((env->totvert + 1) * sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
+
+ /* add the points that should occur before the point to be pasted */
+ if (i > 0)
+ memcpy(fedn, env->data, i * sizeof(FCM_EnvelopeData));
+
+ /* add point to paste at index i */
+ *(fedn + i) = fed;
+
+ /* add the points that occur after the point to be pasted */
+ if (i < env->totvert)
+ memcpy(fedn + i + 1, env->data + i, (env->totvert - i) * sizeof(FCM_EnvelopeData));
+
+ /* replace (+ free) old with new */
+ MEM_freeN(env->data);
+ env->data = fedn;
+
+ env->totvert++;
+ return (env->data + i);
+
+ }
+ else {
+ env->data = MEM_callocN(sizeof(FCM_EnvelopeData), "FCM_EnvelopeData");
+ *(env->data) = fed;
+ env->totvert = 1;
+ return env->data;
+ }
+
+ return NULL;
+}
+
+void rna_FModifierEnvelope_points_remove(FModifier *fmod, ReportList *reports, PointerRNA *point)
+{
+ FCM_EnvelopeData *cp = point->data;
+ FMod_Envelope *env = (FMod_Envelope *)fmod->data;
+ FCM_EnvelopeData *fedn;
+
+ int index = (int)(cp - env->data);
+
+ /* test point is in range */
+ if (index < 0 || index >= env->totvert) {
+ BKE_report(reports, RPT_ERROR, "Control Point not in FEnvelopeModifier");
+ return;
+ }
+
+ if (env->totvert > 1) {
+ /* allocate a new smaller array */
+ fedn = MEM_callocN(sizeof(FCM_EnvelopeData) * (env->totvert - 1), "FCM_EnvelopeData");
+
+ memcpy(fedn, env->data, sizeof(FCM_EnvelopeData) * (index));
+ memcpy(fedn + index, env->data + (index + 1), sizeof(FCM_EnvelopeData) * ((env->totvert - index) - 1));
+
+ /* free old array, and set the new */
+ MEM_freeN(env->data);
+ env->data = fedn;
+ env->totvert--;
+ }
+ else {
+ /* just free array, since the only vert was deleted */
+ if (env->data) {
+ MEM_freeN(env->data);
+ env->data = NULL;
+ }
+ env->totvert = 0;
+ }
+ RNA_POINTER_INVALIDATE(point);
+}
#else
static void rna_def_fmodifier_generator(BlenderRNA *brna)
@@ -770,6 +944,36 @@
/* - selection flags (not implemented in UI yet though) */
}
+static void rna_def_fmodifier_envelope_control_points(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "FModifierEnvelopeControlPoints");
+ srna = RNA_def_struct(brna, "FModifierEnvelopeControlPoints", NULL);
+ RNA_def_struct_sdna(srna, "FModifier");
+
+ RNA_def_struct_ui_text(srna, "Control Points", "Control points defining the shape of the envelope");
+
+ func = RNA_def_function(srna, "add", "rna_FModifierEnvelope_points_add");
+ RNA_def_function_ui_description(func, "Add a control point to a FModifierEnvelope");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_float(func, "frame", 0.0f, -FLT_MAX, FLT_MAX, "",
+ "Frame to add this control-point", -FLT_MAX, FLT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "point", "FModifierEnvelopeControlPoint", "", "Newly created control-point");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_FModifierEnvelope_points_remove");
+ RNA_def_function_ui_description(func, "Remove a control-point from an FModifierEnvelope");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "point", "FModifierEnvelopeControlPoint", "", "Control-point to remove");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
+}
+
+
static void rna_def_fmodifier_envelope(BlenderRNA *brna)
{
StructRNA *srna;
@@ -784,6 +988,7 @@
RNA_def_property_collection_sdna(prop, NULL, "data", "totvert");
RNA_def_property_struct_type(prop, "FModifierEnvelopeControlPoint");
RNA_def_property_ui_text(prop, "Control Points", "Control points defining the shape of the envelope");
+ rna_def_fmodifier_envelope_control_points(brna, prop);
/* Range Settings */
prop = RNA_def_property(srna, "reference_value", PROP_FLOAT, PROP_NONE);

File Metadata

Mime Type
text/x-diff
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
9c/47/36a423ba9b39290c54de4cdac9b7

Event Timeline