[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [13137] trunk/blender/source/blender/src/ poselib.c: == PoseLib - Quick Search for Preview ==
Joshua Leung
aligorith at gmail.com
Sat Jan 5 11:54:33 CET 2008
Revision: 13137
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=13137
Author: aligorith
Date: 2008-01-05 11:54:33 +0100 (Sat, 05 Jan 2008)
Log Message:
-----------
== PoseLib - Quick Search for Preview ==
Now, when Previewing/Browsing poses with Ctrl-L, it is possible to type in part of a name to limit the poses which can get chosen to hone in on the poses you wish to apply more quickly.
* The search is case insensitive, and doesn't look for complete matches (it will 'match' if the whole search-string is found).
* Only basic text manipulation capabilities are available for editing the search string (i.e. backspace, del, home, end, move text-cursor forward ->, move text-cursor backwards <-).
* Pose browsing using the Scroll-Wheel and Page up/down can be used to browse through the matches
* View manipulation is only possible with MMB, as numpad keys are used for search-string input.
In the process, I've recoded the preview function to be more modular. It's now split up more, like the Transform core.
Modified Paths:
--------------
trunk/blender/source/blender/src/poselib.c
Modified: trunk/blender/source/blender/src/poselib.c
===================================================================
--- trunk/blender/source/blender/src/poselib.c 2008-01-05 10:01:05 UTC (rev 13136)
+++ trunk/blender/source/blender/src/poselib.c 2008-01-05 10:54:33 UTC (rev 13137)
@@ -515,6 +515,49 @@
/* ************************************************************* */
+/* Simple struct for storing settings/data for use during PoseLib preview */
+typedef struct tPoseLib_PreviewData {
+ ListBase backups; /* tPoseLib_Backup structs for restoring poses */
+ ListBase searchp; /* LinkData structs storing list of poses which match the current search-string */
+
+ Object *ob; /* object to work on */
+ bArmature *arm; /* object's armature data */
+ bPose *pose; /* object's pose */
+ bAction *act; /* poselib to use */
+ TimeMarker *marker; /* 'active' pose */
+
+ short state; /* state of main loop */
+ short redraw; /* redraw/update settings during main loop */
+ short firsttime; /* first loop... (no restore) */
+
+ int selcount; /* number of selected elements to work on */
+ int totcount; /* total number of elements to work on */
+
+ char headerstr[200]; /* Info-text to print in header */
+
+ char searchstr[64]; /* (Part of) Name to search for to filter poses that get shown */
+ char searchold[64]; /* Previously set searchstr (from last loop run), so that we can detected when to rebuild searchp */
+ short search_cursor; /* position of cursor in searchstr (cursor occurs before the item at the nominated index) */
+} tPoseLib_PreviewData;
+
+/* defines for tPoseLib_PreviewData->state values */
+enum {
+ PL_PREVIEW_ERROR = -1,
+ PL_PREVIEW_RUNNING,
+ PL_PREVIEW_CONFIRM,
+ PL_PREVIEW_CANCEL,
+ PL_PREVIEW_RUNONCE
+};
+
+/* defines for tPoseLib_PreviewData->redraw values */
+enum {
+ PL_PREVIEW_NOREDRAW = 0,
+ PL_PREVIEW_REDRAWALL,
+ PL_PREVIEW_REDRAWHEADER,
+};
+
+/* ---------------------------- */
+
/* simple struct for storing backup info */
typedef struct tPoseLib_Backup {
struct tPoseLib_Backup *next, *prev;
@@ -524,41 +567,46 @@
} 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, bAction *act)
+static void poselib_backup_posecopy (tPoseLib_PreviewData *pld)
{
bActionChannel *achan;
bPoseChannel *pchan;
/* for each posechannel that has an actionchannel in */
- for (achan= act->chanbase.first; achan; achan= achan->next) {
+ for (achan= pld->act->chanbase.first; achan; achan= achan->next) {
/* try to find posechannel */
- pchan= get_pose_channel(pose, achan->name);
+ pchan= get_pose_channel(pld->pose, achan->name);
/* backup data if available */
if (pchan) {
tPoseLib_Backup *plb;
+ /* store backup */
plb= MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup");
plb->pchan= pchan;
memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel));
- BLI_addtail(backups, plb);
+ BLI_addtail(&pld->backups, plb);
+
+ /* mark as being affected */
+ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))
+ pld->selcount++;
+ pld->totcount++;
}
}
}
/* Restores original pose - doesn't do constraints currently */
-static void poselib_backup_restore (ListBase *backups)
+static void poselib_backup_restore (tPoseLib_PreviewData *pld)
{
tPoseLib_Backup *plb;
- for (plb= backups->first; plb; plb= plb->next) {
+ for (plb= pld->backups.first; plb; plb= plb->next) {
memcpy(plb->pchan, &plb->olddata, sizeof(bPoseChannel));
}
}
-
/* ---------------------------- */
/* Applies the appropriate stored pose from the pose-library to the current pose
@@ -566,15 +614,20 @@
* - 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, TimeMarker *marker, char headerstr[])
+static void poselib_apply_pose (tPoseLib_PreviewData *pld)
{
- bPose *pose= ob->pose;
+ bPose *pose= pld->pose;
bPoseChannel *pchan;
- bAction *act= ob->poselib;
+ bAction *act= pld->act;
bActionChannel *achan;
IpoCurve *icu;
- int frame= marker->frame;
+ int frame;
+ if (pld->marker)
+ frame= pld->marker->frame;
+ else
+ return;
+
/* start applying - only those channels which have a key at this point in time! */
for (achan= act->chanbase.first; achan; achan= achan->next) {
short found= 0;
@@ -600,13 +653,18 @@
if (found) {
pchan= get_pose_channel(pose, achan->name);
- 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 */
- execute_action_ipo(achan, pchan);
+ if (pchan) {
+ short ok;
+
+ ok= (pchan->bone) ? (pchan->bone->flag & (BONE_SELECTED|BONE_ACTIVE)) : 0;
+ ok= (ok || pld->selcount) ? 1 : 0;
+
+ if (ok) {
+ /* Evaluates and sets the internal ipo values */
+ calc_ipo(achan->ipo, frame);
+ /* This call also sets the pchan flags */
+ execute_action_ipo(achan, pchan);
+ }
}
}
}
@@ -620,21 +678,22 @@
}
/* Auto-keys/tags bones affected by the pose used from the poselib */
-static void poselib_keytag_pose (Object *ob)
+static void poselib_keytag_pose (tPoseLib_PreviewData *pld)
{
+ bPose *pose= pld->pose;
bPoseChannel *pchan;
- bAction *act= ob->poselib;
+ bAction *act= pld->act;
bActionChannel *achan;
/* start tagging/keying */
for (achan= act->chanbase.first; achan; achan= achan->next) {
/* only for selected action channels */
if (achan->flag & ACHAN_SELECTED) {
- pchan= get_pose_channel(ob->pose, achan->name);
+ pchan= get_pose_channel(pose, achan->name);
if (pchan) {
if (G.flags & G_RECORDKEYS) {
- ID *id= &ob->id;
+ ID *id= &pld->ob->id;
/* Set keys on pose */
if (pchan->flag & POSE_ROT) {
@@ -673,216 +732,361 @@
/* 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)
+static void poselib_preview_get_next (tPoseLib_PreviewData *pld, 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;
+ if ((pld->marker) && (step)) {
+ /* search-string dictates a special approach */
+ if (pld->searchstr[0]) {
+ TimeMarker *marker;
+ LinkData *ld, *ldn, *ldc;
+
+ /* free and rebuild if needed (i.e. if search-str changed) */
+ if (strcmp(pld->searchstr, pld->searchold)) {
+ /* free list of temporary search matches */
+ BLI_freelistN(&pld->searchp);
+
+ /* generate a new list of search matches */
+ for (marker= pld->act->markers.first; marker; marker= marker->next) {
+ /* does the name partially match?
+ * - don't worry about case, to make it easier for users to quickly input a name (or
+ * part of one), which is the whole point of this feature
+ */
+ if (BLI_strcasestr(marker->name, pld->searchstr)) {
+ /* make link-data to store reference to it */
+ ld= MEM_callocN(sizeof(LinkData), "PoseMatch");
+ ld->data= marker;
+ BLI_addtail(&pld->searchp, ld);
+ }
+ }
+
+ /* set current marker to NULL (so that we start from first) */
+ pld->marker= NULL;
+ }
+
+ /* check if any matches */
+ if (pld->searchp.first == NULL) {
+ pld->marker= NULL;
+ return;
+ }
+
+ /* find first match */
+ for (ldc= pld->searchp.first; ldc; ldc= ldc->next) {
+ if (ldc->data == pld->marker)
+ break;
+ }
+ if (ldc == NULL)
+ ldc= pld->searchp.first;
+
+ /* Loop through the matches 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 (ld=ldc; ld && step; ld=ldn, step--)
+ ldn= (ld->next) ? ld->next : pld->searchp.first;
+ }
+ else {
+ for (ld=ldc; ld && step; ld=ldn, step++)
+ ldn= (ld->prev) ? ld->prev : pld->searchp.last;
+ }
+
+ /* set marker */
+ if (ld)
+ pld->marker= ld->data;
}
else {
- for (marker=current; marker && step; marker=next, step++)
- next= (marker->prev) ? marker->prev : act->markers.last;
+ 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=pld->marker; marker && step; marker=next, step--)
+ next= (marker->next) ? marker->next : pld->act->markers.first;
+ }
+ else {
+ for (marker=pld->marker; marker && step; marker=next, step++)
+ next= (marker->prev) ? marker->prev : pld->act->markers.last;
+ }
+
+ /* it should be fairly impossible for marker to be NULL */
+ if (marker)
+ pld->marker= marker;
}
+ }
+}
+
+/* specially handle events for searching */
+static void poselib_preview_handle_search (tPoseLib_PreviewData *pld, unsigned short event, char ascii)
+{
+ if (ascii) {
+ /* character to add to the string */
+ short index= pld->search_cursor;
+ short len= (pld->searchstr[0]) ? strlen(pld->searchstr) : 0;
+ short i;
- /* don't go anywhere if for some reason an error occurred */
- return (marker) ? marker : current;
+ if (len) {
+ for (i = len; i > index; i--)
+ pld->searchstr[i]= pld->searchstr[i-1];
+ }
+ else
+ pld->searchstr[1]= 0;
+
+ pld->searchstr[index]= ascii;
+ pld->search_cursor++;
+
+ poselib_preview_get_next(pld, 1);
+ pld->redraw = PL_PREVIEW_REDRAWALL;
}
- else
- return current;
+ else {
+ /* some form of string manipulation */
+ switch (event) {
+ case BACKSPACEKEY:
+ if (pld->searchstr[0] && pld->search_cursor) {
+ short len= strlen(pld->searchstr);
+ short index= pld->search_cursor;
+ short i;
+
+ for (i = index; i <= len; i++)
+ pld->searchstr[i-1] = pld->searchstr[i];
+
+ pld->search_cursor--;
+
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list