pydrivers: 'frame' is now in the driver namespace,
authorCampbell Barton <ideasman42@gmail.com>
Thu, 17 Nov 2011 07:08:09 +0000 (07:08 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 17 Nov 2011 07:08:09 +0000 (07:08 +0000)
- no need to link to scenes when using a frame from the pydriver, this made linking rigs for eg, quite messy.
- advantage that we get subframe values (where scenes from was fixed to a whole number).

source/blender/blenkernel/intern/fcurve.c
source/blender/editors/interface/interface_anim.c
source/blender/python/BPY_extern.h
source/blender/python/intern/bpy_driver.c
source/blender/python/intern/bpy_driver.h
source/blenderplayer/bad_level_call_stubs/stubs.c

index 5ab997d2c54175f3e5fc0414733135a3793039b7..4bb9dc47fda8d74fc4502947e3ef31b2a35d6c1a 100644 (file)
@@ -1576,7 +1576,7 @@ float driver_get_variable_value (ChannelDriver *driver, DriverVar *dvar)
  *     - "evaltime" is the frame at which F-Curve is being evaluated
  *     - has to return a float value 
  */
  *     - "evaltime" is the frame at which F-Curve is being evaluated
  *     - has to return a float value 
  */
-static float evaluate_driver (ChannelDriver *driver, float UNUSED(evaltime))
+static float evaluate_driver (ChannelDriver *driver, const float evaltime)
 {
        DriverVar *dvar;
        
 {
        DriverVar *dvar;
        
@@ -1663,8 +1663,10 @@ static float evaluate_driver (ChannelDriver *driver, float UNUSED(evaltime))
                                /* this evaluates the expression using Python,and returns its result:
                                 *      - on errors it reports, then returns 0.0f
                                 */
                                /* this evaluates the expression using Python,and returns its result:
                                 *      - on errors it reports, then returns 0.0f
                                 */
-                               driver->curval= BPY_driver_exec(driver);
+                               driver->curval= BPY_driver_exec(driver, evaltime);
                        }
                        }
+#else /* WITH_PYTHON*/
+               (void)evaltime;
 #endif /* WITH_PYTHON*/
                }
                        break;
 #endif /* WITH_PYTHON*/
                }
                        break;
@@ -2087,7 +2089,7 @@ static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime)
 /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") 
  * Note: this is also used for drivers
  */
 /* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime") 
  * Note: this is also used for drivers
  */
-float evaluate_fcurve (FCurve *fcu, float evaltime) 
+float evaluate_fcurve (FCurve *fcu, float evaltime)
 {
        float cvalue= 0.0f;
        float devaltime;
 {
        float cvalue= 0.0f;
        float devaltime;
index 1edd43d4e01eed6af7dc992906c12314ae04613d..5e095bae922089cefbdf166c729eda7ae33ccf75 100644 (file)
@@ -164,24 +164,7 @@ int ui_but_anim_expression_create(uiBut *but, const char *str)
                        /* set the expression */
                        // TODO: need some way of identifying variables used
                        BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
                        /* set the expression */
                        // TODO: need some way of identifying variables used
                        BLI_strncpy_utf8(driver->expression, str, sizeof(driver->expression));
-                       
-                       /* FIXME: for now, assume that 
-                        *      - for expressions, users are likely to be using "frame" -> current frame" as a variable
-                        *      - driver_add_new_variable() adds a single-prop variable by default
-                        */
-                       {
-                               DriverVar *dvar;
-                               DriverTarget *dtar;
-                               
-                               dvar = driver_add_new_variable(driver);
-                               BLI_strncpy(dvar->name, "frame", sizeof(dvar->name));
-                               
-                               dtar = &dvar->targets[0];
-                               dtar->id = (ID *)CTX_data_scene(C); // XXX: should we check that C is valid first?
-                               dtar->idtype= ID_SCE;
-                               dtar->rna_path = BLI_sprintfN("frame_current");
-                       }
-                       
+
                        /* updates */
                        driver->flag |= DRIVER_FLAG_RECOMPILE;
                        WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME, NULL);
                        /* updates */
                        driver->flag |= DRIVER_FLAG_RECOMPILE;
                        WM_event_add_notifier(C, NC_ANIMATION|ND_KEYFRAME, NULL);
index 29e0185c2f242cb37d0332a9090d31e9c24cee2d..51f9063c2898e52957b3b11c23e26005faa47de3 100644 (file)
@@ -74,7 +74,7 @@ void  BPY_modules_load_user(struct bContext *C);
 void   BPY_app_handlers_reset(const short do_all);
 
 void   BPY_driver_reset(void);
 void   BPY_app_handlers_reset(const short do_all);
 
 void   BPY_driver_reset(void);
-float  BPY_driver_exec(struct ChannelDriver *driver);
+float  BPY_driver_exec(struct ChannelDriver *driver, const float evaltime);
 
 int            BPY_button_exec(struct bContext *C, const char *expr, double *value, const short verbose);
 int            BPY_string_exec(struct bContext *C, const char *expr);
 
 int            BPY_button_exec(struct bContext *C, const char *expr, double *value, const short verbose);
 int            BPY_string_exec(struct bContext *C, const char *expr);
index 12fb5ed43b4e95abab07e55f6927abd9ca34a253..2aad4d8f2fe12c055d55378b8231a2e051b52f1e 100644 (file)
@@ -91,6 +91,29 @@ int bpy_pydriver_create_dict(void)
        return 0;
 }
 
        return 0;
 }
 
