A pose-handling script

Current version (September 24, 2006):

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib16d.zip

This is my first script. It is a pose-handling tool which works with Blender poses in Blender Library format. Hopefully I’ve managed to make this compatible with a wide range of armatures. I’ve tested this on four or five myself, but they were all automatically generated by the cr2 bone import script or a bvh import script. Please let me know if this works for anyone else.

This script handles three types of poses.
-Straight Blender Library poses (bone.quats saved directly)
-PoseMatrix poses (which should be able to save IK - I haven’t tested this, but it is based on der_ton’s working code for md5)
-Poses which I call “no roll” because they are compatible with armatures regardless of bone roll settings. These are based on Cambo’s recent BVH script success and are the pose format exported by PoserPython in my companion script.

Default poses are compatible with Blender Library, but I don’t create thumbnails or data files for BL, so BL won’t read them. :frowning: This script can read Blender Library poses, however.

“IK” poseMatrix and “no roll” poses can be used together.

The script also:
-Mirrors poses (symmetry)
-Flips poses right or left
-Screens one side of a pose, right or left
-Loads poses partially, using a slider value, from 1% to 200% intensity
-Can load a pose additive to the existing armature pose

Most of these functions can work in “real time”, without loading a pose. The exception is the partial pose, which doesn’t seem to want to cooperate…

The symmetry functions use a user-definable system in which you can enter your own specific symmetry notation and specify either prefixes or suffixes (as well as use an alternate set of prefixes if you edit the script).

The script can save partial poses for face and hand groups, but the groups are currently hard-coded. This can be expanded if people will tell me what part names they like to use for fingers or face parts. Currently this can be altered by editing the script.

Oh. And there’s a “zero pose” function, which zeroes all bone settings, restoring the default rest state pose.

The script has been prepared with 2.41, but I have no reason to expect it not to be 2.42 compatible…

To do:

-Animation import and export via batch loading and saving of poses.
-Some bone roll tools which I plan to add from another script which I’ve discontinued.
-Whatever anyone cares to suggest (within my as-yet-meager skill range).

I hope this can be useful for someone. Please let me know if there are any problems, questions, or comments.

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib6b_noweight.py

Interesting. I’ll investigate this when I have time…

Aligorith

Hi Basil_Fawlty.
I’ve tryed it on Ryan Dale’s rig a with 2 saved poses with a walk, and loading and flipping and it works a treat. A very useful script great work.

My only comment so far is the gui. Its a little cluttered, Im no GUI wizard but maybe some space and backgrounds for the differant sections? One feature which I think would enhance the script would be a window/list to load and then see you saved poses, and the possiblity to double click on the list item to trigger the pose.

Here is the blend i made with the poses included:
pose_script_test.zip

Thank you for the feedback, nozzy, and thank you for the test file. I was able to test IK pose saving using that file, and it looks like the poseMatrix save method works. The IK pose is successfully saved, but this can’t really be confirmed unless you switch off IK before loading the pose. Perhaps I need to add a function to switch IK on or off with a single click. Hmm. While IK is enabled, Blender Library default poses work fine. I haven’t really worked with IK at all since I started using Blender, so I hope I learned a bit from studying the file.

Your example also helped me track down a bug. It seems that the “len” method doesn’t notice the period (".") in a string. This caused me some temporary panic when I tested symmetry on your example and entered “.r” and “.l” as suffixes. :slight_smile: But it actually does seem to work, once I make sure the dot is being stripped from the suffix if it has been entered. Quite a relief.

I tried to reorganize the GUI a bit. Organizing something like that has always been one of my weaker points. Right now I have section titles, but I’m sure the whole thing still looks pretty cluttered. Can you clarify your suggestion for adding “space and backgrounds”? I’m not sure how much more I can space things out… the buttons are pretty small already. But I’m prepared to try things to make this more accessible. If you can point to any scripts with a GUI which might serve as an example, that would really help. I’m still a beginner at this, you see…

I have a few ideas for the “library”/menu file I/O system you suggest. I’ll have to refresh my knowledge of Python’s os module before I proceed, as I think I’ll probably need to have people specify the folder in which they save their poses. Beyond that, I assume I just need a PupMenu. The function has a toggle button, but right now that’s all there is to it.

