2.5 - Animation Bugfixes:
authorJoshua Leung <aligorith@gmail.com>
Sat, 19 Sep 2009 11:59:23 +0000 (11:59 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sat, 19 Sep 2009 11:59:23 +0000 (11:59 +0000)
* Breakdown tool for Poses (Shift-E in PoseMode) now works. Now this works as a modal operator when invoked, with the horizontal movement of the mouse (left to right) corresponding the placement of the breakdown relative to the endpoint keyframes.

* Moving bones between armature layers in Edit Mode didn't work (wrong variable name used)
* Fixed several notifier-related bugs regarding editing armature settings and the 3d-view not refreshing
* Duplicating bones preserves the rotation mode

* Animation Data for Nodes is now show in Datablocks viewer (i.e. AnimData for NodeTrees has now been wrapped)

source/blender/editors/animation/keyframes_draw.c
source/blender/editors/armature/editarmature.c
source/blender/editors/armature/poseSlide.c
source/blender/editors/armature/poseobject.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/makesrna/intern/rna_nodetree.c

index 8e7789190c39e2fbcecb47a1cf1a6fcaa48ab68d..dcb37f4d2c4ff829418f5c253a9d706d1920f2d5 100644 (file)
@@ -332,6 +332,7 @@ ActKeyColumn *cfra_find_actkeycolumn (ActKeyColumn *ak, float cframe)
 }
 
 /* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */
+// FIXME: this is buggy... next() is ignored completely...
 ActKeyColumn *cfra_find_nearest_next_ak (ActKeyColumn *ak, float cframe, short next)
 {
        ActKeyColumn *akn= NULL;
index 7d196d23c987b9d44baeb98ea194f33b7385c311..394df8111d8918ef5f2a9d9fc8e98899f5ac69ee 100644 (file)
@@ -2630,6 +2630,9 @@ static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
                                                                /* copy transform locks */
                                                                channew->protectflag = chanold->protectflag;
                                                                
+                                                               /* copy rotation mode */
+                                                               channew->rotmode = chanold->rotmode;
+                                                               
                                                                /* copy bone group */
                                                                channew->agrp_index= chanold->agrp_index;
                                                                
index 464dbcba54b8f0e42fed42b4f480830d7f9a1d7e..bbc9ef4d09c94961f79576648aa9da4da2d3c7c9 100644 (file)
@@ -103,6 +103,7 @@ typedef struct tPoseSlideOp {
        Scene *scene;           /* current scene */
        ARegion *ar;            /* region that we're operating in (needed for  */
        Object *ob;                     /* active object that Pose Info comes from */
+       bArmature *arm;         /* armature for pose */
        
        ListBase pfLinks;       /* links between posechannels and f-curves  */
        DLRBT_Tree keys;        /* binary tree for quicker searching for keyframes (when applicable) */
@@ -151,6 +152,7 @@ static int pose_slide_init (bContext *C, wmOperator *op, short mode)
        /* get info from context */
        pso->scene= CTX_data_scene(C);
        pso->ob= CTX_data_active_object(C);
+       pso->arm= (pso->ob)? pso->ob->data : NULL;
        pso->ar= CTX_wm_region(C); /* only really needed when doing modal() */
        
        pso->cframe= pso->scene->r.cfra;
@@ -162,7 +164,7 @@ static int pose_slide_init (bContext *C, wmOperator *op, short mode)
        pso->nextFrame= RNA_int_get(op->ptr, "next_frame");
        
        /* check the settings from the context */
-       if (ELEM3(NULL, pso->ob, pso->ob->adt, pso->ob->adt->action))
+       if (ELEM4(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
                return 0;
        else
                act= pso->ob->adt->action;
@@ -204,6 +206,11 @@ static int pose_slide_init (bContext *C, wmOperator *op, short mode)
        }
        CTX_DATA_END;
        
+       /* set depsgraph flags */
+               /* make sure the lock is set OK, unlock can be accidentally saved? */
+       pso->ob->pose->flag |= POSE_LOCKED;
+       pso->ob->pose->flag &= ~POSE_DO_UNLOCK;
+       
        /* do basic initialise of RB-BST used for finding keyframes, but leave the filling of it up 
         * to the caller of this (usually only invoke() will do it, to make things more efficient).
         */
@@ -289,8 +296,8 @@ static void pose_slide_apply_vec3 (tPoseSlideOp *pso, tPChanFCurveLink *pfl, flo
        /* using this path, find each matching F-Curve for the variables we're interested in */
        while ( (ld= find_next_fcurve_link(&pfl->fcurves, ld, path)) ) {
                FCurve *fcu= (FCurve *)ld->data;
-               float w1, w2, wtot, ctrl, ictrl;
                float sVal, eVal;
+               float w1, w2;
                int ch;
                
                /* get keyframe values for endpoint poses to blend with */
@@ -302,21 +309,26 @@ static void pose_slide_apply_vec3 (tPoseSlideOp *pso, tPChanFCurveLink *pfl, flo
                /* get channel index */
                ch= fcu->array_index;
                
-               /* get the influence of the control */
-               ctrl= pso->percentage;
-               ictrl= 1.0f - pso->percentage;
-               
-               /* calculate the relative weights of the endpoints 
-                *      - these weights are derived from the relative distance of these 
-                *        poses from the current frame
-                *      - they then get normalised, with the results of these normalised 
-                */
-               w1 = cframe - (float)pso->prevFrame;
-               w2 = (float)pso->nextFrame - cframe;
-               
-               wtot = w1 + w2;
-               w1 = w1/wtot;
-               w2 = w2/wtot;
+               /* calculate the relative weights of the endpoints */
+               if (pso->mode == POSESLIDE_BREAKDOWN) {
+                       /* get weights from the percentage control */
+                       w1= pso->percentage;    /* this must come second */
+                       w2= 1.0f - w1;                  /* this must come first */
+               }
+               else {
+                       /*      - these weights are derived from the relative distance of these 
+                        *        poses from the current frame
+                        *      - they then get normalised so that they only sum up to 1
+                        */
+                       float wtot; 
+                       
+                       w1 = cframe - (float)pso->prevFrame;
+                       w2 = (float)pso->nextFrame - cframe;
+                       
+                       wtot = w1 + w2;
+                       w1 = (w1/wtot);
+                       w2 = (w2/wtot);
+               }
                
                /* depending on the mode, */
                switch (pso->mode) {
@@ -332,10 +344,8 @@ static void pose_slide_apply_vec3 (tPoseSlideOp *pso, tPChanFCurveLink *pfl, flo
                                break;
                                
                        case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
-                               // NOTE: just linear interpolation for now, but could add small component of our key if necessary...
-                               // TODO: this doesn't work at all
-                               w2= 1.0f - w1;
-                               vec[ch]= ((sVal * w1) + (eVal * w2));
+                               /* perform simple linear interpolation - coefficient for start must come from pso->percentage... */
+                               vec[ch]= ((sVal * w2) + (eVal * w1));
                                break;
                }
                
@@ -449,15 +459,18 @@ static void pose_slide_apply (bContext *C, wmOperator *op, tPoseSlideOp *pso)
                }
        }
        
-       /* funky depsgraph flags - are these still needed? */
-       pso->ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
-       
-       /* do depsgraph flush */
-       DAG_id_flush_update(&pso->ob->id, OB_RECALC_DATA);
+       /* old optimize trick... this enforces to bypass the depgraph 
+        *      - note: code copied from transform_generics.c -> recalcData()
+        */
+       // FIXME: shouldn't this use the builtin stuff?
+       if ((pso->arm->flag & ARM_DELAYDEFORM)==0)
+               DAG_id_flush_update(&pso->ob->id, OB_RECALC_DATA);  /* sets recalc flags */
+       else
+               where_is_pose(pso->scene, pso->ob);
        
        /* note, notifier might evolve */
-       //WM_event_add_notifier(C, NC_OBJECT|ND_POSE, pso->ob);
-       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, pso->ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_POSE, pso->ob);
+       WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL);
 }
 
 /* ------------------------------------ */
@@ -482,7 +495,7 @@ static int pose_slide_invoke_common (bContext *C, wmOperator *op, tPoseSlideOp *
        /* consolidate these keyframes, and figure out the nearest ones */
        BLI_dlrbTree_linkedlist_sync(&pso->keys);
        
-       /* cancel if no keyframes found... */
+               /* cancel if no keyframes found... */
        if (pso->keys.root) {
                ActKeyColumn *ak;
                
@@ -491,14 +504,24 @@ static int pose_slide_invoke_common (bContext *C, wmOperator *op, tPoseSlideOp *
                
                if (ak == NULL) {
                        /* current frame is not a keyframe, so search */
+                       ActKeyColumn *pk= cfra_find_nearest_next_ak(pso->keys.root, pso->cframe, 0);
+                       ActKeyColumn *nk= cfra_find_nearest_next_ak(pso->keys.root, pso->cframe, 1);
+                       
+                       /* check if we found good keyframes */
+                       if ((pk == nk) && (pk != NULL)) {
+                               if (pk->cfra < pso->cframe)
+                                       nk= nk->next;
+                               else if (nk->cfra > pso->cframe)
+                                       pk= pk->prev;
+                       }
+                       
+                       /* new set the frames */
                                /* prev frame */
-                       ak= cfra_find_nearest_next_ak(pso->keys.root, pso->cframe, 0);
-                       pso->prevFrame= (ak)? (ak->cfra) : (pso->cframe - 1);
+                       pso->prevFrame= (pk)? (pk->cfra) : (pso->cframe - 1);
                        RNA_int_set(op->ptr, "prev_frame", pso->prevFrame);
                                /* next frame */
-                       ak= cfra_find_nearest_next_ak(pso->keys.root, pso->cframe, 1);
-                       pso->nextFrame= (ak)? (ak->cfra) : (pso->cframe + 1);
-                       RNA_int_set(op->ptr, "next_frame", pso->prevFrame);
+                       pso->nextFrame= (nk)? (nk->cfra) : (pso->cframe + 1);
+                       RNA_int_set(op->ptr, "next_frame", pso->nextFrame);
                }
                else {
                        /* current frame itself is a keyframe, so just take keyframes on either side */
@@ -515,18 +538,63 @@ static int pose_slide_invoke_common (bContext *C, wmOperator *op, tPoseSlideOp *
                return OPERATOR_CANCELLED;
        }
        
+       // FIXME: for now, just do modal for breakdowns... 
+       if (pso->mode == POSESLIDE_BREAKDOWN) { 
+               /* initial apply for operator... */
+               pose_slide_apply(C, op, pso);
+               
+               /* add a modal handler for this operator */
+               WM_event_add_modal_handler(C, op);
+               return OPERATOR_RUNNING_MODAL;
+       }
+       else {
+               /* temp static operator code... until a way to include percentage in the formulation comes up */
+               pose_slide_apply(C, op, pso);
+               pose_slide_exit(C, op);
+               return OPERATOR_FINISHED;
+       }
+}
+
+/* common code for modal() */
+static int pose_slide_modal (bContext *C, wmOperator *op, wmEvent *evt)
+{
+       tPoseSlideOp *pso= op->customdata;
        
-       // TODO -----------------------------------
-       // from here on, we should just invoke the modal operator, but for now, just do static...
+       switch (evt->type) {
+               case LEFTMOUSE: /* confirm */
+                       pose_slide_exit(C, op);
+                       return OPERATOR_FINISHED;
+               
+               case ESCKEY:    /* cancel */
+               case RIGHTMOUSE: 
+                       pose_slide_exit(C, op);
+                       return OPERATOR_CANCELLED;
+                       
+               case MOUSEMOVE: /* calculate new position */
+               {
+                       /* calculate percentage based on position of mouse (we only use x-axis for now.
+                        * since this is more conveninent for users to do), and store new percentage value 
+                        */
+                       pso->percentage= (evt->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx);
+                       RNA_float_set(op->ptr, "percentage", pso->percentage);
+                       
+                       /* apply... */
+                       pose_slide_apply(C, op, pso);
+               }
+                       break;
+       }
        
-       /* temp static operator code... */
-       pose_slide_apply(C, op, pso);
-       pose_slide_exit(C, op);
-       return OPERATOR_FINISHED;
+       /* still running... */
+       return OPERATOR_RUNNING_MODAL;
 }
 
-// TODO: common modal + cancel
-
+/* common code for cancel() */
+static int pose_slide_cancel (bContext *C, wmOperator *op)
+{
+       /* cleanup and done */
+       pose_slide_exit(C, op);
+       return OPERATOR_CANCELLED;
+}
 
 /* common code for exec() methods */
 static int pose_slide_exec_common (bContext *C, wmOperator *op, tPoseSlideOp *pso)
@@ -708,12 +776,12 @@ void POSE_OT_breakdown (wmOperatorType *ot)
        /* callbacks */
        ot->exec= pose_slide_breakdown_exec;
        ot->invoke= pose_slide_breakdown_invoke;
-       //ot->modal= pose_slide_modal;
-       //ot->cancel= pose_slide_cancel;
+       ot->modal= pose_slide_modal;
+       ot->cancel= pose_slide_cancel;
        ot->poll= ED_operator_posemode;
        
        /* flags */
-       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;//|OPTYPE_BLOCKING;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING;
        
        /* Properties */
        pose_slide_opdef_properties(ot);
index e5a7a1e167d5b37f492258bce2d9ef4655cb4af5..305e153f8053e7f1336cda76d9d8de328eed7d08 100644 (file)
@@ -1942,7 +1942,7 @@ static int armature_bone_layers_invoke (bContext *C, wmOperator *op, wmEvent *ev
 /* Set the visible layers for the active armature (edit and pose modes) */
 static int armature_bone_layers_exec (bContext *C, wmOperator *op)
 {
-       Object *ob= CTX_data_active_object(C);
+       Object *ob= CTX_data_edit_object(C);
        bArmature *arm= (ob)? ob->data : NULL;
        PointerRNA ptr;
        int layers[16]; /* hardcoded for now - we can only have 16 armature layers, so this should be fine... */
@@ -1955,7 +1955,7 @@ static int armature_bone_layers_exec (bContext *C, wmOperator *op)
        {
                /* get pointer for pchan, and write flags this way */
                RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
-               RNA_boolean_set_array(&ptr, "layers", layers);
+               RNA_boolean_set_array(&ptr, "layer", layers);
        }
        CTX_DATA_END;
        
index 5ea633a47f738dbef2bd6b305946695976259254..a73a16f38ba347f0f30b5829cd5c8f1c856e7479 100644 (file)
@@ -420,6 +420,7 @@ static void view3d_main_area_listener(ARegion *ar, wmNotifier *wmn)
                                case ND_BONE_ACTIVE:
                                case ND_BONE_SELECT:
                                case ND_TRANSFORM:
+                               case ND_POSE:
                                case ND_DRAW:
                                case ND_MODIFIER:
                                case ND_CONSTRAINT:
@@ -560,6 +561,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
                                case ND_BONE_ACTIVE:
                                case ND_BONE_SELECT:
                                case ND_TRANSFORM:
+                               case ND_POSE:
                                case ND_DRAW:
                                case ND_KEYS:
                                        ED_region_tag_redraw(ar);
index 73aaf0837db45b8ec7cbb6213caa37f597aa75bb..b310ff06b8e991957f51c32685a8575436c7c3ef 100644 (file)
@@ -1660,6 +1660,8 @@ static void rna_def_nodetree(BlenderRNA *brna)
        RNA_def_struct_ui_text(srna, "Node Tree", "Node tree consisting of linked nodes used for materials, textures and compositing.");
        RNA_def_struct_sdna(srna, "bNodeTree");
        RNA_def_struct_ui_icon(srna, ICON_NODE);
+       
+       rna_def_animdata_common(srna);
 
        prop = RNA_def_property(srna, "nodes", PROP_COLLECTION, PROP_NONE);
        RNA_def_property_collection_sdna(prop, NULL, "nodes", NULL);