forked from bartvdbraak/blender
== PoseLib - Overhauled Implementation ==
Based on feedback from Ton, I've recoded the way "PoseLibs" are implemented/exposed. Therefore, quite a bit of code has been changed to fit this in better. Now, ANY ACTION can be a "PoseLib". A set of Markers which belong to the Action (it's taken a year, but they're finally back), are used to tag "poses" in the Action. These markers are shown using diamond-shaped blue icons (designed by Matt Ebb) in three shades - unselected/normal, selected, active. Notes: * Each Armature Object has an Action which acts as a PoseLib. * Improved UI presented in buttons panel for this -- added proper buttons for action assigning -- renamed "Validate PoseLib" to "Auto-Sync PoseLib" (this option auto-tags poses based on keyframes found) Like in the 3d-view, use the hotkeys: * Shift-L to add a local marker * Ctrl-Shift-L to rename a local marker * Alt-L to delete selected local markers Note: transforms, etc. are not currently available with these markers == PoseLib Preview == Added a few features here: * Left/Right-Arrow keys now change the poses too (previous and next respectively) * Up/Down-Arrow keys also change the poses, but "jump" to a pose 5 steps away in their respective directions
This commit is contained in:
parent
96935a6c5d
commit
5be2e5aa98
Binary file not shown.
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 64 KiB |
@ -163,15 +163,6 @@ void make_local_action(bAction *act)
|
||||
}
|
||||
}
|
||||
|
||||
static void free_act_poselib (bAction *act)
|
||||
{
|
||||
if (act->poselib) {
|
||||
bPoseLib *pl= act->poselib;
|
||||
|
||||
BLI_freelistN(&pl->poses);
|
||||
MEM_freeN(pl);
|
||||
}
|
||||
}
|
||||
|
||||
void free_action (bAction *act)
|
||||
{
|
||||
@ -187,8 +178,9 @@ void free_action (bAction *act)
|
||||
if (act->chanbase.first)
|
||||
BLI_freelistN(&act->chanbase);
|
||||
|
||||
/* Free PoseLib */
|
||||
free_act_poselib(act);
|
||||
/* Free pose-references */
|
||||
if (act->markers.first)
|
||||
BLI_freelistN(&act->markers);
|
||||
}
|
||||
|
||||
bAction *copy_action (bAction *src)
|
||||
@ -200,6 +192,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);
|
||||
|
@ -225,12 +225,12 @@ void free_object(Object *ob)
|
||||
ob->path= 0;
|
||||
if(ob->ipo) ob->ipo->id.us--;
|
||||
if(ob->action) ob->action->id.us--;
|
||||
if(ob->poselib) ob->poselib->id.us--;
|
||||
if(ob->dup_group) ob->dup_group->id.us--;
|
||||
if(ob->defbase.first)
|
||||
BLI_freelistN(&ob->defbase);
|
||||
if(ob->pose) {
|
||||
free_pose_channels(ob->pose);
|
||||
if (ob->pose->poselib) ob->pose->poselib->id.us--;
|
||||
MEM_freeN(ob->pose);
|
||||
}
|
||||
free_effects(&ob->effect);
|
||||
|
@ -1802,9 +1802,6 @@ static void lib_link_pose(FileData *fd, Object *ob, bPose *pose)
|
||||
}
|
||||
}
|
||||
|
||||
// ob->id.lib???
|
||||
pose->poselib = newlibadr_us(fd, ob->id.lib, pose->poselib);
|
||||
|
||||
if(rebuild) {
|
||||
ob->recalc= OB_RECALC;
|
||||
pose->flag |= POSE_RECALC;
|
||||
@ -1864,13 +1861,10 @@ static void direct_link_action(FileData *fd, bAction *act)
|
||||
bActionChannel *achan;
|
||||
|
||||
link_list(fd, &act->chanbase);
|
||||
link_list(fd, &act->markers);
|
||||
|
||||
for (achan = act->chanbase.first; achan; achan=achan->next)
|
||||
link_list(fd, &achan->constraintChannels);
|
||||
|
||||
act->poselib= newdataadr(fd, act->poselib);
|
||||
if (act->poselib)
|
||||
link_list(fd, &act->poselib->poses);
|
||||
}
|
||||
|
||||
static void direct_link_armature(FileData *fd, bArmature *arm)
|
||||
@ -2790,6 +2784,7 @@ static void lib_link_object(FileData *fd, Main *main)
|
||||
ob->track= newlibadr(fd, ob->id.lib, ob->track);
|
||||
ob->ipo= newlibadr_us(fd, ob->id.lib, ob->ipo);
|
||||
ob->action = newlibadr_us(fd, ob->id.lib, ob->action);
|
||||
ob->poselib= newlibadr_us(fd, ob->id.lib, ob->poselib);
|
||||
ob->dup_group= newlibadr_us(fd, ob->id.lib, ob->dup_group);
|
||||
|
||||
ob->proxy= newlibadr_us(fd, ob->id.lib, ob->proxy);
|
||||
@ -7821,8 +7816,6 @@ static void expand_pose(FileData *fd, Main *mainvar, bPose *pose)
|
||||
expand_constraints(fd, mainvar, &chan->constraints);
|
||||
expand_doit(fd, mainvar, chan->custom);
|
||||
}
|
||||
|
||||
expand_doit(fd, mainvar, pose->poselib);
|
||||
}
|
||||
|
||||
static void expand_armature(FileData *fd, Main *mainvar, bArmature *arm)
|
||||
@ -7900,6 +7893,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
|
||||
expand_doit(fd, mainvar, ob->data);
|
||||
expand_doit(fd, mainvar, ob->ipo);
|
||||
expand_doit(fd, mainvar, ob->action);
|
||||
expand_doit(fd, mainvar, ob->poselib);
|
||||
|
||||
for (md=ob->modifiers.first; md; md=md->next) {
|
||||
expand_modifier(fd, mainvar, md);
|
||||
|
@ -1738,6 +1738,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) {
|
||||
@ -1749,14 +1750,8 @@ static void write_actions(WriteData *wd, ListBase *idbase)
|
||||
write_constraint_channels(wd, &chan->constraintChannels);
|
||||
}
|
||||
|
||||
if (act->poselib) {
|
||||
bPoseLib *pl= act->poselib;
|
||||
bPoseLibRef *plr;
|
||||
|
||||
writestruct(wd, DATA, "bPoseLib", 1, pl);
|
||||
|
||||
for (plr= pl->poses.first; plr; plr= plr->next)
|
||||
writestruct(wd, DATA, "bPoseLibRef", 1, plr);
|
||||
for (marker=act->markers.first; marker; marker=marker->next) {
|
||||
writestruct(wd, DATA, "TimeMarker", 1, marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +100,7 @@ struct Ipo;
|
||||
struct BWinEvent;
|
||||
struct Key;
|
||||
struct ListBase;
|
||||
struct TimeMarker;
|
||||
|
||||
/* Key operations */
|
||||
void transform_action_keys(int mode, int dummy);
|
||||
@ -122,7 +123,7 @@ void free_actcopybuf(void);
|
||||
void copy_actdata(void);
|
||||
void paste_actdata(void);
|
||||
|
||||
/* channel/strip operations */
|
||||
/* Channel/strip operations */
|
||||
void up_sel_action(void);
|
||||
void down_sel_action(void);
|
||||
void top_sel_action(void);
|
||||
@ -141,6 +142,12 @@ int select_channel(struct bAction *act, struct bActionChannel *achan, int select
|
||||
void select_actionchannel_by_name(struct bAction *act, char *name, int select);
|
||||
void selectkeys_leftright (short leftright, short select_mode);
|
||||
|
||||
/* Action Markers */
|
||||
void action_set_activemarker(struct bAction *act, struct TimeMarker *active, short deselect);
|
||||
void action_add_localmarker(struct bAction *act, int frame);
|
||||
void action_rename_localmarker(struct bAction *act);
|
||||
void action_remove_localmarkers(struct bAction *act);
|
||||
|
||||
/* ShapeKey stuff */
|
||||
struct Key *get_action_mesh_key(void);
|
||||
int get_nearest_key_num(struct Key *key, short *mval, float *x);
|
||||
|
@ -35,19 +35,18 @@
|
||||
|
||||
struct Object;
|
||||
struct bAction;
|
||||
struct bPoseLib;
|
||||
struct bPoseLibRef;
|
||||
struct TimeMarker;
|
||||
|
||||
char *poselib_build_poses_menu(struct bPoseLib *pl, char title[]);
|
||||
void poselib_unique_pose_name(struct bPoseLib *pl, char name[]);
|
||||
int poselib_get_free_index(struct bPoseLib *pl);
|
||||
char *poselib_build_poses_menu(struct bAction *act, char title[]);
|
||||
int poselib_get_free_index(struct bAction *act);
|
||||
struct TimeMarker *poselib_get_active_pose(struct bAction *act);
|
||||
|
||||
struct bPoseLib *poselib_init_new(struct Object *ob);
|
||||
struct bPoseLib *poselib_validate(struct Object *ob);
|
||||
struct bAction *poselib_init_new(struct Object *ob);
|
||||
struct bAction *poselib_validate(struct Object *ob);
|
||||
|
||||
void poselib_validate_act(struct bAction *act);
|
||||
|
||||
void poselib_remove_pose(struct Object *ob, struct bPoseLibRef *plr);
|
||||
void poselib_remove_pose(struct Object *ob, struct TimeMarker *marker);
|
||||
void poselib_rename_pose(struct Object *ob);
|
||||
void poselib_add_current_pose(struct Object *ob, int mode);
|
||||
|
||||
|
@ -73,9 +73,9 @@ typedef enum {
|
||||
ICON_SMOOTH,
|
||||
ICON_POTATO,
|
||||
ICON_MARKER_HLT,
|
||||
ICON_NORMALVIEW,
|
||||
ICON_LOCALVIEW,
|
||||
ICON_UNUSEDVIEW,
|
||||
ICON_PMARKER_ACT,
|
||||
ICON_PMARKER_SEL,
|
||||
ICON_PMARKER,
|
||||
ICON_VIEWZOOM,
|
||||
ICON_SORTALPHA,
|
||||
ICON_SORTTIME,
|
||||
|
@ -35,8 +35,14 @@
|
||||
|
||||
struct ListBase;
|
||||
struct View2D;
|
||||
struct TimeMarker;
|
||||
|
||||
/* ******** Markers - General Api ********* */
|
||||
/* ****** Marker Macros - General API ****** */
|
||||
|
||||
/* macro for getting the scene's set of markers */
|
||||
#define SCE_MARKERS (&(G.scene->markers))
|
||||
|
||||
/* ******** Markers - General API ********* */
|
||||
void add_marker(int frame);
|
||||
void duplicate_marker(void);
|
||||
void remove_marker(void);
|
||||
@ -45,17 +51,25 @@ void transform_markers(int mode, int smode);
|
||||
|
||||
void borderselect_markers(void);
|
||||
void deselect_markers(short test, short sel);
|
||||
struct TimeMarker *find_nearest_marker(int clip_y);
|
||||
struct TimeMarker *find_nearest_marker(struct ListBase *markers, int clip_y);
|
||||
|
||||
void nextprev_marker(short dir);
|
||||
void get_minmax_markers(short sel, float *first, float *last);
|
||||
int find_nearest_marker_time(float dx);
|
||||
struct TimeMarker *get_frame_marker(int frame);
|
||||
|
||||
void add_marker_to_cfra_elem(struct ListBase *lb, struct TimeMarker *marker, short only_sel);
|
||||
void make_marker_cfra_list(struct ListBase *lb, short only_sel);
|
||||
|
||||
void draw_markers_timespace(int lines);
|
||||
TimeMarker *get_frame_marker(int frame);
|
||||
/* ********* Markers - Drawing API ********* */
|
||||
|
||||
/* flags for drawing markers */
|
||||
enum {
|
||||
DRAW_MARKERS_LINES = (1<<0),
|
||||
DRAW_MARKERS_LOCAL = (1<<1)
|
||||
};
|
||||
|
||||
void draw_markers_timespace(struct ListBase *markers, int flag);
|
||||
|
||||
/* ******** Animation - Preview Range ************* */
|
||||
void anim_previewrange_set(void);
|
||||
|
@ -511,13 +511,16 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
|
||||
#define B_ARM_CALCPATHS 2303
|
||||
#define B_ARM_CLEARPATHS 2304
|
||||
|
||||
#define B_POSELIB_NEW 2310
|
||||
#define B_POSELIB_VALIDATE 2311
|
||||
#define B_POSELIB_ADDPOSE 2312
|
||||
#define B_POSELIB_REPLACEP 2313
|
||||
#define B_POSELIB_REMOVEP 2314
|
||||
#define B_POSELIB_APPLYP 2315
|
||||
#define B_POSELIB_VALIDATE 2310
|
||||
#define B_POSELIB_ADDPOSE 2311
|
||||
#define B_POSELIB_REPLACEP 2312
|
||||
#define B_POSELIB_REMOVEP 2313
|
||||
#define B_POSELIB_APPLYP 2314
|
||||
|
||||
/* these shouldn't be here... */
|
||||
#define B_POSELIB_BROWSE 2320
|
||||
#define B_POSELIB_ALONE 2321
|
||||
#define B_POSELIB_DELETE 2322
|
||||
|
||||
/* *********************** */
|
||||
#define B_CAMBUTS 2500
|
||||
|
@ -99,26 +99,6 @@ typedef struct bPose {
|
||||
float cyclic_offset[3]; /* result of match and cycles, applied in where_is_pose() */
|
||||
} bPose;
|
||||
|
||||
|
||||
/* "Pose" reference for PoseLib */
|
||||
typedef struct bPoseLibRef {
|
||||
struct bPoseLibRef *next, *prev;
|
||||
int frame; /* frame in the action to look for this pose */
|
||||
char name[32]; /* name of the pose */
|
||||
int flag; /* temporary settings for this pose */
|
||||
} bPoseLibRef;
|
||||
|
||||
/* PoseLib data for Action
|
||||
* PoseLib data is stored in actions so that poselibs can easily be assigned/removed from
|
||||
* a pose. Currently the only data that is stored for a poselib is a set of references to which
|
||||
* frame a named pose occurs in the action.
|
||||
*/
|
||||
typedef struct bPoseLib {
|
||||
ListBase poses; /* List of poses for an action (arranged in chronological order) */
|
||||
int flag; /* Settings (not used yet) */
|
||||
int active_nr; /* Index of the poselib's active pose (for UI) */
|
||||
} bPoseLib;
|
||||
|
||||
/* Action Channels belong to Actions. They are linked with an IPO block, and can also own
|
||||
* Constraint Channels in certain situations.
|
||||
*/
|
||||
@ -137,8 +117,12 @@ typedef struct bActionChannel {
|
||||
*/
|
||||
typedef struct bAction {
|
||||
ID id;
|
||||
|
||||
ListBase chanbase; /* Action Channels in this Action */
|
||||
bPoseLib *poselib; /* PoseLib data of this Action (only if the action is used as poselib) */
|
||||
ListBase markers; /* TimeMarkers local to this Action for labelling 'poses' */
|
||||
|
||||
int active_marker; /* Index of active-marker (first marker = 1) */
|
||||
int pad;
|
||||
} bAction;
|
||||
|
||||
/* Action Editor Space. This is defined here instead of in DNA_space_types.h */
|
||||
|
@ -84,6 +84,7 @@ typedef struct Object {
|
||||
struct Path *path;
|
||||
struct BoundBox *bb;
|
||||
struct bAction *action;
|
||||
struct bAction *poselib;
|
||||
struct bPose *pose;
|
||||
void *data;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -103,6 +103,7 @@
|
||||
#include "BSE_filesel.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
#include "BIF_editaction.h"
|
||||
#include "BIF_editarmature.h"
|
||||
#include "BIF_editconstraint.h"
|
||||
#include "BIF_editdeform.h"
|
||||
@ -3694,6 +3695,7 @@ static void editing_panel_lattice_type(Object *ob, Lattice *lt)
|
||||
void do_armbuts(unsigned short event)
|
||||
{
|
||||
Object *ob= OBACT;
|
||||
bAction *act;
|
||||
|
||||
switch(event) {
|
||||
case B_ARM_RECALCDATA:
|
||||
@ -3731,45 +3733,125 @@ void do_armbuts(unsigned short event)
|
||||
if (ob && ob->pose)
|
||||
pose_clear_paths(ob);
|
||||
break;
|
||||
|
||||
case B_POSELIB_NEW:
|
||||
if (ob && ob->pose)
|
||||
poselib_init_new(ob);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
|
||||
case B_POSELIB_ADDPOSE:
|
||||
if (ob && ob->pose)
|
||||
poselib_add_current_pose(ob, 1);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
break;
|
||||
case B_POSELIB_REPLACEP:
|
||||
if (ob && ob->pose)
|
||||
poselib_add_current_pose(ob, 2);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
break;
|
||||
case B_POSELIB_REMOVEP:
|
||||
if (ob && ob->pose) {
|
||||
bAction *act= ob->pose->poselib;
|
||||
bPoseLib *pl= act->poselib;
|
||||
bPoseLibRef *plr= BLI_findlink(&pl->poses, pl->active_nr-1);
|
||||
bAction *act= ob->poselib;
|
||||
TimeMarker *marker= poselib_get_active_pose(act);
|
||||
|
||||
poselib_remove_pose(ob, plr);
|
||||
poselib_remove_pose(ob, marker);
|
||||
}
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
break;
|
||||
case B_POSELIB_VALIDATE:
|
||||
if (ob && ob->pose) {
|
||||
bAction *act= ob->pose->poselib;
|
||||
|
||||
poselib_validate_act(act);
|
||||
}
|
||||
if (ob && ob->pose)
|
||||
poselib_validate_act(ob->poselib);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
break;
|
||||
case B_POSELIB_APPLYP:
|
||||
if (ob && ob->pose)
|
||||
poselib_preview_poses(ob, 1);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
|
||||
/* note: copied from headerbuttons.c */
|
||||
case B_POSELIB_ALONE: //B_ACTALONE
|
||||
if (ob && ob->id.lib==0) {
|
||||
act= ob->poselib;
|
||||
|
||||
if (act->id.us > 1) {
|
||||
if (okee("Single user")) {
|
||||
ob->poselib= copy_action(act);
|
||||
act->id.us--;
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case B_POSELIB_DELETE: //B_ACTIONDELETE
|
||||
act= ob->poselib;
|
||||
|
||||
if (act)
|
||||
act->id.us--;
|
||||
ob->poselib=NULL;
|
||||
|
||||
BIF_undo_push("Unlink PoseLib");
|
||||
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
break;
|
||||
case B_POSELIB_BROWSE: //B_ACTIONBROWSE:
|
||||
{
|
||||
ID *id, *idtest;
|
||||
int nr= 1;
|
||||
|
||||
if (ob == NULL)
|
||||
break;
|
||||
act= ob->poselib;
|
||||
id= (ID *)act;
|
||||
|
||||
if (G.buts->menunr == -2) {
|
||||
activate_databrowse((ID *)ob->poselib, ID_AC, 0, B_POSELIB_BROWSE, &G.buts->menunr, do_armbuts);
|
||||
return;
|
||||
}
|
||||
if (G.buts->menunr < 0) break;
|
||||
|
||||
/* See if we have selected a valid action */
|
||||
for (idtest= G.main->action.first; idtest; idtest= idtest->next) {
|
||||
if (nr == G.buts->menunr) {
|
||||
break;
|
||||
}
|
||||
nr++;
|
||||
}
|
||||
|
||||
/* Store current action */
|
||||
if (!idtest) {
|
||||
/* 'Add New' option:
|
||||
* - make a copy of an exisiting action
|
||||
* - or make a new empty action if no existing action
|
||||
*/
|
||||
if (act) {
|
||||
idtest= (ID *)copy_action(act);
|
||||
}
|
||||
else {
|
||||
/* a plain action */
|
||||
idtest=(ID *)add_empty_action("PoseLib");
|
||||
}
|
||||
idtest->us--;
|
||||
}
|
||||
|
||||
if ((idtest != id) && (ob)) {
|
||||
act= (bAction *)idtest;
|
||||
|
||||
ob->poselib= act;
|
||||
id_us_plus(idtest);
|
||||
|
||||
if (id) id->us--;
|
||||
|
||||
/* Update everything */
|
||||
BIF_undo_push("Browse PoseLibs");
|
||||
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWHEADERS, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4982,50 +5064,38 @@ static void editing_panel_links(Object *ob)
|
||||
/* poselib for armatures */
|
||||
if (ob->type==OB_ARMATURE) {
|
||||
if ((ob->pose) && (ob->flag & OB_POSEMODE) && (G.obedit != ob)) {
|
||||
bPose *pose= ob->pose;
|
||||
bAction *act= pose->poselib;
|
||||
bAction *act= ob->poselib;
|
||||
|
||||
xco= 143;
|
||||
|
||||
uiDefBut(block, LABEL,0,"PoseLib:", xco, 154, 130,20, 0, 0, 0, 0, 0, "");
|
||||
uiDefBut(block, LABEL,0, "Action (PoseLib):", xco, 154, 130,20, 0, 0, 0, 0, 0, "");
|
||||
|
||||
/* PoseLib Action */
|
||||
if (act) {
|
||||
if (act->poselib==NULL) {
|
||||
uiBlockSetCol(block, TH_REDALERT);
|
||||
uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, REDRAWBUTSEDIT, "AC:", xco, 130, 140, 20, &pose->poselib, "Action to use as PoseLib - (Warning: this Action doesn't have a PoseLib)");
|
||||
uiBlockSetCol(block, TH_AUTO);
|
||||
}
|
||||
else {
|
||||
uiDefIDPoinBut(block, test_actionpoin_but, ID_AC, REDRAWBUTSEDIT, "AC:", xco, 130, 140, 20, &pose->poselib, "Action to use as PoseLib");
|
||||
}
|
||||
}
|
||||
uiDefBut(block, BUT, B_POSELIB_NEW, "New PoseLib", xco,110,70,20, 0, 0, 0, 0, 0, "Creates a new PoseLib");
|
||||
uiDefBut(block, BUT, B_POSELIB_VALIDATE, "Validate PoseLib", xco+70,110,70,20, 0, 0, 0, 0, 0, "Validates active PoseLib");
|
||||
uiBlockSetCol(block, TH_BUT_SETTING2);
|
||||
std_libbuttons(block, 143, 130, 0, NULL, B_POSELIB_BROWSE, ID_AC, 0, (ID *)act, (ID *)ob, &(G.buts->menunr), B_POSELIB_ALONE, 0, B_POSELIB_DELETE, 0, 0);
|
||||
uiBlockSetCol(block, TH_AUTO);
|
||||
|
||||
uiDefBut(block, BUT, B_POSELIB_VALIDATE, "Auto-Sync PoseLib", xco,110,160,20, 0, 0, 0, 0, 0, "Syncs the current PoseLib with the poses available");
|
||||
|
||||
/* poselib pose editing controls */
|
||||
if ((act) && (act->poselib)) {
|
||||
bPoseLib *pl= act->poselib;
|
||||
bPoseLibRef *plr= BLI_findlink(&pl->poses, pl->active_nr-1);
|
||||
int plr_count= BLI_countlist(&pl->poses);
|
||||
char *menustr= poselib_build_poses_menu(pl, "PoseLib Poses");
|
||||
if ((act) && (act->markers.first)) {
|
||||
TimeMarker *marker= poselib_get_active_pose(act);
|
||||
int count= BLI_countlist(&act->markers);
|
||||
char *menustr= poselib_build_poses_menu(act, "PoseLib Poses");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
/* currently 'active' pose */
|
||||
uiDefButI(block, MENU, B_POSELIB_APPLYP, menustr, xco, 85,18,20, &pl->active_nr, 1, plr_count, 0, 0, "Browses Poses in PoseLib. Applies chosen pose.");
|
||||
uiDefButI(block, MENU, B_POSELIB_APPLYP, menustr, xco, 85,18,20, &act->active_marker, 1, count, 0, 0, "Browses Poses in PoseLib. Applies chosen pose.");
|
||||
MEM_freeN(menustr);
|
||||
|
||||
if (pl->active_nr) {
|
||||
but= uiDefBut(block, TEX, REDRAWBUTSEDIT,"", 161,85,140-18-20,20, plr->name, 0, 31, 0, 0, "Displays current PoseLib Pose name. Click to change.");
|
||||
//uiButSetFunc(but, verify_vertexgroup_name_func, defGroup, NULL);
|
||||
//uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
|
||||
|
||||
but = uiDefIconBut(block, BUT, B_POSELIB_REMOVEP, VICON_X, 263, 85, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove this PoseLib Pose from PoseLib");
|
||||
if (act->active_marker) {
|
||||
uiDefBut(block, TEX, REDRAWBUTSEDIT,"", xco+18,85,160-18-20,20, marker->name, 0, 63, 0, 0, "Displays current PoseLib Pose name. Click to change.");
|
||||
uiDefIconBut(block, BUT, B_POSELIB_REMOVEP, VICON_X, xco+160-20, 85, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove this PoseLib Pose from PoseLib");
|
||||
}
|
||||
|
||||
/* add new poses */
|
||||
uiDefBut(block, BUT, B_POSELIB_ADDPOSE, "Add Pose", xco,65,70,20, 0, 0, 0, 0, 0, "Add current pose to PoseLib");
|
||||
uiDefBut(block, BUT, B_POSELIB_REPLACEP, "Replace Pose", xco+70,65,70,20, 0, 0, 0, 0, 0, "Replace existing PoseLib Pose with current pose");
|
||||
uiDefBut(block, BUT, B_POSELIB_ADDPOSE, "Add Pose", xco,65,80,20, 0, 0, 0, 0, 0, "Add current pose to PoseLib");
|
||||
uiDefBut(block, BUT, B_POSELIB_REPLACEP, "Replace Pose", xco+80,65,80,20, 0, 0, 0, 0, 0, "Replace existing PoseLib Pose with current pose");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
}
|
||||
|
@ -883,7 +883,7 @@ void drawactionspace(ScrArea *sa, void *spacedata)
|
||||
glClearColor(col[0], col[1], col[2], 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if(curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
|
||||
if (curarea->winx>SCROLLB+10 && curarea->winy>SCROLLH+10) {
|
||||
if(G.v2d->scroll) {
|
||||
ofsx= curarea->winrct.xmin;
|
||||
ofsy= curarea->winrct.ymin;
|
||||
@ -927,8 +927,10 @@ void drawactionspace(ScrArea *sa, void *spacedata)
|
||||
/* Draw current frame */
|
||||
draw_cfra_action();
|
||||
|
||||
/* Draw markers */
|
||||
draw_markers_timespace(0);
|
||||
/* Draw markers (local behind scene ones, as local obscure scene markers) */
|
||||
if (act)
|
||||
draw_markers_timespace(&act->markers, DRAW_MARKERS_LOCAL);
|
||||
draw_markers_timespace(SCE_MARKERS, 0);
|
||||
|
||||
/* Draw 'curtains' for preview */
|
||||
draw_anim_preview_timespace();
|
||||
|
@ -2247,7 +2247,7 @@ void drawipospace(ScrArea *sa, void *spacedata)
|
||||
draw_anim_preview_timespace();
|
||||
|
||||
/* draw markers */
|
||||
draw_markers_timespace(0);
|
||||
draw_markers_timespace(SCE_MARKERS, 0);
|
||||
|
||||
/* restore viewport */
|
||||
mywinset(sa->win);
|
||||
|
@ -792,7 +792,7 @@ void drawnlaspace(ScrArea *sa, void *spacedata)
|
||||
draw_cfra_action();
|
||||
|
||||
/* draw markers */
|
||||
draw_markers_timespace(0);
|
||||
draw_markers_timespace(SCE_MARKERS, 0);
|
||||
|
||||
/* Draw preview 'curtains' */
|
||||
draw_anim_preview_timespace();
|
||||
|
@ -1064,7 +1064,7 @@ void drawseqspace(ScrArea *sa, void *spacedata)
|
||||
}
|
||||
|
||||
/* Draw markers */
|
||||
draw_markers_timespace(1);
|
||||
draw_markers_timespace(SCE_MARKERS, DRAW_MARKERS_LINES);
|
||||
|
||||
/* restore viewport */
|
||||
mywinset(sa->win);
|
||||
|
@ -220,7 +220,7 @@ void drawsoundspace(ScrArea *sa, void *spacedata)
|
||||
}
|
||||
|
||||
draw_cfra_sound(spacedata);
|
||||
draw_markers_timespace(0);
|
||||
draw_markers_timespace(SCE_MARKERS, 0);
|
||||
|
||||
/* restore viewport */
|
||||
mywinset(curarea->win);
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "BIF_language.h"
|
||||
|
||||
#include "BSE_drawipo.h"
|
||||
#include "BSE_time.h"
|
||||
#include "BSE_view.h"
|
||||
|
||||
#include "blendef.h"
|
||||
@ -84,7 +85,7 @@
|
||||
/* ---- prototypes ------ */
|
||||
void drawtimespace(ScrArea *, void *);
|
||||
|
||||
|
||||
/* draws a current frame indicator for the TimeLine */
|
||||
static void draw_cfra_time(SpaceTime *stime)
|
||||
{
|
||||
float vec[2];
|
||||
@ -144,9 +145,13 @@ static void draw_cfra_time(SpaceTime *stime)
|
||||
|
||||
}
|
||||
|
||||
static void draw_marker(TimeMarker *marker, int lines)
|
||||
/* ---------- */
|
||||
|
||||
/* function to draw markers */
|
||||
static void draw_marker(TimeMarker *marker, int flag)
|
||||
{
|
||||
float xpos, ypixels, xscale, yscale;
|
||||
int icon_id= 0;
|
||||
|
||||
xpos = marker->frame;
|
||||
/* no time correction for framelen! space is drawn with old values */
|
||||
@ -161,7 +166,7 @@ static void draw_marker(TimeMarker *marker, int lines)
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
/* verticle line */
|
||||
if (lines) {
|
||||
if (flag & DRAW_MARKERS_LINES) {
|
||||
setlinestyle(3);
|
||||
if(marker->flag & SELECT)
|
||||
glColor4ub(255,255,255, 96);
|
||||
@ -176,14 +181,20 @@ static void draw_marker(TimeMarker *marker, int lines)
|
||||
}
|
||||
|
||||
/* 5 px to offset icon to align properly, space / pixels corrects for zoom */
|
||||
if(marker->flag & SELECT)
|
||||
BIF_icon_draw(xpos*xscale-5.0, 12.0, ICON_MARKER_HLT);
|
||||
else
|
||||
BIF_icon_draw(xpos*xscale-5.0, 12.0, ICON_MARKER);
|
||||
if (flag & DRAW_MARKERS_LOCAL) {
|
||||
icon_id= (marker->flag & ACTIVE) ? ICON_PMARKER_ACT :
|
||||
(marker->flag & SELECT) ? ICON_PMARKER_SEL :
|
||||
ICON_PMARKER;
|
||||
}
|
||||
else {
|
||||
icon_id= (marker->flag & SELECT) ? ICON_MARKER_HLT :
|
||||
ICON_MARKER;
|
||||
}
|
||||
BIF_icon_draw(xpos*xscale-5.0, 12.0, icon_id);
|
||||
|
||||
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) {
|
||||
@ -202,24 +213,27 @@ static void draw_marker(TimeMarker *marker, int lines)
|
||||
glScalef(xscale, yscale, 1.0);
|
||||
}
|
||||
|
||||
static void draw_markers_time(int lines)
|
||||
/* Draw Scene-Markers for the TimeLine */
|
||||
static void draw_markers_time(int flag)
|
||||
{
|
||||
TimeMarker *marker;
|
||||
|
||||
/* unselected markers are drawn at the first time */
|
||||
for(marker= G.scene->markers.first; marker; marker= marker->next) {
|
||||
if(!(marker->flag & SELECT)) draw_marker(marker, lines);
|
||||
for (marker= G.scene->markers.first; marker; marker= marker->next) {
|
||||
if (!(marker->flag & SELECT)) draw_marker(marker, flag);
|
||||
}
|
||||
|
||||
/* 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= G.scene->markers.first; marker; marker= marker->next) {
|
||||
if(marker->flag & SELECT) draw_marker(marker, lines);
|
||||
* (jiri: it is hack, it could be solved better)
|
||||
*/
|
||||
for (marker= G.scene->markers.first; marker; marker= marker->next) {
|
||||
if (marker->flag & SELECT) draw_marker(marker, flag);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_markers_timespace(int lines)
|
||||
/* Draw specified set of markers for Animation Editors */
|
||||
void draw_markers_timespace(ListBase *markers, int flag)
|
||||
{
|
||||
TimeMarker *marker;
|
||||
float yspace, ypixels;
|
||||
@ -233,21 +247,21 @@ void draw_markers_timespace(int lines)
|
||||
glTranslatef(0.0f, -11.0*yspace/ypixels, 0.0f);
|
||||
|
||||
/* unselected markers are drawn at the first time */
|
||||
for(marker= G.scene->markers.first; marker; marker= marker->next) {
|
||||
if(!(marker->flag & SELECT)) draw_marker(marker, lines);
|
||||
for (marker= markers->first; marker; marker= marker->next) {
|
||||
if (!(marker->flag & SELECT)) draw_marker(marker, flag);
|
||||
}
|
||||
|
||||
/* selected markers are drawn later ... selected markers have to cover unselected
|
||||
* markers laying at the same position as selected markers */
|
||||
for(marker= G.scene->markers.first; marker; marker= marker->next) {
|
||||
if(marker->flag & SELECT) draw_marker(marker, lines);
|
||||
for (marker= markers->first; marker; marker= marker->next) {
|
||||
if (marker->flag & SELECT) draw_marker(marker, flag);
|
||||
}
|
||||
|
||||
glTranslatef(0.0f, -G.v2d->cur.ymin, 0.0f);
|
||||
glTranslatef(0.0f, 11.0*yspace/ypixels, 0.0f);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void draw_anim_preview_timespace()
|
||||
{
|
||||
/* only draw this if preview range is set */
|
||||
|
@ -2227,9 +2227,11 @@ void column_select_action_keys(int mode)
|
||||
}
|
||||
|
||||
/* some quick defines for borderselect modes */
|
||||
#define ACTEDIT_BORDERSEL_ALL 0
|
||||
#define ACTEDIT_BORDERSEL_FRA 1
|
||||
#define ACTEDIT_BORDERSEL_CHA 2
|
||||
enum {
|
||||
ACTEDIT_BORDERSEL_ALL = 0,
|
||||
ACTEDIT_BORDERSEL_FRA,
|
||||
ACTEDIT_BORDERSEL_CHA
|
||||
};
|
||||
|
||||
/* borderselect: for keyframes only */
|
||||
void borderselect_action (void)
|
||||
@ -2351,7 +2353,7 @@ static void mouse_action (int selectmode)
|
||||
bActionChannel *achan= NULL;
|
||||
bConstraintChannel *conchan= NULL;
|
||||
IpoCurve *icu= NULL;
|
||||
TimeMarker *marker;
|
||||
TimeMarker *marker, *pmarker;
|
||||
|
||||
void *act_channel;
|
||||
short sel, act_type;
|
||||
@ -2363,9 +2365,63 @@ static void mouse_action (int selectmode)
|
||||
if (datatype == ACTCONT_ACTION) act= (bAction *)data;
|
||||
|
||||
act_channel= get_nearest_action_key(&selx, &sel, &act_type, &achan);
|
||||
marker=find_nearest_marker(1);
|
||||
marker= find_nearest_marker(SCE_MARKERS, 1);
|
||||
pmarker= (act) ? find_nearest_marker(&act->markers, 1) : NULL;
|
||||
|
||||
if (marker) {
|
||||
/* what about scene's markers? */
|
||||
if (selectmode == SELECT_REPLACE) {
|
||||
deselect_markers(0, 0);
|
||||
marker->flag |= SELECT;
|
||||
}
|
||||
else if (selectmode == SELECT_INVERT) {
|
||||
if (marker->flag & SELECT)
|
||||
marker->flag &= ~SELECT;
|
||||
else
|
||||
marker->flag |= SELECT;
|
||||
}
|
||||
else if (selectmode == SELECT_ADD)
|
||||
marker->flag |= SELECT;
|
||||
else if (selectmode == SELECT_SUBTRACT)
|
||||
marker->flag &= ~SELECT;
|
||||
|
||||
if (act_channel) {
|
||||
std_rmouse_transform(transform_markers);
|
||||
|
||||
allqueue(REDRAWMARKER, 0);
|
||||
}
|
||||
else if (pmarker) {
|
||||
/* action's markers are drawn behind scene markers */
|
||||
if (selectmode == SELECT_REPLACE) {
|
||||
action_set_activemarker(act, pmarker, 1);
|
||||
pmarker->flag |= SELECT;
|
||||
}
|
||||
else if (selectmode == SELECT_INVERT) {
|
||||
if (pmarker->flag & SELECT) {
|
||||
pmarker->flag &= ~SELECT;
|
||||
action_set_activemarker(act, NULL, 0);
|
||||
}
|
||||
else {
|
||||
pmarker->flag |= SELECT;
|
||||
action_set_activemarker(act, pmarker, 0);
|
||||
}
|
||||
}
|
||||
else if (selectmode == SELECT_ADD) {
|
||||
pmarker->flag |= SELECT;
|
||||
action_set_activemarker(act, pmarker, 0);
|
||||
}
|
||||
else if (selectmode == SELECT_SUBTRACT) {
|
||||
pmarker->flag &= ~SELECT;
|
||||
action_set_activemarker(act, NULL, 0);
|
||||
}
|
||||
|
||||
// TODO: local-markers cannot be moved atm...
|
||||
//std_rmouse_transform(transform_markers);
|
||||
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
}
|
||||
else if (act_channel) {
|
||||
/* must have been a channel */
|
||||
switch (act_type) {
|
||||
case ACTTYPE_ICU:
|
||||
icu= (IpoCurve *)act_channel;
|
||||
@ -2410,27 +2466,6 @@ static void mouse_action (int selectmode)
|
||||
allqueue(REDRAWOOPS, 0);
|
||||
allqueue(REDRAWBUTSALL, 0);
|
||||
}
|
||||
else if (marker) {
|
||||
/* not channel, so maybe marker */
|
||||
if (selectmode == SELECT_REPLACE) {
|
||||
deselect_markers(0, 0);
|
||||
marker->flag |= SELECT;
|
||||
}
|
||||
else if (selectmode == SELECT_INVERT) {
|
||||
if (marker->flag & SELECT)
|
||||
marker->flag &= ~SELECT;
|
||||
else
|
||||
marker->flag |= SELECT;
|
||||
}
|
||||
else if (selectmode == SELECT_ADD)
|
||||
marker->flag |= SELECT;
|
||||
else if (selectmode == SELECT_SUBTRACT)
|
||||
marker->flag &= ~SELECT;
|
||||
|
||||
std_rmouse_transform(transform_markers);
|
||||
|
||||
allqueue(REDRAWMARKER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* lefthand side - mouse-click */
|
||||
@ -2699,7 +2734,7 @@ void bottom_sel_action ()
|
||||
if (VISIBLE_ACHAN(achan)) {
|
||||
if (SEL_ACHAN(achan) && !(achan->flag & ACHAN_MOVED)) {
|
||||
/* take it out off the chain keep data */
|
||||
BLI_remlink (&act->chanbase, achan);
|
||||
BLI_remlink(&act->chanbase, achan);
|
||||
/* add at end */
|
||||
BLI_addtail(&act->chanbase, achan);
|
||||
achan->flag |= ACHAN_MOVED;
|
||||
@ -2720,6 +2755,141 @@ void bottom_sel_action ()
|
||||
allqueue(REDRAWNLA, 0);
|
||||
}
|
||||
|
||||
/* **************************************************** */
|
||||
/* ACTION MARKERS (PoseLib features) */
|
||||
/* NOTE: yes, these duplicate code from edittime.c a bit, but these do a bit more...
|
||||
* These could get merged with those someday if need be... (Aligorith, 20071230)
|
||||
*/
|
||||
|
||||
/* Makes the given marker the active one
|
||||
* - deselect indicates whether unactive ones should be deselected too
|
||||
*/
|
||||
void action_set_activemarker (bAction *act, TimeMarker *active, short deselect)
|
||||
{
|
||||
TimeMarker *marker;
|
||||
int index= 0;
|
||||
|
||||
/* sanity checks */
|
||||
if (act == NULL)
|
||||
return;
|
||||
act->active_marker= 0;
|
||||
|
||||
/* set appropriate flags for all markers */
|
||||
for (marker=act->markers.first; marker; marker=marker->next, index++) {
|
||||
/* only active may be active */
|
||||
if (marker == active) {
|
||||
act->active_marker= index + 1;
|
||||
marker->flag |= (SELECT|ACTIVE);
|
||||
}
|
||||
else {
|
||||
if (deselect)
|
||||
marker->flag &= ~(SELECT|ACTIVE);
|
||||
else
|
||||
marker->flag &= ~ACTIVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Adds a local marker to the active action */
|
||||
void action_add_localmarker (bAction *act, int frame)
|
||||
{
|
||||
TimeMarker *marker;
|
||||
char name[64];
|
||||
|
||||
/* sanity checks */
|
||||
if (act == NULL)
|
||||
return;
|
||||
|
||||
/* get name of marker */
|
||||
sprintf(name, "Pose");
|
||||
if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0)
|
||||
return;
|
||||
|
||||
/* add marker to action - replaces any existing marker there */
|
||||
for (marker= act->markers.first; marker; marker= marker->next) {
|
||||
if (marker->frame == frame) {
|
||||
BLI_strncpy(marker->name, name, sizeof(marker->name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (marker == NULL) {
|
||||
marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
|
||||
|
||||
BLI_strncpy(marker->name, name, sizeof(marker->name));
|
||||
marker->frame= frame;
|
||||
|
||||
BLI_addtail(&act->markers, marker);
|
||||
}
|
||||
|
||||
/* sets the newly added marker as the active one */
|
||||
action_set_activemarker(act, marker, 1);
|
||||
|
||||
BIF_undo_push("Action Add Marker");
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
}
|
||||
|
||||
/* Renames the active local marker to the active action */
|
||||
void action_rename_localmarker (bAction *act)
|
||||
{
|
||||
TimeMarker *marker;
|
||||
char name[64];
|
||||
int val;
|
||||
|
||||
/* sanity checks */
|
||||
if (act == NULL)
|
||||
return;
|
||||
|
||||
/* get active marker to rename */
|
||||
if (act->active_marker == 0)
|
||||
return;
|
||||
else
|
||||
val= act->active_marker;
|
||||
|
||||
if (val <= 0) return;
|
||||
marker= BLI_findlink(&act->markers, val-1);
|
||||
if (marker == NULL) return;
|
||||
|
||||
/* get name of marker */
|
||||
sprintf(name, marker->name);
|
||||
if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0)
|
||||
return;
|
||||
|
||||
/* copy name */
|
||||
BLI_strncpy(marker->name, name, sizeof(marker->name));
|
||||
|
||||
/* undo and update */
|
||||
BIF_undo_push("Action Rename Marker");
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
}
|
||||
|
||||
/* Deletes all selected markers, and adjusts things as appropriate */
|
||||
void action_remove_localmarkers (bAction *act)
|
||||
{
|
||||
TimeMarker *marker, *next;
|
||||
|
||||
/* sanity checks */
|
||||
if (act == NULL)
|
||||
return;
|
||||
|
||||
/* remove selected markers */
|
||||
for (marker= act->markers.first; marker; marker= next) {
|
||||
next= marker->next;
|
||||
|
||||
if (marker->flag & SELECT)
|
||||
BLI_freelinkN(&act->markers, marker);
|
||||
}
|
||||
|
||||
/* clear active just in case */
|
||||
act->active_marker= 0;
|
||||
|
||||
/* undo and update */
|
||||
BIF_undo_push("Action Remove Marker(s)");
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
}
|
||||
|
||||
/* **************************************************** */
|
||||
/* EVENT HANDLING */
|
||||
|
||||
@ -2860,6 +3030,18 @@ void winqreadactionspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
allqueue(REDRAWMARKER, 0);
|
||||
break;
|
||||
|
||||
case LKEY:
|
||||
/* poselib manipulation - only for actions */
|
||||
if (datatype == ACTCONT_ACTION) {
|
||||
if (G.qual == LR_SHIFTKEY)
|
||||
action_add_localmarker(data, CFRA);
|
||||
else if (G.qual == (LR_CTRLKEY|LR_SHIFTKEY))
|
||||
action_rename_localmarker(data);
|
||||
else if (G.qual == LR_ALTKEY)
|
||||
action_remove_localmarkers(data);
|
||||
}
|
||||
break;
|
||||
|
||||
case MKEY:
|
||||
if (G.qual & LR_SHIFTKEY) {
|
||||
/* mirror keyframes */
|
||||
|
@ -1465,7 +1465,7 @@ void mouse_select_ipo(void)
|
||||
if(G.sipo->editipo==0) return;
|
||||
|
||||
get_status_editipo();
|
||||
marker=find_nearest_marker(1);
|
||||
marker=find_nearest_marker(SCE_MARKERS, 1);
|
||||
|
||||
/* map ipo-points for editing if scaled ipo */
|
||||
if (NLA_IPO_SCALED) {
|
||||
|
@ -1257,7 +1257,7 @@ static void mouse_nla(int selectmode)
|
||||
|
||||
/* Try object ipo or ob-constraint ipo selection */
|
||||
base= get_nearest_nlachannel_ob_key(&selx, &sel);
|
||||
marker=find_nearest_marker(1);
|
||||
marker=find_nearest_marker(SCE_MARKERS, 1);
|
||||
if (base) {
|
||||
isdone= 1;
|
||||
|
||||
|
@ -791,7 +791,7 @@ void mouse_select_seq(void)
|
||||
int hand,seldir;
|
||||
TimeMarker *marker;
|
||||
|
||||
marker=find_nearest_marker(1);
|
||||
marker=find_nearest_marker(0, 1);
|
||||
|
||||
if (marker) {
|
||||
int oldflag;
|
||||
|
@ -173,7 +173,7 @@ void winqreadsoundspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
getmouseco_areawin(mval);
|
||||
areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
|
||||
|
||||
marker = find_nearest_marker(0);
|
||||
marker = find_nearest_marker(SCE_MARKERS, 0);
|
||||
if (marker) {
|
||||
if ((G.qual & LR_SHIFTKEY)==0)
|
||||
deselect_markers(0, 0);
|
||||
|
@ -473,7 +473,7 @@ void get_minmax_markers(short sel, float *first, float *last)
|
||||
*last= max;
|
||||
}
|
||||
|
||||
TimeMarker *find_nearest_marker(int clip_y)
|
||||
TimeMarker *find_nearest_marker(ListBase *markers, int clip_y)
|
||||
{
|
||||
TimeMarker *marker;
|
||||
float xmin, xmax;
|
||||
@ -483,7 +483,7 @@ TimeMarker *find_nearest_marker(int clip_y)
|
||||
getmouseco_areawin (mval);
|
||||
|
||||
/* first clip selection in Y */
|
||||
if((clip_y) && (mval[1] > 30))
|
||||
if ((clip_y) && (mval[1] > 30))
|
||||
return NULL;
|
||||
|
||||
mval[0]-=7;
|
||||
@ -494,7 +494,7 @@ TimeMarker *find_nearest_marker(int clip_y)
|
||||
xmin= rectf.xmin;
|
||||
xmax= rectf.xmax;
|
||||
|
||||
for(marker= G.scene->markers.first; marker; marker= marker->next) {
|
||||
for (marker= markers->first; marker; marker= marker->next) {
|
||||
if ((marker->frame > xmin) && (marker->frame <= xmax)) {
|
||||
return marker;
|
||||
}
|
||||
@ -877,9 +877,9 @@ void winqreadtimespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
case RIGHTMOUSE: /* select/deselect marker */
|
||||
getmouseco_areawin(mval);
|
||||
areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
|
||||
|
||||
|
||||
cfra= find_nearest_marker_time(dx);
|
||||
|
||||
|
||||
if (G.qual && LR_SHIFTKEY)
|
||||
select_timeline_marker_frame(cfra, 1);
|
||||
else
|
||||
|
@ -174,7 +174,10 @@ enum {
|
||||
ACTMENU_MARKERS_DUPLICATE,
|
||||
ACTMENU_MARKERS_DELETE,
|
||||
ACTMENU_MARKERS_NAME,
|
||||
ACTMENU_MARKERS_MOVE
|
||||
ACTMENU_MARKERS_MOVE,
|
||||
ACTMENU_MARKERS_LOCALADD,
|
||||
ACTMENU_MARKERS_LOCALRENAME,
|
||||
ACTMENU_MARKERS_LOCALDELETE
|
||||
};
|
||||
|
||||
void do_action_buttons(unsigned short event)
|
||||
@ -1103,6 +1106,16 @@ static void do_action_markermenu(void *arg, int event)
|
||||
case ACTMENU_MARKERS_MOVE:
|
||||
transform_markers('g', 0);
|
||||
break;
|
||||
|
||||
case ACTMENU_MARKERS_LOCALADD:
|
||||
action_add_localmarker(G.saction->action, CFRA);
|
||||
break;
|
||||
case ACTMENU_MARKERS_LOCALDELETE:
|
||||
action_remove_localmarkers(G.saction->action);
|
||||
break;
|
||||
case ACTMENU_MARKERS_LOCALRENAME:
|
||||
action_rename_localmarker(G.saction->action);
|
||||
break;
|
||||
}
|
||||
|
||||
allqueue(REDRAWMARKER, 0);
|
||||
@ -1130,7 +1143,15 @@ static uiBlock *action_markermenu(void *arg_unused)
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_NAME, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Grab/Move Marker|Ctrl G", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_MOVE, "");
|
||||
|
||||
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
|
||||
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add Local Marker|Shift L", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALADD, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rename Local Marker|Ctrl Shift L", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALRENAME, "");
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Local Marker|Alt L", 0, yco-=20,
|
||||
menuwidth, 19, NULL, 0.0, 0.0, 1, ACTMENU_MARKERS_LOCALDELETE, "");
|
||||
|
||||
if(curarea->headertype==HEADERTOP) {
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
|
@ -325,6 +325,7 @@ int std_libbuttons(uiBlock *block, short xco, short yco,
|
||||
}
|
||||
|
||||
if( GS(id->name)==ID_IP) len= 110;
|
||||
else if((yco) && (GS(id->name)==ID_AC)) len= 100; // comes from button panel (poselib)
|
||||
else if(yco) len= 140; // comes from button panel
|
||||
else len= 120;
|
||||
|
||||
@ -932,6 +933,7 @@ void do_global_buttons(unsigned short event)
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWIPO, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
break;
|
||||
case B_ACTIONBROWSE:
|
||||
if (!ob)
|
||||
@ -1030,6 +1032,7 @@ void do_global_buttons(unsigned short event)
|
||||
allqueue(REDRAWNLA, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWHEADERS, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1703,7 +1706,8 @@ void do_global_buttons2(short event)
|
||||
if(act->id.lib) {
|
||||
if(okee("Make local")) {
|
||||
make_local_action(act);
|
||||
allqueue(REDRAWACTION,0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1711,12 +1715,13 @@ void do_global_buttons2(short event)
|
||||
case B_ACTALONE:
|
||||
if(ob && ob->id.lib==0) {
|
||||
act= ob->action;
|
||||
|
||||
|
||||
if(act->id.us>1) {
|
||||
if(okee("Single user")) {
|
||||
ob->action=copy_action(act);
|
||||
act->id.us--;
|
||||
allqueue(REDRAWACTION, 0);
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "BSE_editipo.h"
|
||||
|
||||
#include "BDR_drawaction.h"
|
||||
#include "BSE_time.h"
|
||||
|
||||
#include "BIF_poselib.h"
|
||||
#include "BIF_interface.h"
|
||||
@ -72,6 +73,7 @@
|
||||
#include "BIF_toets.h"
|
||||
#include "BIF_toolbox.h"
|
||||
|
||||
|
||||
#include "blendef.h"
|
||||
|
||||
#include "PIL_time.h" /* sleep */
|
||||
@ -86,22 +88,21 @@
|
||||
* It acts as a kind of "glorified clipboard for poses", allowing for naming of poses.
|
||||
*
|
||||
* Features:
|
||||
* - PoseLibs are simply normal Actions, but with a poselib
|
||||
* - PoseLibs are simply normal Actions
|
||||
* - Each "pose" is simply a set of keyframes that occur on a particular frame
|
||||
* -> a bPoseLibRef struct is used to identify and label poses in the Action
|
||||
* -> all bPoseLibRefs are stored in the order they were added
|
||||
* -> keys for poses should occur on each positively numbered frame (starting from frame 1)
|
||||
* -> a set of TimeMarkers that belong to each Action, help 'label' where a 'pose' can be
|
||||
* found in the Action
|
||||
* - The Scrollwheel or PageUp/Down buttons when used in a special mode or after pressing/holding
|
||||
* [a modifier] key, cycles through the poses available for the active pose's poselib, allowing the
|
||||
* animator to preview what action best suits that pose
|
||||
*/
|
||||
/* ************************************************************* */
|
||||
|
||||
/* gets list of poses in poselib as a string */
|
||||
char *poselib_build_poses_menu (bPoseLib *pl, char title[])
|
||||
/* gets list of poses in poselib as a string usable for pupmenu() */
|
||||
char *poselib_build_poses_menu (bAction *act, char title[])
|
||||
{
|
||||
DynStr *pupds= BLI_dynstr_new();
|
||||
bPoseLibRef *plr;
|
||||
TimeMarker *marker;
|
||||
char *str;
|
||||
char buf[64];
|
||||
int i;
|
||||
@ -110,14 +111,14 @@ char *poselib_build_poses_menu (bPoseLib *pl, char title[])
|
||||
sprintf(buf, "%s%%t|", title);
|
||||
BLI_dynstr_append(pupds, buf);
|
||||
|
||||
/* loop through keyingsets, adding them */
|
||||
for (plr=pl->poses.first, i=1; plr; plr=plr->next, i++) {
|
||||
BLI_dynstr_append(pupds, plr->name);
|
||||
/* loop through markers, adding them */
|
||||
for (marker=act->markers.first, i=1; marker; marker=marker->next, i++) {
|
||||
BLI_dynstr_append(pupds, marker->name);
|
||||
|
||||
sprintf(buf, "%%x%d", i);
|
||||
BLI_dynstr_append(pupds, buf);
|
||||
|
||||
if (plr->next)
|
||||
if (marker->next)
|
||||
BLI_dynstr_append(pupds, "|");
|
||||
}
|
||||
|
||||
@ -128,75 +129,28 @@ char *poselib_build_poses_menu (bPoseLib *pl, char title[])
|
||||
return str;
|
||||
}
|
||||
|
||||
/* finds an unique name for pose to be added to poselib */
|
||||
void poselib_unique_pose_name (bPoseLib *pl, char name[])
|
||||
{
|
||||
bPoseLibRef *plr;
|
||||
char tempname[32];
|
||||
int number = 1, exists = 0;
|
||||
char *dot;
|
||||
|
||||
/* See if we are given an empty string */
|
||||
if (name[0] == '\0') {
|
||||
/* give it default name first */
|
||||
strcpy(name, "Pose");
|
||||
}
|
||||
|
||||
/* See if we even need to do this */
|
||||
for (plr= pl->poses.first; plr; plr= plr->next) {
|
||||
if (!strcmp(name, plr->name)) {
|
||||
exists = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (exists == 0)
|
||||
return;
|
||||
|
||||
/* Strip off the suffix */
|
||||
dot = strchr(name, '.');
|
||||
if (dot)
|
||||
*dot=0;
|
||||
|
||||
for (number = 1; number <= 999; number++) {
|
||||
sprintf(tempname, "%s.%03d", name, number);
|
||||
|
||||
exists = 0;
|
||||
for (plr= pl->poses.first; plr; plr= plr->next) {
|
||||
if (strcmp(name, tempname)==0) {
|
||||
exists = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exists == 0) {
|
||||
BLI_strncpy(name, tempname, 32);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* gets the first available frame in poselib to store a pose on
|
||||
* - frames start from 1, and a pose should occur on every frame... 0 is error!
|
||||
*/
|
||||
int poselib_get_free_index (bPoseLib *pl)
|
||||
int poselib_get_free_index (bAction *act)
|
||||
{
|
||||
bPoseLibRef *plr;
|
||||
TimeMarker *marker;
|
||||
int low=0, high=0;
|
||||
|
||||
/* sanity checks */
|
||||
if (ELEM(NULL, pl, pl->poses.first)) return 1;
|
||||
if (ELEM(NULL, act, act->markers.first)) return 1;
|
||||
|
||||
/* loop over poses finding various values (poses are not stored in chronological order) */
|
||||
for (plr= pl->poses.first; plr; plr= plr->next) {
|
||||
for (marker= act->markers.first; marker; marker= marker->next) {
|
||||
/* only increase low if value is 1 greater than low, to find "gaps" where
|
||||
* poses were removed from the poselib
|
||||
*/
|
||||
if (plr->frame == (low + 1))
|
||||
if (marker->frame == (low + 1))
|
||||
low++;
|
||||
|
||||
/* value replaces high if it is the highest value encountered yet */
|
||||
if (plr->frame > high)
|
||||
high= plr->frame;
|
||||
if (marker->frame > high)
|
||||
high= marker->frame;
|
||||
}
|
||||
|
||||
/* - if low is not equal to high, then low+1 is a gap
|
||||
@ -208,46 +162,41 @@ int poselib_get_free_index (bPoseLib *pl)
|
||||
return (high + 1);
|
||||
}
|
||||
|
||||
/* returns the active pose for a poselib */
|
||||
TimeMarker *poselib_get_active_pose (bAction *act)
|
||||
{
|
||||
if ((act) && (act->active_marker))
|
||||
return BLI_findlink(&act->markers, act->active_marker-1);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ************************************************************* */
|
||||
|
||||
/* Initialise a new poselib (whether it is needed or not) */
|
||||
bPoseLib *poselib_init_new (Object *ob)
|
||||
bAction *poselib_init_new (Object *ob)
|
||||
{
|
||||
bPose *pose= (ob) ? ob->pose : NULL;
|
||||
bAction *act;
|
||||
bPoseLib *pl;
|
||||
|
||||
if (ELEM(NULL, ob, pose))
|
||||
/* sanity checks - only for armatures */
|
||||
if (ELEM(NULL, ob, ob->pose))
|
||||
return NULL;
|
||||
|
||||
/* init pose's poselib action (unlink old one if there) */
|
||||
if (pose->poselib)
|
||||
pose->poselib->id.us--;
|
||||
pose->poselib= add_empty_action("PoseLib");
|
||||
act= pose->poselib;
|
||||
/* init object's poselib action (unlink old one if there) */
|
||||
if (ob->poselib)
|
||||
ob->poselib->id.us--;
|
||||
ob->poselib= add_empty_action("PoseLib");
|
||||
|
||||
/* init actions's poselib data */
|
||||
if (act->poselib == NULL)
|
||||
act->poselib= MEM_callocN(sizeof(bPoseLib), "bPoseLib");
|
||||
pl= act->poselib;
|
||||
|
||||
return pl;
|
||||
return ob->poselib;
|
||||
}
|
||||
|
||||
/* Initialise a new poselib (checks if that needs to happen) */
|
||||
bPoseLib *poselib_validate (Object *ob)
|
||||
bAction *poselib_validate (Object *ob)
|
||||
{
|
||||
bPose *pose= (ob) ? ob->pose : NULL;
|
||||
bAction *act= (pose) ? pose->poselib : NULL;
|
||||
bPoseLib *pl= (act) ? act->poselib : NULL;
|
||||
|
||||
if (ELEM(NULL, ob, pose))
|
||||
if (ELEM(NULL, ob, ob->pose))
|
||||
return NULL;
|
||||
|
||||
if (ELEM(NULL, act, pl))
|
||||
else if (ob->poselib == NULL)
|
||||
return poselib_init_new(ob);
|
||||
else
|
||||
return pl;
|
||||
return ob->poselib;
|
||||
}
|
||||
|
||||
|
||||
@ -258,8 +207,7 @@ void poselib_validate_act (bAction *act)
|
||||
{
|
||||
ListBase keys = {NULL, NULL};
|
||||
ActKeyColumn *ak;
|
||||
bPoseLib *pl;
|
||||
bPoseLibRef *plr, *plrn;
|
||||
TimeMarker *marker, *markern;
|
||||
|
||||
/* validate action and poselib */
|
||||
if (act == NULL) {
|
||||
@ -267,49 +215,44 @@ void poselib_validate_act (bAction *act)
|
||||
return;
|
||||
}
|
||||
|
||||
if (act->poselib == NULL)
|
||||
act->poselib= MEM_callocN(sizeof(bPoseLib), "bPoseLib");
|
||||
pl= act->poselib;
|
||||
|
||||
/* determine which frames have keys */
|
||||
action_to_keylist(act, &keys, NULL);
|
||||
|
||||
/* for each key, make sure there is a correspnding pose */
|
||||
for (ak= keys.first; ak; ak= ak->next) {
|
||||
/* check if any pose matches this */
|
||||
for (plr= pl->poses.first; plr; plr= plr->next) {
|
||||
if (IS_EQ(plr->frame, ak->cfra)) {
|
||||
plr->flag = 1;
|
||||
for (marker= act->markers.first; marker; marker= marker->next) {
|
||||
if (IS_EQ(marker->frame, ak->cfra)) {
|
||||
marker->flag = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* add new if none found */
|
||||
if (plr == NULL) {
|
||||
char name[32];
|
||||
if (marker == NULL) {
|
||||
char name[64];
|
||||
|
||||
/* add pose to poselib */
|
||||
plr= MEM_callocN(sizeof(bPoseLibRef), "bPoseLibRef");
|
||||
marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
|
||||
|
||||
strcpy(name, "Pose");
|
||||
poselib_unique_pose_name(pl, name);
|
||||
BLI_strncpy(plr->name, name, sizeof(plr->name));
|
||||
BLI_strncpy(marker->name, name, sizeof(marker->name));
|
||||
|
||||
plr->frame= (int)ak->cfra;
|
||||
plr->flag= 1;
|
||||
marker->frame= (int)ak->cfra;
|
||||
marker->flag= -1;
|
||||
|
||||
BLI_addtail(&pl->poses, plr);
|
||||
BLI_addtail(&act->markers, marker);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove all untagged poses (unused), and remove all tags */
|
||||
for (plr= pl->poses.first; plr; plr= plrn) {
|
||||
plrn= plr->next;
|
||||
for (marker= act->markers.first; marker; marker= markern) {
|
||||
markern= marker->next;
|
||||
|
||||
if (plr->flag == 0)
|
||||
BLI_freelinkN(&pl->poses, plr);
|
||||
if (marker->flag != -1)
|
||||
BLI_freelinkN(&act->markers, marker);
|
||||
else
|
||||
plr->flag = 0;
|
||||
marker->flag = 0;
|
||||
}
|
||||
|
||||
/* free temp memory */
|
||||
@ -353,13 +296,12 @@ void poselib_add_current_pose (Object *ob, int val)
|
||||
bArmature *arm= (ob) ? ob->data : NULL;
|
||||
bPose *pose= (ob) ? ob->pose : NULL;
|
||||
bPoseChannel *pchan;
|
||||
bPoseLib *pl;
|
||||
bPoseLibRef *plr;
|
||||
TimeMarker *marker;
|
||||
bAction *act;
|
||||
bActionChannel *achan;
|
||||
IpoCurve *icu;
|
||||
int frame;
|
||||
char name[32];
|
||||
char name[64];
|
||||
|
||||
/* sanity check */
|
||||
if (ELEM3(NULL, ob, arm, pose))
|
||||
@ -367,7 +309,7 @@ void poselib_add_current_pose (Object *ob, int val)
|
||||
|
||||
/* mode - add new or replace existing */
|
||||
if (val == 0) {
|
||||
if (pose->poselib && pose->poselib->poselib->poses.first) {
|
||||
if ((ob->poselib) && (ob->poselib->markers.first)) {
|
||||
val= pupmenu("PoseLib Add Current Pose%t|Add New%x1|Replace Existing%x2");
|
||||
if (val <= 0) return;
|
||||
}
|
||||
@ -375,24 +317,23 @@ void poselib_add_current_pose (Object *ob, int val)
|
||||
val= 1;
|
||||
}
|
||||
|
||||
if ((pose->poselib) && (val == 2)) {
|
||||
if ((ob->poselib) && (val == 2)) {
|
||||
char *menustr;
|
||||
|
||||
/* get poselib */
|
||||
act= pose->poselib;
|
||||
pl= act->poselib;
|
||||
act= ob->poselib;
|
||||
|
||||
/* get the pose to replace */
|
||||
menustr= poselib_build_poses_menu(pl, "Replace PoseLib Pose");
|
||||
menustr= poselib_build_poses_menu(act, "Replace PoseLib Pose");
|
||||
val= pupmenu(menustr);
|
||||
if (menustr) MEM_freeN(menustr);
|
||||
|
||||
if (val <= 0) return;
|
||||
plr= BLI_findlink(&pl->poses, val-1);
|
||||
if (plr == NULL) return;
|
||||
marker= BLI_findlink(&act->markers, val-1);
|
||||
if (marker == NULL) return;
|
||||
|
||||
/* get the frame from the poselib */
|
||||
frame= plr->frame;
|
||||
frame= marker->frame;
|
||||
}
|
||||
else {
|
||||
/* get name of pose */
|
||||
@ -401,18 +342,26 @@ void poselib_add_current_pose (Object *ob, int val)
|
||||
return;
|
||||
|
||||
/* get/initialise poselib */
|
||||
pl= poselib_validate(ob);
|
||||
act= pose->poselib;
|
||||
act= poselib_validate(ob);
|
||||
|
||||
/* validate name and get frame */
|
||||
poselib_unique_pose_name(pl, name);
|
||||
frame= poselib_get_free_index(pl);
|
||||
frame= poselib_get_free_index(act);
|
||||
|
||||
/* add pose to poselib */
|
||||
plr= MEM_callocN(sizeof(bPoseLibRef), "bPoseLibRef");
|
||||
BLI_strncpy(plr->name, name, sizeof(plr->name));
|
||||
plr->frame= frame;
|
||||
BLI_addtail(&pl->poses, plr);
|
||||
/* add pose to poselib - replaces any existing pose there */
|
||||
for (marker= act->markers.first; marker; marker= marker->next) {
|
||||
if (marker->frame == frame) {
|
||||
BLI_strncpy(marker->name, name, sizeof(marker->name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (marker == NULL) {
|
||||
marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
|
||||
|
||||
BLI_strncpy(marker->name, name, sizeof(marker->name));
|
||||
marker->frame= frame;
|
||||
|
||||
BLI_addtail(&act->markers, marker);
|
||||
}
|
||||
}
|
||||
|
||||
/* loop through selected posechannels, keying their pose to the action */
|
||||
@ -448,7 +397,7 @@ void poselib_add_current_pose (Object *ob, int val)
|
||||
}
|
||||
|
||||
/* store new 'active' pose number */
|
||||
pl->active_nr= BLI_countlist(&pl->poses);
|
||||
act->active_marker= BLI_countlist(&act->markers);
|
||||
|
||||
BIF_undo_push("PoseLib Add Pose");
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
@ -456,12 +405,11 @@ void poselib_add_current_pose (Object *ob, int val)
|
||||
|
||||
|
||||
/* This tool removes the pose that the user selected from the poselib (or the provided pose) */
|
||||
void poselib_remove_pose (Object *ob, bPoseLibRef *plr)
|
||||
void poselib_remove_pose (Object *ob, TimeMarker *marker)
|
||||
{
|
||||
bPose *pose= (ob) ? ob->pose : NULL;
|
||||
bAction *act= (pose) ? pose->poselib : NULL;
|
||||
bAction *act= (ob) ? ob->poselib : NULL;
|
||||
bActionChannel *achan;
|
||||
bPoseLib *pl= (act) ? act->poselib : NULL;
|
||||
char *menustr;
|
||||
int val;
|
||||
|
||||
@ -470,24 +418,24 @@ void poselib_remove_pose (Object *ob, bPoseLibRef *plr)
|
||||
error("PoseLib is only for Armatures in PoseMode");
|
||||
return;
|
||||
}
|
||||
if (ELEM(NULL, act, pl)) {
|
||||
error("Pose doesn't have a valid PoseLib");
|
||||
if (act == NULL) {
|
||||
error("Object doesn't have PoseLib data");
|
||||
return;
|
||||
}
|
||||
|
||||
/* get index (and pointer) of pose to remove */
|
||||
if (plr == NULL) {
|
||||
menustr= poselib_build_poses_menu(pl, "Remove PoseLib Pose");
|
||||
if (marker == NULL) {
|
||||
menustr= poselib_build_poses_menu(act, "Remove PoseLib Pose");
|
||||
val= pupmenu(menustr);
|
||||
if (menustr) MEM_freeN(menustr);
|
||||
|
||||
if (val <= 0) return;
|
||||
plr= BLI_findlink(&pl->poses, val-1);
|
||||
if (plr == NULL) return;
|
||||
marker= BLI_findlink(&act->markers, val-1);
|
||||
if (marker == NULL) return;
|
||||
}
|
||||
else {
|
||||
/* only continue if pose belongs to poselib */
|
||||
if (BLI_findindex(&pl->poses, plr) == -1)
|
||||
if (BLI_findindex(&act->markers, marker) == -1)
|
||||
return;
|
||||
}
|
||||
|
||||
@ -501,7 +449,7 @@ void poselib_remove_pose (Object *ob, bPoseLibRef *plr)
|
||||
for (icu= ipo->curve.first; icu; icu= icu->next) {
|
||||
for (i=0, bezt=icu->bezt; i < icu->totvert; i++, bezt++) {
|
||||
/* check if remove... */
|
||||
if (IS_EQ(bezt->vec[1][0], plr->frame)) {
|
||||
if (IS_EQ(bezt->vec[1][0], marker->frame)) {
|
||||
delete_icu_key(icu, i);
|
||||
break;
|
||||
}
|
||||
@ -510,14 +458,15 @@ void poselib_remove_pose (Object *ob, bPoseLibRef *plr)
|
||||
}
|
||||
|
||||
/* remove poselib from list */
|
||||
BLI_freelinkN(&pl->poses, plr);
|
||||
BLI_freelinkN(&act->markers, marker);
|
||||
|
||||
/* fix active pose number */
|
||||
pl->active_nr= 0;
|
||||
act->active_marker= 0;
|
||||
|
||||
/* undo + redraw */
|
||||
BIF_undo_push("PoseLib Remove Pose");
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -525,10 +474,9 @@ void poselib_remove_pose (Object *ob, bPoseLibRef *plr)
|
||||
void poselib_rename_pose (Object *ob)
|
||||
{
|
||||
bPose *pose= (ob) ? ob->pose : NULL;
|
||||
bAction *act= (pose) ? pose->poselib : NULL;
|
||||
bPoseLib *pl= (act) ? act->poselib : NULL;
|
||||
bPoseLibRef *plr;
|
||||
char *menustr, name[32];
|
||||
bAction *act= (ob) ? ob->poselib : NULL;
|
||||
TimeMarker *marker;
|
||||
char *menustr, name[64];
|
||||
int val;
|
||||
|
||||
/* check if valid poselib */
|
||||
@ -536,34 +484,32 @@ void poselib_rename_pose (Object *ob)
|
||||
error("PoseLib is only for Armatures in PoseMode");
|
||||
return;
|
||||
}
|
||||
if (ELEM(NULL, act, pl)) {
|
||||
error("Pose doesn't have a valid PoseLib");
|
||||
if (act == NULL) {
|
||||
error("Object doesn't have a valid PoseLib");
|
||||
return;
|
||||
}
|
||||
|
||||
/* get index of pose to remove */
|
||||
menustr= poselib_build_poses_menu(pl, "Rename PoseLib Pose");
|
||||
menustr= poselib_build_poses_menu(act, "Rename PoseLib Pose");
|
||||
val= pupmenu(menustr);
|
||||
if (menustr) MEM_freeN(menustr);
|
||||
|
||||
if (val <= 0) return;
|
||||
plr= BLI_findlink(&pl->poses, val-1);
|
||||
if (plr == NULL) return;
|
||||
marker= BLI_findlink(&act->markers, val-1);
|
||||
if (marker == NULL) return;
|
||||
|
||||
/* get name of pose */
|
||||
sprintf(name, plr->name);
|
||||
sprintf(name, marker->name);
|
||||
if (sbutton(name, 0, sizeof(name)-1, "Name: ") == 0)
|
||||
return;
|
||||
|
||||
/* validate name */
|
||||
poselib_unique_pose_name(pl, name); // hmm what happens with the old pose's name...
|
||||
|
||||
/* copy name */
|
||||
BLI_strncpy(plr->name, name, sizeof(plr->name));
|
||||
BLI_strncpy(marker->name, name, sizeof(marker->name));
|
||||
|
||||
/* undo and update */
|
||||
BIF_undo_push("PoseLib Rename Pose");
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
allqueue(REDRAWACTION, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -574,23 +520,17 @@ typedef struct tPoseLib_Backup {
|
||||
struct tPoseLib_Backup *next, *prev;
|
||||
|
||||
bPoseChannel *pchan;
|
||||
|
||||
float oldloc[3];
|
||||
float oldsize[3];
|
||||
float oldquat[4];
|
||||
|
||||
int oldflag;
|
||||
bPoseChannel olddata;
|
||||
} tPoseLib_Backup;
|
||||
|
||||
/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
|
||||
static void poselib_backup_posecopy (ListBase *backups, bPose *pose)
|
||||
static void poselib_backup_posecopy (ListBase *backups, bPose *pose, bAction *act)
|
||||
{
|
||||
bAction *poselib= pose->poselib;
|
||||
bActionChannel *achan;
|
||||
bPoseChannel *pchan;
|
||||
|
||||
/* for each posechannel that has an actionchannel in */
|
||||
for (achan= poselib->chanbase.first; achan; achan= achan->next) {
|
||||
for (achan= act->chanbase.first; achan; achan= achan->next) {
|
||||
/* try to find posechannel */
|
||||
pchan= get_pose_channel(pose, achan->name);
|
||||
|
||||
@ -600,11 +540,8 @@ static void poselib_backup_posecopy (ListBase *backups, bPose *pose)
|
||||
|
||||
plb= MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
|
||||
|
||||
VECCOPY(plb->oldloc, pchan->loc);
|
||||
VECCOPY(plb->oldsize, pchan->size);
|
||||
QUATCOPY(plb->oldquat, pchan->quat);
|
||||
|
||||
plb->pchan= pchan;
|
||||
memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
|
||||
|
||||
BLI_addtail(backups, plb);
|
||||
}
|
||||
@ -617,14 +554,11 @@ static void poselib_backup_restore (ListBase *backups)
|
||||
tPoseLib_Backup *plb;
|
||||
|
||||
for (plb= backups->first; plb; plb= plb->next) {
|
||||
VECCOPY(plb->pchan->loc, plb->oldloc);
|
||||
VECCOPY(plb->pchan->size, plb->oldsize);
|
||||
VECCOPY(plb->pchan->quat, plb->oldquat);
|
||||
|
||||
plb->pchan->flag = plb->oldflag;
|
||||
memcpy(plb->pchan, &plb->olddata, sizeof(bPoseChannel));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ---------------------------- */
|
||||
|
||||
/* Applies the appropriate stored pose from the pose-library to the current pose
|
||||
@ -632,14 +566,14 @@ static void poselib_backup_restore (ListBase *backups)
|
||||
* - gets the string to print in the header
|
||||
* - this code is based on the code for extract_pose_from_action in blenkernel/action.c
|
||||
*/
|
||||
static void poselib_apply_pose (Object *ob, bPoseLibRef *plr, char headerstr[])
|
||||
static void poselib_apply_pose (Object *ob, TimeMarker *marker, char headerstr[])
|
||||
{
|
||||
bPose *pose= ob->pose;
|
||||
bPoseChannel *pchan;
|
||||
bAction *act= pose->poselib;
|
||||
bAction *act= ob->poselib;
|
||||
bActionChannel *achan;
|
||||
IpoCurve *icu;
|
||||
int frame= plr->frame;
|
||||
int frame= marker->frame;
|
||||
|
||||
/* start applying - only those channels which have a key at this point in time! */
|
||||
for (achan= act->chanbase.first; achan; achan= achan->next) {
|
||||
@ -662,11 +596,13 @@ static void poselib_apply_pose (Object *ob, bPoseLibRef *plr, char headerstr[])
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
/* apply pose */
|
||||
/* apply pose - only if posechannel selected? */
|
||||
if (found) {
|
||||
pchan= get_pose_channel(pose, achan->name);
|
||||
|
||||
if (pchan) {
|
||||
if ( (pchan) && (pchan->bone) &&
|
||||
(pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) )
|
||||
{
|
||||
/* Evaluates and sets the internal ipo values */
|
||||
calc_ipo(achan->ipo, frame);
|
||||
/* This call also sets the pchan flags */
|
||||
@ -686,9 +622,8 @@ static void poselib_apply_pose (Object *ob, bPoseLibRef *plr, char headerstr[])
|
||||
/* Auto-keys/tags bones affected by the pose used from the poselib */
|
||||
static void poselib_keytag_pose (Object *ob)
|
||||
{
|
||||
bPose *pose= ob->pose;
|
||||
bPoseChannel *pchan;
|
||||
bAction *act= pose->poselib;
|
||||
bAction *act= ob->poselib;
|
||||
bActionChannel *achan;
|
||||
|
||||
/* start tagging/keying */
|
||||
@ -735,6 +670,35 @@ static void poselib_keytag_pose (Object *ob)
|
||||
|
||||
/* ---------------------------- */
|
||||
|
||||
/* This helper function is called during poselib_preview_poses to find the
|
||||
* pose to preview next (after a change event)
|
||||
*/
|
||||
static TimeMarker *poselib_preview_get_next (bAction *act, TimeMarker *current, int step)
|
||||
{
|
||||
if (step) {
|
||||
TimeMarker *marker, *next;
|
||||
|
||||
/* Loop through the markers in a cyclic fashion, incrementing/decrementing step as appropriate
|
||||
* until step == 0. At this point, marker should be the correct marker.
|
||||
*/
|
||||
if (step > 0) {
|
||||
for (marker=current; marker && step; marker=next, step--)
|
||||
next= (marker->next) ? marker->next : act->markers.first;
|
||||
}
|
||||
else {
|
||||
for (marker=current; marker && step; marker=next, step++)
|
||||
next= (marker->prev) ? marker->prev : act->markers.last;
|
||||
}
|
||||
|
||||
/* don't go anywhere if for some reason an error occurred */
|
||||
return (marker) ? marker : current;
|
||||
}
|
||||
else
|
||||
return current;
|
||||
}
|
||||
|
||||
/* ---------------------------- */
|
||||
|
||||
/* defines for poselib_preview_poses --> ret_val values */
|
||||
enum {
|
||||
PL_PREVIEW_RUNNING = 0,
|
||||
@ -759,9 +723,8 @@ void poselib_preview_poses (Object *ob, short apply_active)
|
||||
|
||||
bPose *pose= (ob) ? (ob->pose) : NULL;
|
||||
bArmature *arm= (ob) ? (ob->data) : NULL;
|
||||
bAction *act= (pose) ? (pose->poselib) : NULL;
|
||||
bPoseLib *pl= (act) ? (act->poselib) : NULL;
|
||||
bPoseLibRef *plr= (pl == NULL) ? NULL : (pl->active_nr) ? BLI_findlink(&pl->poses, pl->active_nr-1) : pl->poses.first;
|
||||
bAction *act= (ob) ? (ob->poselib) : NULL;
|
||||
TimeMarker *marker= poselib_get_active_pose(act);
|
||||
Base *base;
|
||||
|
||||
short ret_val= (apply_active) ? PL_PREVIEW_RUNONCE : PL_PREVIEW_RUNNING;
|
||||
@ -770,21 +733,21 @@ void poselib_preview_poses (Object *ob, short apply_active)
|
||||
char headerstr[200];
|
||||
|
||||
/* check if valid poselib */
|
||||
if (ELEM(NULL, ob, pose)) {
|
||||
if (ELEM3(NULL, ob, pose, arm)) {
|
||||
error("PoseLib is only for Armatures in PoseMode");
|
||||
return;
|
||||
}
|
||||
if (ELEM(NULL, act, pl)) {
|
||||
error("Pose doesn't have a valid PoseLib");
|
||||
if (act == NULL) {
|
||||
error("Object doesn't have a valid PoseLib");
|
||||
return;
|
||||
}
|
||||
if (plr == NULL) {
|
||||
error("PoseLib has no poses to preview");
|
||||
if (marker == NULL) {
|
||||
error("PoseLib has no poses to preview/apply");
|
||||
return;
|
||||
}
|
||||
|
||||
/* make backup of current pose for restoring pose */
|
||||
poselib_backup_posecopy(&backups, pose);
|
||||
poselib_backup_posecopy(&backups, pose, act);
|
||||
|
||||
/* set depsgraph flags */
|
||||
/* make sure the lock is set OK, unlock can be accidentally saved? */
|
||||
@ -805,7 +768,7 @@ void poselib_preview_poses (Object *ob, short apply_active)
|
||||
firsttime = 0;
|
||||
|
||||
/* pose should be the right one to draw */
|
||||
poselib_apply_pose(ob, plr, headerstr);
|
||||
poselib_apply_pose(ob, marker, headerstr);
|
||||
|
||||
/* old optimize trick... this enforces to bypass the depgraph
|
||||
* - note: code copied from transform_generics.c -> recalcData()
|
||||
@ -827,7 +790,7 @@ void poselib_preview_poses (Object *ob, short apply_active)
|
||||
|
||||
/* do header print - if interactively previewing */
|
||||
if (ret_val == PL_PREVIEW_RUNNING) {
|
||||
sprintf(headerstr, "PoseLib Previewing Pose: \"%s\" | Use ScrollWheel or PageUp/Down to change", plr->name);
|
||||
sprintf(headerstr, "PoseLib Previewing Pose: \"%s\" | Use ScrollWheel or PageUp/Down to change", marker->name);
|
||||
headerprint(headerstr);
|
||||
}
|
||||
|
||||
@ -866,17 +829,31 @@ void poselib_preview_poses (Object *ob, short apply_active)
|
||||
ret_val= PL_PREVIEW_CONFIRM;
|
||||
break;
|
||||
|
||||
/* change to previous pose - go back to end of list if no previous (cyclic) */
|
||||
/* change to previous pose (cyclic) */
|
||||
case PAGEUPKEY:
|
||||
case WHEELUPMOUSE:
|
||||
plr= (plr->prev) ? plr->prev : pl->poses.last;
|
||||
case RIGHTARROWKEY:
|
||||
marker= poselib_preview_get_next(act, marker, -1);
|
||||
redraw= PL_PREVIEW_REDRAWALL;
|
||||
break;
|
||||
|
||||
/* change to next pose - go back to start of list if no next (cyclic) */
|
||||
/* change to next pose (cyclic) */
|
||||
case PAGEDOWNKEY:
|
||||
case WHEELDOWNMOUSE:
|
||||
plr= (plr->next) ? plr->next : pl->poses.first;
|
||||
case LEFTARROWKEY:
|
||||
marker= poselib_preview_get_next(act, marker, 1);
|
||||
redraw= PL_PREVIEW_REDRAWALL;
|
||||
break;
|
||||
|
||||
/* jump 5 poses (cyclic, back) */
|
||||
case DOWNARROWKEY:
|
||||
marker= poselib_preview_get_next(act, marker, -5);
|
||||
redraw= PL_PREVIEW_REDRAWALL;
|
||||
break;
|
||||
|
||||
/* jump 5 poses (cyclic, forward) */
|
||||
case UPARROWKEY:
|
||||
marker= poselib_preview_get_next(act, marker, 5);
|
||||
redraw= PL_PREVIEW_REDRAWALL;
|
||||
break;
|
||||
|
||||
@ -931,7 +908,7 @@ void poselib_preview_poses (Object *ob, short apply_active)
|
||||
poselib_keytag_pose(ob);
|
||||
|
||||
/* change active pose setting */
|
||||
pl->active_nr= BLI_findindex(&pl->poses, plr) + 1;
|
||||
act->active_marker= BLI_findindex(&act->markers, marker) + 1;
|
||||
|
||||
/* Update event for pose and deformation children */
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
||||
|
Loading…
Reference in New Issue
Block a user