+/* note, this function should do nothing most runs, only when changing frame */
+static PyObject *bpy_pydriver_InternStr__frame= NULL;
+
+static void bpy_pydriver_update_dict(const float evaltime)
+{
+       /* not thread safe but neither is python */
+       static float evaltime_prev= FLT_MAX;
+
+       if (evaltime_prev != evaltime) {
+
+               /* currently only update the frame */
+               if (bpy_pydriver_InternStr__frame == NULL) {
+                       bpy_pydriver_InternStr__frame= PyUnicode_FromString("frame");
+               }
+
+               PyDict_SetItem(bpy_pydriver_Dict,
+                              bpy_pydriver_InternStr__frame,
+                              PyFloat_FromDouble(evaltime));
+
+               evaltime_prev= evaltime;
+       }
+}
+
 /* Update function, it gets rid of pydrivers global dictionary, forcing
  * BPY_driver_exec to recreate it. This function is used to force
  * reloading the Blender text module "pydrivers.py", if available, so
 /* Update function, it gets rid of pydrivers global dictionary, forcing
  * BPY_driver_exec to recreate it. This function is used to force
  * reloading the Blender text module "pydrivers.py", if available, so
@@ -110,6 +133,11 @@ void BPY_driver_reset(void)
                bpy_pydriver_Dict= NULL;
        }
 
                bpy_pydriver_Dict= NULL;
        }
 
+       if (bpy_pydriver_InternStr__frame) {
+               Py_DECREF(bpy_pydriver_InternStr__frame);
+               bpy_pydriver_InternStr__frame= NULL;
+       }
+
        if (use_gil)
                PyGILState_Release(gilstate);
 
        if (use_gil)
                PyGILState_Release(gilstate);
 
@@ -139,7 +167,7 @@ static void pydriver_error(ChannelDriver *driver)
  * now release the GIL on python operator execution instead, using
  * PyEval_SaveThread() / PyEval_RestoreThread() so we dont lock up blender.
  */
  * now release the GIL on python operator execution instead, using
  * PyEval_SaveThread() / PyEval_RestoreThread() so we dont lock up blender.
  */
-float BPY_driver_exec(ChannelDriver *driver)
+float BPY_driver_exec(ChannelDriver *driver, const float evaltime)
 {
        PyObject *driver_vars=NULL;
        PyObject *retval= NULL;
 {
        PyObject *driver_vars=NULL;
        PyObject *retval= NULL;
@@ -183,6 +211,10 @@ float BPY_driver_exec(ChannelDriver *driver)
                }
        }
 
                }
        }
 
+       /* update global namespace */
+       bpy_pydriver_update_dict(evaltime);
+
+
        if (driver->expr_comp==NULL)
                driver->flag |= DRIVER_FLAG_RECOMPILE;
 
        if (driver->expr_comp==NULL)
                driver->flag |= DRIVER_FLAG_RECOMPILE;
 
@@ -246,6 +278,7 @@ float BPY_driver_exec(ChannelDriver *driver)
                }
        }
 
                }
        }
 
+
 #if 0 // slow, with this can avoid all Py_CompileString above.
        /* execute expression to get a value */
        retval= PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
 #if 0 // slow, with this can avoid all Py_CompileString above.
        /* execute expression to get a value */
        retval= PyRun_String(expr, Py_eval_input, bpy_pydriver_Dict, driver_vars);
index 3e38cacf6d1dce11a734b9ea2a2bebedb1251084..802a3649e203d16c6d94b9bccf5bd20507cc4789 100644 (file)
@@ -33,7 +33,7 @@ int bpy_pydriver_create_dict(void);
 extern PyObject *bpy_pydriver_Dict;
 
 /* externals */
 extern PyObject *bpy_pydriver_Dict;
 
 /* externals */
-float BPY_driver_exec(struct ChannelDriver *driver);
+float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime);
 void BPY_driver_reset(void);
 
 #endif // BPY_DRIVER_H
 void BPY_driver_reset(void);
 
 #endif // BPY_DRIVER_H
index abc5307b9f62bcffc230e0093e7e5db3c68d8a23..b299de0d89770b7e72b449d2e54df2022823e365 100644 (file)
@@ -454,7 +454,7 @@ void BPY_text_free_code(struct Text *text) {}
 void BPY_id_release(struct Text *text) {}
 int BPY_context_member_get(struct Context *C, const char *member, struct bContextDataResult *result) { return 0; }
 void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct) {}
 void BPY_id_release(struct Text *text) {}
 int BPY_context_member_get(struct Context *C, const char *member, struct bContextDataResult *result) { return 0; }
 void BPY_pyconstraint_target(struct bPythonConstraint *con, struct bConstraintTarget *ct) {}
-float BPY_driver_exec(struct ChannelDriver *driver) {return 0.0f;} /* might need this one! */
+float BPY_driver_exec(struct ChannelDriver *driver, const float evaltime) {return 0.0f;} /* might need this one! */
 void BPY_DECREF(void *pyob_ptr) {}
 void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets) {}
 void macro_wrapper(struct wmOperatorType *ot, void *userdata) {} ;
 void BPY_DECREF(void *pyob_ptr) {}
 void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets) {}
 void macro_wrapper(struct wmOperatorType *ot, void *userdata) {} ;