== Action Editor - Groups for Action Channels (Peach Request) ==

Now, you can assign Action Channels to named (folder-like) groups, which help to organise the channels (important for more complex rigs). These are collapsible, can be "protected", and show a "summary" of the keyframes in the channels the Group contains. They are drawn as bright-green (active) or a darker shade of green (not active) channels.

* Each Action has its own set of Groups. 
* An Action-Channel can only occur in one Group at a time. It can also not occur in any group.
* Action-Channels can be moved between Groups
* Groups + grouped-channels always occur BEFORE un-grouped channels

Important Hotkeys:
* Shift-G  :  Adds the selected Action-Channels to the Active Group. This will create a new group if need be
* Ctrl-Shift-G : Always adds a new group, and adds the selected Action-Channels to it
* Alt-G : Removes selected Action-Channels from their groups
* Ctrl-Shift-Alt-G : (Note: this will be removed soon) This is a simple debugging-hotkey I added, which just prints a list of the groups, channels, and their addresses...
* NKey / Ctrl-LMB: While hovering over the name of a group, this shows a popup like for other channels, which allows the editing of the channel's name, etc.


Assorted Notes:
* Some tools may not work yet with this (Ctrl Numpad+/- for example)
* Fixed some bugs in various places in Action Editor code
* Added theme colours for group channels
* The nomenclature of these tools may change in future when a better alternative is found
* The ability to auto-assign action-channels to groups when they are keyframed will be coming up shortly
This commit is contained in:
2008-01-17 23:02:11 +00:00
parent 65d61c2cb6
commit 44c31bb045
13 changed files with 1204 additions and 292 deletions

View File

@@ -44,7 +44,7 @@ struct ListBase;
struct MemFile; struct MemFile;
#define BLENDER_VERSION 245 #define BLENDER_VERSION 245
#define BLENDER_SUBVERSION 12 #define BLENDER_SUBVERSION 13
#define BLENDER_MINVERSION 240 #define BLENDER_MINVERSION 240
#define BLENDER_MINSUBVERSION 0 #define BLENDER_MINSUBVERSION 0

View File

@@ -178,7 +178,11 @@ void free_action (bAction *act)
if (act->chanbase.first) if (act->chanbase.first)
BLI_freelistN(&act->chanbase); BLI_freelistN(&act->chanbase);
/* Free pose-references */ /* Free groups */
if (act->groups.first)
BLI_freelistN(&act->groups);
/* Free pose-references (aka local markers) */
if (act->markers.first) if (act->markers.first)
BLI_freelistN(&act->markers); BLI_freelistN(&act->markers);
} }
@@ -187,19 +191,37 @@ bAction *copy_action (bAction *src)
{ {
bAction *dst = NULL; bAction *dst = NULL;
bActionChannel *dchan, *schan; bActionChannel *dchan, *schan;
bActionGroup *dgrp, *sgrp;
if (!src) return NULL; if (!src) return NULL;
dst= copy_libblock(src); dst= copy_libblock(src);
duplicatelist(&(dst->chanbase), &(src->chanbase)); duplicatelist(&(dst->chanbase), &(src->chanbase));
duplicatelist(&(dst->groups), &(src->groups));
duplicatelist(&(dst->markers), &(src->markers)); duplicatelist(&(dst->markers), &(src->markers));
for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){ for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next) {
for (dgrp=dst->groups.first, sgrp=src->groups.first; dgrp && sgrp; dgrp=dgrp->next, sgrp=sgrp->next) {
if (dchan->grp == sgrp) {
dchan->grp= dgrp;
if (dgrp->channels.first == schan)
dgrp->channels.first= dchan;
if (dgrp->channels.last == schan)
dgrp->channels.last= dchan;
break;
}
}
dchan->ipo = copy_ipo(dchan->ipo); dchan->ipo = copy_ipo(dchan->ipo);
copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels); copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
} }
dst->id.flag |= LIB_FAKEUSER; dst->id.flag |= LIB_FAKEUSER;
dst->id.us++; dst->id.us++;
return dst; return dst;
} }

View File

@@ -1859,12 +1859,24 @@ static void direct_link_bones(FileData *fd, Bone* bone)
static void direct_link_action(FileData *fd, bAction *act) static void direct_link_action(FileData *fd, bAction *act)
{ {
bActionChannel *achan; bActionChannel *achan;
bActionGroup *agrp;
link_list(fd, &act->chanbase); link_list(fd, &act->chanbase);
link_list(fd, &act->groups);
link_list(fd, &act->markers); link_list(fd, &act->markers);
for (achan = act->chanbase.first; achan; achan=achan->next) for (achan = act->chanbase.first; achan; achan=achan->next) {
achan->grp= newdataadr(fd, achan->grp);
link_list(fd, &achan->constraintChannels); link_list(fd, &achan->constraintChannels);
}
for (agrp = act->groups.first; agrp; agrp= agrp->next) {
if (agrp->channels.first) {
agrp->channels.first= newdataadr(fd, agrp->channels.first);
agrp->channels.last= newdataadr(fd, agrp->channels.last);
}
}
} }
static void direct_link_armature(FileData *fd, bArmature *arm) static void direct_link_armature(FileData *fd, bArmature *arm)

