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:
authorJoshua Leung <aligorith@gmail.com>2006-11-15 13:41:28 +0300
committerJoshua Leung <aligorith@gmail.com>2006-11-15 13:41:28 +0300
commita3c1c543f6e1bcb4a2151b6be0786247887bb14c (patch)
tree248af37ba99b823e28df5019e0a208c98c377818 /source/blender
parent95c7c41bd060a55fb2679d53635474dc69703ed7 (diff)
== Action Editor ==
A Plumiferos wishlist item: Markers working in the Action Editor too. * The user can choose between displaying the scene markers (i.e. the markers shown in the timeline) or the markers specific to each action, by using the next list box on the action editor header. This is specific to each instance of the action editor. * The display of the markers currently still needs improvement. At the moment, the triangle icons + text are drawn below all the last row of keyframes. As such, I've made it draw yellow vertical lines which span the height of the action editor, to also indicate markers. Comments on this and also help getting the triangle thingies to 'float' above the bottom scroll bar are warmly appreciated. * There are a few minor update issues with editing a marker in the timeline and the markers in the action editor which will be fixed soon. * There are also a few hotkeys to still add. Enjoy!
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/intern/action.c5
-rw-r--r--source/blender/blenloader/intern/writefile.c5
-rw-r--r--source/blender/include/BIF_editaction.h15
-rw-r--r--source/blender/makesdna/DNA_action_types.h13
-rw-r--r--source/blender/src/drawaction.c91
-rw-r--r--source/blender/src/editaction.c521
-rw-r--r--source/blender/src/edittime.c3
-rw-r--r--source/blender/src/header_action.c120
8 files changed, 670 insertions, 103 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 9f42e682e82..3ee6b89804c 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -176,6 +176,10 @@ void free_action(bAction *act)
free_constraint_channels(&chan->constraintChannels);
}
+ /* Free markers */
+ if (act->markers.first)
+ BLI_freelistN (&act->markers);
+
if (act->chanbase.first)
BLI_freelistN (&act->chanbase);
}
@@ -189,6 +193,7 @@ bAction* copy_action(bAction *src)
dst= copy_libblock(src);
duplicatelist(&(dst->chanbase), &(src->chanbase));
+ duplicatelist(&(dst->markers), &(src->markers));
for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){
dchan->ipo = copy_ipo(dchan->ipo);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 2ee553824ef..2b2ba9f77bd 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1551,6 +1551,7 @@ static void write_actions(WriteData *wd, ListBase *idbase)
{
bAction *act;
bActionChannel *chan;
+ TimeMarker *marker;
for(act=idbase->first; act; act= act->id.next) {
if (act->id.us>0 || wd->current) {
@@ -1560,6 +1561,10 @@ static void write_actions(WriteData *wd, ListBase *idbase)
writestruct(wd, DATA, "bActionChannel", 1, chan);
write_constraint_channels(wd, &chan->constraintChannels);
}
+
+ /* writing dynamic list of TimeMarkers to the blend file */
+ for(marker= act->markers.first; marker; marker= marker->next)
+ writestruct(wd, DATA, "TimeMarker", 1, marker);
}
}
}
diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h
index 4645cb415e8..6ccec20181d 100644
--- a/source/blender/include/BIF_editaction.h
+++ b/source/blender/include/BIF_editaction.h
@@ -67,6 +67,7 @@ struct Object;
struct Ipo;
struct BWinEvent;
struct Key;
+struct ListBase;
/* Key operations */
void delete_meshchannel_keys(struct Key *key);
@@ -81,6 +82,18 @@ void snap_keys_to_frame(void);
void clean_shapekeys(struct Key *key);
void clean_actionchannels(struct bAction *act);
+/* Marker Operations */
+struct ListBase *get_saction_markers(struct SpaceAction *saction);
+void add_saction_marker(struct ListBase *markers, int frame);
+void duplicate_saction_markers(struct ListBase *markers);
+void remove_saction_markers(struct ListBase *markers);
+void rename_saction_markers(struct ListBase *markers);
+void transform_saction_markers(int mode, int smode);
+void deselect_saction_markers(struct ListBase *markers, int test);
+void borderselect_saction_markers(struct ListBase *markers, float xmin, float xmax, int selectmode);
+struct TimeMarker *find_nearest_saction_marker(struct ListBase *markers);
+
+
/* channel/strip operations */
void up_sel_action(void);
void down_sel_action(void);
@@ -99,12 +112,14 @@ void set_extendtype_actionchannels(int extendtype);
/* Select */
void borderselect_mesh(struct Key *key);
void borderselect_action(void);
+void borderselect_markers(struct ListBase *markers);
void deselect_actionchannel_keys(struct bAction *act, int test);
void deselect_actionchannels (struct bAction *act, int test);
void deselect_meshchannel_keys (struct Key *key, int test);
int select_channel(struct bAction *act, struct bActionChannel *chan, int selectmode);
void select_actionchannel_by_name (struct bAction *act, char *name, int select);
+
/* Action */
struct bActionChannel* get_hilighted_action_channel(struct bAction* action);
struct bAction *add_empty_action(int blocktype);
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index d27dc391f24..d9db6e0c889 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -100,7 +100,8 @@ typedef struct bActionChannel {
typedef struct bAction {
ID id;
- ListBase chanbase; /* Channels in this action */
+ ListBase chanbase; /* Action Channels in this action */
+ ListBase markers; /* Markers specific to this action */
} bAction;
typedef struct SpaceAction {
@@ -114,7 +115,7 @@ typedef struct SpaceAction {
View2D v2d;
bAction *action;
int flag;
- short pin, actnr, lock, pad;
+ short pin, actnr, lock, markert;
float timeslide;
} SpaceAction;
@@ -125,7 +126,13 @@ typedef struct SpaceAction {
#define ACHAN_MOVED 0x80000000
/* SpaceAction flag */
-#define SACTION_MOVING 1
+#define SACTION_MOVING 1 /* during transform */
+#define SACTION_SLIDERS 2 /* show sliders (if relevant) - limited to shape keys for now */
+
+/* SpaceAction Marker Type */
+#define SACTION_NOMARKERS 0 /* no markers */
+#define SACTION_SCMARKERS 1 /* markers for current scene */
+#define SACTION_ACMARKERS 2 /* markers from current action */
/* Pose->flag */
#define POSE_RECALC 1
diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c
index e628b9ca672..de36b02ec98 100644
--- a/source/blender/src/drawaction.c
+++ b/source/blender/src/drawaction.c
@@ -215,6 +215,92 @@ void draw_cfra_action(void)
glLineWidth(1.0);
}
+/* Aligorith: for now, just draw them as lines (for debugging) */
+static void draw_marker(TimeMarker *marker)
+{
+ float xpos, xspace, yspace, xpixels, ypixels;
+ float vec[2];
+
+
+ xpos = marker->frame;
+ /* no time correction for framelen! space is drawn with old values */
+
+ xspace= G.v2d->cur.xmax - G.v2d->cur.xmin;
+ yspace= G.v2d->cur.ymax - G.v2d->cur.ymin;
+ xpixels= G.v2d->mask.xmax-G.v2d->mask.xmin;
+ ypixels= G.v2d->mask.ymax-G.v2d->mask.ymin;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ /* draw line through this point */
+ vec[0]= G.scene->r.framelen * xpos;
+
+ vec[1]= G.v2d->cur.ymin;
+ if (marker->flag & SELECT)
+ glColor3ub(0xFF, 0xFF, 0x99);
+ else
+ glColor3ub(0xAA, 0xAA, 0x55);
+ glLineWidth(2.0);
+
+ glBegin(GL_LINE_STRIP);
+ glVertex2fv(vec);
+ vec[1]= G.v2d->cur.ymax;
+ glVertex2fv(vec);
+ glEnd();
+
+
+ /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
+ if(marker->flag & SELECT)
+ BIF_icon_draw(xpos-(5.0*(xspace/xpixels)), (12.0*yspace/ypixels)-CHANNELHEIGHT, ICON_MARKER_HLT);
+ else
+ BIF_icon_draw(xpos-(5.0*(xspace/xpixels)), (12.0*yspace/ypixels)-CHANNELHEIGHT, ICON_MARKER);
+
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glDisable(GL_BLEND);
+
+ /* and the marker name too, shifted slightly to the top-right */
+ if(marker->name && marker->name[0]) {
+ if(marker->flag & SELECT) {
+ BIF_ThemeColor(TH_TEXT_HI);
+ glRasterPos2f(xpos+(4.0*(xspace/xpixels)),
+ ((ypixels<=39.0)?(ypixels-10.0):29.0)*yspace/ypixels);
+ }
+ else {
+ BIF_ThemeColor(TH_TEXT);
+ if((marker->frame <= G.scene->r.cfra) && (marker->frame+5 > G.scene->r.cfra))
+ glRasterPos2f(xpos+(4.0*(xspace/xpixels)),
+ ((ypixels<=39.0)?(ypixels-10.0):29.0)*yspace/ypixels);
+ else
+ glRasterPos2f(xpos+(4.0*(xspace/xpixels)), 17.0*yspace/ypixels);
+ }
+ BMF_DrawString(G.font, marker->name);
+ }
+}
+
+static void draw_markers_action(SpaceAction *saction)
+{
+ ListBase *markers;
+ TimeMarker *marker;
+
+ /* try to get markers */
+ markers = get_saction_markers(saction);
+ if (markers == NULL)
+ return;
+
+ /* unselected markers are drawn at the first time */
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(!(marker->flag & SELECT)) draw_marker(marker);
+ }
+
+ /* selected markers are drawn later ... selected markers have to cover unselected
+ * markers laying at the same position as selected markers
+ * (jiri: it is hack, it could be solved better) */
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT) draw_marker(marker);
+ }
+}
+
/* left hand */
static void draw_action_channel_names(bAction *act)
{
@@ -682,7 +768,7 @@ void drawactionspace(ScrArea *sa, void *spacedata)
*/
draw_mesh_strips(G.saction, key);
}
-
+
/* Draw current frame */
glViewport(ofsx+G.v2d->mask.xmin,
ofsy+G.v2d->mask.ymin,
@@ -694,6 +780,9 @@ void drawactionspace(ScrArea *sa, void *spacedata)
( ofsy+G.v2d->mask.ymax-1)-( ofsy+G.v2d->mask.ymin)+1);
myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
draw_cfra_action();
+
+ /* Draw markers */
+ draw_markers_action(G.saction);
/* Draw scroll */
mywinset(curarea->win); // reset scissor too
diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c
index 14d65d5bf7d..4af44f796b7 100644
--- a/source/blender/src/editaction.c
+++ b/source/blender/src/editaction.c
@@ -135,101 +135,6 @@ static void select_poseelement_by_name (char *name, int select)
}
}
-bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
-{
- bArmature *arm;
- bAction *result=NULL;
- bActionChannel *achan;
- bAction *temp;
- bPoseChannel *pchan;
- ID *id;
- float actstart, actend;
- int oldframe;
- int curframe;
- char newname[64];
-
- if (!act)
- return NULL;
-
- arm = get_armature(armob);
-
- if (G.obedit){
- error ("Actions can't be baked in Edit Mode");
- return NULL;
- }
-
- if (!arm || armob->pose==NULL){
- error ("Select an armature before baking");
- return NULL;
- }
-
- /* Get a new action */
- result = add_empty_action(ID_PO);
- id= (ID *)armob;
-
- /* Assign the new action a unique name */
- sprintf (newname, "%s.BAKED", act->id.name+2);
- rename_id(&result->id, newname);
-
- calc_action_range(act, &actstart, &actend, 1);
-
- oldframe = G.scene->r.cfra;
-
- temp = armob->action;
- armob->action = result;
-
- for (curframe=1; curframe<ceil(actend+1.0f); curframe++){
-
- /* Apply the old action */
-
- G.scene->r.cfra = curframe;
-
- /* Apply the object ipo */
- extract_pose_from_action(armob->pose, act, curframe);
-
- where_is_pose(armob);
-
- /* For each channel: set quats and locs if channel is a bone */
- for (pchan=armob->pose->chanbase.first; pchan; pchan=pchan->next){
-
- /* Apply to keys */
- insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X);
- insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y);
- insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z);
- insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X);
- insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
- insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
- insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W);
- insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X);
- insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
- insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
- }
- }
-
-
- /* Make another pass to ensure all keyframes are set to linear interpolation mode */
- for (achan = result->chanbase.first; achan; achan=achan->next){
- IpoCurve* icu;
- if(achan->ipo) {
- for (icu = achan->ipo->curve.first; icu; icu=icu->next){
- icu->ipo= IPO_LIN;
- }
- }
- }
-
- notice ("Made a new action named \"%s\"", newname);
- G.scene->r.cfra = oldframe;
- armob->action = temp;
-
- /* restore */
- extract_pose_from_action(armob->pose, act, G.scene->r.cfra);
- where_is_pose(armob);
-
- allqueue(REDRAWACTION, 1);
-
- return result;
-}
-
/* apparently within active object context */
/* called extern, like on bone selection */
void select_actionchannel_by_name (bAction *act, char *name, int select)
@@ -697,16 +602,20 @@ static void mouse_action(int selectmode)
float selx;
bActionChannel *chan;
bConstraintChannel *conchan;
+ TimeMarker *marker;
+ ListBase *markers;
short mval[2];
act=G.saction->action;
if (!act)
return;
+ markers= get_saction_markers(G.saction);
getmouseco_areawin (mval);
chan=get_nearest_actionchannel_key(&selx, &sel, &conchan);
-
+ marker=find_nearest_saction_marker(markers);
+
if (chan){
if (selectmode == SELECT_REPLACE) {
selectmode = SELECT_ADD;
@@ -734,6 +643,20 @@ static void mouse_action(int selectmode)
allqueue(REDRAWOOPS, 0);
allqueue(REDRAWBUTSALL, 0);
}
+ else if (marker != NULL) {
+ /* not channel, so maybe marker */
+ if (selectmode == SELECT_REPLACE) {
+ selectmode = SELECT_ADD;
+
+ deselect_saction_markers(markers, 0);
+ marker->flag |= SELECT;
+ }
+
+ std_rmouse_transform(transform_saction_markers);
+
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWTIME, 0);
+ }
}
static void mouse_mesh_action(int selectmode, Key *key)
@@ -743,6 +666,8 @@ static void mouse_mesh_action(int selectmode, Key *key)
*/
IpoCurve *icu;
+ TimeMarker *marker;
+ ListBase *markers;
short sel;
float selx;
short mval[2];
@@ -754,6 +679,9 @@ static void mouse_mesh_action(int selectmode, Key *key)
* data, etc)
*/
+ markers= get_saction_markers(G.saction);
+ marker= find_nearest_saction_marker(markers);
+
/* get the click location, and the cooresponding
* ipo curve and selection time value
*/
@@ -803,12 +731,15 @@ void borderselect_action(void)
bActionChannel *chan;
bConstraintChannel *conchan;
bAction *act;
+ ListBase *markers;
float ymin, ymax;
act=G.saction->action;
if (!act)
return;
+
+ markers = get_saction_markers(G.saction);
if ( (val = get_border(&rect, 3)) ){
if (val == LEFTMOUSE)
@@ -822,7 +753,7 @@ void borderselect_action(void)
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(G.saction->pin==0 && OBACT) {
rectf.xmin= get_action_frame(OBACT, rectf.xmin);
@@ -854,31 +785,46 @@ void borderselect_action(void)
}
}
}
+
+ /* do markers first */
+ if (markers != NULL)
+ borderselect_saction_markers(markers, rectf.xmin, rectf.xmax, selectmode);
+
+
BIF_undo_push("Border Select Action");
allqueue(REDRAWNLA, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0);
+ if (markers != NULL) allqueue(REDRAWTIME, 0);
}
}
void borderselect_mesh(Key *key)
{
+ ListBase *markers;
rcti rect;
int val, adrcodemax, adrcodemin;
short mval[2];
float xmin, xmax;
+ int selectmode;
int (*select_function)(BezTriple *);
IpoCurve *icu;
+ markers = get_saction_markers(G.saction);
+
if ( (val = get_border(&rect, 3)) ){
/* set the selection function based on what
* mouse button had been used in the border
* select
*/
- if (val == LEFTMOUSE)
+ if (val == LEFTMOUSE) {
+ selectmode = SELECT_ADD;
select_function = select_bezier_add;
- else
+ }
+ else {
+ selectmode = SELECT_SUBTRACT;
select_function = select_bezier_subtract;
+ }
/* get the minimum and maximum adrcode numbers
* for the IpoCurves (this is the number that
@@ -909,11 +855,17 @@ void borderselect_mesh(Key *key)
}
}
}
+
+ /* do markers too if any */
+ if (markers != NULL)
+ borderselect_saction_markers(markers, xmin, xmax, selectmode);
+
/* redraw stuff */
BIF_undo_push("Border select Action Key");
allqueue(REDRAWNLA, 0);
allqueue(REDRAWACTION, 0);
allqueue(REDRAWIPO, 0);
+ if (markers != NULL) allqueue(REDRAWTIME, 0);
}
}
@@ -2453,6 +2405,7 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
extern void do_actionbuts(unsigned short event); // drawaction.c
SpaceAction *saction;
bAction *act;
+ ListBase *markers;
Key *key;
float dx,dy;
int doredraw= 0;
@@ -2467,6 +2420,8 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
saction= curarea->spacedata.first;
if (!saction)
return;
+
+ markers = get_saction_markers(saction);
act=saction->action;
if(val) {
@@ -2635,6 +2590,27 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
allqueue(REDRAWNLA, 0);
break;
+ case MKEY:
+ /* marker operations */
+ if (G.qual == 0)
+ add_saction_marker(markers, CFRA);
+ else if (G.qual == LR_ALTKEY) {
+ if( okee("Erase selected markers")==0 )
+ break;
+ remove_saction_markers(markers);
+ }
+ else if (G.qual == LR_CTRLKEY)
+ rename_saction_markers(markers);
+ else if (G.qual == LR_SHIFTKEY)
+ transform_saction_markers('g', 0);
+ else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY))
+ duplicate_saction_markers(markers);
+ else
+ break;
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWTIME, 0);
+ break;
+
case NKEY:
if(G.qual==0) {
numbuts_action();
@@ -2890,7 +2866,256 @@ int get_nearest_key_num(Key *key, short *mval, float *x) {
return (num + 1);
}
+/* ************************************* Action Editor Markers ************************************* */
+
+/* returns the current active markers */
+ListBase *get_saction_markers (SpaceAction *saction)
+{
+ ListBase *markers;
+
+ if (saction->markert == SACTION_SCMARKERS)
+ markers = &(G.scene->markers);
+ else if ((saction->markert == SACTION_ACMARKERS) && (saction->action != NULL))
+ markers = &(saction->action->markers);
+ else
+ markers = NULL;
+
+ return markers;
+}
+
+/* add a TimeMarker - code basically taken from edittime.c */
+void add_saction_marker (ListBase *markers, int frame)
+{
+ TimeMarker *marker;
+
+ /* two markers can't be at the same place */
+ for(marker= markers->first; marker; marker= marker->next)
+ if(marker->frame == frame) return;
+ /* deselect all */
+ for(marker= markers->first; marker; marker= marker->next)
+ marker->flag &= ~SELECT;
+
+ marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
+ marker->flag= SELECT;
+ marker->frame= frame;
+ BLI_addtail(markers, marker);
+
+ BIF_undo_push("Add Marker");
+}
+
+/* remove a TimeMarker - code basically taken from edittime.c */
+void remove_saction_markers(ListBase *markers)
+{
+ TimeMarker *marker;
+
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT){
+ BLI_freelinkN(markers, marker);
+ }
+ }
+
+ BIF_undo_push("Remove Marker");
+}
+
+/* rename a TimeMarker - code basically taken from edittime.c */
+void rename_saction_markers(ListBase *markers)
+{
+ TimeMarker *marker;
+ char name[64];
+
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT) {
+ sprintf(name, marker->name);
+ if (sbutton(name, 0, sizeof(name)-1, "Name: "))
+ BLI_strncpy(marker->name, name, sizeof(marker->name));
+ break;
+ }
+ }
+
+ BIF_undo_push("Rename Marker");
+}
+
+/* duplicate selected TimeMarkers - code basically taken from edittime.c */
+void duplicate_saction_markers(ListBase *markers)
+{
+ TimeMarker *marker, *newmarker;
+
+ /* go through the list of markers, duplicate selected markers and add duplicated copies
+ * to the begining of the list (unselect original markers) */
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT){
+ /* unselect selected marker */
+ marker->flag &= ~SELECT;
+ /* create and set up new marker */
+ newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
+ newmarker->flag= SELECT;
+ newmarker->frame= marker->frame;
+ BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
+ /* new marker is added to the begining of list */
+ BLI_addhead(markers, newmarker);
+ }
+ }
+
+ transform_saction_markers('g', 0);
+}
+
+void transform_saction_markers(int mode, int smode) // mode and smode unused here, for callback
+{
+ SpaceAction *saction= curarea->spacedata.first;
+ TimeMarker *marker, *selmarker=NULL;
+ ListBase *markers;
+ float dx, fac;
+ int a, ret_val= 0, totmark=0, *oldframe, offs, firsttime=1;
+ unsigned short event;
+ short val, pmval[2], mval[2], mvalo[2];
+ char str[32];
+
+ markers= get_saction_markers(saction);
+ if (markers == NULL) return;
+
+ for(marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT) totmark++;
+ }
+ if(totmark==0) return;
+
+ oldframe= MEM_mallocN(totmark*sizeof(int), "marker array");
+ for(a=0, marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT) {
+ oldframe[a]= marker->frame;
+ selmarker= marker; // used for hederprint
+ a++;
+ }
+ }
+
+ dx= G.v2d->mask.xmax-G.v2d->mask.xmin;
+ dx= (G.v2d->cur.xmax-G.v2d->cur.xmin)/dx;
+
+ getmouseco_areawin(pmval);
+ mvalo[0]= pmval[0];
+
+ while(ret_val == 0) {
+
+ getmouseco_areawin(mval);
+
+ if (mval[0] != mvalo[0] || firsttime) {
+ mvalo[0]= mval[0];
+ firsttime= 0;
+
+ fac= (((float)(mval[0] - pmval[0]))*dx);
+
+ apply_keyb_grid(&fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
+ offs= (int)fac;
+
+ for(a=0, marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT) {
+ marker->frame= oldframe[a] + offs;
+ a++;
+ }
+ }
+
+ if(totmark==1) // we print current marker value
+ sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
+ else
+ sprintf(str, "Marker offset %.2f ", (double)(offs));
+
+ headerprint(str);
+
+ force_draw(0); // areas identical to this, 0 = no header
+ }
+ else PIL_sleep_ms(10); // idle
+
+ /* emptying queue and reading events */
+ while( qtest() ) {
+ event= extern_qread(&val);
+
+ if(val) {
+ if(event==ESCKEY || event==RIGHTMOUSE) ret_val= 2;
+ else if(event==LEFTMOUSE || event==RETKEY || event==SPACEKEY) ret_val= 1;
+ }
+ }
+ }
+
+ /* restore? */
+ if(ret_val==2) {
+ for(a=0, marker= markers->first; marker; marker= marker->next) {
+ if(marker->flag & SELECT) {
+ marker->frame= oldframe[a];
+ a++;
+ }
+ }
+ }
+ else {
+ BIF_undo_push("Move Markers");
+ }
+ MEM_freeN(oldframe);
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWTIME, 0);
+}
+
+TimeMarker *find_nearest_saction_marker(ListBase *markers)
+{
+ TimeMarker *marker;
+ float xmin, xmax;
+ rctf rectf;
+ short mval[2];
+
+ getmouseco_areawin (mval);
+ 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);
+
+ xmin= rectf.xmin;
+ xmax= rectf.xmax;
+
+ for(marker= markers->first; marker; marker= marker->next) {
+ if ((marker->frame > xmin) && (marker->frame <= xmax)) {
+ return marker;
+ }
+ }
+
+ return NULL;
+}
+
+/* select/deselect all TimeMarkers */
+void deselect_saction_markers(ListBase *markers, int test)
+{
+ TimeMarker *marker;
+
+ for (marker = markers->first; marker; marker= marker->next) {
+ if (test) {
+ if ((marker->flag & SELECT)==0)
+ marker->flag |= SELECT;
+ }
+ else {
+ if (marker->flag & SELECT)
+ marker->flag &= ~SELECT;
+ }
+ }
+}
+
+void borderselect_saction_markers(ListBase *markers, float xmin, float xmax, int selectmode)
+{
+ TimeMarker *marker;
+
+ for(marker= markers->first; marker; marker= marker->next) {
+ if ((marker->frame > xmin) && (marker->frame <= xmax)) {
+ switch (selectmode) {
+ case SELECT_ADD:
+ if ((marker->flag & SELECT) == 0)
+ marker->flag |= SELECT;
+ break;
+ case SELECT_SUBTRACT:
+ if (marker->flag & SELECT)
+ marker->flag &= ~SELECT;
+ break;
+ }
+ }
+ }
+}
+
+/* ************************************* Action Channel Ordering *********************************** */
void top_sel_action()
{
@@ -3051,6 +3276,9 @@ void bottom_sel_action()
allqueue(REDRAWNLA, 0);
}
+/* ********************************* BAKING STUFF ********************************** */
+/* NOTE: these functions should probably be moved to their own file sometime - Aligorith */
+
void world2bonespace(float boneSpaceMat[][4], float worldSpace[][4], float restPos[][4], float armPos[][4])
{
float imatarm[4][4], imatbone[4][4], tmat[4][4], t2mat[4][4];
@@ -3062,6 +3290,101 @@ void world2bonespace(float boneSpaceMat[][4], float worldSpace[][4], float restP
Mat4MulMat4(boneSpaceMat, restPos, t2mat);
}
+bAction* bake_action_with_client (bAction *act, Object *armob, float tolerance)
+{
+ bArmature *arm;
+ bAction *result=NULL;
+ bActionChannel *achan;
+ bAction *temp;
+ bPoseChannel *pchan;
+ ID *id;
+ float actstart, actend;
+ int oldframe;
+ int curframe;
+ char newname[64];
+
+ if (!act)
+ return NULL;
+
+ arm = get_armature(armob);
+
+ if (G.obedit){
+ error ("Actions can't be baked in Edit Mode");
+ return NULL;
+ }
+
+ if (!arm || armob->pose==NULL){
+ error ("Select an armature before baking");
+ return NULL;
+ }
+
+ /* Get a new action */
+ result = add_empty_action(ID_PO);
+ id= (ID *)armob;
+
+ /* Assign the new action a unique name */
+ sprintf (newname, "%s.BAKED", act->id.name+2);
+ rename_id(&result->id, newname);
+
+ calc_action_range(act, &actstart, &actend, 1);
+
+ oldframe = G.scene->r.cfra;
+
+ temp = armob->action;
+ armob->action = result;
+
+ for (curframe=1; curframe<ceil(actend+1.0f); curframe++){
+
+ /* Apply the old action */
+
+ G.scene->r.cfra = curframe;
+
+ /* Apply the object ipo */
+ extract_pose_from_action(armob->pose, act, curframe);
+
+ where_is_pose(armob);
+
+ /* For each channel: set quats and locs if channel is a bone */
+ for (pchan=armob->pose->chanbase.first; pchan; pchan=pchan->next){
+
+ /* Apply to keys */
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y);
+ insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z);
+ }
+ }
+
+
+ /* Make another pass to ensure all keyframes are set to linear interpolation mode */
+ for (achan = result->chanbase.first; achan; achan=achan->next){
+ IpoCurve* icu;
+ if(achan->ipo) {
+ for (icu = achan->ipo->curve.first; icu; icu=icu->next){
+ icu->ipo= IPO_LIN;
+ }
+ }
+ }
+
+ notice ("Made a new action named \"%s\"", newname);
+ G.scene->r.cfra = oldframe;
+ armob->action = temp;
+
+ /* restore */
+ extract_pose_from_action(armob->pose, act, G.scene->r.cfra);
+ where_is_pose(armob);
+
+ allqueue(REDRAWACTION, 1);
+
+ return result;
+}
+
bAction* bake_obIPO_to_action (Object *ob)
{
diff --git a/source/blender/src/edittime.c b/source/blender/src/edittime.c
index 266d7bda139..919508aec0d 100644
--- a/source/blender/src/edittime.c
+++ b/source/blender/src/edittime.c
@@ -452,6 +452,7 @@ void timeline_grab(int mode, int smode) // mode and smode unused here, for callb
}
MEM_freeN(oldframe);
allqueue(REDRAWTIME, 0);
+ allqueue(REDRAWACTION, 0);
}
/* copy of this is actually in editscreen.c, but event based */
@@ -642,6 +643,7 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
else
add_timeline_marker(CFRA);
allqueue(REDRAWTIME, 0);
+ allqueue(REDRAWACTION, 0);
break;
case SKEY: /* set start frame */
G.scene->r.sfra = CFRA;
@@ -662,6 +664,7 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
remove_timeline_marker();
allqueue(REDRAWTIME, 0);
+ allqueue(REDRAWACTION, 0);
break;
}
}
diff --git a/source/blender/src/header_action.c b/source/blender/src/header_action.c
index de4cafbe3ec..0bb18014b4e 100644
--- a/source/blender/src/header_action.c
+++ b/source/blender/src/header_action.c
@@ -83,6 +83,7 @@
#define ACTMENU_VIEW_ALL 4
#define ACTMENU_VIEW_MAXIMIZE 5
#define ACTMENU_VIEW_LOCK 6
+#define ACTMENU_VIEW_SLIDERS 7
#define ACTMENU_SEL_BORDER 0
#define ACTMENU_SEL_ALL_KEYS 1
@@ -118,6 +119,12 @@
#define ACTMENU_KEY_EXTEND_CYCLIC 2
#define ACTMENU_KEY_EXTEND_CYCLICEXTRAPOLATION 3
+#define ACTMENU_MARKERS_ADD 0
+#define ACTMENU_MARKERS_DUPLICATE 1
+#define ACTMENU_MARKERS_DELETE 2
+#define ACTMENU_MARKERS_NAME 3
+#define ACTMENU_MARKERS_MOVE 4
+
void do_action_buttons(unsigned short event)
{
Object *ob= OBACT;
@@ -234,6 +241,9 @@ static void do_action_viewmenu(void *arg, int event)
if(G.v2d->flag & V2D_VIEWLOCK)
view2d_do_locks(curarea, 0);
break;
+ case ACTMENU_VIEW_SLIDERS: /* Show sliders (when applicable) */
+ G.saction->flag ^= SACTION_SLIDERS;
+ break;
case ACTMENU_VIEW_MAXIMIZE: /* Maximize Window */
/* using event B_FULL */
break;
@@ -262,6 +272,14 @@ static uiBlock *action_viewmenu(void *arg_unused)
"Update Automatically|", 0, yco-=20,
menuwidth, 19, NULL, 0.0, 0.0, 1,
ACTMENU_VIEW_AUTOUPDATE, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6,
+ menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, (G.saction->flag & SACTION_SLIDERS)?ICON_CHECKBOX_HLT:ICON_CHECKBOX_DEHLT,
+ "Show Sliders|", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1,
+ ACTMENU_VIEW_SLIDERS, "");
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
@@ -866,6 +884,80 @@ static uiBlock *action_keymenu(void *arg_unused)
return block;
}
+static void do_action_markermenu(void *arg, int event)
+{
+ SpaceAction *saction;
+ ListBase *lb = NULL;
+
+ saction= curarea->spacedata.first;
+ if (!saction)
+ return;
+
+ /* get set of markers */
+ lb= get_saction_markers(saction);
+ if (lb == NULL)
+ return;
+
+ switch(event)
+ {
+ case ACTMENU_MARKERS_ADD:
+ add_saction_marker(lb, CFRA);
+ break;
+ case ACTMENU_MARKERS_DUPLICATE:
+ duplicate_saction_markers(lb);
+ break;
+ case ACTMENU_MARKERS_DELETE:
+ remove_saction_markers(lb);
+ break;
+ case ACTMENU_MARKERS_NAME:
+ rename_saction_markers(lb);
+ break;
+ case ACTMENU_MARKERS_MOVE:
+ transform_saction_markers('g', 0);
+ break;
+ }
+
+ allqueue(REDRAWACTION, 0);
+ allqueue(REDRAWTIME, 0);
+}
+
+static uiBlock *action_markermenu(void *arg_unused)
+{
+ uiBlock *block;
+ short yco= 0, menuwidth=120;
+
+ block= uiNewBlock(&curarea->uiblocks, "action_markermenu",
+ UI_EMBOSSP, UI_HELV, curarea->headwin);
+ uiBlockSetButmFunc(block, do_action_markermenu, NULL);
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Marker|M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_ADD, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Duplicate Marker(s)|Ctrl Shift M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DUPLICATE, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Marker(s)|Alt M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_DELETE, "");
+
+ uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "(Re)Name Marker(s)|Ctrl M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_NAME, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker(s)|Shift M", 0, yco-=20,
+ menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_MOVE, "");
+
+
+ if(curarea->headertype==HEADERTOP) {
+ uiBlockSetDirection(block, UI_DOWN);
+ }
+ else {
+ uiBlockSetDirection(block, UI_TOP);
+ uiBlockFlipOrder(block);
+ }
+
+ uiTextBoundsBlock(block, 50);
+
+ return block;
+}
+
void action_buttons(void)
{
uiBlock *block;
@@ -942,6 +1034,11 @@ void action_buttons(void)
uiDefPulldownBut(block, action_keymenu, NULL,
"Key", xco, -2, xmax-3, 24, "");
xco+= xmax;
+
+ xmax= GetButStringLength("Marker");
+ uiDefPulldownBut(block, action_markermenu, NULL,
+ "Marker", xco, -2, xmax-3, 24, "");
+ xco+= xmax;
}
uiBlockSetEmboss(block, UI_EMBOSS);
@@ -955,6 +1052,29 @@ void action_buttons(void)
from, &(G.saction->actnr), B_ACTALONE,
B_ACTLOCAL, B_ACTIONDELETE, 0, 0);
+
+ /* Draw marker set selection box */
+ xco+= 8;
+
+ if (G.saction->action != NULL) {
+ uiDefButS(block, MENU, B_REDR,
+ "Markers%t|None%x0|Scene%x1|Action%x2",
+ xco, 0, 80, 20, &(G.saction->markert), 0, 0, 0, 0,
+ "What set of markers to display.");
+ }
+ else {
+ if (G.saction->markert == SACTION_ACMARKERS)
+ G.saction->markert = SACTION_NOMARKERS;
+
+ uiDefButS(block, MENU, B_REDR,
+ "Markers%t|None%x0|Scene%x1",
+ xco, 0, 80, 20, &(G.saction->markert), 0, 0, 0, 0,
+ "What set of markers to display.");
+ }
+
+ xco+=80;
+
+
/* Draw action baker */
xco+= 8;