I fixed the partial pose slider value so it now works with “real time” application. I’d left out a line in the GUI section, so the value wasn’t being passed.

I added the name, “finger” to the hand save group list, so finger parts with that name should be saved in a partial pose for hands now.

I added four bone roll handling functions to the script. These may not be as out of place as they seem at first glance. One of the things I learned from this project is that bone roll affects poses. :slight_smile: The Blender Library default method seems to basically “embed” bone roll into a pose, which can cause pose compatibility issues. This is no longer a problem, thanks to Cambo’s code, but I ended up developing some bone roll tools which may prove useful for someone. They are:

  • Save bone roll settings to a .txt file
  • Load bone roll settings from a .txt file
  • Zero bone roll
  • Restore zeroed bone roll from in-session use of the zero function.

You can use these to, for instance, copy roll settings from a refined armature to one which is automatically created by an import function, or something. I found them useful while developing this script (you can use them to test the “no roll” pose functionality, for instance), but they’re ultimately not as valuable as I’d expected them to be - again, thanks to Cambo. :slight_smile: I have seen at least one suggestion in a thread for a zero bone roll script, so: here it is. :slight_smile:

Finally, I forgot to mention a feature of the script. It can also save a pose from a cluster of empties created by one of the various .bvh import scripts which create such things.

Since my GUI is still cluttered, I should probably clarify a couple of things. Options to export variant poses (Empty, “No Roll”, “IK” (poseMatrix), or IK and No Roll together) are accessed by pressing the “Set pose export options” toggle. To load Empty or No Roll poses, you need to activate the “Load ‘no roll’ pose” toggle in the load section. For IK poses, you need to activate the “Load ‘IK’ pose” toggle. For combo IK/No Roll, you need to activate both toggles for import. I guess I have made it confusing, huh? The more options, the better, I tend to think… :slight_smile:

Current version of script:

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib7c.py

Partial pose save groups are no longer hard-coded. The armature is now examined to find parents with clusters of children and sub-children and select partial save groups from among these.

Sadly, no progress with the GUI yet.

Latest version.

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib7h.py

Thanks. Let me know if there are any problems.

Another update. The GUI has been organized and cleaned up. As nozzy suggested, I added space between sections, section headings, and colored backgrounds. Hopefully the new arrangement is less confusing.

I found that the combination posematrix and restmatrix poses were not doing what I’d expected. They were written and read without errors, but simply encoding the pose in both ways did not deliver poses with constraints data but without embedded bone roll. I was able to re-arrange the process so the combo poses now seem to work. I tested them on my own figure and on the example nozzy sent, with altered bone roll on both and with IK toggled on the nozzy example. No problems that I could see.

Here are some short notes I prepared about the pose types. I had a horrid time tracking this information down so I could make use of it, so I’m eager to spread it around to keep others from having as much trouble as I did. :slight_smile: Let me know if I goofed up any of the algorithms.

This script processes bone quaternion rotations four different ways to produce four varieties of poses.

  1. Blender Library type. This method seems to embed bone roll data in the pose, making it difficult
    to use the pose with armatures other than the source armature.

Save:
quat without processing
Load:
quat without processing

  1. Restmatrix type (exported in bvh data, also from PoserPython). Essentially lacks embedded bone roll
    data in the pose, so the pose can be loaded onto armatures with different bone roll setups.

Save:
quat = (rest_matrix_invert * quat_as_matrix * rest_matrix).toQuat()
Load:
quat = (rest_matrix * quat_as_matrix * rest_matrix_invert).toQuat()

  1. Posematrix type. This type uses the poseMatrix to export IK and constraints. This type also embeds
    bone roll data.

Save:
quat = (posematrix * parent_posematrix).toQuat()
Load:
quat = (quat_as_matrix * (rest_matrix * parent_rest_matrix_invert).invert()).toQuat()

  1. Combination posematrix and restmatrix type. Combined correctly, types 2) and 3) can render a pose which
    both contains IK and constraint data, but lacks embedded bone roll. This is not simply a matter of encoding
    the data both ways on export and import. That works - in the order 3)-2) for export and 2)-3) for import - but
    the bone roll information remains embedded. To export the benefits of both, they are processed as they would be
    if type 3) were saved, then loaded, then saved again as type 2).