View File

@@ -1750,6 +1750,7 @@ static void write_actions(WriteData *wd, ListBase *idbase)
{ {
bAction *act; bAction *act;
bActionChannel *chan; bActionChannel *chan;
bActionGroup *grp;
TimeMarker *marker; TimeMarker *marker;
for(act=idbase->first; act; act= act->id.next) { for(act=idbase->first; act; act= act->id.next) {
@@ -1762,6 +1763,10 @@ static void write_actions(WriteData *wd, ListBase *idbase)
write_constraint_channels(wd, &chan->constraintChannels); write_constraint_channels(wd, &chan->constraintChannels);
} }
for (grp=act->groups.first; grp; grp=grp->next) {
writestruct(wd, DATA, "bActionGroup", 1, grp);
}
for (marker=act->markers.first; marker; marker=marker->next) { for (marker=act->markers.first; marker; marker=marker->next) {
writestruct(wd, DATA, "TimeMarker", 1, marker); writestruct(wd, DATA, "TimeMarker", 1, marker);
} }

View File

@@ -38,6 +38,7 @@ struct Ipo;
struct IpoCurve; struct IpoCurve;
struct gla2DDrawInfo; struct gla2DDrawInfo;
struct bAction; struct bAction;
struct bActionGroup;
struct Object; struct Object;
struct ListBase; struct ListBase;
@@ -75,14 +76,16 @@ void draw_cfra_action(void);
/* Channel Drawing */ /* Channel Drawing */
void draw_icu_channel(struct gla2DDrawInfo *di, struct IpoCurve *icu, float ypos); void draw_icu_channel(struct gla2DDrawInfo *di, struct IpoCurve *icu, float ypos);
void draw_ipo_channel(struct gla2DDrawInfo *di, struct Ipo *ipo, float ypos); void draw_ipo_channel(struct gla2DDrawInfo *di, struct Ipo *ipo, float ypos);
void draw_action_channel(struct gla2DDrawInfo *di, bAction *act, float ypos); void draw_agroup_channel(struct gla2DDrawInfo *di, struct bActionGroup *agrp, float ypos);
void draw_object_channel(struct gla2DDrawInfo *di, Object *ob, float ypos); void draw_action_channel(struct gla2DDrawInfo *di, struct bAction *act, float ypos);
void draw_object_channel(struct gla2DDrawInfo *di, struct Object *ob, float ypos);
/* Keydata Generation */ /* Keydata Generation */
void icu_to_keylist(struct IpoCurve *icu, ListBase *keys, ListBase *blocks); void icu_to_keylist(struct IpoCurve *icu, ListBase *keys, ListBase *blocks);
void ipo_to_keylist(struct Ipo *ipo, ListBase *keys, ListBase *blocks); void ipo_to_keylist(struct Ipo *ipo, ListBase *keys, ListBase *blocks);
void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks); void agroup_to_keylist(struct bActionGroup *agrp, ListBase *keys, ListBase *blocks);
void ob_to_keylist(Object *ob, ListBase *keys, ListBase *blocks); void action_to_keylist(struct bAction *act, ListBase *keys, ListBase *blocks);
void ob_to_keylist(struct Object *ob, ListBase *keys, ListBase *blocks);
#endif /* BDR_DRAWACTION_H */ #endif /* BDR_DRAWACTION_H */

View File

@@ -43,6 +43,7 @@
/* Some types for easier type-testing */ /* Some types for easier type-testing */
enum { enum {
ACTTYPE_NONE= 0, ACTTYPE_NONE= 0,
ACTTYPE_GROUP,
ACTTYPE_ACHAN, ACTTYPE_ACHAN,
ACTTYPE_CONCHAN, ACTTYPE_CONCHAN,
ACTTYPE_ICU, ACTTYPE_ICU,
@@ -53,6 +54,10 @@ enum {
}; };
/* Macros for easier/more consistant state testing */ /* Macros for easier/more consistant state testing */
#define EDITABLE_AGRP(agrp) ((agrp->flag & AGRP_PROTECTED)==0)
#define EXPANDED_AGRP(agrp) (agrp->flag & AGRP_EXPANDED)
#define SEL_AGRP(agrp) ((agrp->flag & AGRP_SELECTED) || (agrp->flag & AGRP_ACTIVE))
#define VISIBLE_ACHAN(achan) ((achan->flag & ACHAN_HIDDEN)==0) #define VISIBLE_ACHAN(achan) ((achan->flag & ACHAN_HIDDEN)==0)
#define EDITABLE_ACHAN(achan) ((VISIBLE_ACHAN(achan)) && ((achan->flag & ACHAN_PROTECTED)==0)) #define EDITABLE_ACHAN(achan) ((VISIBLE_ACHAN(achan)) && ((achan->flag & ACHAN_PROTECTED)==0))
#define EXPANDED_ACHAN(achan) ((VISIBLE_ACHAN(achan)) && (achan->flag & ACHAN_EXPANDED)) #define EXPANDED_ACHAN(achan) ((VISIBLE_ACHAN(achan)) && (achan->flag & ACHAN_EXPANDED))
@@ -81,7 +86,6 @@ enum {
/* constants for setting ipo-extrapolation type */ /* constants for setting ipo-extrapolation type */
enum { enum {
SET_EXTEND_MENU = 9, SET_EXTEND_MENU = 9,
SET_EXTEND_POPUP = 10, SET_EXTEND_POPUP = 10,
@@ -91,9 +95,19 @@ enum {
SET_EXTEND_CYCLICEXTRAPOLATION SET_EXTEND_CYCLICEXTRAPOLATION
}; };
/* constants for channel rearranging */
/* WARNING: don't change exising ones without modifying rearrange func accordingly */
enum {
REARRANGE_ACTCHAN_TOP= -2,
REARRANGE_ACTCHAN_UP= -1,
REARRANGE_ACTCHAN_DOWN= 1,
REARRANGE_ACTCHAN_BOTTOM= 2
};
struct bAction; struct bAction;
struct bActionChannel; struct bActionChannel;
struct bActionGroup;
struct bPoseChannel; struct bPoseChannel;
struct Object; struct Object;
struct Ipo; struct Ipo;
@@ -125,11 +139,14 @@ void free_actcopybuf(void);
void copy_actdata(void); void copy_actdata(void);
void paste_actdata(void); void paste_actdata(void);
/* Channel/strip operations */ /* Group/Channel Operations */
void up_sel_action(void); struct bActionGroup *get_active_actiongroup(struct bAction *act);
void down_sel_action(void); void set_active_actiongroup(struct bAction *act, struct bActionGroup *agrp, short select);
void top_sel_action(void); void action_groups_group(short add_group);
void bottom_sel_action(void); void action_groups_ungroup(void);
/* Channel/Strip Operations */
void rearrange_action_channels(short mode);
void expand_all_action(void); void expand_all_action(void);
void openclose_level_action(short mode); void openclose_level_action(short mode);

View File

@@ -37,9 +37,12 @@
/* FILTERED ACTION DATA - TYPES */ /* FILTERED ACTION DATA - TYPES */
/* types of keyframe data in ActListElem */ /* types of keyframe data in ActListElem */
#define ALE_NONE 0 typedef enum ALE_KEYTYPE {
#define ALE_IPO 1 ALE_NONE = 0,
#define ALE_ICU 2 ALE_IPO,
ALE_ICU,
ALE_GROUP
} ALE_KEYTYPE;
/* This struct defines a structure used for quick access */ /* This struct defines a structure used for quick access */
typedef struct bActListElem { typedef struct bActListElem {
@@ -53,6 +56,8 @@ typedef struct bActListElem {
void *key_data; /* motion data - ipo or ipo-curve */ void *key_data; /* motion data - ipo or ipo-curve */
short datatype; /* type of motion data to expect */ short datatype; /* type of motion data to expect */
struct bActionGroup *grp; /* action group that owns the channel */
void *owner; /* will either be an action channel or fake ipo-channel (for keys) */ void *owner; /* will either be an action channel or fake ipo-channel (for keys) */
short ownertype; /* type of owner */ short ownertype; /* type of owner */
} bActListElem; } bActListElem;
@@ -61,17 +66,21 @@ typedef struct bActListElem {
/* FILTER ACTION DATA - METHODS/TYPES */ /* FILTER ACTION DATA - METHODS/TYPES */
/* filtering flags - under what circumstances should a channel be added */ /* filtering flags - under what circumstances should a channel be added */
#define ACTFILTER_VISIBLE 0x001 /* should channels be visible */ typedef enum ACTFILTER_FLAGS {
#define ACTFILTER_SEL 0x002 /* should channels be selected */ ACTFILTER_VISIBLE = (1<<0), /* should channels be visible */
#define ACTFILTER_FOREDIT 0x004 /* does editable status matter */ ACTFILTER_SEL = (1<<1), /* should channels be selected */
#define ACTFILTER_CHANNELS 0x008 /* do we only care that it is a channel */ ACTFILTER_FOREDIT = (1<<2), /* does editable status matter */
#define ACTFILTER_IPOKEYS 0x010 /* only channels referencing ipo's */ ACTFILTER_CHANNELS = (1<<3), /* do we only care that it is a channel */
#define ACTFILTER_ONLYICU 0x020 /* only reference ipo-curves */ ACTFILTER_IPOKEYS = (1<<4), /* only channels referencing ipo's */
#define ACTFILTER_FORDRAWING 0x040 /* make list for interface drawing */ ACTFILTER_ONLYICU = (1<<5), /* only reference ipo-curves */
ACTFILTER_FORDRAWING = (1<<6) /* make list for interface drawing */
} ACTFILTER_FLAGS;
/* Action Editor - Main Data types */ /* Action Editor - Main Data types */
#define ACTCONT_NONE 0 typedef enum ACTCONT_TYPES {
#define ACTCONT_ACTION 1 ACTCONT_NONE = 0,
#define ACTCONT_SHAPEKEY 2 ACTCONT_ACTION,
ACTCONT_SHAPEKEY
} ACTCONT_TYPES;
#endif #endif

View File

@@ -37,6 +37,8 @@
struct SpaceLink; struct SpaceLink;
struct Object; struct Object;
/* -------------- Poses ----------------- */
/* PoseChannel stores the results of Actions (ipos) and transform information /* PoseChannel stores the results of Actions (ipos) and transform information
with respect to the restposition of Armature bones */ with respect to the restposition of Armature bones */
typedef struct bPoseChannel { typedef struct bPoseChannel {
@@ -98,11 +100,37 @@ typedef struct bPose {
float cyclic_offset[3]; /* result of match and cycles, applied in where_is_pose() */ float cyclic_offset[3]; /* result of match and cycles, applied in where_is_pose() */
} bPose; } bPose;
/* ------------- Action ---------------- */
/* Action-Channel Group. These are stored as a list per-Action, and are only used to
* group that Action's Action-Channels when displayed in the Action Editor.
*
* Even though all Action-Channels live in a big list per Action, each group they are in also
* holds references to the achans within that list which belong to it. Care must be taken to
* ensure that action-groups never end up being the sole 'owner' of a channel.
*/
typedef struct bActionGroup {
struct bActionGroup *next, *prev;
int flag; /* settings for this action-group */
int pad;
char name[32]; /* name of the group */
ListBase channels; /* Note: this must not be touched by standard listbase functions */
} bActionGroup;
/* Action Channels belong to Actions. They are linked with an IPO block, and can also own /* Action Channels belong to Actions. They are linked with an IPO block, and can also own
* Constraint Channels in certain situations. * Constraint Channels in certain situations.
*
* Action-Channels can only belong to one group at a time, but they still live the Action's
* list of achans (to preserve backwards compatability, and also minimise the code
* that would need to be recoded). Grouped achans are stored at the start of the list, according
* to the position of the group in the list, and their position within the group.
*/ */
typedef struct bActionChannel { typedef struct bActionChannel {
struct bActionChannel *next, *prev; struct bActionChannel *next, *prev;
bActionGroup *grp; /* Action Group this Action Channel belongs to */
struct Ipo *ipo; /* IPO block this action channel references */ struct Ipo *ipo; /* IPO block this action channel references */
ListBase constraintChannels; /* Constraint Channels (when Action Channel represents an Object or Bone) */ ListBase constraintChannels; /* Constraint Channels (when Action Channel represents an Object or Bone) */
@@ -119,12 +147,16 @@ typedef struct bAction {
ID id; ID id;
ListBase chanbase; /* Action Channels in this Action */ ListBase chanbase; /* Action Channels in this Action */
ListBase groups; /* Action Groups in the Action */
ListBase markers; /* TimeMarkers local to this Action for labelling 'poses' */ ListBase markers; /* TimeMarkers local to this Action for labelling 'poses' */
int active_marker; /* Index of active-marker (first marker = 1) */ int active_marker; /* Index of active-marker (first marker = 1) */
int pad; int pad;
} bAction; } bAction;
/* ------------- Action Editor --------------------- */
/* Action Editor Space. This is defined here instead of in DNA_space_types.h */ /* Action Editor Space. This is defined here instead of in DNA_space_types.h */
typedef struct SpaceAction { typedef struct SpaceAction {
struct SpaceLink *next, *prev; struct SpaceLink *next, *prev;
@@ -143,6 +175,9 @@ typedef struct SpaceAction {
float timeslide; /* for Time-Slide transform mode drawing - current frame? */ float timeslide; /* for Time-Slide transform mode drawing - current frame? */
} SpaceAction; } SpaceAction;
/* -------------- Action Flags -------------- */
/* Action Channel flags */ /* Action Channel flags */
typedef enum ACHAN_FLAG { typedef enum ACHAN_FLAG {
ACHAN_SELECTED = (1<<0), ACHAN_SELECTED = (1<<0),
@@ -155,6 +190,19 @@ typedef enum ACHAN_FLAG {
ACHAN_MOVED = (1<<31), ACHAN_MOVED = (1<<31),
} ACHAN_FLAG; } ACHAN_FLAG;
/* Action Group flags */
typedef enum AGRP_FLAG {
AGRP_SELECTED = (1<<0),
AGRP_ACTIVE = (1<<1),
AGRP_PROTECTED = (1<<2),
AGRP_EXPANDED = (1<<3),
AGRP_TEMP = (1<<30),
AGRP_MOVED = (1<<31)
} AGRP_FLAG;
/* ------------ Action Editor Flags -------------- */
/* SpaceAction flag */ /* SpaceAction flag */
typedef enum SACTION_FLAG { typedef enum SACTION_FLAG {
/* during transform */ /* during transform */
@@ -178,6 +226,9 @@ typedef enum SACTSNAP_MODES {
/* snap to nearest marker */ /* snap to nearest marker */
SACTSNAP_MARKER, SACTSNAP_MARKER,
} SACTSNAP_MODES; } SACTSNAP_MODES;
/* --------- Pose Flags --------------- */
/* Pose->flag */ /* Pose->flag */
typedef enum POSE_FLAG { typedef enum POSE_FLAG {

View File

@@ -94,6 +94,7 @@
/* 'old' stuff": defines and types, and own include -------------------- */ /* 'old' stuff": defines and types, and own include -------------------- */
#include "blendef.h" #include "blendef.h"
#include "interface.h"
#include "mydevice.h" #include "mydevice.h"
/********************************** Slider Stuff **************************** */ /********************************** Slider Stuff **************************** */
@@ -406,7 +407,7 @@ static void draw_channel_names(void)
if (data == NULL) return; if (data == NULL) return;
/* Clip to the scrollable area */ /* Clip to the scrollable area */
if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) { if (curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
if(G.v2d->scroll) { if(G.v2d->scroll) {
ofsx= curarea->winrct.xmin; ofsx= curarea->winrct.xmin;
ofsy= curarea->winrct.ymin; ofsy= curarea->winrct.ymin;
@@ -434,16 +435,39 @@ static void draw_channel_names(void)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (ale= act_data.first; ale; ale= ale->next) { for (ale= act_data.first; ale; ale= ale->next) {
short indent= 0, offset= 0, sel= 0; short indent= 0, offset= 0, sel= 0, group=0;
int expand= -1, protect = -1, special= -1, mute = -1; int expand= -1, protect = -1, special= -1, mute = -1;
char name[32]; char name[32];
/* determine what needs to be drawn */ /* determine what needs to be drawn */
switch (ale->type) { switch (ale->type) {
case ACTTYPE_GROUP: /* action group */
{
bActionGroup *agrp= (bActionGroup *)ale->data;
group= 2;
indent= 0;
special= -1;
if (EXPANDED_AGRP(agrp))
expand = ICON_TRIA_DOWN;
else
expand = ICON_TRIA_RIGHT;
if (EDITABLE_AGRP(agrp))
protect = ICON_UNLOCKED;
else
protect = ICON_LOCKED;
sel = SEL_AGRP(agrp);
sprintf(name, agrp->name);
}
break;
case ACTTYPE_ACHAN: /* action channel */ case ACTTYPE_ACHAN: /* action channel */
{ {
bActionChannel *achan= (bActionChannel *)ale->data; bActionChannel *achan= (bActionChannel *)ale->data;
group= (ale->grp) ? 1 : 0;
indent = 0; indent = 0;
special = -1; special = -1;
@@ -473,6 +497,7 @@ static void draw_channel_names(void)
bConstraintChannel *conchan = (bConstraintChannel *)ale->data; bConstraintChannel *conchan = (bConstraintChannel *)ale->data;
indent = 2; indent = 2;
group= (ale->grp) ? 1 : 0;
if (EDITABLE_CONCHAN(conchan)) if (EDITABLE_CONCHAN(conchan))
protect = ICON_UNLOCKED; protect = ICON_UNLOCKED;
@@ -496,6 +521,7 @@ static void draw_channel_names(void)
indent = 2; indent = 2;
protect = -1; // for now, until this can be supported by others protect = -1; // for now, until this can be supported by others
group= (ale->grp) ? 1 : 0;
if (icu->flag & IPO_MUTE) if (icu->flag & IPO_MUTE)
mute = ICON_MUTE_IPO_ON; mute = ICON_MUTE_IPO_ON;
@@ -528,6 +554,7 @@ static void draw_channel_names(void)
indent = 1; indent = 1;
special = geticon_ipo_blocktype(achan->ipo->blocktype); special = geticon_ipo_blocktype(achan->ipo->blocktype);
group= (ale->grp) ? 1 : 0;
if (FILTER_IPO_ACHAN(achan)) if (FILTER_IPO_ACHAN(achan))
expand = ICON_TRIA_DOWN; expand = ICON_TRIA_DOWN;
@@ -544,6 +571,7 @@ static void draw_channel_names(void)
indent = 1; indent = 1;
special = ICON_CONSTRAINT; special = ICON_CONSTRAINT;
group= (ale->grp) ? 1 : 0;
if (FILTER_CON_ACHAN(achan)) if (FILTER_CON_ACHAN(achan))
expand = ICON_TRIA_DOWN; expand = ICON_TRIA_DOWN;
@@ -558,9 +586,24 @@ static void draw_channel_names(void)
/* now, start drawing based on this information */ /* now, start drawing based on this information */
/* draw backing strip behind channel name */ /* draw backing strip behind channel name */
BIF_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40)); if (group == 2) {
offset = 7 * indent; /* only for group-channels */
glRectf(x+offset, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2); if (ale->flag & AGRP_ACTIVE)
BIF_ThemeColorShade(TH_GROUP_ACTIVE, 10);
else
BIF_ThemeColorShade(TH_GROUP, 20);
uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
gl_round_box(GL_POLYGON, x, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2, 8);
offset = 0;
}
else {
/* for normal channels */
BIF_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
indent += group;
offset = 7 * indent;
glRectf(x+offset, y-CHANNELHEIGHT/2, (float)NAMEWIDTH, y+CHANNELHEIGHT/2);
}
/* draw expand/collapse triangle */ /* draw expand/collapse triangle */
if (expand > 0) { if (expand > 0) {
@@ -572,7 +615,7 @@ static void draw_channel_names(void)
* only for expand widgets for Ipo and Constraint Channels * only for expand widgets for Ipo and Constraint Channels
*/ */
if (special > 0) { if (special > 0) {
offset = 24; offset = (group) ? 29 : 24;
BIF_icon_draw(x+offset, y-CHANNELHEIGHT/2, special); BIF_icon_draw(x+offset, y-CHANNELHEIGHT/2, special);
offset += 17; offset += 17;
} }
@@ -694,6 +737,12 @@ static void draw_channel_strips(void)
if (ale->datatype != ALE_NONE) { if (ale->datatype != ALE_NONE) {
/* determine if channel is selected */ /* determine if channel is selected */
switch (ale->type) { switch (ale->type) {
case ACTTYPE_GROUP:
{
bActionGroup *agrp = (bActionGroup *)ale->data;
sel = SEL_AGRP(agrp);
}
break;
case ACTTYPE_ACHAN: case ACTTYPE_ACHAN:
{ {
bActionChannel *achan = (bActionChannel *)ale->data; bActionChannel *achan = (bActionChannel *)ale->data;
@@ -752,6 +801,9 @@ static void draw_channel_strips(void)
y = 0.0; y = 0.0;
for (ale= act_data.first; ale; ale= ale->next) { for (ale= act_data.first; ale; ale= ale->next) {
switch (ale->datatype) { switch (ale->datatype) {
case ALE_GROUP:
draw_agroup_channel(di, ale->data, y);
break;
case ALE_IPO: case ALE_IPO:
draw_ipo_channel(di, ale->key_data, y); draw_ipo_channel(di, ale->key_data, y);
break; break;
@@ -1196,6 +1248,17 @@ void draw_icu_channel(gla2DDrawInfo *di, IpoCurve *icu, float ypos)
BLI_freelistN(&blocks); BLI_freelistN(&blocks);
} }
void draw_agroup_channel(gla2DDrawInfo *di, bActionGroup *agrp, float ypos)
{
ListBase keys = {0, 0};
ListBase blocks = {0, 0};
agroup_to_keylist(agrp, &keys, &blocks);
draw_keylist(di, &keys, &blocks, ypos);
BLI_freelistN(&keys);
BLI_freelistN(&blocks);
}
void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos) void draw_action_channel(gla2DDrawInfo *di, bAction *act, float ypos)
{ {
ListBase keys = {0, 0}; ListBase keys = {0, 0};
@@ -1273,6 +1336,27 @@ void ipo_to_keylist(Ipo *ipo, ListBase *keys, ListBase *blocks)
} }
} }
void agroup_to_keylist(bActionGroup *agrp, ListBase *keys, ListBase *blocks)
{
bActionChannel *achan;
bConstraintChannel *conchan;
if (agrp) {
/* loop through action channels */
for (achan= agrp->channels.first; achan && achan!=agrp->channels.last; achan= achan->next) {
/* firstly, add keys from action channel's ipo block */
if (achan->ipo)
ipo_to_keylist(achan->ipo, keys, blocks);
/* then, add keys from constraint channels */
for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
if (conchan->ipo)
ipo_to_keylist(conchan->ipo, keys, blocks);
}
}
}
}
void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks) void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks)
{ {
bActionChannel *achan; bActionChannel *achan;
@@ -1288,7 +1372,7 @@ void action_to_keylist(bAction *act, ListBase *keys, ListBase *blocks)
/* then, add keys from constraint channels */ /* then, add keys from constraint channels */
for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) { for (conchan= achan->constraintChannels.first; conchan; conchan= conchan->next) {
if (conchan->ipo) if (conchan->ipo)
ipo_to_keylist(achan->ipo, keys, blocks); ipo_to_keylist(conchan->ipo, keys, blocks);
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -133,6 +133,12 @@ enum {
ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_BOTTOM ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_BOTTOM
}; };
enum {
ACTMENU_KEY_CHANGROUP_ADD_TOACTIVE = 0,
ACTMENU_KEY_CHANGROUP_ADD_TONEW,
ACTMENU_KEY_CHANGROUP_REMOVE
};
enum { enum {
ACTMENU_KEY_TRANSFORM_MOVE = 0, ACTMENU_KEY_TRANSFORM_MOVE = 0,
ACTMENU_KEY_TRANSFORM_SCALE, ACTMENU_KEY_TRANSFORM_SCALE,
@@ -466,35 +472,19 @@ static uiBlock *action_viewmenu(void *arg_unused)
static void do_action_selectmenu_columnmenu(void *arg, int event) static void do_action_selectmenu_columnmenu(void *arg, int event)
{ {
SpaceAction *saction; switch (event) {
bAction *act; case ACTMENU_SEL_COLUMN_MARKERSBETWEEN:
Key *key; markers_selectkeys_between();
break;
saction = curarea->spacedata.first; case ACTMENU_SEL_COLUMN_KEYS:
if (!saction) return; column_select_action_keys(1);
break;
act = saction->action; case ACTMENU_SEL_COLUMN_MARKERSCOLUMN:
key = get_action_mesh_key(); column_select_action_keys(2);
break;
#if 0 // actionrewite
if (event == ACTMENU_SEL_COLUMN_MARKERSBETWEEN) {
markers_selectkeys_between();
} }
else if (ELEM(event, ACTMENU_SEL_COLUMN_KEYS, ACTMENU_SEL_COLUMN_MARKERSCOLUMN)) {
if (act)
column_select_actionkeys(act, event);
else if (key)
column_select_shapekeys(key, event);
}
else
return;
#endif // actionrewite
allqueue(REDRAWTIME, 0); allqueue(REDRAWMARKER, 0);
allqueue(REDRAWIPO, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWNLA, 0);
allqueue(REDRAWSOUND, 0);
} }
static uiBlock *action_selectmenu_columnmenu(void *arg_unused) static uiBlock *action_selectmenu_columnmenu(void *arg_unused)
@@ -871,16 +861,16 @@ static void do_action_keymenu_chanposmenu(void *arg, int event)
switch(event) switch(event)
{ {
case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_DOWN: case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_DOWN:
down_sel_action(); rearrange_action_channels(REARRANGE_ACTCHAN_DOWN);
break; break;
case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_UP: case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_UP:
up_sel_action(); rearrange_action_channels(REARRANGE_ACTCHAN_UP);
break; break;
case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_TOP: case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_TOP:
top_sel_action(); rearrange_action_channels(REARRANGE_ACTCHAN_TOP);
break; break;
case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_BOTTOM: case ACTMENU_KEY_CHANPOS_MOVE_CHANNEL_BOTTOM:
bottom_sel_action(); rearrange_action_channels(REARRANGE_ACTCHAN_BOTTOM);
break; break;
} }
@@ -923,6 +913,54 @@ static uiBlock *action_keymenu_chanposmenu(void *arg_unused)
return block; return block;
} }
static void do_action_keymenu_changroupmenu(void *arg, int event)
{
switch(event)
{
case ACTMENU_KEY_CHANGROUP_ADD_TOACTIVE:
action_groups_group(0);
break;
case ACTMENU_KEY_CHANGROUP_ADD_TONEW:
action_groups_group(1);
break;
case ACTMENU_KEY_CHANGROUP_REMOVE:
action_groups_ungroup();
break;
}
}
static uiBlock *action_keymenu_changroupmenu(void *arg_unused)
{
uiBlock *block;
short yco= 0, menuwidth=120;
block= uiNewBlock(&curarea->uiblocks, "action_keymenu_changroupmenu",
UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
uiBlockSetButmFunc(block, do_action_keymenu_changroupmenu, NULL);
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Add to Active Group|Shift G", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_CHANGROUP_ADD_TOACTIVE, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Add To New Group|Ctrl Shift G", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_CHANGROUP_ADD_TONEW, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
"Remove From Group|Alt G", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 0,
ACTMENU_KEY_CHANGROUP_REMOVE, "");
uiBlockSetDirection(block, UI_RIGHT);
uiTextBoundsBlock(block, 60);
return block;
}
static void do_action_keymenu_snapmenu(void *arg, int event) static void do_action_keymenu_snapmenu(void *arg, int event)
{ {
switch(event) switch(event)
@@ -1125,6 +1163,14 @@ static uiBlock *action_keymenu(void *arg_unused)
uiDefIconTextBlockBut(block, action_keymenu_intpolmenu, uiDefIconTextBlockBut(block, action_keymenu_intpolmenu,
NULL, ICON_RIGHTARROW_THIN, NULL, ICON_RIGHTARROW_THIN,
"Interpolation Mode", 0, yco-=20, 120, 20, ""); "Interpolation Mode", 0, yco-=20, 120, 20, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBlockBut(block, action_keymenu_changroupmenu,
NULL, ICON_RIGHTARROW_THIN,
"Channel Grouping", 0, yco-=20, 120, 20, "");
uiDefIconTextBlockBut(block, action_keymenu_chanposmenu, uiDefIconTextBlockBut(block, action_keymenu_chanposmenu,
NULL, ICON_RIGHTARROW_THIN, NULL, ICON_RIGHTARROW_THIN,
"Channel Ordering", 0, yco-=20, 120, 20, ""); "Channel Ordering", 0, yco-=20, 120, 20, "");

View File

@@ -453,6 +453,8 @@ void BIF_InitTheme(void)
SETCOL(btheme->tact.hilite, 17, 27, 60, 100); // bar SETCOL(btheme->tact.hilite, 17, 27, 60, 100); // bar
SETCOL(btheme->tact.strip_select, 0xff, 0xff, 0xaa, 255); SETCOL(btheme->tact.strip_select, 0xff, 0xff, 0xaa, 255);
SETCOL(btheme->tact.strip, 0xe4, 0x9c, 0xc6, 255); SETCOL(btheme->tact.strip, 0xe4, 0x9c, 0xc6, 255);
SETCOL(btheme->tact.group, 0x39, 0x7d, 0x1b, 255);
SETCOL(btheme->tact.group_active, 0x7d, 0xe9, 0x60, 255);
/* space nla */ /* space nla */
btheme->tnla= btheme->tv3d; btheme->tnla= btheme->tv3d;
@@ -643,6 +645,8 @@ char *BIF_ThemeColorsPup(int spacetype)
str += sprintf(str, "View Sliders %%x%d|", TH_SHADE1); str += sprintf(str, "View Sliders %%x%d|", TH_SHADE1);
str += sprintf(str, "Channels %%x%d|", TH_SHADE2); str += sprintf(str, "Channels %%x%d|", TH_SHADE2);
str += sprintf(str, "Channels Selected %%x%d|", TH_HILITE); str += sprintf(str, "Channels Selected %%x%d|", TH_HILITE);
str += sprintf(str, "Channel Group %%x%d|", TH_GROUP);
str += sprintf(str, "Active Channel Group %%x%d|", TH_GROUP_ACTIVE);
str += sprintf(str, "Long Key %%x%d|", TH_STRIP); str += sprintf(str, "Long Key %%x%d|", TH_STRIP);
str += sprintf(str, "Long Key selected %%x%d|", TH_STRIP_SELECT); str += sprintf(str, "Long Key selected %%x%d|", TH_STRIP_SELECT);
str += sprintf(str, "Current Frame %%x%d", TH_CFRAME); str += sprintf(str, "Current Frame %%x%d", TH_CFRAME);

View File

@@ -396,6 +396,14 @@ static void init_userdef_file(void)
SETCOL(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255); SETCOL(btheme->ttime.cframe, 0x60, 0xc0, 0x40, 255);
} }
} }
if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 13)) {
bTheme *btheme;
for (btheme= U.themes.first; btheme; btheme= btheme->next) {
/* action channel groups (recolour anyway) */
SETCOL(btheme->tact.group, 0x39, 0x7d, 0x1b, 255);
SETCOL(btheme->tact.group_active, 0x7d, 0xe9, 0x60, 255);
}
}
/* GL Texture Garbage Collection (variable abused above!) */ /* GL Texture Garbage Collection (variable abused above!) */
if (U.textimeout == 0) { if (U.textimeout == 0) {