Added support for manipulating Ipo bezier handles through

the action window. Selecting action keys and pressing VKEY,
HKEY, or shift-HKEY modifies the handles of the keys in
the same way it does in the IPO window. (suggested by Lyubomir)
This commit is contained in:
Chris Want
2003-01-28 03:11:27 +00:00
parent 30861557bc
commit 53b540c627
3 changed files with 323 additions and 58 deletions

View File

@@ -130,6 +130,7 @@ void filter_sampledata(float *data, int sfra, int efra);
void sampledata_to_ipocurve(float *data, int sfra, int efra, struct IpoCurve *icu);
void ipo_record(void);
void sethandles_ipo_keys(struct Ipo *ipo, int code);
void set_ipo_key_selection(struct Ipo *ipo, int sel);
int is_ipo_key_selected(struct Ipo *ipo);
void delete_ipo_keys(struct Ipo *ipo);

View File

@@ -1310,6 +1310,35 @@ static void delete_actionchannels (void)
allqueue(REDRAWNLA, 0);
}
static void sethandles_actionchannel_keys(int code)
{
bAction *act;
bActionChannel *chan;
/* Get the selected action, exit if none are selected
*/
act = G.saction->action;
if (!act)
return;
/* Loop through the channels and set the beziers
* of the selected keys based on the integer code
*/
for (chan = act->chanbase.first; chan; chan=chan->next){
sethandles_ipo_keys(chan->ipo, code);
}
/* Clean up and redraw stuff
*/
remake_action_ipos (act);
allspace(REMAKEIPO, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWNLA, 0);
}
void winqreadactionspace(unsigned short event, short val, char ascii)
{
SpaceAction *saction;
@@ -1375,6 +1404,16 @@ void winqreadactionspace(unsigned short event, short val, char ascii)
allqueue (REDRAWIPO, 0);
}
break;
/*** set the Ipo handles ***/
case VKEY:
sethandles_actionchannel_keys(HD_VECT);
break;
case HKEY:
if(G.qual & LR_SHIFTKEY) sethandles_actionchannel_keys(HD_AUTO);
else sethandles_actionchannel_keys(HD_ALIGN);
break;
case BKEY:
borderselect_action();
break;

View File