Save:
quat = ((posematrix * parent_posematrix) * (rest_matrix * parent_restmatrix_invert).invert()).toQuat()
This is a combination of the save and load for type three. Then it is passed to the save process for type two.
quat = (rest_matrix_invert * quat_as_matrix * rest_matrix).toQuat()
Load:
quat = (rest_matrix * quat_as_matrix * rest_matrix_invert).toQuat()

That’s kind of a shorthand version of the pose data handling in the script. Type 2 poses are based on the work of Campbell Barton. Type three poses are based on scripts by der_ton and others.

The current version is here:

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib8c.py

As before, please let me know if you have any trouble. Having heard nothing, I assume things either work or no one’s bothering to try the script. Or maybe I smell funny. :slight_smile:

Thanks.

Hi again, looking great Basil_fawlty. Alot better layout, but maybe a little
vertical space between buttons and titles?
I hit a problem on loading a pose. I done a test on the same rig. I first choose to save the pose with "Ik and no “roll” and I then tryed to load the same pose flipped with the “No Roll” option choosen.
It looks like the legs flip right but the legs and the arms didn’t look right. This only happens when flipping loading the pose straight works fine.
How is it going with loading poses to a list?
Keep up the good work.

Hi nozzy. Thanks for the feedback.

Regarding the GUI, are you suggesting more space between buttons and neighboring buttons, or between buttons as a group and the section headings? My quandary with more spacing is that the current design makes the GUI awfully tall already, and I worry about making it unwieldy for anyone who might use it. As it is, the example you sent has the script spilling over outside of the script window, requiring that things be moved around before all the buttons can be viewed. So I should ask: is that bothersome to people? Is it more important to make the design uncluttered or somewhat compact? The buttons can’t really be much shorter, either, as they become difficult to read at a certain point. Any thoughts you have would help.

I think I was able to reproduce your bug. When I tested things before releasing that last version, I used the “Apply load settings to current pose” button, rather than directly loading poses, to verify symmetry functionality. Realtime application worked, but you are correct: flip had a problem when used together with “no roll” and pose load. I think it was mainly an order-of-events issue. The conditions are different when flipping the pose in real time with the apply button and when loading a pose. With apply, all the rotation data is there at the outset, so there aren’t many complications when looking for the flipped counterpart bone and processing the values properly. When loading, however, the data comes in one line at a time, so a separate process is needed.

But I re-worked pose-flipping and hopefully made it (slightly) less of a hack. I think it will benefit from further refinement, but it seems to be working. It looks like the error is gone, from my tests. Can you see if you can recreate the error with this script version?

The list for loading poses is on my “to do” list, but it looks like it needs to be done after the flip function is finalized. It is higher on the list than IK toggle functions and animation support. Once I get flip and the GUI finalized I’ll be working on list loading. Would list saving be worthwhile, or just loading? What do you think?

Added:

  • Option for user to define minimum and maximum group sizes for automatic partial save group determination.
  • Option to load only parts in selected partial save group when loading a pose.
  • Option to exclude selected partial save group parts when loading a pose.
  • Changed the combination toggle/PupMenu handling to allow selection of multiple menu options (by accessing the menu repeatedly). This allows the selection of multiple partial save groups at one time. Each menu has a “deselect all options” to deactivate the toggle. Options which can’t be used together have been made mutually exclusive.
  • Rewrote pose flipping. Still WIP, but the reported bug is hopefully fixed.

New version:

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib8g.py

Thanks.

