diff options
author | Joshua Leung <aligorith@gmail.com> | 2008-12-29 04:19:25 +0300 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2008-12-29 04:19:25 +0300 |
commit | 97a82102d4d24a94d8360a6f5f054e44f6fb1993 (patch) | |
tree | f204580537752d9aa602aaaae66246affe042f66 /source/blender | |
parent | 87cae4caed35c50b2ef70fb104d6f057670eb94e (diff) |
2.5 - Action Editor / Animation Stuff:
* Brought back clean (OKEY), sample (Shift-OKEY), and delete (XKEY/DELKEY) tools for the Action Editor.
Currently clean uses a predefined threshold (as a rna-prop, though it's still lacking the popup to set this when it is called)
* Added new file for 'destructive' keyframe operations/tools.
* Got keyframing.c compiling. Now, some of these tools need to be operatorised. Also, the API there might change when enough of the system is stable for RNA-IPO work to take place (so that it can be tested).
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_action.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 11 | ||||
-rw-r--r-- | source/blender/editors/animation/anim_deps.c | 2 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_edit.c | 5 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframes_general.c | 364 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 533 | ||||
-rw-r--r-- | source/blender/editors/include/ED_anim_api.h | 4 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframes_edit.h | 13 | ||||
-rw-r--r-- | source/blender/editors/include/ED_keyframing.h | 11 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_edit_keyframes.c | 257 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_header.c | 157 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_ops.c | 10 | ||||
-rw-r--r-- | source/blender/editors/space_action/action_select.c | 40 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/space_outliner.c | 1 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 2 |
16 files changed, 1254 insertions, 161 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index a0c8be7d7f8..574d4154e86 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -51,6 +51,7 @@ struct ID; extern "C" { #endif +struct bAction *add_empty_action(const char name[]); /** * Removes and deallocates all channels from a pose. diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index beef3e1ef1d..f2a92b9024f 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -81,6 +81,17 @@ /* ***************** Library data level operations on action ************** */ +bAction *add_empty_action(const char name[]) +{ + bAction *act; + + act= alloc_libblock(&G.main->action, ID_AC, name); + act->id.flag |= LIB_FAKEUSER; + act->id.us++; + + return act; +} + static void make_local_action_channels(bAction *act) { bActionChannel *chan; diff --git a/source/blender/editors/animation/anim_deps.c b/source/blender/editors/animation/anim_deps.c index f825a38bd7d..fbd9f5ecdb7 100644 --- a/source/blender/editors/animation/anim_deps.c +++ b/source/blender/editors/animation/anim_deps.c @@ -73,7 +73,7 @@ static unsigned int screen_view3d_layers(bScreen *screen) /* generic update flush, reads from context Screen (layers) and scene */ /* this is for compliancy, later it can do all windows etc */ -void ED_anim_dag_flush_update(bContext *C) +void ED_anim_dag_flush_update(const bContext *C) { Scene *scene= CTX_data_scene(C); bScreen *screen= CTX_wm_screen(C); diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index b8a3b8acb19..8a7a7582ee3 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -17,8 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. + * The Original Code is Copyright (C) 2008 Blender Foundation * * Contributor(s): Joshua Leung * @@ -30,6 +29,8 @@ #include <math.h> #include <float.h> +#include "MEM_guardedalloc.h" + #include "BLI_blenlib.h" #include "BLI_arithb.h" diff --git a/source/blender/editors/animation/keyframes_general.c b/source/blender/editors/animation/keyframes_general.c new file mode 100644 index 00000000000..57a4d6952c7 --- /dev/null +++ b/source/blender/editors/animation/keyframes_general.c @@ -0,0 +1,364 @@ +/** + * $Id: + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation + * All rights reserved. + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <string.h> +#include <math.h> +#include <float.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "DNA_action_types.h" +#include "DNA_curve_types.h" +#include "DNA_ipo_types.h" +#include "DNA_key_types.h" +#include "DNA_object_types.h" +#include "DNA_space_types.h" +#include "DNA_scene_types.h" + +#include "BKE_action.h" +#include "BKE_ipo.h" +#include "BKE_key.h" +#include "BKE_utildefines.h" + +#include "ED_anim_api.h" +#include "ED_keyframing.h" +#include "ED_keyframes_edit.h" + +/* This file contains code for various keyframe-editing tools which are 'destructive' + * (i.e. they will modify the order of the keyframes, and change the size of the array). + * While some of these tools may eventually be moved out into blenkernel, for now, it is + * fine to have these calls here. + * + * There are also a few tools here which cannot be easily coded for in the other system (yet). + * These may also be moved around at some point, but for now, they + * + * - Joshua Leung, Dec 2008 + */ + +/* **************************************************** */ + +/* Only delete the nominated keyframe from provided ipo-curve. + * Not recommended to be used many times successively. For that + * there is delete_ipo_keys(). + */ +void delete_icu_key(IpoCurve *icu, int index, short do_recalc) +{ + /* firstly check that index is valid */ + if (index < 0) + index *= -1; + if (icu == NULL) + return; + if (index >= icu->totvert) + return; + + /* Delete this key */ + memmove(&icu->bezt[index], &icu->bezt[index+1], sizeof(BezTriple)*(icu->totvert-index-1)); + icu->totvert--; + + /* recalc handles - only if it won't cause problems */ + if (do_recalc) + calchandles_ipocurve(icu); +} + +/* Delete selected keyframes in given IPO block */ +void delete_ipo_keys(Ipo *ipo) +{ + IpoCurve *icu, *next; + int i; + + if (ipo == NULL) + return; + + for (icu= ipo->curve.first; icu; icu= next) { + /* store pointer to next ipo-curve, as we may delete the current one */ + next = icu->next; + + /* Delete selected BezTriples */ + for (i=0; i<icu->totvert; i++) { + if (icu->bezt[i].f2 & SELECT) { + memmove(&icu->bezt[i], &icu->bezt[i+1], sizeof(BezTriple)*(icu->totvert-i-1)); + icu->totvert--; + i--; + } + } + + /* Only delete if there isn't an ipo-driver still hanging around on an empty curve */ + if ((icu->totvert==0) && (icu->driver==NULL)) { + BLI_remlink(&ipo->curve, icu); + free_ipo_curve(icu); + } + } +} + +/* ---------------- */ + +/* duplicate selected keyframes for the given IPO block */ +void duplicate_ipo_keys(Ipo *ipo) +{ + IpoCurve *icu; + BezTriple *newbezt; + int i; + + if (ipo == NULL) + return; + + for (icu= ipo->curve.first; icu; icu= icu->next) { + for (i=0; i<icu->totvert; i++) { + /* If a key is selected */ + if (icu->bezt[i].f2 & SELECT) { + /* Expand the list */ + newbezt = MEM_callocN(sizeof(BezTriple) * (icu->totvert+1), "beztriple"); + + memcpy(newbezt, icu->bezt, sizeof(BezTriple) * (i+1)); + memcpy(newbezt+i+1, icu->bezt+i, sizeof(BezTriple)); + memcpy(newbezt+i+2, icu->bezt+i+1, sizeof (BezTriple) *(icu->totvert-(i+1))); + icu->totvert++; + + /* reassign pointers... (free old, and add new) */ + MEM_freeN(icu->bezt); + icu->bezt=newbezt; + + /* Unselect the current key*/ + BEZ_DESEL(&icu->bezt[i]); + i++; + + /* Select the copied key */ + BEZ_SEL(&icu->bezt[i]); + } + } + } +} + +/* **************************************************** */ +/* Various Tools */ + +/* Basic IPO-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only */ +void clean_ipo_curve(IpoCurve *icu, float thresh) +{ + BezTriple *old_bezts, *bezt, *beztn; + BezTriple *lastb; + int totCount, i; + + /* check if any points */ + if ((icu == NULL) || (icu->totvert <= 1)) + return; + + /* make a copy of the old BezTriples, and clear IPO curve */ + old_bezts = icu->bezt; + totCount = icu->totvert; + icu->bezt = NULL; + icu->totvert = 0; + + /* now insert first keyframe, as it should be ok */ + bezt = old_bezts; + insert_vert_icu(icu, bezt->vec[1][0], bezt->vec[1][1], 0); + + /* Loop through BezTriples, comparing them. Skip any that do + * not fit the criteria for "ok" points. + */ + for (i=1; i<totCount; i++) { + float prev[2], cur[2], next[2]; + + /* get BezTriples and their values */ + if (i < (totCount - 1)) { + beztn = (old_bezts + (i+1)); + next[0]= beztn->vec[1][0]; next[1]= beztn->vec[1][1]; + } + else { + beztn = NULL; + next[0] = next[1] = 0.0f; + } + lastb= (icu->bezt + (icu->totvert - 1)); + bezt= (old_bezts + i); + + /* get references for quicker access */ + prev[0] = lastb->vec[1][0]; prev[1] = lastb->vec[1][1]; + cur[0] = bezt->vec[1][0]; cur[1] = bezt->vec[1][1]; + + /* check if current bezt occurs at same time as last ok */ + if (IS_EQT(cur[0], prev[0], thresh)) { + /* If there is a next beztriple, and if occurs at the same time, only insert + * if there is a considerable distance between the points, and also if the + * current is further away than the next one is to the previous. + */ + if (beztn && (IS_EQT(cur[0], next[0], thresh)) && + (IS_EQT(next[1], prev[1], thresh)==0)) + { + /* only add if current is further away from previous */ + if (cur[1] > next[1]) { + if (IS_EQT(cur[1], prev[1], thresh) == 0) { + /* add new keyframe */ + insert_vert_icu(icu, cur[0], cur[1], 0); + } + } + } + else { + /* only add if values are a considerable distance apart */ + if (IS_EQT(cur[1], prev[1], thresh) == 0) { + /* add new keyframe */ + insert_vert_icu(icu, cur[0], cur[1], 0); + } + } + } + else { + /* checks required are dependent on whether this is last keyframe or not */ + if (beztn) { + /* does current have same value as previous and next? */ + if (IS_EQT(cur[1], prev[1], thresh) == 0) { + /* add new keyframe*/ + insert_vert_icu(icu, cur[0], cur[1], 0); + } + else if (IS_EQT(cur[1], next[1], thresh) == 0) { + /* add new keyframe */ + insert_vert_icu(icu, cur[0], cur[1], 0); + } + } + else { + /* add if value doesn't equal that of previous */ + if (IS_EQT(cur[1], prev[1], thresh) == 0) { + /* add new keyframe */ + insert_vert_icu(icu, cur[0], cur[1], 0); + } + } + } + } + + /* now free the memory used by the old BezTriples */ + if (old_bezts) + MEM_freeN(old_bezts); +} + +/* ---------------- */ + +/* temp struct used for smooth_ipo */ +typedef struct tSmooth_Bezt { + float *h1, *h2, *h3; /* bezt->vec[0,1,2][1] */ +} tSmooth_Bezt; + +/* Use a weighted moving-means method to reduce intensity of fluctuations */ +//mode= pupmenu("Smooth IPO%t|Tweak Points%x1|Flatten Handles%x2"); +void smooth_ipo_curve(IpoCurve *icu, short mode) +{ + BezTriple *bezt; + int i, x, totSel = 0; + + /* first loop through - count how many verts are selected, and fix up handles + * this is done for both modes + */ + bezt= icu->bezt; + for (i=0; i < icu->totvert; i++, bezt++) { + if (BEZSELECTED(bezt)) { + /* line point's handles up with point's vertical position */ + bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1]; + if ((bezt->h1==HD_AUTO) || (bezt->h1==HD_VECT)) bezt->h1= HD_ALIGN; + if ((bezt->h2==HD_AUTO) || (bezt->h2==HD_VECT)) bezt->h2= HD_ALIGN; + + /* add value to total */ + totSel++; + } + } + + /* check if adjust values too... */ + if (mode == 2) { + /* if any points were selected, allocate tSmooth_Bezt points to work on */ + if (totSel >= 3) { + tSmooth_Bezt *tarray, *tsb; + + /* allocate memory in one go */ + tsb= tarray= MEM_callocN(totSel*sizeof(tSmooth_Bezt), "tSmooth_Bezt Array"); + + /* populate tarray with data of selected points */ + bezt= icu->bezt; + for (i=0, x=0; (i < icu->totvert) && (x < totSel); i++, bezt++) { + if (BEZSELECTED(bezt)) { + /* tsb simply needs pointer to vec, and index */ + tsb->h1 = &bezt->vec[0][1]; + tsb->h2 = &bezt->vec[1][1]; + tsb->h3 = &bezt->vec[2][1]; + + /* advance to the next tsb to populate */ + if (x < totSel- 1) + tsb++; + else + break; + } + } + + /* calculate the new smoothed ipo's with weighted averages: + * - this is done with two passes + * - uses 5 points for each operation (which stores in the relevant handles) + * - previous: w/a ratio = 3:5:2:1:1 + * - next: w/a ratio = 1:1:2:5:3 + */ + + /* round 1: calculate previous and next */ + tsb= tarray; + for (i=0; i < totSel; i++, tsb++) { + /* don't touch end points (otherwise, curves slowly explode) */ + if (ELEM(i, 0, (totSel-1)) == 0) { + const tSmooth_Bezt *tP1 = tsb - 1; + const tSmooth_Bezt *tP2 = (i-2 > 0) ? (tsb - 2) : (NULL); + const tSmooth_Bezt *tN1 = tsb + 1; + const tSmooth_Bezt *tN2 = (i+2 < totSel) ? (tsb + 2) : (NULL); + + const float p1 = *tP1->h2; + const float p2 = (tP2) ? (*tP2->h2) : (*tP1->h2); + const float c1 = *tsb->h2; + const float n1 = *tN1->h2; + const float n2 = (tN2) ? (*tN2->h2) : (*tN1->h2); + + /* calculate previous and next */ + *tsb->h1= (3*p2 + 5*p1 + 2*c1 + n1 + n2) / 12; + *tsb->h3= (p2 + p1 + 2*c1 + 5*n1 + 3*n2) / 12; + } + } + + /* round 2: calculate new values and reset handles */ + tsb= tarray; + for (i=0; i < totSel; i++, tsb++) { + /* calculate new position by averaging handles */ + *tsb->h2 = (*tsb->h1 + *tsb->h3) / 2; + + /* reset handles now */ + *tsb->h1 = *tsb->h2; + *tsb->h3 = *tsb->h2; + } + + /* free memory required for tarray */ + MEM_freeN(tarray); + } + } + + /* recalculate handles */ + calchandles_ipocurve(icu); +} + +/* **************************************************** */ diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index a86cf3719d3..ac41a63760d 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -55,9 +55,12 @@ #include "DNA_key_types.h" #include "DNA_lamp_types.h" #include "DNA_object_types.h" +#include "DNA_object_fluidsim.h" +#include "DNA_particle_types.h" #include "DNA_material_types.h" #include "DNA_screen_types.h" #include "DNA_scene_types.h" +#include "DNA_sequence_types.h" #include "DNA_space_types.h" #include "DNA_texture_types.h" #include "DNA_userdef_types.h" @@ -65,10 +68,9 @@ #include "DNA_view3d_types.h" #include "DNA_world_types.h" -#include "BKE_global.h" +#include "BKE_context.h" #include "BKE_utildefines.h" #include "BKE_blender.h" -#include "BKE_main.h" // XXX not needed old cruft? #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" @@ -77,31 +79,35 @@ #include "BKE_ipo.h" #include "BKE_key.h" #include "BKE_object.h" +#include "BKE_particle.h" #include "BKE_material.h" +#include "BKE_modifier.h" +#include "ED_anim_api.h" #include "ED_keyframing.h" +#include "ED_keyframes_edit.h" #if 0 // XXX resolve these old dependencies! -#include "BIF_butspace.h" -#include "BIF_editaction.h" -#include "BIF_editkey.h" -#include "BIF_interface.h" -#include "BIF_mywindow.h" -#include "BIF_poseobject.h" -#include "BIF_screen.h" -#include "BIF_space.h" -#include "BIF_toolbox.h" -#include "BIF_toets.h" - -#include "BSE_editipo.h" -#include "BSE_node.h" -#include "BSE_time.h" -#include "BSE_view.h" - -#include "blendef.h" - -#include "PIL_time.h" /* sleep */ -#include "mydevice.h" + #include "BIF_butspace.h" + #include "BIF_editaction.h" + #include "BIF_editkey.h" + #include "BIF_interface.h" + #include "BIF_mywindow.h" + #include "BIF_poseobject.h" + #include "BIF_screen.h" + #include "BIF_space.h" + #include "BIF_toolbox.h" + #include "BIF_toets.h" + + #include "BSE_editipo.h" + #include "BSE_node.h" + #include "BSE_time.h" + #include "BSE_view.h" + + #include "blendef.h" + + #include "PIL_time.h" /* sleep */ + #include "mydevice.h" #endif // XXX resolve these old dependencies! @@ -169,6 +175,284 @@ typedef struct bKeyingContext { int tot; /* number of keyingsets in */ } bKeyingContext; + +/* ************************************************** */ +/* IPO DATA VERIFICATION */ +// XXX these will need to be modified for use with RNA-IPO... + +/* depending type, it returns ipo, if needed it creates one */ +/* returns either action ipo or "real" ipo */ +/* arguments define full context; + - *from has to be set always, to Object in case of Actions + - blocktype defines available channels of Ipo struct (blocktype ID_OB can be in action too) + - if actname, use this to locate actionchannel, and optional constname + - if bonename, the constname is the ipo to the constraint +*/ + +/* note: check header_ipo.c, spaceipo_assign_ipo() too */ +Ipo *verify_ipo(ID *from, short blocktype, char actname[], char constname[], char bonename[], short add) +{ + /* lib-linked data is not appropriate here */ + if ((from==NULL) || (from->lib)) + return NULL; + + /* first check action ipos */ + if (actname && actname[0]) { + Object *ob= (Object *)from; + bActionChannel *achan; + + if (GS(from->name)!=ID_OB) { + printf("called ipo system for action with wrong base pointer\n"); + return NULL; + } + + if ((ob->action==NULL) && (add)) + ob->action= add_empty_action("Action"); + + if (add) + achan= verify_action_channel(ob->action, actname); + else + achan= get_action_channel(ob->action, actname); + + if (achan) { + /* automatically assign achan to act-group based on pchan's grouping */ + //if ((blocktype == ID_PO) && (add)) + // verify_pchan2achan_grouping(ob->action, ob->pose, actname); + + /* constraint exception */ + if (blocktype==ID_CO) { + bConstraintChannel *conchan; + + if (add) + conchan= verify_constraint_channel(&achan->constraintChannels, constname); + else + conchan= get_constraint_channel(&achan->constraintChannels, constname); + + if (conchan) { + if ((conchan->ipo==NULL) && (add)) + conchan->ipo= add_ipo("CoIpo", ID_CO); + return conchan->ipo; + } + } + else { + if ((achan->ipo==NULL) && (add)) + achan->ipo= add_ipo("ActIpo", blocktype); + return achan->ipo; + } + } + } + else { + switch (GS(from->name)) { + case ID_OB: + { + Object *ob= (Object *)from; + + /* constraint exception */ + if (blocktype==ID_CO) { + /* check the local constraint ipo */ + if (bonename && bonename[0] && ob->pose) { + bPoseChannel *pchan= get_pose_channel(ob->pose, bonename); + bConstraint *con; + + for (con= pchan->constraints.first; con; con= con->next) { + if (strcmp(con->name, constname)==0) + break; + } + + if (con) { + if ((con->ipo==NULL) && (add)) + con->ipo= add_ipo("CoIpo", ID_CO); + return con->ipo; + } + } + else { /* the actionchannel */ + bConstraintChannel *conchan; + + if (add) + conchan= verify_constraint_channel(&ob->constraintChannels, constname); + else + conchan= get_constraint_channel(&ob->constraintChannels, constname); + + if (conchan) { + if ((conchan->ipo==NULL) && (add)) + conchan->ipo= add_ipo("CoIpo", ID_CO); + return conchan->ipo; + } + } + } + else if (blocktype==ID_OB) { + if ((ob->ipo==NULL) && (add)) + ob->ipo= add_ipo("ObIpo", ID_OB); + return ob->ipo; + } + else if (blocktype==ID_KE) { + Key *key= ob_get_key((Object *)from); + + if (key) { + if ((key->ipo==NULL) && (add)) + key->ipo= add_ipo("KeyIpo", ID_KE); + return key->ipo; + } + return NULL; + } + else if (blocktype== ID_FLUIDSIM) { + Object *ob= (Object *)from; + + FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); + if(fluidmd) { + FluidsimSettings *fss= fluidmd->fss; + + if ((fss->ipo==NULL) && (add)) + fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM); + return fss->ipo; + } + } + else if(blocktype== ID_PA) { + Object *ob= (Object *)from; + ParticleSystem *psys= psys_get_current(ob); + + if (psys) { + if ((psys->part->ipo==NULL) && (add)) + psys->part->ipo= add_ipo("ParticleIpo", ID_PA); + return psys->part->ipo; + } + return NULL; + } + } + break; + case ID_MA: + { + Material *ma= (Material *)from; + + if ((ma->ipo==NULL) && (add)) + ma->ipo= add_ipo("MatIpo", ID_MA); + return ma->ipo; + } + break; + case ID_TE: + { + Tex *tex= (Tex *)from; + + if ((tex->ipo==NULL) && (add)) + tex->ipo= add_ipo("TexIpo", ID_TE); + return tex->ipo; + } + break; + case ID_SEQ: + { + Sequence *seq= (Sequence *)from; /* note, sequence is mimicing Id */ + + if ((seq->ipo==NULL) && (add)) + seq->ipo= add_ipo("SeqIpo", ID_SEQ); + //update_seq_ipo_rect(seq); // XXX + return seq->ipo; + } + break; + case ID_CU: + { + Curve *cu= (Curve *)from; + + if ((cu->ipo==NULL) && (add)) + cu->ipo= add_ipo("CuIpo", ID_CU); + return cu->ipo; + } + break; + case ID_WO: + { + World *wo= (World *)from; + + if ((wo->ipo==NULL) && (add)) + wo->ipo= add_ipo("WoIpo", ID_WO); + return wo->ipo; + } + break; + case ID_LA: + { + Lamp *la= (Lamp *)from; + + if ((la->ipo==NULL) && (add)) + la->ipo= add_ipo("LaIpo", ID_LA); + return la->ipo; + } + break; + case ID_CA: + { + Camera *ca= (Camera *)from; + + if ((ca->ipo==NULL) && (add)) + ca->ipo= add_ipo("CaIpo", ID_CA); + return ca->ipo; + } + break; + case ID_SO: + { +#if 0 // depreceated + bSound *snd= (bSound *)from; + + if ((snd->ipo==NULL) && (add)) + snd->ipo= add_ipo("SndIpo", ID_SO); + return snd->ipo; +#endif // depreceated + } + break; + } + } + + return NULL; +} + +/* Returns and creates + * Make sure functions check for NULL or they will crash! + */ +IpoCurve *verify_ipocurve(ID *from, short blocktype, char actname[], char constname[], char bonename[], int adrcode, short add) +{ + Ipo *ipo; + IpoCurve *icu= NULL; + + /* return 0 if lib */ + /* creates ipo too (if add) */ + ipo= verify_ipo(from, blocktype, actname, constname, bonename, add); + + if ((ipo) && (ipo->id.lib==NULL) && (from->lib==NULL)) { + /* try to find matching curve */ + icu= find_ipocurve(ipo, adrcode); + + /* make a new one if none found (and can add) */ + if ((icu==NULL) && (add)) { + icu= MEM_callocN(sizeof(IpoCurve), "ipocurve"); + + /* set default settings */ + icu->flag |= (IPO_VISIBLE|IPO_AUTO_HORIZ); + if (ipo->curve.first==NULL) + icu->flag |= IPO_ACTIVE; /* first one added active */ + + icu->blocktype= blocktype; + icu->adrcode= adrcode; + + set_icu_vars(icu); + + /* default curve interpolation - from userpref */ + icu->ipo= U.ipo_new; + + /* add curve to IPO-block */ + BLI_addtail(&ipo->curve, icu); + + /* special type-dependent stuff */ + switch (GS(from->name)) { + case ID_SEQ: { + //Sequence *seq= (Sequence *)from; + + //update_seq_icu_rects(seq); // XXX + break; + } + } + } + } + + /* return ipo-curve */ + return icu; +} + /* ************************************************** */ /* KEYFRAME INSERTION */ @@ -382,7 +666,6 @@ void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) } } -#if 0 // XXX code to clean up /* ------------------- Get Data ------------------------ */ @@ -787,11 +1070,11 @@ short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrc IpoCurve *icu; /* get ipo-curve */ - //icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1); // XXX this call needs to be in blenkernel + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1); /* only continue if we have an ipo-curve to add keyframe to */ if (icu) { - float cfra = frame_to_float(CFRA); + float cfra =1.0f;//= frame_to_float(CFRA); float curval= 0.0f; /* apply special time tweaking */ @@ -803,10 +1086,10 @@ short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrc cfra= get_action_frame(ob, cfra); /* ancient time-offset cruft */ - if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } + //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + // /* actually frametofloat calc again! */ + // cfra-= give_timeoffset(ob)*G.scene->r.framelen; + //} } /* obtain value to give keyframe */ @@ -894,13 +1177,12 @@ short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrc * Note: here is one of the places where we don't want new ipo + ipo-curve added! * so 'add' var must be 0 */ - // XXX funcs here need to be recoded in blenkernel... - //ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0); - //icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0); + ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0); + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0); /* only continue if we have an ipo-curve to remove keyframes from */ if (icu) { - float cfra = frame_to_float(CFRA); + float cfra = 1.0f;//frame_to_float(CFRA); short found = -1; int i; @@ -913,10 +1195,10 @@ short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrc cfra= get_action_frame(ob, cfra); /* ancient time-offset cruft */ - if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } + //if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + // /* actually frametofloat calc again! */ + // cfra-= give_timeoffset(ob)*G.scene->r.framelen; + //} } /* try to find index of beztriple to get rid of */ @@ -1101,7 +1383,8 @@ static short incl_non_del_keys (bKeyingSet *ks, const char mode[]) /* check if include shapekey entry */ static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[]) { - Object *ob= (G.obedit)? (G.obedit) : (OBACT); + //Object *ob= (G.obedit)? (G.obedit) : (OBACT); // XXX + Object *ob= NULL; char *newname= NULL; if(ob==NULL) @@ -1366,7 +1649,8 @@ bKeyingSet defks_buts_shading_tex[] = /* check if include particles entry */ static short incl_buts_ob (bKeyingSet *ks, const char mode[]) { - Object *ob= OBACT; + //Object *ob= OBACT; // xxx + Object *ob= NULL; /* only if object is mesh type */ if(ob==NULL) return 0; @@ -1396,15 +1680,17 @@ bKeyingSet defks_buts_object[] = /* check if include internal-renderer entry */ static short incl_buts_cam1 (bKeyingSet *ks, const char mode[]) { + Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first! /* only if renderer is internal renderer */ - return (G.scene->r.renderer==R_INTERN); + return (scene->r.renderer==R_INTERN); } /* check if include external-renderer entry */ static short incl_buts_cam2 (bKeyingSet *ks, const char mode[]) { + Scene *scene= NULL; // FIXME this will cause a crash, but we need an extra arg first! /* only if renderer is internal renderer */ - return (G.scene->r.renderer!=R_INTERN); + return (scene->r.renderer!=R_INTERN); } /* array for camera keyingset defines */ @@ -1464,8 +1750,9 @@ typedef enum eKS_Contexts { /* ---------------- KeyingSet Tools ------------------- */ /* helper for commonkey_context_get() - get keyingsets for 3d-view */ -static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc) +static void commonkey_context_getv3d (const bContext *C, ListBase *sources, bKeyingContext **ksc) { + Scene *scene= CTX_data_scene(C); Object *ob; IpoCurve *icu; @@ -1475,7 +1762,8 @@ static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc) /* pose-level */ ob= OBACT; *ksc= &ks_contexts[KSC_V3D_PCHAN]; - set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ + // XXX + //set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ /* loop through posechannels */ for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { @@ -1497,62 +1785,60 @@ static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc) } } else { - Base *base; - /* object-level */ *ksc= &ks_contexts[KSC_V3D_OBJECT]; /* loop through bases */ - for (base= FIRSTBASE; base; base= base->next) { - if (TESTBASELIB(base)) { - bCommonKeySrc *cks; - - /* add new keyframing destination */ - cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); - BLI_addtail(sources, cks); - - /* set id-block to key to */ - ob= base->object; - cks->id= (ID *)ob; - - /* when ob's keyframes are in an action, default to using 'Object' as achan name */ - if (ob->ipoflag & OB_ACTION_OB) - cks->actname= "Object"; - - /* set ipo-flags */ - // TODO: add checks for lib-linked data - if ((ob->ipo) || (ob->action)) { - if (ob->ipo) { - cks->ipo= ob->ipo; - } - else { - bActionChannel *achan; - - cks->act= ob->action; - achan= get_action_channel(ob->action, cks->actname); - - if (achan && achan->ipo) - cks->ipo= achan->ipo; - } - /* cks->ipo can be NULL while editing */ - if(cks->ipo) { - /* deselect all ipo-curves */ - for (icu= cks->ipo->curve.first; icu; icu= icu->next) { - icu->flag &= ~IPO_SELECT; - } + // XXX but we're only supposed to do this on editable ones! + CTX_DATA_BEGIN(C, Base*, base, selected_bases) { + bCommonKeySrc *cks; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + ob= base->object; + cks->id= (ID *)ob; + + /* when ob's keyframes are in an action, default to using 'Object' as achan name */ + if (ob->ipoflag & OB_ACTION_OB) + cks->actname= "Object"; + + /* set ipo-flags */ + // TODO: add checks for lib-linked data + if ((ob->ipo) || (ob->action)) { + if (ob->ipo) { + cks->ipo= ob->ipo; + } + else { + bActionChannel *achan; + + cks->act= ob->action; + achan= get_action_channel(ob->action, cks->actname); + + if (achan && achan->ipo) + cks->ipo= achan->ipo; + } + /* cks->ipo can be NULL while editing */ + if(cks->ipo) { + /* deselect all ipo-curves */ + for (icu= cks->ipo->curve.first; icu; icu= icu->next) { + icu->flag &= ~IPO_SELECT; } } } } + CTX_DATA_END; } } /* helper for commonkey_context_get() - get keyingsets for buttons window */ -static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) +static void commonkey_context_getsbuts (const bContext *C, ListBase *sources, bKeyingContext **ksc) { - bCommonKeySrc *cks; - #if 0 // XXX dunno what's the future of this stuff... + bCommonKeySrc *cks; + /* check on tab-type */ switch (G.buts->mainb) { case CONTEXT_SHADING: /* ------------- Shading buttons ---------------- */ @@ -1690,21 +1976,25 @@ static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) /* get keyingsets for appropriate context */ -static void commonkey_context_get (ScrArea *sa, short mode, ListBase *sources, bKeyingContext **ksc) +static void commonkey_context_get (const bContext *C, ScrArea *sa, short mode, ListBase *sources, bKeyingContext **ksc) { + /* get current view if no view is defined */ + if (sa == NULL) + sa= CTX_wm_area(C); + /* check view type */ switch (sa->spacetype) { /* 3d view - first one tested as most often used */ case SPACE_VIEW3D: { - commonkey_context_getv3d(sources, ksc); + commonkey_context_getv3d(C, sources, ksc); } break; /* buttons view */ case SPACE_BUTS: { - commonkey_context_getsbuts(sources, ksc); + commonkey_context_getsbuts(C, sources, ksc); } break; @@ -1721,6 +2011,7 @@ static void commonkey_context_get (ScrArea *sa, short mode, ListBase *sources, b /* timeline view - keyframe buttons */ case SPACE_TIME: { + bScreen *sc= CTX_wm_screen(C); ScrArea *sab; int bigarea= 0; @@ -1731,12 +2022,12 @@ static void commonkey_context_get (ScrArea *sa, short mode, ListBase *sources, b //sab= find_biggest_area_of_type(SPACE_VIEW3D); sab= NULL; // XXX for now... if (sab) { - commonkey_context_getv3d(sources, ksc); + commonkey_context_getv3d(C, sources, ksc); return; } /* if not found, sab is now NULL, so perform own biggest area test */ - for (sa= G.curscreen->areabase.first; sa; sa= sa->next) { // XXX this has changed! + for (sa= sc->areabase.first; sa; sa= sa->next) { // XXX this has changed! int area= sa->winx * sa->winy; if (sa->spacetype != SPACE_TIME) { @@ -1749,15 +2040,18 @@ static void commonkey_context_get (ScrArea *sa, short mode, ListBase *sources, b /* use whichever largest area was found (it shouldn't be a time window) */ if (sab) - commonkey_context_get(sab, mode, sources, ksc); + commonkey_context_get(C, sab, mode, sources, ksc); } break; } } /* flush updates after all operations */ -static void commonkey_context_finish (ListBase *sources) +static void commonkey_context_finish (const bContext *C, ListBase *sources) { + ScrArea *curarea= CTX_wm_area(C); + Scene *scene= CTX_data_scene(C); + /* check view type */ switch (curarea->spacetype) { /* 3d view - first one tested as most often used */ @@ -1765,16 +2059,18 @@ static void commonkey_context_finish (ListBase *sources) { /* either pose or object level */ if (OBACT && (OBACT->pose)) { - Object *ob= OBACT; + //Object *ob= OBACT; /* recalculate ipo handles, etc. */ - if (ob->action) - remake_action_ipos(ob->action); + // XXX this method has been removed! + //if (ob->action) + // remake_action_ipos(ob->action); /* recalculate bone-paths on adding new keyframe? */ + // XXX missing function // TODO: currently, there is no setting to turn this on/off globally - if (ob->pose->flag & POSE_RECALCPATHS) - pose_recalculate_paths(ob); + //if (ob->pose->flag & POSE_RECALCPATHS) + // pose_recalculate_paths(ob); } else { bCommonKeySrc *cks; @@ -1793,19 +2089,17 @@ static void commonkey_context_finish (ListBase *sources) } /* flush refreshes after undo */ -static void commonkey_context_refresh (void) +static void commonkey_context_refresh (const bContext *C) { + ScrArea *curarea= CTX_wm_area(C); + /* check view type */ switch (curarea->spacetype) { /* 3d view - first one tested as most often used */ case SPACE_VIEW3D: { /* do refreshes */ - DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); - - //allspace(REMAKEIPO, 0); - //allqueue(REDRAWVIEW3D, 0); - //allqueue(REDRAWMARKER, 0); + ED_anim_dag_flush_update(C); } break; @@ -1889,8 +2183,7 @@ static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index) /* ---------------- Keyframe Management API -------------------- */ /* Display a menu for handling the insertion of keyframes based on the active view */ -// TODO: add back an option for repeating last keytype -void common_modifykey (short mode) +void common_modifykey (const bContext *C, short mode) { ListBase dsources = {NULL, NULL}; bKeyingContext *ksc= NULL; @@ -1906,7 +2199,7 @@ void common_modifykey (short mode) /* delegate to other functions or get keyingsets to use * - if the current area doesn't have its own handling, there will be data returned... */ - commonkey_context_get(curarea, mode, &dsources, &ksc); + commonkey_context_get(C, NULL, mode, &dsources, &ksc); /* check that there is data to operate on */ if (ELEM(NULL, dsources.first, ksc)) { @@ -1919,8 +2212,10 @@ void common_modifykey (short mode) menustr= build_keyingsets_menu(ksc, "Delete"); else menustr= build_keyingsets_menu(ksc, "Insert"); - menu_nr= pupmenu(menustr); - if (menustr) MEM_freeN(menustr); + // XXX: this goes to the invoke! + //menu_nr= pupmenu(menustr); + //if (menustr) MEM_freeN(menustr); + menu_nr = -1; // XXX for now /* no item selected or shapekey entry? */ if (menu_nr < 1) { @@ -1928,9 +2223,10 @@ void common_modifykey (short mode) BLI_freelistN(&dsources); /* check if insert new shapekey */ - if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT)) - insert_shapekey(OBACT); - else + // XXX missing function! + //if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT)) + // insert_shapekey(OBACT); + //else ksc->lastused= NULL; return; @@ -2053,7 +2349,7 @@ void common_modifykey (short mode) } /* apply post-keying flushes for this data sources */ - commonkey_context_finish(&dsources); + commonkey_context_finish(C, &dsources); ksc->lastused= ks; /* free temp data */ @@ -2064,27 +2360,26 @@ void common_modifykey (short mode) BLI_snprintf(buf, 64, "Delete %s Key", ks->name); else BLI_snprintf(buf, 64, "Insert %s Key", ks->name); - BIF_undo_push(buf); + //BIF_undo_push(buf); /* queue updates for contexts */ - commonkey_context_refresh(); + commonkey_context_refresh(C); } /* ---- */ /* used to insert keyframes from any view */ -void common_insertkey (void) +void common_insertkey (const bContext *C) { - common_modifykey(COMMONKEY_MODE_INSERT); + common_modifykey(C, COMMONKEY_MODE_INSERT); } /* used to insert keyframes from any view */ -void common_deletekey (void) +void common_deletekey (const bContext *C) { - common_modifykey(COMMONKEY_MODE_DELETE); + common_modifykey(C, COMMONKEY_MODE_DELETE); } -#endif // XXX reenable this file again later... /* ************************************************** */ /* KEYFRAME DETECTION */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 492e2a22b84..4e55f8c364c 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -285,8 +285,8 @@ void ANIM_nla_mapping_apply(struct Object *ob, struct Ipo *ipo, short restore, s /* --------- anim_deps.c, animation updates -------- */ /* generic update flush, reads from Context screen (layers) and scene */ -void ED_anim_dag_flush_update(struct bContext *C); -void ED_update_for_newframe(struct bContext *C, int mute); +void ED_anim_dag_flush_update(const struct bContext *C); +void ED_update_for_newframe(const struct bContext *C, int mute); /* ************************************************* */ /* OPERATORS */ diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index 3b553320f32..75faaf85d14 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -83,7 +83,7 @@ typedef enum eEditKeyframes_Mirror { } eEditKeyframes_Mirror; /* ************************************************ */ -/* Editing API */ +/* Non-Destuctive Editing API (keyframes_edit.c) */ /* --- Generic Properties for Bezier Edit Tools ----- */ @@ -129,9 +129,20 @@ BeztEditFunc ANIM_editkeyframes_ipo(short mode); void ANIM_editkeyframes_ipocurve_ipotype(struct IpoCurve *icu); /* ************************************************ */ +/* Destructive Editing API (keyframes_general.c) */ + +void delete_icu_key(struct IpoCurve *icu, int index, short do_recalc); +void delete_ipo_keys(struct Ipo *ipo); +void duplicate_ipo_keys(struct Ipo *ipo); + +void clean_ipo_curve(struct IpoCurve *icu, float thresh); +void smooth_ipo_curve(struct IpoCurve *icu, short mode); + +/* ************************************************ */ // XXX all of these funcs should be depreceated or at least renamed! +/* in keyframes_edit.c */ short is_ipo_key_selected(struct Ipo *ipo); void set_ipo_key_selection(struct Ipo *ipo, short sel); diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index f4be3f06c6b..9529058b952 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -31,9 +31,16 @@ struct ListBase; struct ID; +struct Ipo; struct IpoCurve; struct BezTriple; +/* ************ IPO/IPO-Curve Management ************** */ +// XXX these will need to be updated for RNA-IPO stuff + +struct Ipo *verify_ipo(struct ID *from, short blocktype, char actname[], char constname[], char bonename[], short add); +struct IpoCurve *verify_ipocurve(struct ID *from, short blocktype, char actname[], char constname[], char bonename[], int adrcode, short add); + /* ************ Keyframing Management **************** */ /* Lesser Keyframing API call: @@ -84,8 +91,8 @@ short deletekey(struct ID *id, int blocktype, char *actname, char *constname, in * These handle keyframes management from various spaces. They will handle the menus * required for each space. */ -void common_insertkey(void); -void common_deletekey(void); +void common_insertkey(const struct bContext *C); +void common_deletekey(const struct bContext *C); /* ************ Auto-Keyframing ********************** */ /* Notes: diff --git a/source/blender/editors/space_action/action_edit_keyframes.c b/source/blender/editors/space_action/action_edit_keyframes.c index 4975a2cd6de..df62de9bd83 100644 --- a/source/blender/editors/space_action/action_edit_keyframes.c +++ b/source/blender/editors/space_action/action_edit_keyframes.c @@ -89,18 +89,265 @@ /* GENERAL STUFF */ // TODO: -// - clean -// - sample // - delete // - insert key // - copy/paste +/* ******************** Delete Keyframes Operator ************************* */ + +static void delete_action_keys (bAnimContext *ac) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* filter data */ + if (ac->datatype == ANIMCONT_GPENCIL) + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT); + else + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_IPOKEYS); + ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype); + + /* loop through filtered data and delete selected keys */ + for (ale= anim_data.first; ale; ale= ale->next) { + //if (ale->type == ANIMTYPE_GPLAYER) + // delete_gplayer_frames((bGPDlayer *)ale->data); + //else + delete_ipo_keys((Ipo *)ale->key_data); + } + + /* free filtered list */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +static int actkeys_delete_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* delete keyframes */ + delete_action_keys(&ac); + + /* validate keyframes after editing */ + ANIM_editkeyframes_refresh(&ac); + + /* set notifier tha things have changed */ + ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead! + + return OPERATOR_FINISHED; +} + +void ACT_OT_keyframes_delete (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Delete Keyframes"; + ot->idname= "ACT_OT_keyframes_delete"; + + /* api callbacks */ + ot->exec= actkeys_delete_exec; + ot->poll= ED_operator_areaactive; + + /* flags */ + ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; +} + +/* ******************** Clean Keyframes Operator ************************* */ + +static void clean_action_keys (bAnimContext *ac, float thresh) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_SEL | ANIMFILTER_ONLYICU); + ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype); + + /* loop through filtered data and clean curves */ + for (ale= anim_data.first; ale; ale= ale->next) + clean_ipo_curve((IpoCurve *)ale->key_data, thresh); + + /* free temp data */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +static int actkeys_clean_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + float thresh; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + if (ac.datatype == ANIMCONT_GPENCIL) + return OPERATOR_PASS_THROUGH; + + /* get cleaning threshold */ + thresh= RNA_float_get(op->ptr, "threshold"); + + /* clean keyframes */ + clean_action_keys(&ac, thresh); + + /* validate keyframes after editing */ + ANIM_editkeyframes_refresh(&ac); + + /* set notifier tha things have changed */ + ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead! + + return OPERATOR_FINISHED; +} + +void ACT_OT_keyframes_clean (wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name= "Clean Keyframes"; + ot->idname= "ACT_OT_keyframes_clean"; + + /* api callbacks */ + //ot->invoke= // XXX we need that number popup for this! + ot->exec= actkeys_clean_exec; + ot->poll= ED_operator_areaactive; + + /* flags */ + ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; + + /* properties */ + prop= RNA_def_property(ot->srna, "threshold", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_default(prop, 0.001f); +} + +/* ******************** Sample Keyframes Operator *********************** */ + +/* little cache for values... */ +typedef struct tempFrameValCache { + float frame, val; +} tempFrameValCache; + +/* Evaluates the curves between each selected keyframe on each frame, and keys the value */ +static void sample_action_keys (bAnimContext *ac) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + + /* filter data */ + filter= (ANIMFILTER_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_ONLYICU); + ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype); + + /* loop through filtered data and add keys between selected keyframes on every frame */ + for (ale= anim_data.first; ale; ale= ale->next) { + IpoCurve *icu= (IpoCurve *)ale->key_data; + BezTriple *bezt, *start=NULL, *end=NULL; + tempFrameValCache *value_cache, *fp; + int sfra, range; + int i, n; + + /* find selected keyframes... once pair has been found, add keyframes */ + for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) { + /* check if selected, and which end this is */ + if (BEZSELECTED(bezt)) { + if (start) { + /* set end */ + end= bezt; + + /* cache values then add keyframes using these values, as adding + * keyframes while sampling will affect the outcome... + */ + range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) ); + sfra= (int)( floor(start->vec[1][0]) ); + + if (range) { + value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache"); + + /* sample values */ + for (n=0, fp=value_cache; n<range && fp; n++, fp++) { + fp->frame= (float)(sfra + n); + fp->val= eval_icu(icu, fp->frame); + } + + /* add keyframes with these */ + for (n=0, fp=value_cache; n<range && fp; n++, fp++) { + insert_vert_icu(icu, fp->frame, fp->val, 1); + } + + /* free temp cache */ + MEM_freeN(value_cache); + + /* as we added keyframes, we need to compensate so that bezt is at the right place */ + bezt = icu->bezt + i + range - 1; + i += (range - 1); + } + + /* bezt was selected, so it now marks the start of a whole new chain to search */ + start= bezt; + end= NULL; + } + else { + /* just set start keyframe */ + start= bezt; + end= NULL; + } + } + } + + /* recalculate channel's handles? */ + calchandles_ipocurve(icu); + } + + /* admin and redraws */ + BLI_freelistN(&anim_data); +} + +/* ------------------- */ + +static int actkeys_sample_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + if (ac.datatype == ANIMCONT_GPENCIL) + return OPERATOR_PASS_THROUGH; + + /* sample keyframes */ + sample_action_keys(&ac); + + /* validate keyframes after editing */ + ANIM_editkeyframes_refresh(&ac); + + /* set notifier tha things have changed */ + ED_area_tag_redraw(CTX_wm_area(C)); // FIXME... should be updating 'keyframes' data context or so instead! + + return OPERATOR_FINISHED; +} + +void ACT_OT_keyframes_sample (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Sample Keyframes"; + ot->idname= "ACT_OT_keyframes_sample"; + + /* api callbacks */ + ot->exec= actkeys_sample_exec; + ot->poll= ED_operator_areaactive; + + /* flags */ + ot->flag= OPTYPE_REGISTER/*|OPTYPE_UNDO*/; +} + /* ************************************************************************** */ /* SETTINGS STUFF */ -// TODO: -// - wkey stuff - /* ******************** Set Extrapolation-Type Operator *********************** */ /* defines for set ipo-type for selected keyframes tool */ diff --git a/source/blender/editors/space_action/action_header.c b/source/blender/editors/space_action/action_header.c index 04958aede0f..d04ffd0935d 100644 --- a/source/blender/editors/space_action/action_header.c +++ b/source/blender/editors/space_action/action_header.c @@ -62,14 +62,165 @@ /* ********************************************************* */ /* Menu Defines... */ -// XXX button events +/* button events */ enum { B_REDR = 0, B_ACTCOPYKEYS, B_ACTPASTEKEYS, } eActHeader_ButEvents; -// ---------------- menus +/* ------------------------------- */ +/* enums declaring constants that are used as menu event codes */ + +enum { + ACTMENU_VIEW_CENTERVIEW= 0, + ACTMENU_VIEW_AUTOUPDATE, + ACTMENU_VIEW_PLAY3D, + ACTMENU_VIEW_PLAYALL, + ACTMENU_VIEW_ALL, + ACTMENU_VIEW_MAXIMIZE, + ACTMENU_VIEW_LOCK, + ACTMENU_VIEW_SLIDERS, + ACTMENU_VIEW_NEXTMARKER, + ACTMENU_VIEW_PREVMARKER, + ACTMENU_VIEW_NEXTKEYFRAME, + ACTMENU_VIEW_PREVKEYFRAME, + ACTMENU_VIEW_TIME, + ACTMENU_VIEW_NOHIDE, + ACTMENU_VIEW_FRANUM, + ACTMENU_VIEW_TRANSDELDUPS, + ACTMENU_VIEW_HORIZOPTIMISE, + ACTMENU_VIEW_GCOLORS, + ACTMENU_VIEW_PREVRANGESET, + ACTMENU_VIEW_PREVRANGECLEAR, + ACTMENU_VIEW_PREVRANGEAUTO +}; + +enum { + ACTMENU_SEL_BORDER = 0, + ACTMENU_SEL_BORDERC, + ACTMENU_SEL_BORDERM, + ACTMENU_SEL_ALL_KEYS, + ACTMENU_SEL_ALL_CHAN, + ACTMENU_SEL_ALL_MARKERS, + ACTMENU_SEL_INVERSE_KEYS, + ACTMENU_SEL_INVERSE_MARKERS, + ACTMENU_SEL_INVERSE_CHANNELS, + ACTMENU_SEL_LEFTKEYS, + ACTMENU_SEL_RIGHTKEYS +}; + +enum { + ACTMENU_SEL_COLUMN_KEYS = 1, + ACTMENU_SEL_COLUMN_CFRA, + ACTMENU_SEL_COLUMN_MARKERSCOLUMN, + ACTMENU_SEL_COLUMN_MARKERSBETWEEN +}; + +enum { + ACTMENU_CHANNELS_OPENLEVELS = 0, + ACTMENU_CHANNELS_CLOSELEVELS, + ACTMENU_CHANNELS_EXPANDALL, + ACTMENU_CHANNELS_SHOWACHANS, + ACTMENU_CHANNELS_DELETE +}; + +enum { + ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_UP = 0, + ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_DOWN, + ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_TOP, + ACTMENU_CHANNELS_CHANPOS_MOVE_CHANNEL_BOTTOM +}; + +enum { + ACTMENU_CHANNELS_GROUP_ADD_TOACTIVE = 0, + ACTMENU_CHANNELS_GROUP_ADD_TONEW, + ACTMENU_CHANNELS_GROUP_REMOVE, + ACTMENU_CHANNELS_GROUP_SYNCPOSE +}; + +enum { + ACTMENU_CHANNELS_SETTINGS_TOGGLE = 0, + ACTMENU_CHANNELS_SETTINGS_ENABLE, + ACTMENU_CHANNELS_SETTINGS_DISABLE, +}; + +enum { + ACTMENU_KEY_DUPLICATE = 0, + ACTMENU_KEY_DELETE, + ACTMENU_KEY_CLEAN, + ACTMENU_KEY_SAMPLEKEYS, + ACTMENU_KEY_INSERTKEY +}; + +enum { + ACTMENU_KEY_TRANSFORM_MOVE = 0, + ACTMENU_KEY_TRANSFORM_SCALE, + ACTMENU_KEY_TRANSFORM_SLIDE, + ACTMENU_KEY_TRANSFORM_EXTEND +}; + +enum { + ACTMENU_KEY_HANDLE_AUTO = 0, + ACTMENU_KEY_HANDLE_ALIGN, + ACTMENU_KEY_HANDLE_FREE, + ACTMENU_KEY_HANDLE_VECTOR +}; + +enum { + ACTMENU_KEY_INTERP_CONST = 0, + ACTMENU_KEY_INTERP_LINEAR, + ACTMENU_KEY_INTERP_BEZIER +}; + +enum { + ACTMENU_KEY_EXTEND_CONST = 0, + ACTMENU_KEY_EXTEND_EXTRAPOLATION, + ACTMENU_KEY_EXTEND_CYCLIC, + ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION +}; + +enum { + ACTMENU_KEY_SNAP_NEARFRAME = 1, + ACTMENU_KEY_SNAP_CURFRAME, + ACTMENU_KEY_SNAP_NEARMARK, + ACTMENU_KEY_SNAP_NEARTIME, + ACTMENU_KEY_SNAP_CFRA2KEY, +}; + +enum { + ACTMENU_KEY_MIRROR_CURFRAME = 1, + ACTMENU_KEY_MIRROR_YAXIS, + ACTMENU_KEY_MIRROR_XAXIS, + ACTMENU_KEY_MIRROR_MARKER +}; + +enum { + ACTMENU_MARKERS_ADD = 0, + ACTMENU_MARKERS_DUPLICATE, + ACTMENU_MARKERS_DELETE, + ACTMENU_MARKERS_NAME, + ACTMENU_MARKERS_MOVE, + ACTMENU_MARKERS_LOCALADD, + ACTMENU_MARKERS_LOCALRENAME, + ACTMENU_MARKERS_LOCALDELETE, + ACTMENU_MARKERS_LOCALMOVE +}; + +/* ------------------------------- */ +/* macros for easier state testing (only for use here) */ + +/* test if active action editor is showing any markers */ +#if 0 + #define G_SACTION_HASMARKERS \ + ((G.saction->action && G.saction->action->markers.first) \ + || (G.scene->markers.first)) +#endif + +/* ------------------------------- */ + +/* *************************************************************** */ +/* menus */ /* Key menu --------------------------- */ @@ -288,7 +439,7 @@ static uiBlock *action_viewmenu(bContext *C, uiMenuBlockHandle *handle, void *ar uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Nothing yet", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 3, ""); - if(curarea->headertype==HEADERTOP) { + if (curarea->headertype==HEADERTOP) { uiBlockSetDirection(block, UI_DOWN); } else { diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h index 6f51ce49888..6f0b5c9899d 100644 --- a/source/blender/editors/space_action/action_intern.h +++ b/source/blender/editors/space_action/action_intern.h @@ -73,6 +73,10 @@ enum { /* ***************************************** */ /* action_edit_keyframes.c */ +void ACT_OT_keyframes_delete(struct wmOperatorType *ot); +void ACT_OT_keyframes_clean(struct wmOperatorType *ot); +void ACT_OT_keyframes_sample(struct wmOperatorType *ot); + void ACT_OT_keyframes_handletype(struct wmOperatorType *ot); void ACT_OT_keyframes_ipotype(struct wmOperatorType *ot); void ACT_OT_keyframes_expotype(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c index d6a7fda2704..cd9be252fa8 100644 --- a/source/blender/editors/space_action/action_ops.c +++ b/source/blender/editors/space_action/action_ops.c @@ -75,6 +75,9 @@ void action_operatortypes(void) WM_operatortype_append(ACT_OT_keyframes_handletype); WM_operatortype_append(ACT_OT_keyframes_ipotype); WM_operatortype_append(ACT_OT_keyframes_expotype); + WM_operatortype_append(ACT_OT_keyframes_sample); + WM_operatortype_append(ACT_OT_keyframes_clean); + WM_operatortype_append(ACT_OT_keyframes_delete); } /* ************************** registration - keymaps **********************************/ @@ -114,6 +117,13 @@ static void action_keymap_keyframes (ListBase *keymap) WM_keymap_add_item(keymap, "ACT_OT_keyframes_handletype", HKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ACT_OT_keyframes_ipotype", TKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "ACT_OT_keyframes_expotype", EKEY, KM_PRESS, KM_SHIFT, 0); // temp... + + /* destructive */ + WM_keymap_add_item(keymap, "ACT_OT_keyframes_clean", OKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_keyframes_sample", OKEY, KM_PRESS, KM_SHIFT, 0); + + WM_keymap_add_item(keymap, "ACT_OT_keyframes_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "ACT_OT_keyframes_delete", DELKEY, KM_PRESS, 0, 0); } /* --------------- */ diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 46bf2549087..d356d7a7f42 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -88,31 +88,23 @@ /* ************************************************************************** */ /* GENERAL STUFF */ -#if 0 /* this function finds the channel that mouse is floating over */ -void *get_nearest_act_channel (short mval[], short *ret_type, void **owner) +void *get_nearest_act_channel (bAnimContext *ac, int mval[2], short *ret_type, void **owner) { - ListBase act_data = {NULL, NULL}; - bActListElem *ale; - void *data; - short datatype; + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; int filter; + View2D *v2d= &ac->ar->v2d; int clickmin, clickmax; - float x,y; + float x, y; + void *data= NULL; /* init 'owner' return val */ *owner= NULL; - /* determine what type of data we are operating on */ - data = get_action_context(&datatype); - if (data == NULL) { - *ret_type= ACTTYPE_NONE; - return NULL; - } - - areamouseco_to_ipoco(G.v2d, mval, &x, &y); - clickmin = (int) (((CHANNELHEIGHT/2) - y) / (CHANNELHEIGHT+CHANNELSKIP)); + UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); + clickmin = (int) ((ACHANNEL_HEIGHT_HALF - y) / (ACHANNEL_STEP)); clickmax = clickmin; if (clickmax < 0) { @@ -121,10 +113,10 @@ void *get_nearest_act_channel (short mval[], short *ret_type, void **owner) } /* filter data */ - filter= (ACTFILTER_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS); - actdata_filter(&act_data, filter, data, datatype); + filter= (ANIMFILTER_FORDRAWING | ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS); + ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype); - for (ale= act_data.first; ale; ale= ale->next) { + for (ale= anim_data.first; ale; ale= ale->next) { if (clickmax < 0) break; if (clickmin <= 0) { @@ -133,7 +125,7 @@ void *get_nearest_act_channel (short mval[], short *ret_type, void **owner) data= ale->data; /* if an 'ID' has been set, this takes presidence as owner (for dopesheet) */ - if (datatype == ACTCONT_DOPESHEET) { + if (ac->datatype == ANIMCONT_DOPESHEET) { /* return pointer to ID as owner instead */ if (ale->id) *owner= ale->id; @@ -145,7 +137,7 @@ void *get_nearest_act_channel (short mval[], short *ret_type, void **owner) *owner= ale->owner; } - BLI_freelistN(&act_data); + BLI_freelistN(&anim_data); return data; } @@ -154,12 +146,12 @@ void *get_nearest_act_channel (short mval[], short *ret_type, void **owner) } /* cleanup */ - BLI_freelistN(&act_data); + BLI_freelistN(&anim_data); - *ret_type= ACTTYPE_NONE; + *ret_type= ANIMTYPE_NONE; return NULL; } -#endif + /* used only by mouse_action. It is used to find the location of the nearest * keyframe to where the mouse clicked, diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 48c12c527c5..b84e337625a 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -402,7 +402,6 @@ static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar) /* own keymap */ keymap= WM_keymap_listbase(wm, "Outliner", SPACE_OOPS, 0); /* XXX weak? */ WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); - } static void outliner_rna_draw(const bContext *C, ARegion *ar) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 975403c3a5f..4ef2f32c914 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -207,7 +207,7 @@ typedef struct UserDef { short smooth_viewtx; /* miliseconds to spend spinning the view */ short glreslimit; short ndof_pan, ndof_rotate; - short curssize, pad; + short curssize, ipo_new; // char pad[8]; char versemaster[160]; char verseuser[160]; |