@@ -2663,76 +2663,301 @@ void mouse_select_ipo()
}
}
void sethandles_ipo(int code)
int icu_keys_bezier_loop(IpoCurve *icu,
int (*bezier_function)(BezTriple *),
void (ipocurve_function)(struct IpoCurve *icu))
{
/* code==1: set autohandle */
/* code==2: set vectorhandle */
/* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
/* This loops through the beziers in the Ipocurve, and executes
* the generic user provided 'bezier_function' on each one.
* Optionally executes the generic function ipocurve_function on the
* IPO curve after looping (eg. calchandles_ipocurve)
*/
int b;
BezTriple *bezt;
b = icu->totvert;
bezt = icu->bezt;
/* if bezier_function has been specified
* then loop through each bezier executing
* it.
*/
if (bezier_function != NULL) {
while(b--) {
/* exit with return code 1 if the bezier function
* returns 1 (good for when you are only interested
* in finding the first bezier that
* satisfies a condition).
*/
if (bezier_function(bezt)) return 1;
bezt++;
}
}
/* if ipocurve_function has been specified
* then execute it
*/
if (ipocurve_function != NULL)
ipocurve_function(icu);
return 0;
}
int ipo_keys_bezier_loop(Ipo *ipo,
int (*bezier_function)(BezTriple *),
void (ipocurve_function)(struct IpoCurve *icu))
{
/* This loops through the beziers that are attached to
* the selected keys on the Ipocurves of the Ipo, and executes
* the generic user provided 'bezier_function' on each one.
* Optionally executes the generic function ipocurve_function on a
* IPO curve after looping (eg. calchandles_ipocurve)
*/
IpoCurve *icu;
/* Loop through each curve in the Ipo
*/
for (icu=ipo->curve.first; icu; icu=icu->next){
if (icu_keys_bezier_loop(icu,bezier_function, ipocurve_function))
return 1;
}
return 0;
}
int selected_bezier_loop(int (*looptest)(EditIpo *),
int (*bezier_function)(BezTriple *),
void (ipocurve_function)(struct IpoCurve *icu))
{
/* This loops through the beziers that are attached to
* selected keys in editmode in the IPO window, and executes
* the generic user-provided 'bezier_function' on each one
* that satisfies the 'looptest' function. Optionally executes
* the generic function ipocurve_function on a IPO curve
* after looping (eg. calchandles_ipocurve)
*/
EditIpo *ei;
BezTriple *bezt;
int a, b, ok=0;
int a, b;
if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
if(code==1 || code==2) {
/* Get the first Edit Ipo from the selected Ipos
*/
ei= G.sipo->editipo;
/* Loop throught all of the selected Ipo's
*/
for(a=0; a<G.sipo->totipo; a++, ei++) {
if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
/* Do a user provided test on the Edit Ipo
* to determine whether we want to process it
*/
if (looptest(ei)) {
/* Loop through the selected
* beziers on the Edit Ipo
*/
bezt = ei->icu->bezt;
b = ei->icu->totvert;
while(b--) {
if(bezt->f1 || bezt->f3) {
if(bezt->f1) bezt->h1= code;
if(bezt->f3) bezt->h2= code;
/* if bezier_function has been specified
* then loop through each bezier executing
* it.
*/
if (bezier_function != NULL) {
while(b--) {
/* exit with return code 1 if the bezier function
* returns 1 (good for when you are only interested
* in finding the first bezier that
* satisfies a condition).
*/
if (bezier_function(bezt)) return 1;
bezt++;
}
}
/* if ipocurve_function has been specified
* then execute it
*/
if (ipocurve_function != NULL)
ipocurve_function(ei->icu);
}
/* nufte flourdje zim ploopydu <-- random dutch looking comment ;) */
}
return 0;
}
int set_bezier_auto(BezTriple *bezt)
{
/* Sets the selected bezier handles to type 'auto'
*/
/* is a handle selected? If so
* set it to type auto
*/
if(bezt->f1 || bezt->f3) {
if(bezt->f1) bezt->h1= 1; /* the secret code for auto */
if(bezt->f3) bezt->h2= 1;
/* if the handles are not of the same type, set them
* to type free
*/
if(bezt->h1!=bezt->h2) {
if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
}
}
bezt++;
return 0;
}
calchandles_ipocurve(ei->icu);
int set_bezier_vector(BezTriple *bezt)
{
/* Sets the selected bezier handles to type 'vector'
*/
/* is a handle selected? If so
* set it to type vector
*/
if(bezt->f1 || bezt->f3) {
if(bezt->f1) bezt->h1= 2; /* the code for vector */
if(bezt->f3) bezt->h2= 2;
/* if the handles are not of the same type, set them
* to type free
*/
if(bezt->h1!=bezt->h2) {
if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE;
if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE;
}
}
return 0;
}
int bezier_isfree(BezTriple *bezt)
{
/* queries whether the handle should be set
* to type 'free' (I think)
*/
if(bezt->f1 && bezt->h1) return 1;
if(bezt->f3 && bezt->h2) return 1;
return 0;
}
int set_bezier_free(BezTriple *bezt)
{
/* Sets selected bezier handles to type 'free'
*/
if(bezt->f1) bezt->h1= HD_FREE;
if(bezt->f3) bezt->h2= HD_FREE;
return 0;
}
int set_bezier_align(BezTriple *bezt)
{
/* Sets selected bezier handles to type 'align'
*/
if(bezt->f1) bezt->h1= HD_ALIGN;
if(bezt->f3) bezt->h2= HD_ALIGN;
return 0;
}
int vis_edit_icu_bez(EditIpo *ei) {
/* A 4 part test for an EditIpo :
* is it a) visible
* b) in edit mode
* c) does it contain an Ipo Curve
* d) does that ipo curve have a bezier
*
* (The reason why I don't just use the macro
* is I need a pointer to a function.)
*/
return ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt);
}
void sethandles_ipo_keys(Ipo *ipo, int code)
{
/* this function lets you set bezier handles all to
* one type for some Ipo's (e.g. with hotkeys through
* the action window).
*/
/* code==1: set autohandle */
/* code==2: set vectorhandle */
/* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
switch(code) {
case 1:
/*** Set to auto ***/
ipo_keys_bezier_loop(ipo, set_bezier_auto,
calchandles_ipocurve);
break;
case 2:
/*** Set to vector ***/
ipo_keys_bezier_loop(ipo, set_bezier_vector,
calchandles_ipocurve);
break;
default:
if ( ipo_keys_bezier_loop(ipo, bezier_isfree, NULL) ) {
/*** Set to free ***/
ipo_keys_bezier_loop(ipo, set_bezier_free,
calchandles_ipocurve);
}
else {
/* is er 1 handle NIET vrij: alles vrijmaken, else ALIGNED maken */
/*** Set to align ***/
ipo_keys_bezier_loop(ipo, set_bezier_align,
calchandles_ipocurve);
}
break;
}
ei= G.sipo->editipo;
for(a=0; a<G.sipo->totipo; a++, ei++) {
if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
bezt= ei->icu->bezt;
b= ei->icu->totvert;
while(b--) {
if(bezt->f1 && bezt->h1) ok= 1;
if(bezt->f3 && bezt->h2) ok= 1;
if(ok) break;
bezt++;
}
}
}
if(ok) ok= HD_FREE;
else ok= HD_ALIGN;
ei= G.sipo->editipo;
for(a=0; a<G.sipo->totipo; a++, ei++) {
if ISPOIN4(ei, flag & IPO_VISIBLE, flag & IPO_EDIT, icu, icu->bezt) {
bezt= ei->icu->bezt;
b= ei->icu->totvert;
while(b--) {
if(bezt->f1) bezt->h1= ok;
if(bezt->f3 ) bezt->h2= ok;
}
bezt++;
}
calchandles_ipocurve(ei->icu);
void sethandles_ipo(int code)
{
/* this function lets you set bezier handles all to
* one type for some selected keys in edit mode in the
* IPO window (e.g. with hotkeys)
*/
/* code==1: set autohandle */
/* code==2: set vectorhandle */
/* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */
if(G.sipo->ipo && G.sipo->ipo->id.lib) return;
switch(code) {
case 1:
/*** Set to auto ***/
selected_bezier_loop(vis_edit_icu_bez, set_bezier_auto,
calchandles_ipocurve);
break;
case 2:
/*** Set to vector ***/
selected_bezier_loop(vis_edit_icu_bez, set_bezier_vector,
calchandles_ipocurve);
break;
default:
if (selected_bezier_loop(vis_edit_icu_bez, bezier_isfree, NULL) ) {
/*** Set to free ***/
selected_bezier_loop(vis_edit_icu_bez, set_bezier_free,
calchandles_ipocurve);
}
else {
/*** Set to align ***/
selected_bezier_loop(vis_edit_icu_bez, set_bezier_align,
calchandles_ipocurve);
}
break;
}
editipo_changed(G.sipo, 1);
}
void set_ipotype()
{
EditIpo *ei;