Another update.

  • Cleanup and reworking for the symmetrize and flip functions. The code is somewhat less ugly now, but probably still just as kludge-worthy. I did some digging, looking for alternate approaches, and found that paste_posebuf in the Blender source simply flips y and z euler values to flip a pose, so the official function is pretty much what I have had all along. I found that one can get the same result by flipping quaternions: flipquat = [q[0],q[1],-q[2],-q[3]]. So I use that now, but it makes no discernible difference.

  • Added an option to zero the torso chain or other un-mirrored bones when using symmetrize right/left to mirror a pose.

  • Made keyframing configurable. Now it can be set to ask, to keyframe automatically, or not to keyframe at all.

  • Hopefully finalized the functions to screen out root part rotation or translation when loading or applying a pose. I’m trying to keep this compatible with a Poser cr2 two-part root setup and also make it as broadly applicable as I know how. Please let me know if anyone tries it and it fails in any way…

  • Added list browsing! I don’t know if it’s quite what nozzy may have envisioned, but it’s in place and it seems stable. I’m dissatisfied with some of Blender’s menu button handling, however, so I made it an option. You can toggle between file browsing (default) and list browsing via the load options menu. Then you still need to browse for your pose folder. Without specifying a fixed location for a user’s pose folder(s), I’m not sure how to take the need to browse at some point out of the equation…

  • Added a save function to work with the list loading. You can select the option, in the save menu, to save poses to the selected list load folder. Then you simply have to specify the save name. This is quicker than file browsing, I’ve found.

  • Added save protections to make sure that a file extension is appended to a pose file and to check to prevent overwriting a file when saving. I believe Blender Library uses the .blend extension for poses, and I’ve kept that in place to remain as consistent as possible with BL formatting. The list browser screens out files which don’t have a .blend extension (or .Bpose, an alternate I’ve used for some files). Let me know if I should expand or change the file extension handling in any way.

  • Added a load menu option to specify the length of the browsing list. I found that response is both slow and a bit unpredictable if the list has more than three columns, on my system, at least. I set the default at three 18 item comlumns, but this can be altered. Browse lists are split up into a series of smaller lists to make them easier to handle.

That’s it for now.

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib10e.py

Thanks.

This looks like a useful script Basil - I hope to be at the point to need it sooner or late :slight_smile:

Question - the Blender Library you’re talking about is the new Library script, correct? If you are saying that the roll & pose are being combined and shouldn’t be, you should give him a shout and request that to be changed. Also, you mentioned about it not showing up because there’s no default. I would think that there should be a default, might be another suggestion/request.

Suggestion - I’m not familiar with what the Python GUI can do but maybe the buttons could be separated into more panels/popups so it isn’t so crowded. Or maybe redraw them in a context sensitive way.

Sorry for the infrequent replys been very busy. The scripts looking good, and works as expexted. A Idea to get more space but without increasing the size would be to maybe move the “options” for all the different parameters to a separate tab/page. So the GUI could be even more relaxed and the options and functions that are not use as oftan have a separate area and not just a dropdown list, but maybe toggle buttons, etc.

Is been a while I’ve seen this in a script, the old "Yable ", and “BMG” gear script bmg-0.0.2.zip used to have it, with differant areas on differant tabbed pages.

Another suggestion is having a refresh button on the pose list if a i save out a pose and want to have it in the list at the moment i have to re-search for the pose directory.

At the moment your list is in a drop-down but I was wondering if there is a GUI window with scrolling where items can be selected to trigger events? If It possible to move the gui to tabbed pages, it would then be perfect to have a separate page for the pose list in a window. You then open up possiblities to have the flip/symmetry/sceen/zero buttons in the area with the new window.

The possible work-flow would then be load some poses into your list/window, select your options for the pose and double-click on the pose to trigger the pose and its effects on the rig.

Im traveling for a few weeks now, but I’ll keep checking in when I get the time. This could really be a nice help to the animation process in blender, keep up the good work :slight_smile:

Thank you both for your comments. I’ve contacted Mariano, dgebel, but I haven’t had any response yet. Hopefully I haven’t given offense. It’s probably bad form to offer scripting advice when your own abilities aren’t terribly developed.

Nozzy, it sounds like you’re requesting something akin to Tkinter’s scrolling listboxes. I’ve been frustrated a few times by Blender’s lack of such a widget. I have a couple of example scripts which show that something like this can be done. It’s a matter of whether it’s within my skill range, at this point. Luckily, I have worked on a scrolling textbox with another language (cough Game Maker cough), and most of the principles involved with that should be transferrable. I hope so, because scrollbars are a PITA, and I don’t want to have to go through the headache of developing them all over again. :slight_smile: I’m going to see what I can do with that suggestion, anyway.

