Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/src/editaction.c')
-rw-r--r--source/blender/src/editaction.c5244
1 files changed, 0 insertions, 5244 deletions
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
deleted file mode 100644
index e230c97f010..00000000000
--- a/source/blender/src/editaction.c
+++ /dev/null
@@ -1,5244 +0,0 @@
-/**
- * $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) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
- * The Original Code is: all of this file.
- *
- * Contributor(s): 2007, Joshua Leung (major rewrite of Action Editor)
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#include <string.h>
-#include <stddef.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "PIL_time.h"
-
-#include "BLI_blenlib.h"
-#include "BLI_arithb.h"
-
-#include "DNA_action_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_space_types.h"
-#include "DNA_userdef_types.h"
-#include "DNA_constraint_types.h"
-#include "DNA_key_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_nla_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_gpencil_types.h"
-
-#include "BKE_action.h"
-#include "BKE_armature.h"
-#include "BKE_constraint.h"
-#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
-#include "BKE_global.h"
-#include "BKE_ipo.h"
-#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
-#include "BKE_utildefines.h"
-#include "BKE_object.h" /* for where_is_object in obanim -> action baking */
-
-#include "BIF_butspace.h"
-#include "BIF_editaction.h"
-#include "BIF_editarmature.h"
-#include "BIF_editnla.h"
-#include "BIF_editview.h"
-#include "BIF_gl.h"
-#include "BIF_interface.h"
-#include "BIF_keyframing.h"
-#include "BIF_mywindow.h"
-#include "BIF_poseobject.h"
-#include "BIF_screen.h"
-#include "BIF_space.h"
-#include "BIF_toolbox.h"
-#include "BIF_transform.h"
-
-#include "BSE_edit.h"
-#include "BSE_drawipo.h"
-#include "BSE_headerbuttons.h"
-#include "BSE_editaction_types.h"
-#include "BSE_editipo.h"
-#include "BSE_time.h"
-#include "BSE_trans_types.h"
-
-#include "BDR_drawaction.h"
-#include "BDR_editobject.h"
-#include "BDR_gpencil.h"
-
-#include "mydevice.h"
-#include "blendef.h"
-#include "nla.h"
-
-/* **************************************************** */
-/* ACTION API */
-
-/* this function adds a new Action block */
-bAction *add_empty_action (char *name)
-{
- bAction *act;
-
- act= alloc_libblock(&G.main->action, ID_AC, name);
- act->id.flag |= LIB_FAKEUSER;
- act->id.us++;
-
- return act;
-}
-
-/* generic get current action call, for action window context */
-bAction *ob_get_action (Object *ob)
-{
- bActionStrip *strip;
-
- if(ob->action)
- return ob->action;
-
- for (strip=ob->nlastrips.first; strip; strip=strip->next) {
- if (strip->flag & ACTSTRIP_SELECT)
- return strip->act;
- }
- return NULL;
-}
-
-/* used by ipo, outliner, buttons to find the active channel */
-bActionChannel *get_hilighted_action_channel (bAction *action)
-{
- bActionChannel *achan;
-
- if (!action)
- return NULL;
-
- for (achan= action->chanbase.first; achan; achan= achan->next) {
- if (VISIBLE_ACHAN(achan)) {
- if (SEL_ACHAN(achan) && (achan->flag & ACHAN_HILIGHTED))
- return achan;
- }
- }
-
- return NULL;
-}
-
-/* ----------------------------------------- */
-
-void remake_action_ipos (bAction *act)
-{
- bActionChannel *achan;
- bConstraintChannel *conchan;
- IpoCurve *icu;
-
- for (achan= act->chanbase.first; achan; achan= achan->next) {
- if (achan->ipo) {
- for (icu = achan->ipo->curve.first; icu; icu=icu->next) {
- sort_time_ipocurve(icu);
- testhandles_ipocurve(icu);
- }
- }
- for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
- if (conchan->ipo) {
- for (icu = conchan->ipo->curve.first; icu; icu=icu->next) {
- sort_time_ipocurve(icu);
- testhandles_ipocurve(icu);
- }
- }
- }
- }
-
- synchronize_action_strips();
-}
-
-/* **************************************************** */
-/* FILTER->EDIT STRUCTURES */
-/*
- * This method involves generating a list of edit structures which enable
- * tools to naively perform the actions they require without all the boiler-plate
- * associated with loops within loops and checking for cases to ignore.
- */
-
-/* this function allocates memory for a new bActListElem struct for the
- * provided action channel-data.
- */
-bActListElem *make_new_actlistelem (void *data, short datatype, void *owner, short ownertype)
-{
- bActListElem *ale= NULL;
-
- /* only allocate memory if there is data to convert */
- if (data) {
- /* allocate and set generic data */
- ale= MEM_callocN(sizeof(bActListElem), "bActListElem");
-
- ale->data= data;
- ale->type= datatype;
- ale->owner= owner;
- ale->ownertype= ownertype;
-
- if ((owner) && (ownertype == ACTTYPE_ACHAN)) {
- bActionChannel *ochan= (bActionChannel *)owner;
- ale->grp= ochan->grp;
- }
- else
- ale->grp= NULL;
-
- /* do specifics */
- switch (datatype) {
- case ACTTYPE_GROUP:
- {
- bActionGroup *agrp= (bActionGroup *)data;
-
- ale->flag= agrp->flag;
-
- ale->key_data= NULL;
- ale->datatype= ALE_GROUP;
- }
- break;
- case ACTTYPE_ACHAN:
- {
- bActionChannel *achan= (bActionChannel *)data;
-
- ale->flag= achan->flag;
-
- if (achan->ipo) {
- ale->key_data= achan->ipo;
- ale->datatype= ALE_IPO;
- }
- else {
- ale->key_data= NULL;
- ale->datatype= ALE_NONE;
- }
- }
- break;
- case ACTTYPE_CONCHAN:
- case ACTTYPE_CONCHAN2:
- {
- bConstraintChannel *conchan= (bConstraintChannel *)data;
-
- ale->flag= conchan->flag;
-
- if (datatype == ACTTYPE_CONCHAN2) {
- /* CONCHAN2 is a hack so that constraint-channels keyframes can be edited */
- if (conchan->ipo) {
- ale->key_data= conchan->ipo;
- ale->datatype= ALE_IPO;
- }
- else {
- ale->key_data= NULL;
- ale->datatype= ALE_NONE;
- }
- }
- else {
- if (conchan->ipo && conchan->ipo->curve.first) {
- /* we assume that constraint ipo blocks only have 1 curve:
- * INFLUENCE, so we pretend that a constraint channel is
- * really just a Ipo-Curve channel instead.
- */
- ale->key_data= conchan->ipo->curve.first;
- ale->datatype= ALE_ICU;
- }
- else {
- ale->key_data= NULL;
- ale->datatype= ALE_NONE;
- }
- }
- }
- break;
- case ACTTYPE_ICU:
- {
- IpoCurve *icu= (IpoCurve *)data;
-
- ale->flag= icu->flag;
- ale->key_data= icu;
- ale->datatype= ALE_ICU;
- }
- break;
-
- case ACTTYPE_FILLIPO:
- case ACTTYPE_FILLCON:
- {
- bActionChannel *achan= (bActionChannel *)data;
-
- if (datatype == ACTTYPE_FILLIPO)
- ale->flag= FILTER_IPO_ACHAN(achan);
- else
- ale->flag= FILTER_CON_ACHAN(achan);
-
- ale->key_data= NULL;
- ale->datatype= ALE_NONE;
- }
- break;
- case ACTTYPE_IPO:
- {
- ale->flag= 0;
- ale->key_data= data;
- ale->datatype= ALE_IPO;
- }
- break;
- case ACTTYPE_GPLAYER:
- {
- bGPDlayer *gpl= (bGPDlayer *)data;
-
- ale->flag= gpl->flag;
-
- ale->key_data= NULL;
- ale->datatype= ALE_GPFRAME;
- }
- break;
- }
- }
-
- /* return created datatype */
- return ale;
-}
-
-/* ----------------------------------------- */
-
-static void actdata_filter_actionchannel (ListBase *act_data, bActionChannel *achan, int filter_mode)
-{
- bActListElem *ale;
- bConstraintChannel *conchan;
- IpoCurve *icu;
-
- /* only work with this channel and its subchannels if it is visible */
- if (!(filter_mode & ACTFILTER_VISIBLE) || VISIBLE_ACHAN(achan)) {
- /* only work with this channel and its subchannels if it is editable */
- if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_ACHAN(achan)) {
- /* check if this achan should only be included if it is selected */
- if (!(filter_mode & ACTFILTER_SEL) || SEL_ACHAN(achan)) {
- /* are we only interested in the ipo-curves? */
- if ((filter_mode & ACTFILTER_ONLYICU)==0) {
- ale= make_new_actlistelem(achan, ACTTYPE_ACHAN, achan, ACTTYPE_ACHAN);
- if (ale) BLI_addtail(act_data, ale);
- }
- }
- else {
- /* for insert key... this check could be improved */
- return;
- }
-
- /* check if expanded - if not, continue on to next action channel */
- if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ACTFILTER_ONLYICU)==0) {
- /* only exit if we don't need to include constraint channels for group-channel keyframes */
- if ( !(filter_mode & ACTFILTER_IPOKEYS) || (achan->grp == NULL) || (EXPANDED_AGRP(achan->grp)==0) )
- return;
- }
-
- /* ipo channels */
- if ((achan->ipo) && (filter_mode & ACTFILTER_IPOKEYS)==0) {
- /* include ipo-expand widget? */
- if ((filter_mode & ACTFILTER_CHANNELS) && (filter_mode & ACTFILTER_ONLYICU)==0) {
- ale= make_new_actlistelem(achan, ACTTYPE_FILLIPO, achan, ACTTYPE_ACHAN);
- if (ale) BLI_addtail(act_data, ale);
- }
-
- /* add ipo-curve channels? */
- if (FILTER_IPO_ACHAN(achan) || (filter_mode & ACTFILTER_ONLYICU)) {
- /* loop through ipo-curve channels, adding them */
- for (icu= achan->ipo->curve.first; icu; icu=icu->next) {
- ale= make_new_actlistelem(icu, ACTTYPE_ICU, achan, ACTTYPE_ACHAN);
- if (ale) BLI_addtail(act_data, ale);
- }
- }
- }
-
- /* constraint channels */
- if (achan->constraintChannels.first) {
- /* include constraint-expand widget? */
- if ( (filter_mode & ACTFILTER_CHANNELS) && !(filter_mode & ACTFILTER_ONLYICU)
- && !(filter_mode & ACTFILTER_IPOKEYS) )
- {
- ale= make_new_actlistelem(achan, ACTTYPE_FILLCON, achan, ACTTYPE_ACHAN);
- if (ale) BLI_addtail(act_data, ale);
- }
-
- /* add constraint channels? */
- if (FILTER_CON_ACHAN(achan) || (filter_mode & ACTFILTER_IPOKEYS) || (filter_mode & ACTFILTER_ONLYICU)) {
- /* loop through constraint channels, checking and adding them */
- for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
- /* only work with this channel and its subchannels if it is editable */
- if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_CONCHAN(conchan)) {
- /* check if this conchan should only be included if it is selected */
- if (!(filter_mode & ACTFILTER_SEL) || SEL_CONCHAN(conchan)) {
- if (filter_mode & ACTFILTER_IPOKEYS) {
- ale= make_new_actlistelem(conchan, ACTTYPE_CONCHAN2, achan, ACTTYPE_ACHAN);
- if (ale) BLI_addtail(act_data, ale);
- }
- else {
- ale= make_new_actlistelem(conchan, ACTTYPE_CONCHAN, achan, ACTTYPE_ACHAN);
- if (ale) BLI_addtail(act_data, ale);
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-static void actdata_filter_action (ListBase *act_data, bAction *act, int filter_mode)
-{
- bActListElem *ale=NULL;
- bActionGroup *agrp;
- bActionChannel *achan, *lastchan=NULL;
-
- /* loop over groups */
- for (agrp= act->groups.first; agrp; agrp= agrp->next) {
- /* add this group as a channel first */
- if (!(filter_mode & ACTFILTER_ONLYICU) && !(filter_mode & ACTFILTER_IPOKEYS)) {
- /* check if filtering by selection */
- if ( !(filter_mode & ACTFILTER_SEL) || SEL_AGRP(agrp) ) {
- ale= make_new_actlistelem(agrp, ACTTYPE_GROUP, NULL, ACTTYPE_NONE);
- if (ale) BLI_addtail(act_data, ale);
- }
- }
-
- /* store reference to last channel of group */
- if (agrp->channels.last)
- lastchan= agrp->channels.last;
-
-
- /* there are some situations, where only the channels of the active group should get considered */
- if (!(filter_mode & ACTFILTER_ACTGROUPED) || (agrp->flag & AGRP_ACTIVE)) {
- /* filters here are a bit convoulted...
- * - groups show a "summary" of keyframes beside their name which must accessable for tools which handle keyframes
- * - groups can be collapsed (and those tools which are only interested in channels rely on knowing that group is closed)
- *
- * cases when we should include action-channels and so-forth inside group:
- * - we don't care about visibility
- * - group is expanded
- * - we're interested in keyframes, but not if they appear in selected channels
- */
- if ( (!(filter_mode & ACTFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) ||
- ( ((filter_mode & ACTFILTER_IPOKEYS) || (filter_mode & ACTFILTER_ONLYICU)) &&
- (!(filter_mode & ACTFILTER_SEL) || (SEL_AGRP(agrp))) ) )
- {
- if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
- for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
- actdata_filter_actionchannel(act_data, achan, filter_mode);
- }
-
- /* remove group from filtered list if last element is group
- * (i.e. only if group had channels, which were all hidden)
- */
- if ( (ale) && (act_data->last == ale) &&
- (ale->data == agrp) && (agrp->channels.first) )
- {
- BLI_freelinkN(act_data, ale);
- }
- }
- }
- }
- }
-
- /* loop over un-grouped action channels (only if we're not only considering those channels in the active group) */
- if (!(filter_mode & ACTFILTER_ACTGROUPED)) {
- for (achan=(lastchan)?lastchan->next:act->chanbase.first; achan; achan=achan->next) {
- actdata_filter_actionchannel(act_data, achan, filter_mode);
- }
- }
-}
-
-static void actdata_filter_shapekey (ListBase *act_data, Key *key, int filter_mode)
-{
- bActListElem *ale;
- KeyBlock *kb;
- IpoCurve *icu;
- int i;
-
- /* are we filtering for display or editing */
- if (filter_mode & ACTFILTER_FORDRAWING) {
- /* for display - loop over shapekeys, adding ipo-curve references where needed */
- kb= key->block.first;
-
- /* loop through possible shapekeys, manually creating entries */
- for (i= 1; i < key->totkey; i++) {
- ale= MEM_callocN(sizeof(bActListElem), "bActListElem");
- kb = kb->next;
-
- ale->data= kb;
- ale->type= ACTTYPE_SHAPEKEY; /* 'abused' usage of this type */
- ale->owner= key;
- ale->ownertype= ACTTYPE_SHAPEKEY;
- ale->datatype= ALE_NONE;
- ale->index = i;
-
- if (key->ipo) {
- for (icu= key->ipo->curve.first; icu; icu=icu->next) {
- if (icu->adrcode == i) {
- ale->key_data= icu;
- ale->datatype= ALE_ICU;
- break;
- }
- }
- }
-
- BLI_addtail(act_data, ale);
- }
- }
- else {
- /* loop over ipo curves if present - for editing */
- if (key->ipo) {
- if (filter_mode & ACTFILTER_IPOKEYS) {
- ale= make_new_actlistelem(key->ipo, ACTTYPE_IPO, key, ACTTYPE_SHAPEKEY);
- if (ale) BLI_addtail(act_data, ale);
- }
- else {
- for (icu= key->ipo->curve.first; icu; icu=icu->next) {
- ale= make_new_actlistelem(icu, ACTTYPE_ICU, key, ACTTYPE_SHAPEKEY);
- if (ale) BLI_addtail(act_data, ale);
- }
- }
- }
- }
-}
-
-
-static void actdata_filter_gpencil (ListBase *act_data, bScreen *sc, int filter_mode)
-{
- bActListElem *ale;
- ScrArea *sa;
- bGPdata *gpd;
- bGPDlayer *gpl;
-
- /* check if filtering types are appropriate */
- if ( !(filter_mode & (ACTFILTER_IPOKEYS|ACTFILTER_ONLYICU|ACTFILTER_ACTGROUPED)) )
- {
- /* special hack for fullscreen area (which must be this one then):
- * - we use the curarea->full as screen to get spaces from, since the
- * old (pre-fullscreen) screen was stored there...
- * - this is needed as all data would otherwise disappear
- */
- if ((curarea->full) && (curarea->spacetype==SPACE_ACTION))
- sc= curarea->full;
-
- /* loop over spaces in current screen, finding gpd blocks (could be slow!) */
- for (sa= sc->areabase.first; sa; sa= sa->next) {
- /* try to get gp data */
- gpd= gpencil_data_getactive(sa);
- if (gpd == NULL) continue;
-
- /* add gpd as channel too (if for drawing, and it has layers) */
- if ((filter_mode & ACTFILTER_FORDRAWING) && (gpd->layers.first)) {
- /* add to list */
- ale= make_new_actlistelem(gpd, ACTTYPE_GPDATABLOCK, sa, ACTTYPE_SPECIALDATA);
- if (ale) BLI_addtail(act_data, ale);
- }
-
- /* only add layers if they will be visible (if drawing channels) */
- if ( !(filter_mode & ACTFILTER_VISIBLE) || (EXPANDED_GPD(gpd)) ) {
- /* loop over layers as the conditions are acceptable */
- for (gpl= gpd->layers.first; gpl; gpl= gpl->next) {
- /* only if selected */
- if (!(filter_mode & ACTFILTER_SEL) || SEL_GPL(gpl)) {
- /* only if editable */
- if (!(filter_mode & ACTFILTER_FOREDIT) || EDITABLE_GPL(gpl)) {
- /* add to list */
- ale= make_new_actlistelem(gpl, ACTTYPE_GPLAYER, gpd, ACTTYPE_GPDATABLOCK);
- if (ale) BLI_addtail(act_data, ale);
- }
- }
- }
- }
- }
- }
-}
-
-/* This function filters the active data source to leave only the desired
- * data types. 'Public' api call.
- * *act_data: is a pointer to a ListBase, to which the filtered action data
- * will be placed for use.
- * filter_mode: how should the data be filtered - bitmapping accessed flags
- */
-void actdata_filter (ListBase *act_data, int filter_mode, void *data, short datatype)
-{
- /* only filter data if there's somewhere to put it */
- if (data && act_data) {
- bActListElem *ale, *next;
-
- /* firstly filter the data */
- switch (datatype) {
- case ACTCONT_ACTION:
- actdata_filter_action(act_data, data, filter_mode);
- break;
- case ACTCONT_SHAPEKEY:
- actdata_filter_shapekey(act_data, data, filter_mode);
- break;
- case ACTCONT_GPENCIL:
- actdata_filter_gpencil(act_data, data, filter_mode);
- break;
- }
-
- /* remove any weedy entries */
- for (ale= act_data->first; ale; ale= next) {
- next= ale->next;
-
- if (ale->type == ACTTYPE_NONE)
- BLI_freelinkN(act_data, ale);
-
- if (filter_mode & ACTFILTER_IPOKEYS) {
- if (ale->datatype != ALE_IPO)
- BLI_freelinkN(act_data, ale);
- else if (ale->key_data == NULL)
- BLI_freelinkN(act_data, ale);
- }
- }
- }
-}
-
-/* **************************************************** */
-/* GENERAL ACTION TOOLS */
-
-/* gets the key data from the currently selected
- * mesh/lattice. If a mesh is not selected, or does not have
- * key data, then we return NULL (currently only
- * returns key data for RVK type meshes). If there
- * is an action that is pinned, return null
- */
-/* Note: there's a similar function in key.c (ob_get_key) */
-Key *get_action_mesh_key(void)
-{
- Object *ob;
- Key *key;
-
- ob = OBACT;
- if (ob == NULL)
- return NULL;
-
- if (G.saction->pin) return NULL;
-
- if (ob->type==OB_MESH)
- key = ((Mesh *)ob->data)->key;
- else if (ob->type==OB_LATTICE)
- key = ((Lattice *)ob->data)->key;
- else if (ELEM(ob->type, OB_CURVE, OB_SURF))
- key= ((Curve *)ob->data)->key;
- else
- return NULL;
-
- if (key) {
- if (key->type == KEY_RELATIVE)
- return key;
- }
-
- return NULL;
-}
-
-/* TODO: kill this! */
-int get_nearest_key_num (Key *key, short *mval, float *x)
-{
- /* returns the key num that cooresponds to the
- * y value of the mouse click. Does not check
- * if this is a valid keynum. Also gives the Ipo
- * x coordinate.
- */
- int num;
- float y;
-
- areamouseco_to_ipoco(G.v2d, mval, x, &y);
- num = (int) ((CHANNELHEIGHT/2 - y) / (CHANNELHEIGHT+CHANNELSKIP));
-
- return (num + 1);
-}
-
-/* this function finds the channel that mouse is floating over */
-void *get_nearest_act_channel (short mval[], short *ret_type, void **owner)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- void *data;
- short datatype;
- int filter;
-
- int clickmin, clickmax;
- float x,y;
-
- /* 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));
- clickmax = clickmin;
-
- if (clickmax < 0) {
- *ret_type= ACTTYPE_NONE;
- return NULL;
- }
-
- /* filter data */
- filter= (ACTFILTER_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS);
- actdata_filter(&act_data, filter, data, datatype);
-
- for (ale= act_data.first; ale; ale= ale->next) {
- if (clickmax < 0)
- break;
- if (clickmin <= 0) {
- /* found match */
- *ret_type= ale->type;
- data= ale->data;
- *owner= ale->owner;
-
- BLI_freelistN(&act_data);
-
- return data;
- }
- --clickmin;
- --clickmax;
- }
-
- /* cleanup */
- BLI_freelistN(&act_data);
-
- *ret_type= ACTTYPE_NONE;
- return NULL;
-}
-
-/* used only by mouse_action. It is used to find the location of the nearest
- * keyframe to where the mouse clicked,
- */
-static void *get_nearest_action_key (float *selx, short *sel, short *ret_type, bActionChannel **par)
-{
- ListBase act_data = {NULL, NULL};
- ListBase act_keys = {NULL, NULL};
- bActListElem *ale;
- ActKeyColumn *ak;
- void *data;
- short datatype;
- int filter;
-
- rctf rectf;
- float xmin, xmax, x, y;
- int clickmin, clickmax;
- short mval[2];
- short found = 0;
-
- getmouseco_areawin (mval);
-
- /* action-channel */
- *par= 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));
- clickmax = clickmin;
-
- mval[0]-=7;
- areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
- mval[0]+=14;
- areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
-
- /* if action is mapped in NLA, it returns a correction */
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- xmin= get_action_frame(OBACT, rectf.xmin);
- xmax= get_action_frame(OBACT, rectf.xmax);
- }
- else {
- xmin= rectf.xmin;
- xmax= rectf.xmax;
- }
-
- if (clickmax < 0) {
- *ret_type= ACTTYPE_NONE;
- return NULL;
- }
-
- /* filter data */
- filter= (ACTFILTER_FORDRAWING | ACTFILTER_VISIBLE | ACTFILTER_CHANNELS);
- actdata_filter(&act_data, filter, data, datatype);
-
- for (ale= act_data.first; ale; ale= ale->next) {
- if (clickmax < 0)
- break;
- if (clickmin <= 0) {
- /* found match */
-
- /* make list of keyframes */
- if (ale->key_data) {
- switch (ale->datatype) {
- case ALE_IPO:
- {
- Ipo *ipo= (Ipo *)ale->key_data;
- ipo_to_keylist(ipo, &act_keys, NULL, NULL);
- }
- break;
- case ALE_ICU:
- {
- IpoCurve *icu= (IpoCurve *)ale->key_data;
- icu_to_keylist(icu, &act_keys, NULL, NULL);
- }
- break;
- }
- }
- else if (ale->type == ACTTYPE_GROUP) {
- bActionGroup *agrp= (bActionGroup *)ale->data;
- agroup_to_keylist(agrp, &act_keys, NULL, NULL);
- }
- else if (ale->type == ACTTYPE_GPDATABLOCK) {
- /* cleanup */
- BLI_freelistN(&act_data);
-
- /* this channel currently doens't have any keyframes... must ignore! */
- *ret_type= ACTTYPE_NONE;
- return NULL;
- }
- else if (ale->type == ACTTYPE_GPLAYER) {
- bGPDlayer *gpl= (bGPDlayer *)ale->data;
- gpl_to_keylist(gpl, &act_keys, NULL, NULL);
- }
-
- /* loop through keyframes, finding one that was clicked on */
- for (ak= act_keys.first; ak; ak= ak->next) {
- if (IN_RANGE(ak->cfra, xmin, xmax)) {
- *selx= ak->cfra;
- found= 1;
- break;
- }
- }
- /* no matching keyframe found - set to mean frame value so it doesn't actually select anything */
- if (found == 0)
- *selx= ((xmax+xmin) / 2);
-
- /* figure out what to return */
- if (datatype == ACTCONT_ACTION) {
- *par= ale->owner; /* assume that this is an action channel */
- *ret_type= ale->type;
- data = ale->data;
- }
- else if (datatype == ACTCONT_SHAPEKEY) {
- data = ale->key_data;
- *ret_type= ACTTYPE_ICU;
- }
- else if (datatype == ACTCONT_GPENCIL) {
- data = ale->data;
- *ret_type= ACTTYPE_GPLAYER;
- }
-
- /* cleanup tempolary lists */
- BLI_freelistN(&act_keys);
- act_keys.first = act_keys.last = NULL;
-
- BLI_freelistN(&act_data);
-
- return data;
- }
- --clickmin;
- --clickmax;
- }
-
- /* cleanup */
- BLI_freelistN(&act_data);
-
- *ret_type= ACTTYPE_NONE;
- return NULL;
-}
-
-void *get_action_context (short *datatype)
-{
- bAction *act;
- Key *key;
-
- /* get pointers to active action/shapekey blocks */
- act = (G.saction)? G.saction->action: NULL;
- key = get_action_mesh_key();
-
- /* check mode selector */
- if (G.saction) {
- switch (G.saction->mode) {
- case SACTCONT_ACTION:
- *datatype= ACTCONT_ACTION;
- return act;
-
- case SACTCONT_SHAPEKEY:
- *datatype= ACTCONT_SHAPEKEY;
- return key;
-
- case SACTCONT_GPENCIL:
- *datatype= ACTCONT_GPENCIL;
- return G.curscreen; // FIXME: add that dopesheet type thing here!
-
- default: /* includes SACTCONT_DOPESHEET for now */
- *datatype= ACTCONT_NONE;
- return NULL;
- }
- }
- else {
- /* resort to guessing based on what is available */
- if (act) {
- *datatype= ACTCONT_ACTION;
- return act;
- }
- else if (key) {
- *datatype= ACTCONT_SHAPEKEY;
- return key;
- }
- else {
- *datatype= ACTCONT_NONE;
- return NULL;
- }
- }
-}
-
-/* Quick-tool for preview-range functionality in Action Editor for setting Preview-Range
- * bounds to extents of Action, when Ctrl-Alt-P is used. Only available for actions.
- */
-void action_previewrange_set (bAction *act)
-{
- float start, end;
-
- /* sanity check */
- if (act == NULL)
- return;
-
- /* calculate range + make sure it is adjusted for nla-scaling */
- calc_action_range(act, &start, &end, 0);
- if (NLA_ACTION_SCALED) {
- start= get_action_frame_inv(OBACT, start);
- end= get_action_frame_inv(OBACT, end);
- }
-
- /* set preview range */
- G.scene->r.psfra= (int)start;
- G.scene->r.pefra= (int)end;
-
- BIF_undo_push("Set anim-preview range");
- allqueue(REDRAWTIME, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWBUTSALL, 0);
-}
-
-/* **************************************************** */
-/* ACTION CHANNEL GROUPS */
-
-/* Get the active action-group for an Action */
-bActionGroup *get_active_actiongroup (bAction *act)
-{
- bActionGroup *agrp= NULL;
-
- if (act && act->groups.first) {
- for (agrp= act->groups.first; agrp; agrp= agrp->next) {
- if (agrp->flag & AGRP_ACTIVE)
- break;
- }
- }
-
- return agrp;
-}
-
-/* Make the given Action-Group the active one */
-void set_active_actiongroup (bAction *act, bActionGroup *agrp, short select)
-{
- bActionGroup *grp;
-
- /* sanity checks */
- if (act == NULL)
- return;
-
- /* Deactive all others */
- for (grp= act->groups.first; grp; grp= grp->next) {
- if ((grp==agrp) && (select))
- grp->flag |= AGRP_ACTIVE;
- else
- grp->flag &= ~AGRP_ACTIVE;
- }
-}
-
-/* Add given channel into (active) group
- * - assumes that channel is not linked to anything anymore
- * - always adds at the end of the group
- */
-static void action_groups_addachan (bAction *act, bActionGroup *agrp, bActionChannel *achan)
-{
- bActionChannel *chan;
- short done=0;
-
- /* sanity checks */
- if (ELEM3(NULL, act, agrp, achan))
- return;
-
- /* if no channels, just add to two lists at the same time */
- if (act->chanbase.first == NULL) {
- achan->next = achan->prev = NULL;
-
- agrp->channels.first = agrp->channels.last = achan;
- act->chanbase.first = act->chanbase.last = achan;
-
- achan->grp= agrp;
- return;
- }
-
- /* try to find a channel to slot this in before/after */
- for (chan= act->chanbase.first; chan; chan= chan->next) {
- /* if channel has no group, then we have ungrouped channels, which should always occur after groups */
- if (chan->grp == NULL) {
- BLI_insertlinkbefore(&act->chanbase, chan, achan);
-
- if (agrp->channels.first == NULL)
- agrp->channels.first= achan;
- agrp->channels.last= achan;
-
- done= 1;
- break;
- }
-
- /* if channel has group after current, we can now insert (otherwise we have gone too far) */
- else if (chan->grp == agrp->next) {
- BLI_insertlinkbefore(&act->chanbase, chan, achan);
-
- if (agrp->channels.first == NULL)
- agrp->channels.first= achan;
- agrp->channels.last= achan;
-
- done= 1;
- break;
- }
-
- /* if channel has group we're targeting, check whether it is the last one of these */
- else if (chan->grp == agrp) {
- if ((chan->next) && (chan->next->grp != agrp)) {
- BLI_insertlinkafter(&act->chanbase, chan, achan);
- agrp->channels.last= achan;
- done= 1;
- break;
- }
- else if (chan->next == NULL) {
- BLI_addtail(&act->chanbase, achan);
- agrp->channels.last= achan;
- done= 1;
- break;
- }
- }
-
- /* if channel has group before target, check whether the next one is something after target */
- else if (chan->grp == agrp->prev) {
- if (chan->next) {
- if ((chan->next->grp != chan->grp) && (chan->next->grp != agrp)) {
- BLI_insertlinkafter(&act->chanbase, chan, achan);
-
- agrp->channels.first= achan;
- agrp->channels.last= achan;
-
- done= 1;
- break;
- }
- }
- else {
- BLI_insertlinkafter(&act->chanbase, chan, achan);
-
- agrp->channels.first= achan;
- agrp->channels.last= achan;
-
- done= 1;
- break;
- }
- }
- }
-
- /* only if added, set channel as belonging to this group */
- if (done) {
- achan->grp= agrp;
- }
- else
- printf("Error: ActionChannel: '%s' couldn't be added to Group: '%s' \n", achan->name, agrp->name);
-}
-
-/* Remove the given channel from all groups */
-static void action_groups_removeachan (bAction *act, bActionChannel *achan)
-{
- /* sanity checks */
- if (ELEM(NULL, act, achan))
- return;
-
- /* check if any group used this directly */
- if (achan->grp) {
- bActionGroup *agrp= achan->grp;
-
- if (agrp->channels.first == agrp->channels.last) {
- if (agrp->channels.first == achan) {
- agrp->channels.first= NULL;
- agrp->channels.last= NULL;
- }
- }
- else if (agrp->channels.first == achan) {
- if ((achan->next) && (achan->next->grp==agrp))
- agrp->channels.first= achan->next;
- else
- agrp->channels.first= NULL;
- }
- else if (agrp->channels.last == achan) {
- if ((achan->prev) && (achan->prev->grp==agrp))
- agrp->channels.last= achan->prev;
- else
- agrp->channels.last= NULL;
- }
-
- achan->grp= NULL;
- }
-
- /* now just remove from list */
- BLI_remlink(&act->chanbase, achan);
-}
-
-/* Add a new Action-Group or add channels to active one */
-void action_groups_group (short add_group)
-{
- bAction *act;
- bActionChannel *achan, *anext;
- bActionGroup *agrp;
- void *data;
- short datatype;
-
- /* validate type of data we are working on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_ACTION) return;
- act= (bAction *)data;
-
- /* get active group */
- if ((act->groups.first==NULL) || (add_group)) {
- /* Add a new group, and make it active */
- agrp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
-
- agrp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED);
- sprintf(agrp->name, "Group");
-
- BLI_addtail(&act->groups, agrp);
- BLI_uniquename(&act->groups, agrp, "Group", offsetof(bActionGroup, name), 32);
-
- set_active_actiongroup(act, agrp, 1);
-
- add_group= 1;
- }
- else {
- agrp= get_active_actiongroup(act);
-
- if (agrp == NULL) {
- error("No Active Action Group");
- return;
- }
- }
-
- /* loop through action-channels, finding those that are selected + visible to move */
- // FIXME: this should be done with action api instead
- for (achan= act->chanbase.first; achan; achan= anext) {
- anext= achan->next;
-
- /* make sure not already in new-group */
- if (achan->grp != agrp) {
- if ((achan->grp==NULL) || (EXPANDED_AGRP(achan->grp))) {
- if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) {
- /* unlink from everything else */
- action_groups_removeachan(act, achan);
-
- /* add to end of group's channels */
- action_groups_addachan(act, agrp, achan);
- }
- }
- }
- }
-
- /* updates and undo */
- if (add_group)
- BIF_undo_push("Add Action Group");
- else
- BIF_undo_push("Add to Action Group");
-
- allqueue(REDRAWACTION, 0);
-}
-
-/* Remove selected channels from their groups */
-void action_groups_ungroup (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- bAction *act;
- void *data;
- short datatype;
- short filter;
-
- /* validate type of data we are working on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_ACTION) return;
- act= (bAction *)data;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE|ACTFILTER_SEL);
- actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
-
- /* Only ungroup selected action-channels */
- for (ale= act_data.first; ale; ale= ale->next) {
- if (ale->type == ACTTYPE_ACHAN) {
- action_groups_removeachan(act, ale->data);
- BLI_addtail(&act->chanbase, ale->data);
- }
- }
-
- BLI_freelistN(&act_data);
-
- /* updates and undo */
- BIF_undo_push("Remove From Action Groups");
-
- allqueue(REDRAWACTION, 0);
-}
-
-/* Copy colors from a specified theme's color set to an Action/Bone Group */
-void actionbone_group_copycolors (bActionGroup *grp, short init_new)
-{
- /* error checking */
- if (grp == NULL)
- return;
-
- /* only do color copying if using a custom color */
- if (grp->customCol) {
- if (grp->customCol > 0) {
- /* copy theme colors on-to group's custom color in case user tries to edit color */
- bTheme *btheme= U.themes.first;
- ThemeWireColor *col_set= &btheme->tarm[(grp->customCol - 1)];
-
- memcpy(&grp->cs, col_set, sizeof(ThemeWireColor));
- }
- else if (init_new) {
- /* init custom colors with a generic multi-color rgb set, if not initialised already (and allowed to do so) */
- if (grp->cs.solid[0] == 0) {
- /* define for setting colors in theme below */
- #define SETCOL(col, r, g, b, a) col[0]=r; col[1]=g; col[2]= b; col[3]= a;
-
- SETCOL(grp->cs.solid, 0xff, 0x00, 0x00, 255);
- SETCOL(grp->cs.select, 0x81, 0xe6, 0x14, 255);
- SETCOL(grp->cs.active, 0x18, 0xb6, 0xe0, 255);
-
- #undef SETCOL
- }
- }
- }
-}
-
-/* This function is used when inserting keyframes for pose-channels. It assigns the
- * action-channel with the nominated name to a group with the same name as that of
- * the pose-channel with the nominated name.
- *
- * Note: this function calls validate_action_channel if action channel doesn't exist
- */
-void verify_pchan2achan_grouping (bAction *act, bPose *pose, char name[])
-{
- bActionChannel *achan;
- bPoseChannel *pchan;
-
- /* sanity checks */
- if (ELEM3(NULL, act, pose, name))
- return;
- if (name[0] == 0)
- return;
-
- /* try to get the channels */
- pchan= get_pose_channel(pose, name);
- if (pchan == NULL) return;
- achan= verify_action_channel(act, name);
-
- /* check if pchan has a group */
- if ((pchan->agrp_index > 0) && (achan->grp == NULL)) {
- bActionGroup *agrp, *grp=NULL;
-
- /* get group to try to be like */
- agrp= (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
- if (agrp == NULL) {
- error("PoseChannel has invalid group!");
- return;
- }
-
- /* try to find a group which is similar to the one we want (or add one) */
- for (grp= act->groups.first; grp; grp= grp->next) {
- if (!strcmp(grp->name, agrp->name))
- break;
- }
- if (grp == NULL) {
- grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
-
- grp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED);
-
- /* copy name */
- sprintf(grp->name, agrp->name);
-
- /* deal with group-color copying (grp is destination, agrp is source) */
- memcpy(grp, agrp, sizeof(bActionGroup));
- actionbone_group_copycolors(grp, 1);
-
- BLI_addtail(&act->groups, grp);
- }
-
- /* make sure this channel is definitely not connected to anything before adding to group */
- action_groups_removeachan(act, achan);
- action_groups_addachan(act, grp, achan);
- }
-}
-
-/* This function is used when the user specifically requests to sync changes of pchans + bone groups
- * to achans + action groups. All achans are detached from their groups, and all groups are destroyed.
- * They are then recreated when the achans are reassigned to groups.
- *
- * Note: This doesn't preserve hand-created groups, and will operate on ALL action-channels regardless of
- * whether they were selected or active. More specific filtering can be added later.
- */
-void sync_pchan2achan_grouping ()
-{
- void *data;
- short datatype;
- bAction *act;
- bActionChannel *achan, *next, *last;
- bPose *pose;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if ((datatype != ACTCONT_ACTION) || (data==NULL)) return;
- if ((G.saction->pin) || (OBACT==NULL) || (OBACT->type != OB_ARMATURE)) {
- error("Action doesn't belong to active armature");
- return;
- }
-
- /* get data */
- act= (bAction *)data;
- pose= OBACT->pose;
-
- /* remove achan->group links, then delete all groups */
- for (achan= act->chanbase.first; achan; achan= achan->next)
- achan->grp = NULL;
- BLI_freelistN(&act->groups);
-
- /* loop through all achans, reassigning them to groups (colors are resyncronised) */
- last= act->chanbase.last;
- for (achan= act->chanbase.first; achan && achan!=last; achan= next) {
- next= achan->next;
- verify_pchan2achan_grouping(act, pose, achan->name);
- }
-
- /* undo and redraw */
- BIF_undo_push("Sync Armature-Data and Action");
- allqueue(REDRAWACTION, 0);
-}
-
-/* **************************************************** */
-/* TRANSFORM TOOLS */
-
-/* main call to start transforming keyframes */
-void transform_action_keys (int mode, int dummy)
-{
- void *data;
- short datatype;
- short context = (U.flag & USER_DRAGIMMEDIATE)?CTX_TWEAK:CTX_NONE;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- switch (mode) {
- case 'g':
- {
- initTransform(TFM_TIME_TRANSLATE, context);
- Transform();
- }
- break;
- case 's':
- {
- initTransform(TFM_TIME_SCALE, context);
- Transform();
- }
- break;
- case 't':
- {
- initTransform(TFM_TIME_SLIDE, context);
- Transform();
- }
- break;
- case 'e':
- {
- initTransform(TFM_TIME_EXTEND, context);
- Transform();
- }
- break;
- }
-}
-
-/* ----------------------------------------- */
-
-/* duplicate keyframes */
-void duplicate_action_keys (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- void *data;
- short datatype;
- int filter;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* filter data */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop through filtered data and duplicate selected keys */
- for (ale= act_data.first; ale; ale= ale->next) {
- if (ale->type == ACTTYPE_GPLAYER)
- duplicate_gplayer_frames(ale->data);
- else
- duplicate_ipo_keys((Ipo *)ale->key_data);
- }
-
- /* free filtered list */
- BLI_freelistN(&act_data);
-
- /* now, go into transform-grab mode, to move keys */
- BIF_TransformSetUndo("Add Duplicate");
- transform_action_keys('g', 0);
-}
-
-/* this function is responsible for snapping the current frame to selected data */
-void snap_cfra_action()
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
-
- /* get data */
- data= get_action_context(&datatype);
- if (data == NULL) return;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* snap current frame to selected data */
- snap_cfra_ipo_keys(NULL, -1);
-
- for (ale= act_data.first; ale; ale= ale->next) {
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
- snap_cfra_ipo_keys(ale->key_data, 0);
- actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
- }
- else
- snap_cfra_ipo_keys(ale->key_data, 0);
- }
- BLI_freelistN(&act_data);
-
- snap_cfra_ipo_keys(NULL, 1);
-
- BIF_undo_push("Snap Current Frame to Keys");
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-/* this function is responsible for snapping keyframes to frame-times */
-void snap_action_keys(short mode)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
- char str[32];
-
- /* get data */
- data= get_action_context(&datatype);
- if (data == NULL) return;
-
- /* determine mode */
- switch (mode) {
- case 1:
- strcpy(str, "Snap Keys To Nearest Frame");
- break;
- case 2:
- if (G.saction->flag & SACTION_DRAWTIME)
- strcpy(str, "Snap Keys To Current Time");
- else
- strcpy(str, "Snap Keys To Current Frame");
- break;
- case 3:
- strcpy(str, "Snap Keys To Nearest Marker");
- break;
- case 4:
- strcpy(str, "Snap Keys To Nearest Second");
- break;
- default:
- return;
- }
-
- /* filter data */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* snap to frame */
- for (ale= act_data.first; ale; ale= ale->next) {
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
- snap_ipo_keys(ale->key_data, mode);
- actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
- }
- else if (ale->type == ACTTYPE_GPLAYER)
- snap_gplayer_frames(ale->data, mode);
- else
- snap_ipo_keys(ale->key_data, mode);
- }
- BLI_freelistN(&act_data);
-
- if (datatype == ACTCONT_ACTION)
- remake_action_ipos(data);
-
- BIF_undo_push(str);
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWVIEW3D, 0);
-}
-
-/* this function is responsible for snapping keyframes to frame-times */
-void mirror_action_keys(short mode)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
- char str[32];
-
- /* get data */
- data= get_action_context(&datatype);
- if (data == NULL) return;
-
- /* determine mode */
- switch (mode) {
- case 1:
- strcpy(str, "Mirror Keys Over Current Frame");
- break;
- case 2:
- strcpy(str, "Mirror Keys Over Y-Axis");
- break;
- case 3:
- strcpy(str, "Mirror Keys Over X-Axis");
- break;
- case 4:
- strcpy(str, "Mirror Keys Over Marker");
- break;
- default:
- return;
- }
-
- /* filter data */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* mirror */
- for (ale= act_data.first; ale; ale= ale->next) {
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
- mirror_ipo_keys(ale->key_data, mode);
- actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
- }
- else if (ale->type == ACTTYPE_GPLAYER)
- mirror_gplayer_frames(ale->data, mode);
- else
- mirror_ipo_keys(ale->key_data, mode);
- }
- BLI_freelistN(&act_data);
-
- if (datatype == ACTCONT_ACTION)
- remake_action_ipos(data);
-
- BIF_undo_push(str);
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-/* **************************************************** */
-/* ADD/REMOVE KEYFRAMES */
-
-/* This function allows the user to insert keyframes on the current
- * frame from the Action Editor, using the current values of the channels
- * to be keyframed.
- */
-void insertkey_action(void)
-{
- void *data;
- short datatype;
-
- Object *ob= OBACT;
- short mode;
- float cfra;
-
- /* get data */
- data= get_action_context(&datatype);
- if (data == NULL) return;
- cfra = frame_to_float(CFRA);
-
- if (datatype == ACTCONT_ACTION) {
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
-
- /* ask user what to keyframe */
- mode = pupmenu("Insert Key%t|All Channels%x1|Only Selected Channels%x2|In Active Group%x3");
- if (mode <= 0) return;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU );
- if (mode == 2) filter |= ACTFILTER_SEL;
- else if (mode == 3) filter |= ACTFILTER_ACTGROUPED;
-
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop through ipo curves retrieved */
- for (ale= act_data.first; ale; ale= ale->next) {
- /* verify that this is indeed an ipo curve */
- if (ale->key_data && ale->owner) {
- bActionChannel *achan= (bActionChannel *)ale->owner;
- bConstraintChannel *conchan= (ale->type==ACTTYPE_CONCHAN) ? ale->data : NULL;
- IpoCurve *icu= (IpoCurve *)ale->key_data;
-
- if (ob)
- insertkey((ID *)ob, icu->blocktype, achan->name, ((conchan)?(conchan->name):(NULL)), icu->adrcode, 0);
- else
- insert_vert_icu(icu, cfra, icu->curval, 0);
- }
- }
-
- /* cleanup */
- BLI_freelistN(&act_data);
- }
- else if (datatype == ACTCONT_SHAPEKEY) {
- Key *key= (Key *)data;
- IpoCurve *icu;
-
- /* ask user if they want to insert a keyframe */
- mode = okee("Insert Keyframe?");
- if (mode <= 0) return;
-
- if (key->ipo) {
- for (icu= key->ipo->curve.first; icu; icu=icu->next) {
- insert_vert_icu(icu, cfra, icu->curval, 0);
- }
- }
- }
- else {
- /* this tool is not supported in this mode */
- return;
- }
-
- BIF_undo_push("Insert Key");
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWBUTSOBJECT, 0);
-}
-
-/* delete selected keyframes */
-void delete_action_keys (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- void *data;
- short datatype;
- int filter;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* filter data */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop through filtered data and delete selected keys */
- for (ale= act_data.first; ale; ale= ale->next) {
- if (ale->type == ACTTYPE_GPLAYER)
- delete_gplayer_frames((bGPDlayer *)ale->data);
- else
- delete_ipo_keys((Ipo *)ale->key_data);
- }
-
- /* free filtered list */
- BLI_freelistN(&act_data);
-
- if (datatype == ACTCONT_ACTION)
- remake_action_ipos(data);
-
- BIF_undo_push("Delete Action Keys");
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-/* delete selected action-channels (only achans and conchans are considered) */
-void delete_action_channels (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale, *next;
- bAction *act;
- void *data;
- short datatype;
- int filter;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_ACTION) return;
- act= (bAction *)data;
-
- /* deal with groups first */
- if (act->groups.first) {
- bActionGroup *agrp, *grp;
- bActionChannel *chan, *nchan;
-
- /* unlink achan's that belonged to this group (and make sure they're not selected if they weren't visible) */
- for (agrp= act->groups.first; agrp; agrp= grp) {
- grp= agrp->next;
-
- /* remove if group is selected */
- if (SEL_AGRP(agrp)) {
- for (chan= agrp->channels.first; chan && chan->grp==agrp; chan= nchan) {
- nchan= chan->next;
-
- action_groups_removeachan(act, chan);
- BLI_addtail(&act->chanbase, chan);
-
- if (EXPANDED_AGRP(agrp) == 0)
- chan->flag &= ~(ACHAN_SELECTED|ACHAN_HILIGHTED);
- }
-
- BLI_freelinkN(&act->groups, agrp);
- }
- }
- }
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_CHANNELS | ACTFILTER_SEL);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* remove irrelevant entries */
- for (ale= act_data.first; ale; ale= next) {
- next= ale->next;
-
- if (ale->type != ACTTYPE_ACHAN)
- BLI_freelinkN(&act_data, ale);
- }
-
- /* clean up action channels */
- for (ale= act_data.first; ale; ale= next) {
- bActionChannel *achan= (bActionChannel *)ale->data;
- bConstraintChannel *conchan, *cnext;
- next= ale->next;
-
- /* release references to ipo users */
- if (achan->ipo)
- achan->ipo->id.us--;
-
- for (conchan= achan->constraintChannels.first; conchan; conchan=cnext) {
- cnext= conchan->next;
-
- if (conchan->ipo)
- conchan->ipo->id.us--;
- }
-
- /* remove action-channel from group(s) */
- if (achan->grp)
- action_groups_removeachan(act, achan);
-
- /* free memory */
- BLI_freelistN(&achan->constraintChannels);
- BLI_freelinkN(&act->chanbase, achan);
- BLI_freelinkN(&act_data, ale);
- }
-
- remake_action_ipos(data);
-
- BIF_undo_push("Delete Action Channels");
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-/* 'Clean' IPO curves - remove any unnecessary keyframes */
-void clean_action (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype, ok;
-
- /* don't proceed any further if nothing to work on or user refuses */
- data= get_action_context(&datatype);
- ok= fbutton(&G.scene->toolsettings->clean_thresh,
- 0.0000001f, 1.0f, 0.001f, 0.1f,
- "Clean Threshold");
- if (!ok) return;
- if (datatype == ACTCONT_GPENCIL) return;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_SEL | ACTFILTER_ONLYICU);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop through filtered data and clean curves */
- for (ale= act_data.first; ale; ale= ale->next) {
- clean_ipo_curve((IpoCurve *)ale->key_data);
- }
-
- /* admin and redraws */
- BLI_freelistN(&act_data);
-
- BIF_undo_push("Clean Action");
- allqueue(REMAKEIPO, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-
-/* 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 */
-void sample_action_keys (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
-
- /* sanity checks */
- data= get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype == ACTCONT_GPENCIL) return;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_ONLYICU);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop through filtered data and add keys between selected keyframes on every frame */
- for (ale= act_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(&act_data);
-
- BIF_undo_push("Sample Action Keys");
- allqueue(REMAKEIPO, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-/* **************************************************** */
-/* COPY/PASTE FOR ACTIONS */
-/* - The copy/paste buffer currently stores a set of Action Channels, with temporary
- * IPO-blocks, and also temporary IpoCurves which only contain the selected keyframes.
- * - Only pastes between compatable data is possible (i.e. same achan->name, ipo-curve type, etc.)
- * Unless there is only one element in the buffer, names are also tested to check for compatability.
- * - All pasted frames are offset by the same amount. This is calculated as the difference in the times of
- * the current frame and the 'first keyframe' (i.e. the earliest one in all channels).
- * - The earliest frame is calculated per copy operation.
- */
-
-/* globals for copy/paste data (like for other copy/paste buffers) */
-ListBase actcopybuf = {NULL, NULL};
-static float actcopy_firstframe= 999999999.0f;
-
-/* This function frees any MEM_calloc'ed copy/paste buffer data */
-void free_actcopybuf ()
-{
- bActionChannel *achan, *anext;
- bConstraintChannel *conchan, *cnext;
-
- for (achan= actcopybuf.first; achan; achan= anext) {
- anext= achan->next;
-
- if (achan->ipo) {
- free_ipo(achan->ipo);
- MEM_freeN(achan->ipo);
- }
-
- for (conchan=achan->constraintChannels.first; conchan; conchan=cnext) {
- cnext= conchan->next;
-
- if (conchan->ipo) {
- free_ipo(conchan->ipo);
- MEM_freeN(conchan->ipo);
- }
-
- BLI_freelinkN(&achan->constraintChannels, conchan);
- }
-
- BLI_freelinkN(&actcopybuf, achan);
- }
-
- actcopybuf.first= actcopybuf.last= NULL;
- actcopy_firstframe= 999999999.0f;
-}
-
-/* This function adds data to the copy/paste buffer, freeing existing data first
- * Only the selected action channels gets their selected keyframes copied.
- */
-void copy_actdata ()
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
-
- /* clear buffer first */
- free_actcopybuf();
-
- /* get data */
- data= get_action_context(&datatype);
- if (data == NULL) return;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* assume that each of these is an ipo-block */
- for (ale= act_data.first; ale; ale= ale->next) {
- bActionChannel *achan;
- Ipo *ipo= ale->key_data;
- Ipo *ipn;
- IpoCurve *icu, *icn;
- BezTriple *bezt;
- int i;
-
- /* coerce an action-channel out of owner */
- if (ale->ownertype == ACTTYPE_ACHAN) {
- bActionChannel *achanO= ale->owner;
- achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan");
- strcpy(achan->name, achanO->name);
- }
- else if (ale->ownertype == ACTTYPE_SHAPEKEY) {
- achan= MEM_callocN(sizeof(bActionChannel), "ActCopyPasteAchan");
- strcpy(achan->name, "#ACP_ShapeKey");
- }
- else
- continue;
- BLI_addtail(&actcopybuf, achan);
-
- /* add constraint channel if needed, then add new ipo-block */
- if (ale->type == ACTTYPE_CONCHAN) {
- bConstraintChannel *conchanO= ale->data;
- bConstraintChannel *conchan;
-
- conchan= MEM_callocN(sizeof(bConstraintChannel), "ActCopyPasteConchan");
- strcpy(conchan->name, conchanO->name);
- BLI_addtail(&achan->constraintChannels, conchan);
-
- conchan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo");
- }
- else {
- achan->ipo= ipn= MEM_callocN(sizeof(Ipo), "ActCopyPasteIpo");
- }
- ipn->blocktype = ipo->blocktype;
-
- /* now loop through curves, and only copy selected keyframes */
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- /* allocate a new curve */
- icn= MEM_callocN(sizeof(IpoCurve), "ActCopyPasteIcu");
- icn->blocktype = icu->blocktype;
- icn->adrcode = icu->adrcode;
- BLI_addtail(&ipn->curve, icn);
-
- /* find selected BezTriples to add to the buffer (and set first frame) */
- for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
- if (BEZSELECTED(bezt)) {
- /* add to buffer ipo-curve */
- insert_bezt_icu(icn, bezt);
-
- /* check if this is the earliest frame encountered so far */
- if (bezt->vec[1][0] < actcopy_firstframe)
- actcopy_firstframe= bezt->vec[1][0];
- }
- }
- }
- }
-
- /* check if anything ended up in the buffer */
- if (ELEM(NULL, actcopybuf.first, actcopybuf.last))
- error("Nothing copied to buffer");
-
- /* free temp memory */
- BLI_freelistN(&act_data);
-}
-
-void paste_actdata ()
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
- Object *ob= OBACT;
-
- const float offset = (float)(CFRA - actcopy_firstframe);
- char *actname = NULL, *conname = NULL;
- short no_name= 0;
-
- /* check if buffer is empty */
- if (ELEM(NULL, actcopybuf.first, actcopybuf.last)) {
- error("No data in buffer to paste");
- return;
- }
- /* check if single channel in buffer (disregard names if so) */
- if (actcopybuf.first == actcopybuf.last)
- no_name= 1;
-
- /* get data */
- data= get_action_context(&datatype);
- if (data == NULL) return;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* from selected channels */
- for (ale= act_data.first; ale; ale= ale->next) {
- Ipo *ipo_src = NULL;
- bActionChannel *achan;
- IpoCurve *ico, *icu;
- BezTriple *bezt;
- int i;
-
- /* find suitable IPO-block from buffer to paste from */
- for (achan= actcopybuf.first; achan; achan= achan->next) {
- /* try to match data */
- if (ale->ownertype == ACTTYPE_ACHAN) {
- bActionChannel *achant= ale->owner;
-
- /* check if we have a corresponding action channel */
- if ((no_name) || (strcmp(achan->name, achant->name)==0)) {
- actname= achant->name;
-
- /* check if this is a constraint channel */
- if (ale->type == ACTTYPE_CONCHAN) {
- bConstraintChannel *conchant= ale->data;
- bConstraintChannel *conchan;
-
- for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
- if (strcmp(conchan->name, conchant->name)==0) {
- conname= conchant->name;
- ipo_src= conchan->ipo;
- break;
- }
- }
- if (ipo_src) break;
- }
- else {
- ipo_src= achan->ipo;
- break;
- }
- }
- }
- else if (ale->ownertype == ACTTYPE_SHAPEKEY) {
- /* check if this action channel is "#ACP_ShapeKey" */
- if ((no_name) || (strcmp(achan->name, "#ACP_ShapeKey")==0)) {
- actname= NULL;
- ipo_src= achan->ipo;
- break;
- }
- }
- }
-
- /* this shouldn't happen, but it might */
- if (ipo_src == NULL)
- continue;
-
- /* loop over curves, pasting keyframes */
- for (ico= ipo_src->curve.first; ico; ico= ico->next) {
- /* get IPO-curve to paste to (IPO-curve might not exist for destination, so gets created) */
- icu= verify_ipocurve((ID *)ob, ico->blocktype, actname, conname, NULL, ico->adrcode, 1);
-
- if (icu) {
- /* just start pasting, with the the first keyframe on the current frame, and so on */
- for (i=0, bezt=ico->bezt; i < ico->totvert; i++, bezt++) {
- /* temporarily apply offset to src beztriple while copying */
- bezt->vec[0][0] += offset;
- bezt->vec[1][0] += offset;
- bezt->vec[2][0] += offset;
-
- /* insert the keyframe */
- insert_bezt_icu(icu, bezt);
-
- /* un-apply offset from src beztriple after copying */
- bezt->vec[0][0] -= offset;
- bezt->vec[1][0] -= offset;
- bezt->vec[2][0] -= offset;
- }
-
- /* recalculate channel's handles? */
- calchandles_ipocurve(icu);
- }
- }
- }
-
- /* free temp memory */
- BLI_freelistN(&act_data);
-
- /* do depsgraph updates (for 3d-view)? */
- if ((ob) && (G.saction->pin==0)) {
- if (ob->type == OB_ARMATURE)
- DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
- else
- DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
- }
-
- /* undo and redraw stuff */
- allqueue(REDRAWVIEW3D, 0);
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
- BIF_undo_push("Paste Action Keyframes");
-}
-
-/* **************************************************** */
-/* VARIOUS SETTINGS */
-
-/* This function combines several features related to setting
- * various ipo extrapolation/interpolation
- */
-void action_set_ipo_flags (short mode, short event)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- void *data;
- short datatype;
- int filter;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype == ACTCONT_GPENCIL) return;
-
- /* determine which set of processing we are doing */
- switch (mode) {
- case SET_EXTEND_POPUP:
- {
- /* present popup menu for ipo extrapolation type */
- event
- = pupmenu("Channel Extending Type %t|"
- "Constant %x11|"
- "Extrapolation %x12|"
- "Cyclic %x13|"
- "Cyclic extrapolation %x14");
- if (event < 1) return;
- }
- break;
- case SET_IPO_POPUP:
- {
- /* present popup menu for ipo interpolation type */
- event
- = pupmenu("Channel Ipo Type %t|"
- "Constant %x1|"
- "Linear %x2|"
- "Bezier %x3");
- if (event < 1) return;
- }
- break;
-
- case SET_IPO_MENU: /* called from menus */
- case SET_EXTEND_MENU:
- break;
-
- default: /* weird, unhandled case */
- return;
- }
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_SEL | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop through setting flags */
- for (ale= act_data.first; ale; ale= ale->next) {
- Ipo *ipo= (Ipo *)ale->key_data;
-
- /* depending on the mode */
- switch (mode) {
- case SET_EXTEND_POPUP: /* extrapolation */
- case SET_EXTEND_MENU:
- {
- switch (event) {
- case SET_EXTEND_CONSTANT:
- setexprap_ipoloop(ipo, IPO_HORIZ);
- break;
- case SET_EXTEND_EXTRAPOLATION:
- setexprap_ipoloop(ipo, IPO_DIR);
- break;
- case SET_EXTEND_CYCLIC:
- setexprap_ipoloop(ipo, IPO_CYCL);
- break;
- case SET_EXTEND_CYCLICEXTRAPOLATION:
- setexprap_ipoloop(ipo, IPO_CYCLX);
- break;
- }
- }
- break;
- case SET_IPO_POPUP: /* interpolation */
- case SET_IPO_MENU:
- {
- setipotype_ipo(ipo, event);
- }
- break;
- }
- }
-
- /* cleanup */
- BLI_freelistN(&act_data);
-
- if (datatype == ACTCONT_ACTION)
- remake_action_ipos(data);
-
- BIF_undo_push("Set Ipo Type");
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-/* this function sets the handles on keyframes */
-void sethandles_action_keys (int code)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- void *data;
- short datatype;
- int filter;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype == ACTCONT_GPENCIL) return;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_FOREDIT | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop through setting flags */
- for (ale= act_data.first; ale; ale= ale->next) {
- sethandles_ipo_keys((Ipo *)ale->key_data, code);
- }
-
- /* cleanup */
- BLI_freelistN(&act_data);
- if (datatype == ACTCONT_ACTION)
- remake_action_ipos(data);
-
- BIF_undo_push("Set Handle Type");
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-/* ----------------------------------------- */
-
-/* this gets called when nkey is pressed (no Transform Properties panel yet) */
-static void numbuts_action ()
-{
- void *data;
- short datatype;
-
- void *act_channel, *channel_owner;
- short chantype;
-
- bActionGroup *agrp= NULL;
- bActionChannel *achan= NULL;
- bConstraintChannel *conchan= NULL;
- IpoCurve *icu= NULL;
- KeyBlock *kb= NULL;
- bGPdata *gpd= NULL;
- bGPDlayer *gpl= NULL;
-
- short mval[2];
-
- int but=0;
- char str[128];
- short expand, protect, mute;
- float slidermin, slidermax;
-
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* figure out what is under cursor */
- getmouseco_areawin(mval);
- if (mval[0] > NAMEWIDTH)
- return;
- act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner);
-
- /* create items for clever-numbut */
- if (chantype == ACTTYPE_ACHAN) {
- /* Action Channel */
- achan= (bActionChannel *)act_channel;
-
- strcpy(str, achan->name);
- protect= (achan->flag & ACHAN_PROTECTED);
- expand = (achan->flag & ACHAN_EXPANDED);
- mute = (achan->ipo)? (achan->ipo->muteipo): 0;
-
- add_numbut(but++, TEX, "ActChan: ", 0, 31, str, "Name of Action Channel");
- add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Channel is Expanded");
- add_numbut(but++, TOG|SHO, "Muted", 0, 24, &mute, "Channel is Muted");
- add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected");
- }
- else if (chantype == ACTTYPE_CONCHAN) {
- /* Constraint Channel */
- conchan= (bConstraintChannel *)act_channel;
-
- strcpy(str, conchan->name);
- protect= (conchan->flag & CONSTRAINT_CHANNEL_PROTECTED);
- mute = (conchan->ipo)? (conchan->ipo->muteipo): 0;
-
- add_numbut(but++, TEX, "ConChan: ", 0, 29, str, "Name of Constraint Channel");
- add_numbut(but++, TOG|SHO, "Muted", 0, 24, &mute, "Channel is Muted");
- add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected");
- }
- else if (chantype == ACTTYPE_ICU) {
- /* IPO Curve */
- icu= (IpoCurve *)act_channel;
-
- if (G.saction->pin)
- sprintf(str, getname_ipocurve(icu, NULL));
- else
- sprintf(str, getname_ipocurve(icu, OBACT));
-
- if (IS_EQ(icu->slide_max, icu->slide_min)) {
- if (IS_EQ(icu->ymax, icu->ymin)) {
- icu->slide_min= -100.0;
- icu->slide_max= 100.0;
- }
- else {
- icu->slide_min= icu->ymin;
- icu->slide_max= icu->ymax;
- }
- }
- slidermin= icu->slide_min;
- slidermax= icu->slide_max;
-
- //protect= (icu->flag & IPO_PROTECT);
- mute = (icu->flag & IPO_MUTE);
-
- add_numbut(but++, NUM|FLO, "Slider Min:", -10000, slidermax, &slidermin, 0);
- add_numbut(but++, NUM|FLO, "Slider Max:", slidermin, 10000, &slidermax, 0);
- add_numbut(but++, TOG|SHO, "Muted", 0, 24, &mute, "Channel is Muted");
- //add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Channel is Protected");
- }
- else if (chantype == ACTTYPE_SHAPEKEY) {
- /* Shape Key */
- kb= (KeyBlock *)act_channel;
-
- if (kb->name[0] == '\0') {
- Key *key= (Key *)data;
- int keynum= BLI_findindex(&key->block, kb);
-
- sprintf(str, "Key %d", keynum);
- }
- else
- strcpy(str, kb->name);
-
- if (kb->slidermin >= kb->slidermax) {
- kb->slidermin = 0.0;
- kb->slidermax = 1.0;
- }
-
- add_numbut(but++, TEX, "KB: ", 0, 24, str,
- "Does this really need a tool tip?");
- add_numbut(but++, NUM|FLO, "Slider Min:",
- -10000, kb->slidermax, &kb->slidermin, 0);
- add_numbut(but++, NUM|FLO, "Slider Max:",
- kb->slidermin, 10000, &kb->slidermax, 0);
- }
- else if (chantype == ACTTYPE_GROUP) {
- /* Action Group */
- agrp= (bActionGroup *)act_channel;
-
- strcpy(str, agrp->name);
- protect= (agrp->flag & AGRP_PROTECTED);
- expand = (agrp->flag & AGRP_EXPANDED);
-
- add_numbut(but++, TEX, "ActGroup: ", 0, 31, str, "Name of Action Group");
- add_numbut(but++, TOG|SHO, "Expanded", 0, 24, &expand, "Action Group is Expanded");
- add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Group is Protected");
- }
- else if (chantype == ACTTYPE_GPLAYER) {
- /* Grease-Pencil Layer */
- gpd= (bGPdata *)channel_owner;
- gpl= (bGPDlayer *)act_channel;
-
- strcpy(str, gpl->info);
- protect= (gpl->flag & GP_LAYER_LOCKED);
- mute = (gpl->flag & GP_LAYER_HIDE);
-
- add_numbut(but++, TEX, "GP-Layer: ", 0, 128, str, "Name of Grease Pencil Layer");
- add_numbut(but++, TOG|SHO, "Hide", 0, 24, &mute, "Grease Pencil Layer is Visible");
- add_numbut(but++, TOG|SHO, "Protected", 0, 24, &protect, "Grease Pencil Layer is Protected");
- }
- else {
- /* nothing under-cursor */
- return;
- }
-
- /* draw clever-numbut */
- if (do_clever_numbuts(str, but, REDRAW)) {
- /* restore settings based on type */
- if (icu) {
- icu->slide_min= slidermin;
- icu->slide_max= slidermax;
-
- //if (protect) icu->flag |= IPO_PROTECT;
- //else icu->flag &= ~IPO_PROTECT;
- if (mute) icu->flag |= IPO_MUTE;
- else icu->flag &= ~IPO_MUTE;
- }
- else if (conchan) {
- strcpy(conchan->name, str);
-
- if (protect) conchan->flag |= CONSTRAINT_CHANNEL_PROTECTED;
- else conchan->flag &= ~CONSTRAINT_CHANNEL_PROTECTED;
-
- if (conchan->ipo)
- conchan->ipo->muteipo = mute;
- }
- else if (achan) {
- strcpy(achan->name, str);
-
- if (expand) achan->flag |= ACHAN_EXPANDED;
- else achan->flag &= ~ACHAN_EXPANDED;
-
- if (protect) achan->flag |= ACHAN_PROTECTED;
- else achan->flag &= ~ACHAN_PROTECTED;
-
- if (achan->ipo)
- achan->ipo->muteipo = mute;
- }
- else if (agrp) {
- strcpy(agrp->name, str);
- BLI_uniquename(&( ((bAction *)data)->groups ), agrp, "Group", offsetof(bActionGroup, name), 32);
-
- if (expand) agrp->flag |= AGRP_EXPANDED;
- else agrp->flag &= ~AGRP_EXPANDED;
-
- if (protect) agrp->flag |= AGRP_PROTECTED;
- else agrp->flag &= ~AGRP_PROTECTED;
- }
- else if (gpl) {
- strcpy(gpl->info, str);
- BLI_uniquename(&gpd->layers, gpl, "GP_Layer", offsetof(bGPDlayer, info), 128);
-
- if (mute) gpl->flag |= GP_LAYER_HIDE;
- else gpl->flag &= ~GP_LAYER_HIDE;;
-
- if (protect) gpl->flag |= GP_LAYER_LOCKED;
- else gpl->flag &= ~GP_LAYER_LOCKED;
- }
-
- allqueue(REDRAWACTION, 0);
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWVIEW3D, 0);
- }
-}
-
-/* Set/clear a particular flag (setting) for all selected + visible channels
- * mode: 0 = toggle, 1 = turn on, 2 = turn off
- */
-void setflag_action_channels (short mode)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
- char str[32];
- short val;
-
- /* get data */
- data= get_action_context(&datatype);
- if (data == NULL) return;
-
- /* get setting to affect */
- if (mode == 2) {
- val= pupmenu("Disable Setting%t|Protect %x1|Mute%x2");
- sprintf(str, "Disable Action Setting");
- }
- else if (mode == 1) {
- val= pupmenu("Enable Setting%t|Protect %x1|Mute%x2");
- sprintf(str, "Enable Action Setting");
- }
- else {
- val= pupmenu("Toggle Setting%t|Protect %x1|Mute%x2");
- sprintf(str, "Toggle Action Setting");
- }
- if (val <= 0) return;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_CHANNELS | ACTFILTER_SEL);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* affect selected channels */
- for (ale= act_data.first; ale; ale= ale->next) {
- switch (ale->type) {
- case ACTTYPE_GROUP:
- {
- bActionGroup *agrp= (bActionGroup *)ale->data;
-
- /* only 'protect' is available */
- if (val == 1) {
- if (mode == 2)
- agrp->flag &= ~AGRP_PROTECTED;
- else if (mode == 1)
- agrp->flag |= AGRP_PROTECTED;
- else
- agrp->flag ^= AGRP_PROTECTED;
- }
- }
- break;
- case ACTTYPE_ACHAN:
- {
- bActionChannel *achan= (bActionChannel *)ale->data;
-
- /* 'protect' and 'mute' */
- if ((val == 2) && (achan->ipo)) {
- Ipo *ipo= achan->ipo;
-
- /* mute */
- if (mode == 2)
- ipo->muteipo= 0;
- else if (mode == 1)
- ipo->muteipo= 1;
- else
- ipo->muteipo= (ipo->muteipo) ? 0 : 1;
- }
- else if (val == 1) {
- /* protected */
- if (mode == 2)
- achan->flag &= ~ACHAN_PROTECTED;
- else if (mode == 1)
- achan->flag |= ACHAN_PROTECTED;
- else
- achan->flag ^= ACHAN_PROTECTED;
- }
- }
- break;
- case ACTTYPE_CONCHAN:
- {
- bConstraintChannel *conchan= (bConstraintChannel *)ale->data;
-
- /* 'protect' and 'mute' */
- if ((val == 2) && (conchan->ipo)) {
- Ipo *ipo= conchan->ipo;
-
- /* mute */
- if (mode == 2)
- ipo->muteipo= 0;
- else if (mode == 1)
- ipo->muteipo= 1;
- else
- ipo->muteipo= (ipo->muteipo) ? 0 : 1;
- }
- else if (val == 1) {
- /* protect */
- if (mode == 2)
- conchan->flag &= ~CONSTRAINT_CHANNEL_PROTECTED;
- else if (mode == 1)
- conchan->flag |= CONSTRAINT_CHANNEL_PROTECTED;
- else
- conchan->flag ^= CONSTRAINT_CHANNEL_PROTECTED;
- }
- }
- break;
- case ACTTYPE_ICU:
- {
- IpoCurve *icu= (IpoCurve *)ale->data;
-
- /* mute */
- if (val == 2) {
- if (mode == 2)
- icu->flag &= ~IPO_MUTE;
- else if (mode == 1)
- icu->flag |= IPO_MUTE;
- else
- icu->flag ^= IPO_MUTE;
- }
- }
- break;
- case ACTTYPE_GPLAYER:
- {
- bGPDlayer *gpl= (bGPDlayer *)ale->data;
-
- /* 'protect' and 'mute' */
- if (val == 2) {
- /* mute */
- if (mode == 2)
- gpl->flag &= ~GP_LAYER_HIDE;
- else if (mode == 1)
- gpl->flag |= GP_LAYER_HIDE;
- else
- gpl->flag ^= GP_LAYER_HIDE;
- }
- else if (val == 1) {
- /* protected */
- if (mode == 2)
- gpl->flag &= ~GP_LAYER_LOCKED;
- else if (mode == 1)
- gpl->flag |= GP_LAYER_LOCKED;
- else
- gpl->flag ^= GP_LAYER_LOCKED;
- }
- }
- break;
- }
- }
- BLI_freelistN(&act_data);
-
- BIF_undo_push(str);
- allspace(REMAKEIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWNLA, 0);
-}
-
-/* **************************************************** */
-/* CHANNEL SELECTION */
-
-/* select_mode = SELECT_REPLACE
- * = SELECT_ADD
- * = SELECT_SUBTRACT
- * = SELECT_INVERT
- */
-static void select_action_group (bAction *act, bActionGroup *agrp, int selectmode)
-{
- /* Select the channel based on the selection mode */
- short select;
-
- switch (selectmode) {
- case SELECT_ADD:
- agrp->flag |= AGRP_SELECTED;
- break;
- case SELECT_SUBTRACT:
- agrp->flag &= ~AGRP_SELECTED;
- break;
- case SELECT_INVERT:
- agrp->flag ^= AGRP_SELECTED;
- break;
- }
- select = (agrp->flag & AGRP_SELECTED) ? 1 : 0;
-
- set_active_actiongroup(act, agrp, select);
-}
-
-static void hilight_channel (bAction *act, bActionChannel *achan, short select)
-{
- bActionChannel *curchan;
-
- if (!act)
- return;
-
- for (curchan=act->chanbase.first; curchan; curchan=curchan->next) {
- if (curchan==achan && select)
- curchan->flag |= ACHAN_HILIGHTED;
- else
- curchan->flag &= ~ACHAN_HILIGHTED;
- }
-}
-
-/* Syncs selection of channels with selection of object elements in posemode */
-/* messy call... */
-static void select_poseelement_by_name (char *name, int select)
-{
- Object *ob= OBACT;
- bPoseChannel *pchan;
-
- if ((ob==NULL) || (ob->type!=OB_ARMATURE))
- return;
-
- if (abs(select) == 2) {
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
- pchan->bone->flag &= ~(BONE_ACTIVE);
- }
-
- pchan= get_pose_channel(ob->pose, name);
- if (pchan) {
- if (select)
- pchan->bone->flag |= (BONE_SELECTED);
- else
- pchan->bone->flag &= ~(BONE_SELECTED);
- if (select == 2)
- pchan->bone->flag |= (BONE_ACTIVE);
- }
-}
-
-/* apparently within active object context */
-/* called extern, like on bone selection */
-void select_actionchannel_by_name (bAction *act, char *name, int select)
-{
- bActionChannel *achan;
-
- if (act == NULL)
- return;
-
- for (achan = act->chanbase.first; achan; achan= achan->next) {
- if (!strcmp(achan->name, name)) {
- if (select) {
- achan->flag |= ACHAN_SELECTED;
- hilight_channel(act, achan, 1);
- }
- else {
- achan->flag &= ~ACHAN_SELECTED;
- hilight_channel(act, achan, 0);
- }
- return;
- }
- }
-}
-
-/* select_mode = SELECT_REPLACE
- * = SELECT_ADD
- * = SELECT_SUBTRACT
- * = SELECT_INVERT
- */
-
-/* exported for outliner (ton) */
-/* apparently within active object context */
-int select_channel (bAction *act, bActionChannel *achan, int selectmode)
-{
- /* Select the channel based on the selection mode */
- int flag;
-
- switch (selectmode) {
- case SELECT_ADD:
- achan->flag |= ACHAN_SELECTED;
- break;
- case SELECT_SUBTRACT:
- achan->flag &= ~ACHAN_SELECTED;
- break;
- case SELECT_INVERT:
- achan->flag ^= ACHAN_SELECTED;
- break;
- }
- flag = (achan->flag & ACHAN_SELECTED) ? 1 : 0;
-
- hilight_channel(act, achan, flag);
- select_poseelement_by_name(achan->name, flag);
-
- return flag;
-}
-
-static int select_constraint_channel (bAction *act,
- bConstraintChannel *conchan,
- int selectmode)
-{
- /* Select the constraint channel based on the selection mode */
- int flag;
-
- switch (selectmode) {
- case SELECT_ADD:
- conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
- break;
- case SELECT_SUBTRACT:
- conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
- break;
- case SELECT_INVERT:
- conchan->flag ^= CONSTRAINT_CHANNEL_SELECT;
- break;
- }
- flag = (conchan->flag & CONSTRAINT_CHANNEL_SELECT) ? 1 : 0;
-
- return flag;
-}
-
-int select_icu_channel (bAction *act, IpoCurve *icu, int selectmode)
-{
- /* Select the channel based on the selection mode */
- int flag;
-
- switch (selectmode) {
- case SELECT_ADD:
- icu->flag |= IPO_SELECT;
- break;
- case SELECT_SUBTRACT:
- icu->flag &= ~IPO_SELECT;
- break;
- case SELECT_INVERT:
- icu->flag ^= IPO_SELECT;
- break;
- }
- flag = (icu->flag & IPO_SELECT) ? 1 : 0;
- return flag;
-}
-
-int select_gplayer_channel (bGPdata *gpd, bGPDlayer *gpl, int selectmode)
-{
- /* Select the channel based on the selection mode */
- int flag;
-
- switch (selectmode) {
- case SELECT_ADD:
- gpl->flag |= GP_LAYER_SELECT;
- break;
- case SELECT_SUBTRACT:
- gpl->flag &= ~GP_LAYER_SELECT;
- break;
- case SELECT_INVERT:
- gpl->flag ^= GP_LAYER_SELECT;
- break;
- }
-
- flag = (gpl->flag & GP_LAYER_SELECT) ? 1 : 0;
- if (flag)
- gpencil_layer_setactive(gpd, gpl);
-
- return flag;
-}
-
-
-/* select only the active action-group's action channels */
-void select_action_group_channels (bAction *act, bActionGroup *agrp)
-{
- bActionChannel *achan;
-
- /* error checking */
- if (ELEM(NULL, act, agrp))
- return;
-
- /* deselect all other channels */
- deselect_actionchannels(act, 0);
-
- /* only select channels in group */
- for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
- select_channel(act, achan, SELECT_ADD);
-
- /* messy... set active bone */
- select_poseelement_by_name(achan->name, 1);
- }
-}
-
-/* ----------------------------------------- */
-
-/* De-selects or inverts the selection of Channels in a given Action
- * mode: 0 = default behaviour (select all), 1 = test if (de)select all, 2 = invert all
- */
-void deselect_actionchannels (bAction *act, short mode)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter, sel=1;
-
- /* filter data */
- filter= ACTFILTER_VISIBLE;
- actdata_filter(&act_data, filter, act, ACTCONT_ACTION);
-
- /* See if we should be selecting or deselecting */
- if (mode == 1) {
- for (ale= act_data.first; ale; ale= ale->next) {
- if (sel == 0)
- break;
-
- switch (ale->type) {
- case ACTTYPE_GROUP:
- if (ale->flag & AGRP_SELECTED)
- sel= 0;
- break;
- case ACTTYPE_ACHAN:
- if (ale->flag & ACHAN_SELECTED)
- sel= 0;
- break;
- case ACTTYPE_CONCHAN:
- if (ale->flag & CONSTRAINT_CHANNEL_SELECT)
- sel=0;
- break;
- case ACTTYPE_ICU:
- if (ale->flag & IPO_SELECT)
- sel=0;
- break;
- }
- }
- }
- else
- sel= 0;
-
- /* Now set the flags */
- for (ale= act_data.first; ale; ale= ale->next) {
- switch (ale->type) {
- case ACTTYPE_GROUP:
- {
- bActionGroup *agrp= (bActionGroup *)ale->data;
-
- if (mode == 2)
- agrp->flag ^= AGRP_SELECTED;
- else if (sel)
- agrp->flag |= AGRP_SELECTED;
- else
- agrp->flag &= ~AGRP_SELECTED;
-
- agrp->flag &= ~AGRP_ACTIVE;
- }
- break;
- case ACTTYPE_ACHAN:
- {
- bActionChannel *achan= (bActionChannel *)ale->data;
-
- if (mode == 2)
- achan->flag ^= AGRP_SELECTED;
- else if (sel)
- achan->flag |= ACHAN_SELECTED;
- else
- achan->flag &= ~ACHAN_SELECTED;
-
- select_poseelement_by_name(achan->name, sel);
- achan->flag &= ~ACHAN_HILIGHTED;
- }
- break;
- case ACTTYPE_CONCHAN:
- {
- bConstraintChannel *conchan= (bConstraintChannel *)ale->data;
-
- if (mode == 2)
- conchan->flag ^= CONSTRAINT_CHANNEL_SELECT;
- else if (sel)
- conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
- else
- conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
- }
- break;
- case ACTTYPE_ICU:
- {
- IpoCurve *icu= (IpoCurve *)ale->data;
-
- if (mode == 2)
- icu->flag ^= IPO_SELECT;
- else if (sel)
- icu->flag |= IPO_SELECT;
- else
- icu->flag &= ~IPO_SELECT;
-
- icu->flag &= ~IPO_ACTIVE;
- }
- break;
- }
- }
-
- /* Cleanup */
- BLI_freelistN(&act_data);
-}
-
-/* deselects channels in the action editor */
-void deselect_action_channels (short mode)
-{
- void *data;
- short datatype;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* based on type */
- if (datatype == ACTCONT_ACTION)
- deselect_actionchannels(data, mode);
- else if (datatype == ACTCONT_GPENCIL)
- deselect_gpencil_layers(data, mode);
- // should shapekey channels be allowed to do this?
-}
-
-/* deselects keyframes in the action editor */
-void deselect_action_keys (short test, short sel)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* determine type-based settings */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
-
- /* filter data */
- actdata_filter(&act_data, filter, data, datatype);
-
- /* See if we should be selecting or deselecting */
- if (test) {
- for (ale= act_data.first; ale; ale= ale->next) {
- if (ale->type == ACTTYPE_GPLAYER) {
- if (is_gplayer_frame_selected(ale->data)) {
- sel= 0;
- break;
- }
- }
- else {
- if (is_ipo_key_selected(ale->key_data)) {
- sel= 0;
- break;
- }
- }
- }
- }
-
- /* Now set the flags */
- for (ale= act_data.first; ale; ale= ale->next) {
- if (ale->type == ACTTYPE_GPLAYER)
- set_gplayer_frame_selection(ale->data, sel);
- else
- set_ipo_key_selection(ale->key_data, sel);
- }
-
- /* Cleanup */
- BLI_freelistN(&act_data);
-}
-
-/* selects all keyframes in the action editor - per channel or time
- * mode = 0: all in channel; mode = 1: all in frame
- */
-void selectall_action_keys (short mval[], short mode, short select_mode)
-{
- void *data;
- short datatype;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- if (select_mode == SELECT_REPLACE) {
- deselect_action_keys(0, 0);
- select_mode = SELECT_ADD;
- }
-
- /* depending on mode */
- switch (mode) {
- case 0: /* all in channel*/
- {
- void *act_channel, *channel_owner;
- short chantype;
-
- /* get channel, and act according to type */
- act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner);
- switch (chantype) {
- case ACTTYPE_GROUP:
- {
- bActionGroup *agrp= (bActionGroup *)act_channel;
- bActionChannel *achan;
- bConstraintChannel *conchan;
-
- for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
- select_ipo_bezier_keys(achan->ipo, select_mode);
-
- for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
- select_ipo_bezier_keys(conchan->ipo, select_mode);
- }
- }
- break;
- case ACTTYPE_ACHAN:
- {
- bActionChannel *achan= (bActionChannel *)act_channel;
- select_ipo_bezier_keys(achan->ipo, select_mode);
- }
- break;
- case ACTTYPE_CONCHAN:
- {
- bConstraintChannel *conchan= (bConstraintChannel *)act_channel;
- select_ipo_bezier_keys(conchan->ipo, select_mode);
- }
- break;
- case ACTTYPE_ICU:
- {
- IpoCurve *icu= (IpoCurve *)act_channel;
- select_icu_bezier_keys(icu, select_mode);
- }
- break;
- case ACTTYPE_GPLAYER:
- {
- bGPDlayer *gpl= (bGPDlayer *)act_channel;
- select_gpencil_frames(gpl, select_mode);
- }
- break;
- }
- }
- break;
- case 1: /* all in frame */
- {
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- rcti rect;
- rctf rectf;
-
- /* use bounding box to find kframe */
- rect.xmin = rect.xmax = mval[0];
- rect.ymin = rect.ymax = mval[1];
-
- mval[0]= rect.xmin;
- mval[1]= rect.ymin+2;
- areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
- rectf.xmax= rectf.xmin;
- rectf.ymax= rectf.ymin;
-
- rectf.xmin = rectf.xmin - 0.5f;
- rectf.xmax = rectf.xmax + 0.5f;
-
- /* filter data */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* Now set the flags */
- for (ale= act_data.first; ale; ale= ale->next) {
- borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, select_mode);
- }
-
- /* Cleanup */
- BLI_freelistN(&act_data);
- }
- break;
- }
-
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
-}
-
-/* Selects all visible keyframes between the specified markers */
-void markers_selectkeys_between (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
- float min, max;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* get extreme markers */
- get_minmax_markers(1, &min, &max);
- if (min==max) return;
- min -= 0.5f;
- max += 0.5f;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* select keys in-between */
- for (ale= act_data.first; ale; ale= ale->next) {
- if(NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
- borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
- actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
- }
- else {
- borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
- }
- }
-
- /* Cleanup */
- BLI_freelistN(&act_data);
-}
-
-/* Selects all the keyframes on either side of the current frame (depends on which side the mouse is on) */
-void selectkeys_leftright (short leftright, short select_mode)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
- float min, max;
-
- if (select_mode==SELECT_REPLACE) {
- select_mode=SELECT_ADD;
- deselect_action_keys(0, 0);
- }
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- if (leftright == 1) {
- min = -MAXFRAMEF;
- max = (float)(CFRA + 0.1f);
- }
- else {
- min = (float)(CFRA - 0.1f);
- max = MAXFRAMEF;
- }
-
- /* filter data */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* select keys on the side where most data occurs */
- for (ale= act_data.first; ale; ale= ale->next) {
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
- borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
- actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
- }
- else if (ale->type == ACTTYPE_GPLAYER)
- borderselect_gplayer_frames(ale->data, min, max, SELECT_ADD);
- else
- borderselect_ipo_key(ale->key_data, min, max, SELECT_ADD);
- }
-
- /* Cleanup */
- BLI_freelistN(&act_data);
-
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWIPO, 0);
-}
-
-/* ----------------------------------------- */
-
-/* Jumps to the frame where the next/previous keyframe (that is visible) occurs
- * dir: indicates direction
- */
-void nextprev_action_keyframe (short dir)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
-
- ListBase elems= {NULL, NULL};
- CfraElem *ce, *nearest=NULL;
- float dist, min_dist= 1000000;
-
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* abort if no direction */
- if (dir == 0)
- return;
-
- /* get list of keyframes that can be used (in global-time) */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- for (ale= act_data.first; ale; ale= ale->next) {
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- actstrip_map_ipo_keys(OBACT, ale->key_data, 0, 1);
- make_cfra_list(ale->key_data, &elems);
- actstrip_map_ipo_keys(OBACT, ale->key_data, 1, 1);
- }
- else if (ale->type == ACTTYPE_GPLAYER)
- gplayer_make_cfra_list(ale->key_data, &elems, 0);
- else
- make_cfra_list(ale->key_data, &elems);
- }
-
- BLI_freelistN(&act_data);
-
- /* find nearest keyframe to current frame */
- for (ce= elems.first; ce; ce= ce->next) {
- dist= ABS(ce->cfra - CFRA);
-
- if (dist < min_dist) {
- min_dist= dist;
- nearest= ce;
- }
- }
-
- /* if a nearest keyframe was found, use the one either side */
- if (nearest) {
- short changed= 0;
-
- if ((dir > 0) && (nearest->next)) {
- CFRA= (int)nearest->next->cfra;
- changed= 1;
- }
- else if ((dir < 0) && (nearest->prev)) {
- CFRA= (int)nearest->prev->cfra;
- changed= 1;
- }
-
- if (changed) {
- update_for_newframe();
- allqueue(REDRAWALL, 0);
- }
- }
-
- /* free temp data */
- BLI_freelistN(&elems);
-}
-
-/* ----------------------------------------- */
-
-/* This function makes a list of the selected keyframes
- * in the ipo curves it has been passed
- */
-static void make_sel_cfra_list (Ipo *ipo, ListBase *elems)
-{
- IpoCurve *icu;
-
- if (ipo == NULL) return;
-
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- BezTriple *bezt;
- int a= 0;
-
- for (bezt=icu->bezt; a<icu->totvert; a++, bezt++) {
- if (bezt && BEZSELECTED(bezt))
- add_to_cfra_elem(elems, bezt);
- }
- }
-}
-
-/* This function selects all key frames in the same column(s) as a already selected key(s)
- * or marker(s), or all the keyframes on a particular frame (triggered by a RMB on x-scrollbar)
- */
-void column_select_action_keys (int mode)
-{
- ListBase elems= {NULL, NULL};
- CfraElem *ce;
- IpoCurve *icu;
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* build list of columns */
- switch (mode) {
- case 1: /* list of selected keys */
- if (datatype == ACTCONT_GPENCIL) {
- filter= (ACTFILTER_VISIBLE);
- actdata_filter(&act_data, filter, data, datatype);
-
- for (ale= act_data.first; ale; ale= ale->next)
- gplayer_make_cfra_list(ale->data, &elems, 1);
- }
- else {
- filter= (ACTFILTER_VISIBLE | ACTFILTER_IPOKEYS);
- actdata_filter(&act_data, filter, data, datatype);
-
- for (ale= act_data.first; ale; ale= ale->next)
- make_sel_cfra_list(ale->key_data, &elems);
- }
-
- BLI_freelistN(&act_data);
- break;
- case 2: /* list of selected markers */
- make_marker_cfra_list(&elems, 1);
-
- /* apply scaled action correction if needed */
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- for (ce= elems.first; ce; ce= ce->next)
- ce->cfra= get_action_frame(OBACT, ce->cfra);
- }
- break;
- case 3: /* current frame */
- /* make a single CfraElem */
- ce= MEM_callocN(sizeof(CfraElem), "cfraElem");
- BLI_addtail(&elems, ce);
-
- /* apply scaled action correction if needed */
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION)
- ce->cfra= (float)get_action_frame(OBACT, (float)CFRA);
- else
- ce->cfra= (float)CFRA;
- }
-
- /* loop through all of the keys and select additional keyframes
- * based on the keys found to be selected above
- */
- if (datatype == ACTCONT_GPENCIL)
- filter= (ACTFILTER_VISIBLE);
- else
- filter= (ACTFILTER_VISIBLE | ACTFILTER_ONLYICU);
- actdata_filter(&act_data, filter, data, datatype);
-
- for (ale= act_data.first; ale; ale= ale->next) {
- for (ce= elems.first; ce; ce= ce->next) {
- /* select elements with frame number matching cfraelem */
- if (ale->type == ACTTYPE_GPLAYER) {
- bGPDlayer *gpl= (bGPDlayer *)ale->data;
- bGPDframe *gpf;
-
- for (gpf= gpl->frames.first; gpf; gpf= gpf->next) {
- if ( (int)ce->cfra == gpf->framenum )
- gpf->flag |= GP_FRAME_SELECT;
- }
- }
- else {
- for (icu= ale->key_data; icu; icu= icu->next) {
- BezTriple *bezt;
- int verts = 0;
-
- for (bezt=icu->bezt; verts<icu->totvert; bezt++, verts++) {
- if (bezt) {
- if( (int)(ce->cfra) == (int)(bezt->vec[1][0]) )
- bezt->f2 |= 1;
- }
- }
- }
- }
- }
- }
-
- BLI_freelistN(&act_data);
- BLI_freelistN(&elems);
-}
-
-/* borderselect: for action-channels */
-void borderselect_actionchannels (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
-
- rcti rect;
- rctf rectf;
- int val, selectmode;
- short mval[2];
- float ymin, ymax;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (ELEM(datatype, ACTCONT_ACTION, ACTCONT_GPENCIL)==0) return;
-
- /* draw and handle the borderselect stuff (ui) and get the select rect */
- if ( (val = get_border(&rect, 3)) ) {
- selectmode= ((val==LEFTMOUSE) ? SELECT_ADD : SELECT_SUBTRACT);
-
- mval[0]= rect.xmin;
- mval[1]= rect.ymin+2;
- areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
- mval[0]= rect.xmax;
- mval[1]= rect.ymax-2;
- areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
-
- ymax = CHANNELHEIGHT/2;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_CHANNELS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop over data, doing border select */
- for (ale= act_data.first; ale; ale= ale->next) {
- ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
-
- /* if channel is within border-select region, alter it */
- if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
- /* only the following types can be selected */
- switch (ale->type) {
- case ACTTYPE_GROUP: /* action group */
- {
- bActionGroup *agrp= (bActionGroup *)ale->data;
-
- if (selectmode == SELECT_ADD)
- agrp->flag |= AGRP_SELECTED;
- else
- agrp->flag &= ~AGRP_SELECTED;
- }
- break;
- case ACTTYPE_ACHAN: /* action channel */
- case ACTTYPE_FILLIPO: /* expand ipo curves = action channel */
- case ACTTYPE_FILLCON: /* expand constraint channels = action channel */
- {
- bActionChannel *achan= (bActionChannel *)ale->data;
-
- if (selectmode == SELECT_ADD)
- achan->flag |= ACHAN_SELECTED;
- else
- achan->flag &= ~ACHAN_SELECTED;
-
- /* messy... set active bone */
- select_poseelement_by_name(achan->name, selectmode);
- }
- break;
- case ACTTYPE_CONCHAN: /* constraint channel */
- {
- bConstraintChannel *conchan = (bConstraintChannel *)ale->data;
-
- if (selectmode == SELECT_ADD)
- conchan->flag |= CONSTRAINT_CHANNEL_SELECT;
- else
- conchan->flag &= ~CONSTRAINT_CHANNEL_SELECT;
- }
- break;
- case ACTTYPE_ICU: /* ipo-curve channel */
- {
- IpoCurve *icu = (IpoCurve *)ale->data;
-
- if (selectmode == SELECT_ADD)
- icu->flag |= IPO_SELECT;
- else
- icu->flag &= ~IPO_SELECT;
- }
- break;
- case ACTTYPE_GPLAYER: /* grease-pencil layer */
- {
- bGPDlayer *gpl = (bGPDlayer *)ale->data;
-
- if (selectmode == SELECT_ADD)
- gpl->flag |= GP_LAYER_SELECT;
- else
- gpl->flag &= ~GP_LAYER_SELECT;
- }
- break;
- }
-
- /* select action-channel 'owner' */
- if ((ale->owner) && (ale->ownertype == ACTTYPE_ACHAN)) {
- bActionChannel *achano= (bActionChannel *)ale->owner;
-
- /* messy... set active bone */
- select_poseelement_by_name(achano->name, selectmode);
- }
- }
-
- ymax=ymin;
- }
-
- /* cleanup */
- BLI_freelistN(&act_data);
-
- BIF_undo_push("Border Select Action");
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWVIEW3D, 0);
- }
-}
-
-/* some quick defines for borderselect modes */
-enum {
- ACTEDIT_BORDERSEL_ALL = 0,
- ACTEDIT_BORDERSEL_FRA,
- ACTEDIT_BORDERSEL_CHA
-};
-
-/* borderselect: for keyframes only */
-void borderselect_action (void)
-{
- ListBase act_data = {NULL, NULL};
- bActListElem *ale;
- int filter;
- void *data;
- short datatype;
-
- rcti rect;
- rctf rectf;
- int val, selectmode, mode;
- int (*select_function)(BezTriple *);
- short mval[2];
- float ymin, ymax;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* what should be selected (based on the starting location of cursor) */
- getmouseco_areawin(mval);
- if (IN_2D_VERT_SCROLL(mval))
- mode = ACTEDIT_BORDERSEL_CHA;
- else if (IN_2D_HORIZ_SCROLL(mval))
- mode = ACTEDIT_BORDERSEL_FRA;
- else
- mode = ACTEDIT_BORDERSEL_ALL;
-
- /* draw and handle the borderselect stuff (ui) and get the select rect */
- if ( (val = get_border(&rect, 3)) ) {
- if (val == LEFTMOUSE) {
- selectmode = SELECT_ADD;
- select_function = select_bezier_add;
- }
- else {
- selectmode = SELECT_SUBTRACT;
- select_function = select_bezier_subtract;
- }
-
- mval[0]= rect.xmin;
- mval[1]= rect.ymin+2;
- areamouseco_to_ipoco(G.v2d, mval, &rectf.xmin, &rectf.ymin);
- mval[0]= rect.xmax;
- mval[1]= rect.ymax-2;
- areamouseco_to_ipoco(G.v2d, mval, &rectf.xmax, &rectf.ymax);
-
- /* if action is mapped in NLA, it returns a correction */
- if (NLA_ACTION_SCALED && datatype==ACTCONT_ACTION) {
- rectf.xmin= get_action_frame(OBACT, rectf.xmin);
- rectf.xmax= get_action_frame(OBACT, rectf.xmax);
- }
-
- ymax = CHANNELHEIGHT/2;
-
- /* filter data */
- filter= (ACTFILTER_VISIBLE | ACTFILTER_CHANNELS);
- actdata_filter(&act_data, filter, data, datatype);
-
- /* loop over data, doing border select */
- for (ale= act_data.first; ale; ale= ale->next) {
- ymin=ymax-(CHANNELHEIGHT+CHANNELSKIP);
-
- /* what gets selected depends on the mode (based on initial position of cursor) */
- switch (mode) {
- case ACTEDIT_BORDERSEL_FRA: /* all in frame(s) */
- if (ale->key_data) {
- if (ale->datatype == ALE_IPO)
- borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, selectmode);
- else if (ale->datatype == ALE_ICU)
- borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_function);
- }
- else if (ale->type == ACTTYPE_GROUP) {
- bActionGroup *agrp= ale->data;
- bActionChannel *achan;
- bConstraintChannel *conchan;
-
- for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
- borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode);
-
- for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
- borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode);
- }
- }
- else if (ale->type == ACTTYPE_GPLAYER) {
- borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
- }
- break;
- case ACTEDIT_BORDERSEL_CHA: /* all in channel(s) */
- if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
- if (ale->key_data) {
- if (ale->datatype == ALE_IPO)
- select_ipo_bezier_keys(ale->key_data, selectmode);
- else if (ale->datatype == ALE_ICU)
- select_icu_bezier_keys(ale->key_data, selectmode);
- }
- else if (ale->type == ACTTYPE_GROUP) {
- bActionGroup *agrp= ale->data;
- bActionChannel *achan;
- bConstraintChannel *conchan;
-
- for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
- select_ipo_bezier_keys(achan->ipo, selectmode);
-
- for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
- select_ipo_bezier_keys(conchan->ipo, selectmode);
- }
- }
- else if (ale->type == ACTTYPE_GPLAYER) {
- select_gpencil_frames(ale->data, selectmode);
- }
- }
- break;
- default: /* any keyframe inside region defined by region */
- if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
- if (ale->key_data) {
- if (ale->datatype == ALE_IPO)
- borderselect_ipo_key(ale->key_data, rectf.xmin, rectf.xmax, selectmode);
- else if (ale->datatype == ALE_ICU)
- borderselect_icu_key(ale->key_data, rectf.xmin, rectf.xmax, select_function);
- }
- else if (ale->type == ACTTYPE_GROUP) {
- bActionGroup *agrp= ale->data;
- bActionChannel *achan;
- bConstraintChannel *conchan;
-
- for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
- borderselect_ipo_key(achan->ipo, rectf.xmin, rectf.xmax, selectmode);
-
- for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
- borderselect_ipo_key(conchan->ipo, rectf.xmin, rectf.xmax, selectmode);
- }
- }
- else if (ale->type == ACTTYPE_GPLAYER) {
- borderselect_gplayer_frames(ale->data, rectf.xmin, rectf.xmax, selectmode);
- }
- }
- }
-
- ymax=ymin;
- }
-
- /* cleanup */
- BLI_freelistN(&act_data);
-
- BIF_undo_push("Border Select Action");
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- }
-}
-
-/* **************************************************** */
-/* MOUSE-HANDLING */
-
-/* right-hand side - mouse click */
-static void mouse_action (int selectmode)
-{
- void *data;
- short datatype;
-
- bAction *act= NULL;
- bActionGroup *agrp= NULL;
- bActionChannel *achan= NULL;
- bConstraintChannel *conchan= NULL;
- IpoCurve *icu= NULL;
- bGPdata *gpd = NULL;
- bGPDlayer *gpl = NULL;
- TimeMarker *marker, *pmarker;
-
- void *act_channel;
- short sel, act_type = 0;
- float selx = 0.0;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype == ACTCONT_ACTION) act= (bAction *)data;
- if (datatype == ACTCONT_GPENCIL) gpd= (bGPdata *)data;
-
- act_channel= get_nearest_action_key(&selx, &sel, &act_type, &achan);
- marker= find_nearest_marker(SCE_MARKERS, 1);
- pmarker= (act) ? find_nearest_marker(&act->markers, 1) : NULL;
-
- if (marker) {
- /* what about scene's markers? */
- if (selectmode == SELECT_REPLACE) {
- deselect_markers(0, 0);
- marker->flag |= SELECT;
- }
- else if (selectmode == SELECT_INVERT) {
- if (marker->flag & SELECT)
- marker->flag &= ~SELECT;
- else
- marker->flag |= SELECT;
- }
- else if (selectmode == SELECT_ADD)
- marker->flag |= SELECT;
- else if (selectmode == SELECT_SUBTRACT)
- marker->flag &= ~SELECT;
-
- std_rmouse_transform(transform_markers);
-
- allqueue(REDRAWMARKER, 0);
- }
- else if (pmarker) {
- /* action's markers are drawn behind scene markers */
- if (selectmode == SELECT_REPLACE) {
- action_set_activemarker(act, pmarker, 1);
- pmarker->flag |= SELECT;
- }
- else if (selectmode == SELECT_INVERT) {
- if (pmarker->flag & SELECT) {
- pmarker->flag &= ~SELECT;
- action_set_activemarker(act, NULL, 0);
- }
- else {
- pmarker->flag |= SELECT;
- action_set_activemarker(act, pmarker, 0);
- }
- }
- else if (selectmode == SELECT_ADD) {
- pmarker->flag |= SELECT;
- action_set_activemarker(act, pmarker, 0);
- }
- else if (selectmode == SELECT_SUBTRACT) {
- pmarker->flag &= ~SELECT;
- action_set_activemarker(act, NULL, 0);
- }
-
- // TODO: local-markers cannot be moved atm...
- //std_rmouse_transform(transform_markers);
-
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWBUTSEDIT, 0);
- }
- else if (act_channel) {
- /* must have been a channel */
- switch (act_type) {
- case ACTTYPE_ICU:
- icu= (IpoCurve *)act_channel;
- break;
- case ACTTYPE_CONCHAN:
- conchan= (bConstraintChannel *)act_channel;
- break;
- case ACTTYPE_ACHAN:
- achan= (bActionChannel *)act_channel;
- break;
- case ACTTYPE_GROUP:
- agrp= (bActionGroup *)act_channel;
- break;
- case ACTTYPE_GPLAYER:
- gpl= (bGPDlayer *)act_channel;
- break;
- default:
- return;
- }
-
- if (selectmode == SELECT_REPLACE) {
- selectmode = SELECT_ADD;
-
- deselect_action_keys(0, 0);
-
- if (datatype == ACTCONT_ACTION) {
- deselect_action_channels(0);
-
- /* Highlight either an Action-Channel or Action-Group */
- if (achan) {
- achan->flag |= ACHAN_SELECTED;
- hilight_channel(act, achan, 1);
- select_poseelement_by_name(achan->name, 2); /* 2 is activate */
- }
- else if (agrp) {
- agrp->flag |= AGRP_SELECTED;
- set_active_actiongroup(act, agrp, 1);
- }
- }
- else if (datatype == ACTCONT_GPENCIL) {
- deselect_action_channels(0);
-
- /* Highlight gpencil layer */
- gpl->flag |= GP_LAYER_SELECT;
- gpencil_layer_setactive(gpd, gpl);
- }
- }
-
- if (icu)
- select_icu_key(icu, selx, selectmode);
- else if (conchan)
- select_ipo_key(conchan->ipo, selx, selectmode);
- else if (achan)
- select_ipo_key(achan->ipo, selx, selectmode);
- else if (agrp) {
- for (achan= agrp->channels.first; achan && achan->grp==agrp; achan= achan->next) {
- select_ipo_key(achan->ipo, selx, selectmode);
-
- for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next)
- select_ipo_key(conchan->ipo, selx, selectmode);
- }
- }
- else if (gpl)
- select_gpencil_frame(gpl, (int)selx, selectmode);
-
- std_rmouse_transform(transform_action_keys);
-
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWOOPS, 0);
- allqueue(REDRAWBUTSALL, 0);
- }
-}
-
-/* lefthand side - mouse-click */
-static void mouse_actionchannels (short mval[])
-{
- bAction *act= G.saction->action;
- void *data, *act_channel, *channel_owner;
- short datatype, chantype;
-
- /* determine what type of data we are operating on */
- data = get_action_context(&datatype);
- if (data == NULL) return;
-
- /* get channel to work on */
- act_channel= get_nearest_act_channel(mval, &chantype, &channel_owner);
-
- /* action to take depends on what channel we've got */
- switch (chantype) {
- case ACTTYPE_GROUP:
- {
- bActionGroup *agrp= (bActionGroup *)act_channel;
-
- if ((mval[0] < 16) && (agrp->channels.first)) {
- /* toggle expand */
- agrp->flag ^= AGRP_EXPANDED;
- }
- else if (mval[0] >= (NAMEWIDTH-16)) {
- /* toggle protection/locking */
- agrp->flag ^= AGRP_PROTECTED;
- }
- else {
- /* select/deselect group */
- if (G.qual == LR_SHIFTKEY) {
- /* inverse selection status of group */
- select_action_group(act, agrp, SELECT_INVERT);
- }
- else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY)) {
- /* select all in group (and deselect everthing else) */
- select_action_group_channels(act, agrp);
- select_action_group(act, agrp, SELECT_ADD);
- }
- else {
- /* select group by itself */
- deselect_actionchannels(act, 0);
- select_action_group(act, agrp, SELECT_ADD);
- }
- }
- }
- break;
- case ACTTYPE_ACHAN:
- {
- bActionChannel *achan= (bActionChannel *)act_channel;
-
- if (mval[0] >= (NAMEWIDTH-16)) {
- /* toggle protect */
- achan->flag ^= ACHAN_PROTECTED;
- }
- else if ((mval[0] >= (NAMEWIDTH-32)) && (achan->ipo)) {
- /* toggle mute */
- achan->ipo->muteipo = (achan->ipo->muteipo)? 0: 1;
- }
- else if (mval[0] <= 17) {
- /* toggle expand */
- achan->flag ^= ACHAN_EXPANDED;
- }
- else {
- /* select/deselect achan */
- if (G.qual & LR_SHIFTKEY) {
- select_channel(act, achan, SELECT_INVERT);
- }
- else {
- deselect_actionchannels(act, 0);
- select_channel(act, achan, SELECT_ADD);
- }
-
- /* messy... set active bone */
- select_poseelement_by_name(achan->name, 2);
- }
- }
- break;
- case ACTTYPE_FILLIPO:
- {
- bActionChannel *achan= (bActionChannel *)act_channel;
-
- achan->flag ^= ACHAN_SHOWIPO;
-
- if ((mval[0] > 24) && (achan->flag & ACHAN_SHOWIPO)) {
- /* select+make active achan */
- deselect_actionchannels(act, 0);
- select_channel(act, achan, SELECT_ADD);
-
- /* messy... set active bone */
- select_poseelement_by_name(achan->name, 2);
- }
- }
- break;
- case ACTTYPE_FILLCON:
- {
- bActionChannel *achan= (bActionChannel *)act_channel;
-
- achan->flag ^= ACHAN_SHOWCONS;
-
- if ((mval[0] > 24) && (achan->flag & ACHAN_SHOWCONS)) {
- /* select+make active achan */
- deselect_actionchannels(act, 0);
- select_channel(act, achan, SELECT_ADD);
-
- /* messy... set active bone */
- select_poseelement_by_name(achan->name, 2);
- }
- }
- break;
- case ACTTYPE_ICU:
- {
- IpoCurve *icu= (IpoCurve *)act_channel;
-
-#if 0 /* disabled until all ipo tools support this -------> */
- if (mval[0] >= (NAMEWIDTH-16)) {
- /* toggle protection */
- icu->flag ^= IPO_PROTECT;
- }
-#endif /* <------- end of disabled code */
- if (mval[0] >= (NAMEWIDTH-16)) {
- /* toggle mute */
- icu->flag ^= IPO_MUTE;
- }
- else {
- /* select/deselect */
- select_icu_channel(act, icu, SELECT_INVERT);
- }
-
- allspace(REMAKEIPO, 0);
- }
- break;
- case ACTTYPE_CONCHAN:
- {
- bConstraintChannel *conchan= (bConstraintChannel *)act_channel;
-
- if (mval[0] >= (NAMEWIDTH-16)) {
- /* toggle protection */
- conchan->flag ^= CONSTRAINT_CHANNEL_PROTECTED;
- }
- else if ((mval[0] >= (NAMEWIDTH-32)) && (conchan->ipo)) {
- /* toggle mute */
- conchan->ipo->muteipo = (conchan->ipo->muteipo)? 0: 1;
- }
- else {
- /* select/deselect */
- select_constraint_channel(act, conchan, SELECT_INVERT);
- }
- }
- break;
- case ACTTYPE_GPDATABLOCK:
- {
- bGPdata *gpd= (bGPdata *)act_channel;
-
- /* toggle expand */
- gpd->flag ^= GP_DATA_EXPAND;
- }
- break;
- case ACTTYPE_GPLAYER:
- {
- bGPdata *gpd= (bGPdata *)channel_owner;
- bGPDlayer *gpl= (bGPDlayer *)act_channel;
-
- if (mval[0] >= (NAMEWIDTH-16)) {
- /* toggle lock */
- gpl->flag ^= GP_LAYER_LOCKED;
- }
- else if (mval[0] >= (NAMEWIDTH-32)) {
- /* toggle hide */
- gpl->flag ^= GP_LAYER_HIDE;
- }
- else {
- /* select/deselect */
- if (G.qual & LR_SHIFTKEY) {
- select_gplayer_channel(gpd, gpl, SELECT_INVERT);
- }
- else {
- deselect_gpencil_layers(data, 0);
- select_gplayer_channel(gpd, gpl, SELECT_INVERT);
- }
- }
- }
- break;
- default:
- return;
- }
-
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWTIME, 0);
- allqueue(REDRAWOOPS, 0);
- allqueue(REDRAWBUTSALL, 0);
-}
-
-/* **************************************************** */
-/* ACTION CHANNEL RE-ORDERING */
-
-/* make sure all action-channels belong to a group (and clear action's list) */
-static void split_groups_action_temp (bAction *act, bActionGroup *tgrp)
-{
- bActionChannel *achan;
- bActionGroup *agrp;
-
- /* Separate action-channels into lists per group */
- for (agrp= act->groups.first; agrp; agrp= agrp->next) {
- if (agrp->channels.first) {
- achan= agrp->channels.last;
- act->chanbase.first= achan->next;
-
- achan= agrp->channels.first;
- achan->prev= NULL;
-
- achan= agrp->channels.last;
- achan->next= NULL;
- }
- }
-
- /* Initialise memory for temp-group */
- memset(tgrp, 0, sizeof(bActionGroup));
- tgrp->flag |= (AGRP_EXPANDED|AGRP_TEMP);
- strcpy(tgrp->name, "#TempGroup");
-
- /* Move any action-channels not already moved, to the temp group */
- if (act->chanbase.first) {
- /* start of list */
- achan= act->chanbase.first;
- achan->prev= NULL;
- tgrp->channels.first= achan;
- act->chanbase.first= NULL;
-
- /* end of list */
- achan= act->chanbase.last;
- achan->next= NULL;
- tgrp->channels.last= achan;
- act->chanbase.last= NULL;
- }
-
- /* Add temp-group to list */
- BLI_addtail(&act->groups, tgrp);
-}
-
-/* link lists of channels that groups have */
-static void join_groups_action_temp (bAction *act)
-{
- bActionGroup *agrp;
- bActionChannel *achan;
-
- for (agrp= act->groups.first; agrp; agrp= agrp->next) {
- ListBase tempGroup;
-
- /* add list of channels to action's channels */
- tempGroup= agrp->channels;
- addlisttolist(&act->chanbase, &agrp->channels);
- agrp->channels= tempGroup;
-
- /* clear moved flag */
- agrp->flag &= ~AGRP_MOVED;
-
- /* if temp-group... remove from list (but don't free as it's on the stack!) */
- if (agrp->flag & AGRP_TEMP) {
- BLI_remlink(&act->groups, agrp);
- break;
- }
- }
-
- /* clear "moved" flag from all achans */
- for (achan= act->chanbase.first; achan; achan= achan->next)
- achan->flag &= ~ACHAN_MOVED;
-}
-
-
-static short rearrange_actchannel_is_ok (Link *channel, short type)
-{
- if (type == ACTTYPE_GROUP) {
- bActionGroup *agrp= (bActionGroup *)channel;
-
- if (SEL_AGRP(agrp) && !(agrp->flag & AGRP_MOVED))
- return 1;
- }
- else if (type == ACTTYPE_ACHAN) {
- bActionChannel *achan= (bActionChannel *)channel;
-
- if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED))
- return 1;
- }
-
- return 0;
-}
-
-static short rearrange_actchannel_after_ok (Link *channel, short type)
-{
- if (type == ACTTYPE_GROUP) {
- bActionGroup *agrp= (bActionGroup *)channel;
-
- if (agrp->flag & AGRP_TEMP)
- return 0;
- }
-
- return 1;
-}
-
-
-static short rearrange_actchannel_top (ListBase *list, Link *channel, short type)
-{
- if (rearrange_actchannel_is_ok(channel, type)) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* make it first element */
- BLI_insertlinkbefore(list, list->first, channel);
-
- return 1;
- }
-
- return 0;
-}
-
-static short rearrange_actchannel_up (ListBase *list, Link *channel, short type)
-{
- if (rearrange_actchannel_is_ok(channel, type)) {
- Link *prev= channel->prev;
-
- if (prev) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* push it up */
- BLI_insertlinkbefore(list, prev, channel);
-
- return 1;
- }
- }
-
- return 0;
-}
-
-static short rearrange_actchannel_down (ListBase *list, Link *channel, short type)
-{
- if (rearrange_actchannel_is_ok(channel, type)) {
- Link *next = (channel->next) ? channel->next->next : NULL;
-
- if (next) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* move it down */
- BLI_insertlinkbefore(list, next, channel);
-
- return 1;
- }
- else if (rearrange_actchannel_after_ok(list->last, type)) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* add at end */
- BLI_addtail(list, channel);
-
- return 1;
- }
- else {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* add just before end */
- BLI_insertlinkbefore(list, list->last, channel);
-
- return 1;
- }
- }
-
- return 0;
-}
-
-static short rearrange_actchannel_bottom (ListBase *list, Link *channel, short type)
-{
- if (rearrange_actchannel_is_ok(channel, type)) {
- if (rearrange_actchannel_after_ok(list->last, type)) {
- /* take it out off the chain keep data */
- BLI_remlink(list, channel);
-
- /* add at end */
- BLI_addtail(list, channel);
-
- return 1;
- }
- }
-
- return 0;
-}
-
-
-/* Change the order of action-channels
- * mode: REARRANGE_ACTCHAN_*
- */
-void rearrange_action_channels (short mode)
-{
- bAction *act;
- bActionChannel *achan, *chan;
- bActionGroup *agrp, *grp;
- bActionGroup tgrp;
-
- void *data;
- short datatype;
-
- short (*rearrange_func)(ListBase *, Link *, short);
- short do_channels = 1;
- char undostr[60];
-
- /* Get the active action, exit if none are selected */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_ACTION) return;
- act= (bAction *)data;
-
- /* exit if invalid mode */
- switch (mode) {
- case REARRANGE_ACTCHAN_TOP:
- strcpy(undostr, "Channel(s) to Top");
- rearrange_func= rearrange_actchannel_top;
- break;
- case REARRANGE_ACTCHAN_UP:
- strcpy(undostr, "Channel(s) Move Up");
- rearrange_func= rearrange_actchannel_up;
- break;
- case REARRANGE_ACTCHAN_DOWN:
- strcpy(undostr, "Channel(s) Move Down");
- rearrange_func= rearrange_actchannel_down;
- break;
- case REARRANGE_ACTCHAN_BOTTOM:
- strcpy(undostr, "Channel(s) to Bottom");
- rearrange_func= rearrange_actchannel_bottom;
- break;
- default:
- return;
- }
-
- /* make sure we're only operating with groups */
- split_groups_action_temp(act, &tgrp);
-
- /* rearrange groups first (and then, only consider channels if the groups weren't moved) */
- #define GET_FIRST(list) ((mode > 0) ? (list.first) : (list.last))
- #define GET_NEXT(item) ((mode > 0) ? (item->next) : (item->prev))
-
- for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) {
- /* Get next group to consider */
- grp= GET_NEXT(agrp);
-
- /* try to do group first */
- if (rearrange_func(&act->groups, (Link *)agrp, ACTTYPE_GROUP)) {
- do_channels= 0;
- agrp->flag |= AGRP_MOVED;
- }
- }
-
- if (do_channels) {
- for (agrp= GET_FIRST(act->groups); agrp; agrp= grp) {
- /* Get next group to consider */
- grp= GET_NEXT(agrp);
-
- /* only consider action-channels if they're visible (group expanded) */
- if (EXPANDED_AGRP(agrp)) {
- for (achan= GET_FIRST(agrp->channels); achan; achan= chan) {
- /* Get next channel to consider */
- chan= GET_NEXT(achan);
-
- /* Try to do channel */
- if (rearrange_func(&agrp->channels, (Link *)achan, ACTTYPE_ACHAN))
- achan->flag |= ACHAN_MOVED;
- }
- }
- }
- }
- #undef GET_FIRST
- #undef GET_NEXT
-
- /* assemble lists into one list (and clear moved tags) */
- join_groups_action_temp(act);
-
- /* Undo + redraw */
- BIF_undo_push(undostr);
- allqueue(REDRAWACTION, 0);
-}
-
-/* ******************************************************************* */
-/* CHANNEL VISIBILITY/FOLDING */
-
-/* Expand all channels to show full hierachy */
-void expand_all_action (void)
-{
- void *data;
- short datatype;
-
- bAction *act;
- bActionChannel *achan;
- bActionGroup *agrp;
- short mode= 1;
-
- /* Get the selected action, exit if none are selected */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_ACTION) return;
- act= (bAction *)data;
-
- /* check if expand all, or close all */
- for (agrp= act->groups.first; agrp; agrp= agrp->next) {
- if (EXPANDED_AGRP(agrp)) {
- mode= 0;
- break;
- }
- }
-
- if (mode == 0) {
- for (achan= act->chanbase.first; achan; achan= achan->next) {
- if (VISIBLE_ACHAN(achan)) {
- if (EXPANDED_ACHAN(achan)) {
- mode= 0;
- break;
- }
- }
- }
- }
-
- /* expand/collapse depending on mode */
- for (agrp= act->groups.first; agrp; agrp= agrp->next) {
- if (mode == 1)
- agrp->flag |= AGRP_EXPANDED;
- else
- agrp->flag &= ~AGRP_EXPANDED;
- }
-
- for (achan=act->chanbase.first; achan; achan= achan->next) {
- if (VISIBLE_ACHAN(achan)) {
- if (mode == 1)
- achan->flag |= (ACHAN_EXPANDED|ACHAN_SHOWIPO|ACHAN_SHOWCONS);
- else
- achan->flag &= ~(ACHAN_EXPANDED|ACHAN_SHOWIPO|ACHAN_SHOWCONS);
- }
- }
-
- /* Cleanup and do redraws */
- BIF_undo_push("Expand Action Hierachy");
- allqueue(REDRAWACTION, 0);
-}
-
-/* Expands those groups which are hiding a selected actionchannel */
-void expand_obscuregroups_action (void)
-{
- void *data;
- short datatype;
-
- bAction *act;
- bActionChannel *achan;
-
- /* Get the selected action, exit if none are selected */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_ACTION) return;
- act= (bAction *)data;
-
- /* check if expand all, or close all */
- for (achan= act->chanbase.first; achan; achan= achan->next) {
- if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) {
- if (achan->grp)
- achan->grp->flag |= AGRP_EXPANDED;
- }
- }
-
- /* Cleanup and do redraws */
- BIF_undo_push("Show Group-Hidden Channels");
- allqueue(REDRAWACTION, 0);
-}
-
-/* For visible channels, expand/collapse one level */
-void openclose_level_action (short mode)
-{
- void *data;
- short datatype;
-
- bAction *act;
- bActionChannel *achan;
- bActionGroup *agrp;
-
- /* Get the selected action, exit if none are selected */
- data = get_action_context(&datatype);
- if (data == NULL) return;
- if (datatype != ACTCONT_ACTION) return;
- act= (bAction *)data;
-
- /* Abort if no operation required */
- if (mode == 0) return;
-
- /* Only affect selected channels */
- for (achan= act->chanbase.first; achan; achan= achan->next) {
- /* make sure if there is a group, it isn't about to be collapsed and is open */
- if ( (achan->grp==NULL) || (EXPANDED_AGRP(achan->grp) && SEL_AGRP(achan->grp)==0) ) {
- if (VISIBLE_ACHAN(achan) && SEL_ACHAN(achan)) {
- if (EXPANDED_ACHAN(achan)) {
- if (FILTER_IPO_ACHAN(achan) || FILTER_CON_ACHAN(achan)) {
- if (mode < 0)
- achan->flag &= ~(ACHAN_SHOWIPO|ACHAN_SHOWCONS);
- }
- else {
- if (mode > 0)
- achan->flag |= (ACHAN_SHOWIPO|ACHAN_SHOWCONS);
- else
- achan->flag &= ~ACHAN_EXPANDED;
- }
- }
- else {
- if (mode > 0)
- achan->flag |= ACHAN_EXPANDED;
- }
- }
- }
- }
-
- /* Expand/collapse selected groups */
- for (agrp= act->groups.first; agrp; agrp= agrp->next) {
- if (SEL_AGRP(agrp)) {
- if (mode < 0)
- agrp->flag &= ~AGRP_EXPANDED;
- else
- agrp->flag |= AGRP_EXPANDED;
- }
- }
-
- /* Cleanup and do redraws */
- BIF_undo_push("Expand/Collapse Action Level");
- allqueue(REDRAWACTION, 0);
-}
-
-/* **************************************************** */
-/* ACTION MARKERS (PoseLib features) */
-/* NOTE: yes, these duplicate code from edittime.c a bit, but these do a bit more...
- * These could get merged with those someday if need be... (Aligorith, 20071230)
- */
-
-/* Makes the given marker the active one
- * - deselect indicates whether unactive ones should be deselected too
- */
-void action_set_activemarker (bAction *act, TimeMarker *active, short deselect)
-{
- TimeMarker *marker;
- int index= 0;
-
- /* sanity checks */
- if (act == NULL)
- return;
- act->active_marker= 0;
-
- /* set appropriate flags for all markers */
- for (marker=act->markers.first; marker; marker=marker->next, index++) {
- /* only active may be active */
- if (marker == active) {
- act->active_marker= index + 1;
- marker->flag |= (SELECT|ACTIVE);
- }
- else {
- if (deselect)
- marker->flag &= ~(SELECT|ACTIVE);
- else
- marker->flag &= ~ACTIVE;
- }
- }
-}
-
-/* Adds a local marker to the active action */
-void action_add_localmarker (bAction *act, int frame)
-{
- TimeMarker *marker;
- char name[64];
-
- /* sanity checks */
- if (act == NULL)
- return;
-
- /* get name of marker */
- sprintf(name, "Pose");
- if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0)
- return;
-
- /* add marker to action - replaces any existing marker there */
- for (marker= act->markers.first; marker; marker= marker->next) {
- if (marker->frame == frame) {
- BLI_strncpy(marker->name, name, sizeof(marker->name));
- break;
- }
- }
- if (marker == NULL) {
- marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
-
- BLI_strncpy(marker->name, name, sizeof(marker->name));
- marker->frame= frame;
-
- BLI_addtail(&act->markers, marker);
- }
-
- /* validate the name */
- BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64);
-
- /* sets the newly added marker as the active one */
- action_set_activemarker(act, marker, 1);
-
- BIF_undo_push("Action Add Marker");
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWBUTSEDIT, 0);
-}
-
-/* Renames the active local marker to the active action */
-void action_rename_localmarker (bAction *act)
-{
- TimeMarker *marker;
- char name[64];
- int val;
-
- /* sanity checks */
- if (act == NULL)
- return;
-
- /* get active marker to rename */
- if (act->active_marker == 0)
- return;
- else
- val= act->active_marker;
-
- if (val <= 0) return;
- marker= BLI_findlink(&act->markers, val-1);
- if (marker == NULL) return;
-
- /* get name of marker */
- sprintf(name, marker->name);
- if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0)
- return;
-
- /* copy then validate name */
- BLI_strncpy(marker->name, name, sizeof(marker->name));
- BLI_uniquename(&act->markers, marker, "Pose", offsetof(TimeMarker, name), 64);
-
- /* undo and update */
- BIF_undo_push("Action Rename Marker");
- allqueue(REDRAWBUTSEDIT, 0);
- allqueue(REDRAWACTION, 0);
-}
-
-/* Deletes all selected markers, and adjusts things as appropriate */
-void action_remove_localmarkers (bAction *act)
-{
- TimeMarker *marker, *next;
-
- /* sanity checks */
- if (act == NULL)
- return;
-
- /* remove selected markers */
- for (marker= act->markers.first; marker; marker= next) {
- next= marker->next;
-
- if (marker->flag & SELECT)
- BLI_freelinkN(&act->markers, marker);
- }
-
- /* clear active just in case */
- act->active_marker= 0;
-
- /* undo and update */
- BIF_undo_push("Action Remove Marker(s)");
- allqueue(REDRAWBUTSEDIT, 0);
- allqueue(REDRAWACTION, 0);
-}
-
-/* **************************************************** */
-/* EVENT HANDLING */
-
-void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
-{
- extern void do_actionbuts(unsigned short event); // drawaction.c
- SpaceAction *saction;
- void *data;
- short datatype;
- float dx, dy;
- int doredraw= 0;
- int cfra;
- short mval[2];
- unsigned short event= evt->event;
- short val= evt->val;
- short mousebut = L_MOUSE;
-
- if (curarea->win==0) return;
-
- saction= curarea->spacedata.first;
- if (!saction)
- return;
-
- data= get_action_context(&datatype);
-
- if (val) {
- if ( uiDoBlocks(&curarea->uiblocks, event, 1)!=UI_NOTHING ) event= 0;
-
- /* swap mouse buttons based on user preference */
- if (U.flag & USER_LMOUSESELECT) {
- if (event == LEFTMOUSE) {
- event = RIGHTMOUSE;
- mousebut = L_MOUSE;
- }
- else if (event == RIGHTMOUSE) {
- event = LEFTMOUSE;
- mousebut = R_MOUSE;
- }
- }
-
- getmouseco_areawin(mval);
-
- switch(event) {
- case UI_BUT_EVENT:
- do_actionbuts(val); /* window itself */
- break;
-
- /* LEFTMOUSE and RIGHTMOUSE event codes can be swapped above,
- * based on user preference USER_LMOUSESELECT
- */
- case LEFTMOUSE:
- if (view2dmove(LEFTMOUSE)) /* only checks for sliders */
- break;
- else if ((G.v2d->mask.xmin==0) || (mval[0] > ACTWIDTH)) {
- /* moving time-marker / current frame */
- do {
- getmouseco_areawin(mval);
- areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
-
- cfra= (int)(dx+0.5f);
- if (cfra < 1) cfra= 1;
-
- if (cfra != CFRA) {
- CFRA= cfra;
- update_for_newframe();
- force_draw_all(0);
- }
- else
- PIL_sleep_ms(30);
- }
- while(get_mbut() & mousebut);
- break;
- }
- /* passed on as selection */
- case RIGHTMOUSE:
- /* Clicking in the channel area */
- if ((G.v2d->mask.xmin) && (mval[0] < NAMEWIDTH)) {
- if (ELEM(datatype, ACTCONT_ACTION, ACTCONT_GPENCIL)) {
- /* mouse is over action channels */
- if (G.qual == LR_CTRLKEY)
- numbuts_action();
- else
- mouse_actionchannels(mval);
- }
- else
- numbuts_action();
- }
- else {
- short select_mode= (G.qual & LR_SHIFTKEY)? SELECT_INVERT: SELECT_REPLACE;
-
- /* Clicking in the vertical scrollbar selects
- * all of the keys for that channel at that height
- */
- if (IN_2D_VERT_SCROLL(mval))
- selectall_action_keys(mval, 0, select_mode);
-
- /* Clicking in the horizontal scrollbar selects
- * all of the keys within 0.5 of the nearest integer
- * frame
- */
- else if (IN_2D_HORIZ_SCROLL(mval))
- selectall_action_keys(mval, 1, select_mode);
-
- /* Clicking in the main area of the action window
- * selects keys and markers
- */
- else if (G.qual & LR_ALTKEY) {
- areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
-
- /* sends a 1 for left and 0 for right */
- selectkeys_leftright((dx < (float)CFRA), select_mode);
- }
- else
- mouse_action(select_mode);
- }
- break;
-
- case MIDDLEMOUSE:
- case WHEELUPMOUSE:
- case WHEELDOWNMOUSE:
- view2dmove(event); /* in drawipo.c */
- break;
-
- case AKEY:
- if (mval[0] < NAMEWIDTH) {
- deselect_action_channels(1);
- BIF_undo_push("(De)Select Action Channels");
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWIPO, 0);
- }
- else if (mval[0] > ACTWIDTH) {
- if (G.qual == LR_CTRLKEY) {
- deselect_markers(1, 0);
- BIF_undo_push("(De)Select Markers");
- allqueue(REDRAWTIME, 0);
- allqueue(REDRAWIPO, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWSOUND, 0);
- }
- else {
- deselect_action_keys(1, 1);
- BIF_undo_push("(De)Select Keys");
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWIPO, 0);
- }
- }
- break;
-
- case BKEY:
- if (G.qual & LR_CTRLKEY) {
- borderselect_markers();
- }
- else {
- if (mval[0] <= ACTWIDTH)
- borderselect_actionchannels();
- else
- borderselect_action();
- }
- break;
-
- case CKEY:
- /* scroll the window so the current
- * frame is in the center.
- */
- center_currframe();
- break;
-
- case DKEY:
- if (mval[0] > ACTWIDTH) {
- if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY))
- duplicate_marker();
- else if (G.qual == LR_SHIFTKEY)
- duplicate_action_keys();
- }
- break;
-
- case EKEY:
- if (mval[0] >= ACTWIDTH)
- transform_action_keys('e', 0);
- break;
-
- case GKEY:
- /* Action Channel Groups */
- if (G.qual == LR_SHIFTKEY)
- action_groups_group(0);
- else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY))
- action_groups_group(1);
- else if (G.qual == LR_ALTKEY)
- action_groups_ungroup();
-
- /* Transforms */
- else {
- if (mval[0] >= ACTWIDTH) {
- if (G.qual == LR_CTRLKEY)
- transform_markers('g', 0);
- else
- transform_action_keys('g', 0);
- }
- }
- break;
-
- case HKEY:
- if (G.qual & LR_SHIFTKEY) {
- if (okee("Set Keys to Auto Handle"))
- sethandles_action_keys(HD_AUTO);
- }
- else {
- if (okee("Toggle Keys Aligned Handle"))
- sethandles_action_keys(HD_ALIGN);
- }
- break;
-
- case IKEY:
- if (G.qual & LR_CTRLKEY) {
- if (mval[0] < ACTWIDTH) {
- deselect_action_channels(2);
- BIF_undo_push("Inverse Action Channels");
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWIPO, 0);
- }
- else if (G.qual & LR_SHIFTKEY) {
- deselect_markers(0, 2);
- BIF_undo_push("Inverse Markers");
- allqueue(REDRAWMARKER, 0);
- }
- else {
- deselect_action_keys(0, 2);
- BIF_undo_push("Inverse Keys");
- allqueue(REDRAWACTION, 0);
- allqueue(REDRAWNLA, 0);
- allqueue(REDRAWIPO, 0);
- }
- }
- break;
-
- case KKEY:
- if (G.qual == LR_ALTKEY)
- markers_selectkeys_between();
- else if (G.qual == LR_SHIFTKEY)
- column_select_action_keys(2);
- else if (G.qual == LR_CTRLKEY)
- column_select_action_keys(3);
- else
- column_select_action_keys(1);
-
- allqueue(REDRAWMARKER, 0);
- break;
-
- case LKEY:
- /* poselib manipulation - only for actions */
- if (datatype == ACTCONT_ACTION) {
- if (G.qual == LR_SHIFTKEY)
- action_add_localmarker(data, CFRA);
- else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY))
- action_rename_localmarker(data);
- else if (G.qual == LR_ALTKEY)
- action_remove_localmarkers(data);
- else if (G.qual == LR_CTRLKEY) {
- G.saction->flag |= SACTION_POSEMARKERS_MOVE;
- transform_markers('g', 0);
- G.saction->flag &= ~SACTION_POSEMARKERS_MOVE;
- }
- }
- break;
-
- case MKEY:
- if (G.qual & LR_SHIFTKEY) {
- /* mirror keyframes */
- if (data) {
- if (G.saction->flag & SACTION_DRAWTIME)
- val = pupmenu("Mirror Keys Over%t|Current Time%x1|Vertical Axis%x2|Horizontal Axis %x3|Selected Marker %x4");
- else
- val = pupmenu("Mirror Keys Over%t|Current Frame%x1|Vertical Axis%x2|Horizontal Axis %x3|Selected Marker %x4");
-
- mirror_action_keys(val);
- }
- }
- else {
- /* marker operations */
- if (G.qual == 0)
- add_marker(CFRA);
- else if (G.qual == LR_CTRLKEY)
- rename_marker();
- else
- break;
- allqueue(REDRAWMARKER, 0);
- }
- break;
-
- case NKEY:
- if (G.qual==0) {
- /* panel will not always show useful info! */
- if (mval[0] > ACTWIDTH) {
- add_blockhandler(curarea, ACTION_HANDLER_PROPERTIES, UI_PNL_TO_MOUSE);
- scrarea_queue_winredraw(curarea);
- }
- else
- numbuts_action();
- }
- break;
-
- case OKEY:
- if (G.qual & LR_ALTKEY)
- sample_action_keys();
- else
- clean_action();
- break;
-
- case PKEY:
- if (G.qual == (LR_CTRLKEY|LR_ALTKEY)) /* set preview range to range of action */
- action_previewrange_set(G.saction->action);
- else if (G.qual & LR_CTRLKEY) /* set preview range */
- anim_previewrange_set();
- else if (G.qual & LR_ALTKEY) /* clear preview range */
- anim_previewrange_clear();
-
- allqueue(REDRAWMARKER, 0);
- allqueue(REDRAWBUTSALL, 0);
- break;
-
- case SKEY:
- if (mval[0]>=ACTWIDTH) {
- if (G.qual == (LR_SHIFTKEY|LR_CTRLKEY)) {
- if (data) {
- snap_cfra_action();
- }
- }
- else if (G.qual & LR_SHIFTKEY) {
- if (data) {
- if (G.saction->flag & SACTION_DRAWTIME)
- val = pupmenu("Snap Keys To%t|Nearest Second%x4|Current Time%x2|Nearest Marker %x3");
- else
- val = pupmenu("Snap Keys To%t|Nearest Frame%x1|Current Frame%x2|Nearest Marker %x3");
-
- snap_action_keys(val);
- }
- }
- else {
- transform_action_keys('s', 0);
- }
- }
- break;
-
- case TKEY:
- if (G.qual & LR_SHIFTKEY)
- action_set_ipo_flags(SET_IPO_POPUP, 0);
- else if (G.qual & LR_CTRLKEY) {
- val= pupmenu("Time value%t|Frames %x1|Seconds%x2");
-
- if (val > 0) {
- if (val == 2) saction->flag |= SACTION_DRAWTIME;
- else saction->flag &= ~SACTION_DRAWTIME;
-
- doredraw= 1;
- }
- }
- else
- transform_action_keys ('t', 0);
- break;
-
- case VKEY:
- if (okee("Set Keys to Vector Handle"))
- sethandles_action_keys(HD_VECT);
- break;
-
- case WKEY:
- /* toggle/turn-on\off-based-on-setting */
- if (G.qual) {
- if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY))
- val= 1;
- else if (G.qual == LR_ALTKEY)
- val= 2;
- else
- val= 0;
-
- setflag_action_channels(val);
- }
- break;
-
- case PAGEUPKEY:
- if (datatype == ACTCONT_ACTION) {
- if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY))
- rearrange_action_channels(REARRANGE_ACTCHAN_TOP);
- else if (G.qual == LR_SHIFTKEY)
- rearrange_action_channels(REARRANGE_ACTCHAN_UP);
- else if (G.qual == LR_CTRLKEY)
- nextprev_action_keyframe(1);
- else
- nextprev_marker(1);
- }
- else if (datatype == ACTCONT_SHAPEKEY) {
- /* only jump to markers possible (key channels can't be moved yet) */
- if (G.qual == LR_CTRLKEY)
- nextprev_action_keyframe(1);
- else
- nextprev_marker(1);
- }
- break;
- case PAGEDOWNKEY:
- if (datatype == ACTCONT_ACTION) {
- if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY))
- rearrange_action_channels(REARRANGE_ACTCHAN_BOTTOM);
- else if (G.qual == LR_SHIFTKEY)
- rearrange_action_channels(REARRANGE_ACTCHAN_DOWN);
- else if (G.qual == LR_CTRLKEY)
- nextprev_action_keyframe(-1);
- else
- nextprev_marker(-1);
- }
- else if (datatype == ACTCONT_SHAPEKEY) {
- /* only jump to markers possible (key channels can't be moved yet) */
- if (G.qual == LR_CTRLKEY)
- nextprev_action_keyframe(-1);
- else
- nextprev_marker(-1);
- }
- break;
-
- case DELKEY:
- case XKEY:
- /* markers are incorported under shift-modifier (it does go against conventions, but oh well :/) */
- if (G.qual == LR_SHIFTKEY) {
- if (okee("Erase selected marker(s)?")) {
- if (mval[0] >= NAMEWIDTH)
- remove_marker();
- }
- }
- else {
- if (okee("Erase selected?")) {
- if (mval[0] < NAMEWIDTH) {
- if (datatype == ACTCONT_ACTION)
- delete_action_channels();
- else if (datatype == ACTCONT_GPENCIL)
- delete_gpencil_layers();
- }
- else
- delete_action_keys();
- }
- }
-
- allqueue(REDRAWMARKER, 0);
-
- break;
-
- case ACCENTGRAVEKEY:
- if (datatype == ACTCONT_ACTION) {
- if (G.qual == LR_SHIFTKEY)
- expand_obscuregroups_action();
- else
- expand_all_action();
- }
- break;
-
- case PADPLUSKEY:
- if (G.qual == LR_CTRLKEY) {
- if (datatype == ACTCONT_ACTION)
- openclose_level_action(1);
- }
- else {
- view2d_zoom(G.v2d, 0.1154f, sa->winx, sa->winy);
- test_view2d(G.v2d, sa->winx, sa->winy);
- view2d_do_locks(curarea, V2D_LOCK_COPY);
-
- doredraw= 1;
- }
- break;
- case PADMINUS:
- if (G.qual == LR_CTRLKEY) {
- if (datatype == ACTCONT_ACTION)
- openclose_level_action(-1);
- }
- else {
- view2d_zoom(G.v2d, -0.15f, sa->winx, sa->winy);
- test_view2d(G.v2d, sa->winx, sa->winy);
- view2d_do_locks(curarea, V2D_LOCK_COPY);
-
- doredraw= 1;
- }
- break;
-
- case HOMEKEY:
- do_action_buttons(B_ACTHOME); /* header */
- break;
- }
- }
-
- if (doredraw) addqueue(curarea->win, REDRAW, 1);
-}
-
-/* **************************************************** */