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:
-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;