The bmg example is helpful. The tabbed interface via toggles shouldn’t be hard to implement. I’ll get started on that.

In the meantime, before I start hacking around trying to build a listbox, here is a version with some refinements to the pull-down menu lists. This fixes a few flaws with displayed values and also refreshes automatically to show newly saved poses in the selected folder. It also enables the use of multiple partial save groups for use with both save and load.

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib10g.py

As ever, thank you for your comments, and please let me know if anyone finds a problem.

A new version.

-Tabbed GUI with five separate “pages” for different functions. Vertical spacing added between buttons. Some functions have been given buttons as well as menu entries.

  • Added a pose-browsing listbox. This can be used to select your pose folder and then load a selected pose with a double-click.

  • Added a bones listbox. This allows customized group selections to screen saving, loading, or realtime application.

Both of the listboxes are more-or-less the same as those in the example I recently posted. I’ve revised them slightly, hopefully to improve handling a bit. The old version was reconstructing the lists with each draw event. This one only refills them when there is a need to do so. Tab switching has also been altered and it seems much quicker now.

I’ve had to build these listboxes from scratch, so I am particularly concerned about any reports regarding how they handle. Are they slow for anyone? Is mouse handling difficult at any point? The only real problem I’ve noted is that the listboxes do not screen out a click on a pupmenu which overlays the listbox. I’m trying to see what I can do about that. If anyone notes anything, please let me know.

Looking at nozzy’s workflow suggestion, it seems like the pose listbox should possibly be accessible at the same time as the load settings. It wouldn’t be hard to add an option to display two “pages” side-by-side. My question about that idea would be whether the adjacent pages should be full-sized, or narrower than usual. It would not be hard to adjust the width. I’ll tinker with the idea.

If the listboxes work for people, I will probably use a listbox similar to the bones list when adding animation functions. I’d like to have an easy-access way to work with keyframing, for instance.

Barring any reported bugs or suggestions, I will be moving on to animation support next.

Please let me know if there are any problems with this version. I’d also love to hear from anyone who might offer pointers for bringing this script more into line with the “correct” scripting standards for Blender.

Thanks.

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib12f.py

I’ll try and have a bash at this over the weekend, but I’m likely to be too occupied by, whatyacallit - oh ya, “life”.
“Don’t talk to me about life…”

The new script does not run for me on 2.42a, and I get no message in the dos window.
I tryed your listbox script, its really nice perfect for this kind of script.

I was thinking that it would be nice to have just a few of the option buttons,eg, the flip. Ones that would be used oftan. Keeping it to the size you have now with tabs is definatly the way to go I think.

If you can work out why it not running for me, and when I get a look at it with your tabs I can draw a mock up of what I think would be a nice layout.

It is not good news that it isn’t working, nozzy. :frowning: My apologies.

I’ve developed and tested previous versions only in 241. This one has been developed and tested in 242. It works for me, so far. I’ve encountered a couple of troublesome 242-specific bugs involving conflicts between functions in some of the tabs, but I’ve fixed all of those I’ve encountered. hopefully I’ve found all of them… and hopefully those bugs explain why the previous version didn’t work for you.

This one adds a few things:

  • Dual tab viewing, to use a list tab and an options tab side-by-side.

  • Variable widths for the buttons/tabs. You can specify a width setting.

-Added the ability to make bones list selections by working with children and sub-children of the active selection. The active selection is now highlighted in red.

  • Corrected some errors with partial groups and bones list selections for screening load, save, or realtime application.

  • Rewrote the flip function again and added a second type of flip. Type 1 is as before, flipping a pose over itself. Type 2 is useful in some situations when you have non-symmetrized selections. It allows you to flip the selected bones over themselves.

  • Added a numerical entry tab. This may represent a reinvention of the wheel on some levels. I conceived and developed it in 241, after encountering limitations with Blender’s own numerical entry tab. In 242, many of the flaws I had encountered seem to have been fixed, so this may not be as useful as I’d expected. This allows you to select a bone in the bones listbox and manipulate it using the dials on the number tab. It may have some benefits. It allows you to see values at six decimal places, configures the translation sensitivity corresponding to the scale of your armature, and allows you to use euler.unique for rotation entries. It can insert keyframes to allow numerical changes to keyframed poses, but 242 seems to have added that already.

  • Expanded boneroll save and load to save head and tail data and allow you to load either roll alone or roll with head and tail.

I hope this one works better for you, nozzy. If not, I’m not sure what to suggest, but I’ll certainly try to fix things. Can you tell me anything at all about the circumstances under which it failed to run? Did it just not start up? Did it start up and crash? There was no console error message, but was there a popup error in Blender? Anything at all might be helpful. The crash errors I fixed with 242 produced a pythondll crash warning and closed Blender - obviously very bad. Anything like that? Please let me know whatever you can.

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib13e.py

The new version works perfectly :slight_smile: And its looking really great, the new layout works a treat.

The previous version just would start and I never got any warnings.

You have done a great job with the listboxes, and the choise to have dual layout. I also love the number input on the bones in pose mode and the new flip mode, but not sure what the input in edit mode would be for.

Some of the GUI is not refreshing all the time when jumping between tabs
, the previous tab sometimes is in the background. But it only happens rarely.

This is such a useful script and one I will be using a lot. Its a shame Im the only one giving you feed back, Im sure there is a lot more people out there that could give you some constructive tips on what they think.

Cheers.

I’ve finally gotten around to trying this. Good work dude :slight_smile:

Just one comment about the listboxes - have you considered the people whose mice don’t have mouse-wheels? My mouse has a mmb, but no scroll wheel. What if pressing the up/down arrows keys or even the page up/down keys over the listbox scrolled it as well.

One of my favourite features of this, is the panel where you can set the transforms of the selected bone. Very handy!

Keep up the good work.

Aligorith

Thank you both for the comments. I’ve been worried about stability in 242. I had no problems at all in 241. Everything was rock-solid. But switching to 242 suddenly brought periodic crashes. Very bad. It seems that 242 is generally less tolerant about some approaches - and, being paranoid, I wonder a bit if this new emphasis on “correct” coding methods accompanies changes which make Blender Python less tolerant of “incorrect” methods. Hmm. Oh, well.

Nozzy, can you tell me anything about these refresh failures? I saw something like that while developing the tabs, but I fixed them. One of my 242 bug fixes may have restored them. Anything you can tell me may help.

Algorith, I added an option to use a slider bar with the listboxes. You can toggle this option in the “options” tab.

This update presents mainly bug fixes, but there are a few a couple of minor changes.

  • The partial application slider wasn’t being properly passed to a listbox click pose activation. Fixed.

  • Altered most of the pose application symmetry features to symmetrize loc as well as rot. (Those not altered were already doing this.)

  • Added arrow up and down hotkeys to the listboxes, for Algorith.

  • Hopefully repaired an error in button implementation. The documentation suggests that memory problems can result if buttons are not linked to global variables. I think most of mine have been linked to local variables all this time (how embarassing…). This has been rectified. Hopefully this represents much of the gui-related instability I’ve seen since moving from 241 to 242.

  • Changed a bit of code which seemed like a likely candidate for the tab refresh errors reported by nozzy.

  • Added a “remove all keyframes” option to the load tab general options menu. This was actually in 13e, but I neglected to mention it. This will remove every single keyframe for every action, so use it with caution - if at all. It’s mainly there for my use, while I develop more refined keyframe handling functions.

I’ve tried the script in 242a, but that version of Blender seems to have non-Python related stability problems on my system, so I’ve switched back to the first version of 242. If anyone can tell me how to find out if I’m encountering a known 242a bug, please do. Blender crashes out with a consistent BSOD Windows error whenever I run 242a while Internet Explorer is open (a bit of a problem, since the Python API documentation is in html). There may be more to it than that, but IE has been a common factor each time. In none of these cases was I running the script, so I don’t think this impends anything for this script’s functionality in 242a. Generally I was crashed out upon starting Blender.

Now I really do plan on moving on to animation. :slight_smile: Unfortunately, documentation of some features is hard to come by. The new actionstrips functionality looks like just what I need, but I’m going to have to do some digging, I think, to see how any of it works.

As ever, please let me know if there are problems, questions, or comments.

http://www.kuroyumes-developmentzone.com/~Cage/PoseLib13f.py