2011-02-23 10:52:22 +00:00
/*
2009-01-13 12:32:01 +00:00
* * * * * * BEGIN GPL LICENSE BLOCK * * * * *
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
2010-02-12 13:34:04 +00:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2009-01-13 12:32:01 +00:00
*
* The Original Code is Copyright ( C ) 2007 , Blender Foundation
* This is a new part of Blender
*
* Contributor ( s ) : Joshua Leung
*
* * * * * * END GPL LICENSE BLOCK * * * * *
*/
2011-02-27 20:29:51 +00:00
2013-02-28 00:01:20 +00:00
/** \file blender/editors/armature/pose_lib.c
2011-02-27 20:29:51 +00:00
* \ ingroup edarmature
*/
2009-01-13 12:32:01 +00:00
# include <string.h>
# include <math.h>
# include "MEM_guardedalloc.h"
# include "BLI_blenlib.h"
2009-07-18 07:11:37 +00:00
# include "BLI_dlrbTree.h"
2017-01-16 17:33:34 +01:00
# include "BLI_string_utils.h"
2009-01-13 12:32:01 +00:00
2015-08-16 17:32:01 +10:00
# include "BLT_translation.h"
2011-06-15 11:41:15 +00:00
2009-04-15 01:10:36 +00:00
# include "DNA_anim_types.h"
2009-01-13 12:32:01 +00:00
# include "DNA_armature_types.h"
# include "DNA_object_types.h"
# include "DNA_scene_types.h"
2009-04-15 01:10:36 +00:00
# include "BKE_animsys.h"
2009-01-13 12:32:01 +00:00
# include "BKE_action.h"
# include "BKE_armature.h"
# include "BKE_depsgraph.h"
2013-02-05 12:46:15 +00:00
# include "BKE_global.h"
2011-02-15 11:47:09 +00:00
# include "BKE_idprop.h"
2018-06-07 12:47:00 +02:00
# include "BKE_main.h"
2011-02-16 00:17:22 +00:00
# include "BKE_library.h"
2011-09-14 01:48:55 +00:00
# include "BKE_object.h"
2009-01-13 12:32:01 +00:00
2009-04-15 03:22:22 +00:00
# include "BKE_context.h"
# include "BKE_report.h"
2009-01-13 12:32:01 +00:00
2009-04-15 01:10:36 +00:00
# include "RNA_access.h"
2009-04-15 03:22:22 +00:00
# include "RNA_define.h"
2010-01-27 21:19:39 +00:00
# include "RNA_enum_types.h"
2009-04-15 01:10:36 +00:00
2009-04-15 03:22:22 +00:00
# include "WM_api.h"
2009-01-13 12:32:01 +00:00
# include "WM_types.h"
2009-04-15 03:22:22 +00:00
# include "UI_interface.h"
# include "UI_resources.h"
2009-01-13 12:32:01 +00:00
# include "ED_anim_api.h"
# include "ED_armature.h"
# include "ED_keyframes_draw.h"
# include "ED_keyframing.h"
# include "ED_keyframes_edit.h"
2009-04-15 03:22:22 +00:00
# include "ED_screen.h"
2012-01-02 17:15:24 +00:00
# include "ED_object.h"
2009-01-13 12:32:01 +00:00
# include "armature_intern.h"
/* ******* XXX ********** */
2010-12-03 12:30:59 +00:00
static void action_set_activemarker ( void * UNUSED ( a ) , void * UNUSED ( b ) , void * UNUSED ( c ) ) { }
2009-01-13 12:32:01 +00:00
/* ************************************************************* */
2018-06-04 09:31:30 +02:00
/* == POSE-LIBRARY TOOL FOR BLENDER ==
2018-06-01 18:19:39 +02:00
*
* Overview :
2012-05-08 20:18:33 +00:00
* This tool allows animators to store a set of frequently used poses to dump into
* the active action to help in " budget " productions to quickly block out new actions .
* It acts as a kind of " glorified clipboard for poses " , allowing for naming of poses .
2009-01-13 12:32:01 +00:00
*
* Features :
* - PoseLibs are simply normal Actions
* - Each " pose " is simply a set of keyframes that occur on a particular frame
* - > 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
*/
/* ************************************************************* */
2018-06-04 09:31:30 +02:00
/* gets the first available frame in poselib to store a pose on
2009-01-13 12:32:01 +00:00
* - frames start from 1 , and a pose should occur on every frame . . . 0 is error !
*/
2012-05-08 20:18:33 +00:00
static int poselib_get_free_index ( bAction * act )
2009-01-13 12:32:01 +00:00
{
TimeMarker * marker ;
2012-05-08 20:18:33 +00:00
int low = 0 , high = 0 ;
2013-11-26 06:39:14 +11:00
bool changed = false ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* sanity checks */
if ( ELEM ( NULL , act , act - > markers . first ) ) return 1 ;
2018-06-04 09:31:30 +02:00
/* As poses are not stored in chronological order, we must iterate over this list
2011-07-17 12:37:38 +00:00
* a few times until we don ' t make any new discoveries ( mostly about the lower bound ) .
* Prevents problems with deleting then trying to add new poses [ # 27412 ]
*/
do {
2013-11-26 06:39:14 +11:00
changed = false ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
for ( marker = act - > markers . first ; marker ; marker = marker - > next ) {
2011-07-17 12:37:38 +00:00
/* only increase low if value is 1 greater than low, to find "gaps" where
* poses were removed from the poselib
*/
if ( marker - > frame = = ( low + 1 ) ) {
low + + ;
2013-11-26 06:39:14 +11:00
changed = true ;
2011-07-17 12:37:38 +00:00
}
2018-06-04 09:31:30 +02:00
2011-07-17 12:37:38 +00:00
/* value replaces high if it is the highest value encountered yet */
if ( marker - > frame > high ) {
2012-05-08 20:18:33 +00:00
high = marker - > frame ;
2013-11-26 06:39:14 +11:00
changed = true ;
2011-07-17 12:37:38 +00:00
}
}
} while ( changed ! = 0 ) ;
2018-06-04 09:31:30 +02:00
/* - if low is not equal to high, then low+1 is a gap
* - if low is equal to high , then high + 1 is the next index ( add at end )
2009-01-13 12:32:01 +00:00
*/
2018-06-04 09:31:30 +02:00
if ( low < high )
2009-01-13 12:32:01 +00:00
return ( low + 1 ) ;
2018-06-04 09:31:30 +02:00
else
2009-01-13 12:32:01 +00:00
return ( high + 1 ) ;
}
/* returns the active pose for a poselib */
2012-05-08 20:18:33 +00:00
static TimeMarker * poselib_get_active_pose ( bAction * act )
2018-06-04 09:31:30 +02:00
{
2009-01-13 12:32:01 +00:00
if ( ( act ) & & ( act - > active_marker ) )
2012-05-08 20:18:33 +00:00
return BLI_findlink ( & act - > markers , act - > active_marker - 1 ) ;
2009-01-13 12:32:01 +00:00
else
return NULL ;
}
2011-02-16 06:18:20 +00:00
/* Get object that Pose Lib should be found on */
2012-05-08 20:18:33 +00:00
/* XXX C can be zero */
static Object * get_poselib_object ( bContext * C )
2011-02-16 06:18:20 +00:00
{
2011-02-25 16:05:26 +00:00
ScrArea * sa ;
2018-06-04 09:31:30 +02:00
2011-02-20 21:32:21 +00:00
/* sanity check */
if ( C = = NULL )
return NULL ;
2018-06-04 09:31:30 +02:00
2011-02-25 16:05:26 +00:00
sa = CTX_wm_area ( C ) ;
2018-06-04 09:31:30 +02:00
if ( sa & & ( sa - > spacetype = = SPACE_BUTS ) )
2012-01-02 17:15:24 +00:00
return ED_object_context ( C ) ;
2011-02-16 06:18:20 +00:00
else
2012-05-05 14:03:12 +00:00
return BKE_object_pose_armature_get ( CTX_data_active_object ( C ) ) ;
2011-02-16 06:18:20 +00:00
}
/* Poll callback for operators that require existing PoseLib data (with poses) to work */
2018-07-02 11:47:00 +02:00
static bool has_poselib_pose_data_poll ( bContext * C )
2011-02-16 06:18:20 +00:00
{
Object * ob = get_poselib_object ( C ) ;
return ( ob & & ob - > poselib ) ;
}
2015-08-22 18:16:55 +12:00
/* Poll callback for operators that require existing PoseLib data (with poses)
* as they need to do some editing work on those poses ( i . e . not on lib - linked actions )
*/
2018-07-02 11:47:00 +02:00
static bool has_poselib_pose_data_for_editing_poll ( bContext * C )
2015-08-22 18:16:55 +12:00
{
Object * ob = get_poselib_object ( C ) ;
2017-11-06 17:17:10 +01:00
return ( ob & & ob - > poselib & & ! ID_IS_LINKED ( ob - > poselib ) ) ;
2015-08-22 18:16:55 +12:00
}
2011-02-16 06:18:20 +00:00
/* ----------------------------------- */
2009-01-13 12:32:01 +00:00
2012-03-01 12:20:18 +00:00
/* Initialize a new poselib (whether it is needed or not) */
2018-06-07 12:47:00 +02:00
static bAction * poselib_init_new ( Main * bmain , Object * ob )
2009-01-13 12:32:01 +00:00
{
/* sanity checks - only for armatures */
if ( ELEM ( NULL , ob , ob - > pose ) )
return NULL ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* init object's poselib action (unlink old one if there) */
if ( ob - > poselib )
2011-02-16 00:17:22 +00:00
id_us_min ( & ob - > poselib - > id ) ;
2018-06-04 09:31:30 +02:00
2018-06-07 12:47:00 +02:00
ob - > poselib = BKE_action_add ( bmain , " PoseLib " ) ;
2014-06-16 21:59:42 +12:00
ob - > poselib - > idroot = ID_OB ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
return ob - > poselib ;
}
2012-03-01 12:20:18 +00:00
/* Initialize a new poselib (checks if that needs to happen) */
2018-06-07 12:47:00 +02:00
static bAction * poselib_validate ( Main * bmain , Object * ob )
2009-01-13 12:32:01 +00:00
{
if ( ELEM ( NULL , ob , ob - > pose ) )
return NULL ;
else if ( ob - > poselib = = NULL )
2018-06-07 12:47:00 +02:00
return poselib_init_new ( bmain , ob ) ;
2009-01-13 12:32:01 +00:00
else
return ob - > poselib ;
}
/* ************************************************************* */
2011-02-16 00:17:22 +00:00
/* Pose Lib UI Operators */
2012-05-08 20:18:33 +00:00
static int poselib_new_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2011-02-16 00:17:22 +00:00
{
2018-06-07 12:47:00 +02:00
Main * bmain = CTX_data_main ( C ) ;
2011-02-16 06:18:20 +00:00
Object * ob = get_poselib_object ( C ) ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* sanity checks */
if ( ob = = NULL )
return OPERATOR_CANCELLED ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* new method here deals with the rest... */
2018-06-07 12:47:00 +02:00
poselib_init_new ( bmain , ob ) ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* notifier here might evolve? */
2012-05-08 20:18:33 +00:00
WM_event_add_notifier ( C , NC_OBJECT | ND_POSE , NULL ) ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
return OPERATOR_FINISHED ;
}
2012-04-29 17:11:40 +00:00
void POSELIB_OT_new ( wmOperatorType * ot )
2011-02-16 00:17:22 +00:00
{
/* identifiers */
2011-09-15 13:20:18 +00:00
ot - > name = " New Pose Library " ;
2011-02-16 00:17:22 +00:00
ot - > idname = " POSELIB_OT_new " ;
2011-09-15 13:20:18 +00:00
ot - > description = " Add New Pose Library to active Object " ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* callbacks */
ot - > exec = poselib_new_exec ;
2012-03-22 07:26:09 +00:00
ot - > poll = ED_operator_posemode ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* flags */
2012-05-08 20:18:33 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2011-02-16 00:17:22 +00:00
}
/* ------------------------------------------------ */
2012-05-08 20:18:33 +00:00
static int poselib_unlink_exec ( bContext * C , wmOperator * UNUSED ( op ) )
2011-02-16 00:17:22 +00:00
{
2011-02-16 06:18:20 +00:00
Object * ob = get_poselib_object ( C ) ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* sanity checks */
if ( ELEM ( NULL , ob , ob - > poselib ) )
return OPERATOR_CANCELLED ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* there should be a poselib (we just checked above!), so just lower its user count and remove */
id_us_min ( & ob - > poselib - > id ) ;
ob - > poselib = NULL ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* notifier here might evolve? */
2012-05-08 20:18:33 +00:00
WM_event_add_notifier ( C , NC_OBJECT | ND_POSE , NULL ) ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
return OPERATOR_FINISHED ;
}
2012-04-29 17:11:40 +00:00
void POSELIB_OT_unlink ( wmOperatorType * ot )
2011-02-16 00:17:22 +00:00
{
/* identifiers */
2011-09-15 13:20:18 +00:00
ot - > name = " Unlink Pose Library " ;
2011-02-16 00:17:22 +00:00
ot - > idname = " POSELIB_OT_unlink " ;
2011-09-15 13:20:18 +00:00
ot - > description = " Remove Pose Library from active Object " ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* callbacks */
ot - > exec = poselib_unlink_exec ;
2012-03-22 07:26:09 +00:00
ot - > poll = has_poselib_pose_data_poll ;
2018-06-04 09:31:30 +02:00
2011-02-16 00:17:22 +00:00
/* flags */
2012-05-08 20:18:33 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2011-02-16 00:17:22 +00:00
}
/* ************************************************************* */
/* Pose Editing Operators */
2009-01-13 12:32:01 +00:00
2018-06-04 09:31:30 +02:00
/* This tool automagically generates/validates poselib data so that it corresponds to the data
2011-02-16 06:18:20 +00:00
* in the action . This is for use in making existing actions usable as poselibs .
*/
2012-07-03 17:20:21 +00:00
static int poselib_sanitize_exec ( bContext * C , wmOperator * op )
2011-02-16 06:18:20 +00:00
{
Object * ob = get_poselib_object ( C ) ;
2012-05-08 20:18:33 +00:00
bAction * act = ( ob ) ? ob - > poselib : NULL ;
2011-02-16 06:18:20 +00:00
DLRBT_Tree keys ;
ActKeyColumn * ak ;
TimeMarker * marker , * markern ;
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* validate action */
2012-02-27 10:35:39 +00:00
if ( act = = NULL ) {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_WARNING , " No action to validate " ) ;
2011-02-16 06:18:20 +00:00
return OPERATOR_CANCELLED ;
}
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* determine which frames have keys */
BLI_dlrbTree_init ( & keys ) ;
2012-05-08 20:18:33 +00:00
action_to_keylist ( NULL , act , & keys , NULL ) ;
2011-02-16 06:18:20 +00:00
BLI_dlrbTree_linkedlist_sync ( & keys ) ;
2012-07-06 23:56:59 +00:00
2011-02-16 06:18:20 +00:00
/* for each key, make sure there is a corresponding pose */
2012-05-08 20:18:33 +00:00
for ( ak = keys . first ; ak ; ak = ak - > next ) {
2011-02-16 06:18:20 +00:00
/* check if any pose matches this */
2012-07-06 23:56:59 +00:00
/* TODO: don't go looking through the list like this every time... */
2012-05-08 20:18:33 +00:00
for ( marker = act - > markers . first ; marker ; marker = marker - > next ) {
2014-08-04 10:22:45 +10:00
if ( IS_EQ ( ( double ) marker - > frame , ( double ) ak - > cfra ) ) {
2011-02-16 06:18:20 +00:00
marker - > flag = - 1 ;
break ;
}
}
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* add new if none found */
if ( marker = = NULL ) {
/* add pose to poselib */
2012-05-08 20:18:33 +00:00
marker = MEM_callocN ( sizeof ( TimeMarker ) , " ActionMarker " ) ;
2018-06-04 09:31:30 +02:00
2017-07-12 01:33:08 +12:00
BLI_snprintf ( marker - > name , sizeof ( marker - > name ) , " F%d Pose " , ( int ) ak - > cfra ) ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
marker - > frame = ( int ) ak - > cfra ;
marker - > flag = - 1 ;
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
BLI_addtail ( & act - > markers , marker ) ;
}
}
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* remove all untagged poses (unused), and remove all tags */
2012-05-08 20:18:33 +00:00
for ( marker = act - > markers . first ; marker ; marker = markern ) {
markern = marker - > next ;
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
if ( marker - > flag ! = - 1 )
BLI_freelinkN ( & act - > markers , marker ) ;
else
marker - > flag = 0 ;
}
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* free temp memory */
BLI_dlrbTree_free ( & keys ) ;
2018-06-04 09:31:30 +02:00
/* send notifiers for this - using keyframe editing notifiers, since action
* may be being shown in anim editors as active action
2011-07-17 12:37:38 +00:00
*/
2012-05-08 20:18:33 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
return OPERATOR_FINISHED ;
}
2012-07-03 17:20:21 +00:00
void POSELIB_OT_action_sanitize ( wmOperatorType * ot )
2011-02-16 06:18:20 +00:00
{
/* identifiers */
2012-07-03 17:20:21 +00:00
ot - > name = " Sanitize Pose Library Action " ;
ot - > idname = " POSELIB_OT_action_sanitize " ;
2011-09-15 13:20:18 +00:00
ot - > description = " Make action suitable for use as a Pose Library " ;
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* callbacks */
2012-07-03 17:20:21 +00:00
ot - > exec = poselib_sanitize_exec ;
2015-08-22 18:16:55 +12:00
ot - > poll = has_poselib_pose_data_for_editing_poll ;
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* flags */
2012-05-08 20:18:33 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2011-02-16 06:18:20 +00:00
}
/* ------------------------------------------ */
2015-08-22 18:16:55 +12:00
/* Poll callback for adding poses to a PoseLib */
2018-07-02 11:47:00 +02:00
static bool poselib_add_poll ( bContext * C )
2015-08-22 18:16:55 +12:00
{
/* There are 2 cases we need to be careful with:
* 1 ) When this operator is invoked from a hotkey , there may be no PoseLib yet
* 2 ) If a PoseLib already exists , we can ' t edit the action if it is a lib - linked
* actions , as data will be lost when saving the file
*/
if ( ED_operator_posemode ( C ) ) {
Object * ob = get_poselib_object ( C ) ;
if ( ob ) {
2017-11-06 17:17:10 +01:00
if ( ( ob - > poselib = = NULL ) | | ! ID_IS_LINKED ( ob - > poselib ) ) {
2015-08-22 18:16:55 +12:00
return true ;
}
}
}
return false ;
}
2012-05-08 20:18:33 +00:00
static void poselib_add_menu_invoke__replacemenu ( bContext * C , uiLayout * layout , void * UNUSED ( arg ) )
2009-04-15 03:22:22 +00:00
{
2012-05-08 20:18:33 +00:00
Object * ob = get_poselib_object ( C ) ;
bAction * act = ob - > poselib ; /* never NULL */
2009-04-15 03:22:22 +00:00
TimeMarker * marker ;
2018-06-04 09:31:30 +02:00
2012-01-22 03:30:07 +00:00
wmOperatorType * ot = WM_operatortype_find ( " POSELIB_OT_pose_add " , 1 ) ;
BLI_assert ( ot ! = NULL ) ;
2009-10-13 05:50:26 +00:00
/* set the operator execution context correctly */
uiLayoutSetOperatorContext ( layout , WM_OP_EXEC_DEFAULT ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* add each marker to this menu */
2012-05-08 20:18:33 +00:00
for ( marker = act - > markers . first ; marker ; marker = marker - > next ) {
2010-08-23 10:46:31 +00:00
PointerRNA props_ptr ;
2017-10-31 16:58:26 +11:00
uiItemFullO_ptr (
layout , ot ,
marker - > name , ICON_ARMATURE_DATA , NULL ,
WM_OP_EXEC_DEFAULT , 0 , & props_ptr ) ;
2010-08-23 10:46:31 +00:00
RNA_int_set ( & props_ptr , " frame " , marker - > frame ) ;
RNA_string_set ( & props_ptr , " name " , marker - > name ) ;
}
2009-04-15 03:22:22 +00:00
}
2013-03-13 09:03:46 +00:00
static int poselib_add_menu_invoke ( bContext * C , wmOperator * op , const wmEvent * UNUSED ( event ) )
2009-04-15 03:22:22 +00:00
{
2012-05-08 20:18:33 +00:00
Scene * scene = CTX_data_scene ( C ) ;
Object * ob = get_poselib_object ( C ) ;
bPose * pose = ( ob ) ? ob - > pose : NULL ;
2009-04-22 18:39:44 +00:00
uiPopupMenu * pup ;
uiLayout * layout ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* sanity check */
2018-06-04 09:31:30 +02:00
if ( ELEM ( NULL , ob , pose ) )
2009-04-15 03:22:22 +00:00
return OPERATOR_CANCELLED ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* start building */
2014-11-09 21:20:40 +01:00
pup = UI_popup_menu_begin ( C , op - > type - > name , ICON_NONE ) ;
layout = UI_popup_menu_layout ( pup ) ;
2009-05-28 23:37:55 +00:00
uiLayoutSetOperatorContext ( layout , WM_OP_EXEC_DEFAULT ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* add new (adds to the first unoccupied frame) */
2011-10-20 20:38:26 +00:00
uiItemIntO ( layout , IFACE_ ( " Add New " ) , ICON_NONE , " POSELIB_OT_pose_add " , " frame " , poselib_get_free_index ( ob - > poselib ) ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* check if we have any choices to add a new pose in any other way */
if ( ( ob - > poselib ) & & ( ob - > poselib - > markers . first ) ) {
/* add new (on current frame) */
2011-10-20 20:38:26 +00:00
uiItemIntO ( layout , IFACE_ ( " Add New (Current Frame) " ) , ICON_NONE , " POSELIB_OT_pose_add " , " frame " , CFRA ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* replace existing - submenu */
2011-10-20 20:38:26 +00:00
uiItemMenuF ( layout , IFACE_ ( " Replace Existing... " ) , 0 , poselib_add_menu_invoke__replacemenu , NULL ) ;
2009-04-15 03:22:22 +00:00
}
2018-06-04 09:31:30 +02:00
2014-11-09 21:20:40 +01:00
UI_popup_menu_end ( C , pup ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* this operator is only for a menu, not used further */
2014-10-28 17:51:06 +01:00
return OPERATOR_INTERFACE ;
2009-04-15 03:22:22 +00:00
}
2012-05-08 20:18:33 +00:00
static int poselib_add_exec ( bContext * C , wmOperator * op )
2009-01-13 12:32:01 +00:00
{
2018-06-07 12:47:00 +02:00
Main * bmain = CTX_data_main ( C ) ;
2012-05-08 20:18:33 +00:00
Object * ob = get_poselib_object ( C ) ;
2018-06-07 12:47:00 +02:00
bAction * act = poselib_validate ( bmain , ob ) ;
2012-05-08 20:18:33 +00:00
bPose * pose = ( ob ) ? ob - > pose : NULL ;
2009-01-13 12:32:01 +00:00
TimeMarker * marker ;
2016-09-28 13:54:57 +02:00
KeyingSet * ks ;
2012-05-08 20:18:33 +00:00
int frame = RNA_int_get ( op - > ptr , " frame " ) ;
2009-01-13 12:32:01 +00:00
char name [ 64 ] ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* sanity check (invoke should have checked this anyway) */
2018-06-04 09:31:30 +02:00
if ( ELEM ( NULL , ob , pose ) )
2009-04-15 03:22:22 +00:00
return OPERATOR_CANCELLED ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* get name to give to pose */
RNA_string_get ( op - > ptr , " name " , name ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* add pose to poselib - replaces any existing pose there
* - for the ' replace ' option , this should end up finding the appropriate marker ,
* so no new one will be added
*/
2012-05-08 20:18:33 +00:00
for ( marker = act - > markers . first ; marker ; marker = marker - > next ) {
2009-04-15 03:22:22 +00:00
if ( marker - > frame = = frame ) {
BLI_strncpy ( marker - > name , name , sizeof ( marker - > name ) ) ;
break ;
2009-01-13 12:32:01 +00:00
}
}
2009-04-15 03:22:22 +00:00
if ( marker = = NULL ) {
2012-05-08 20:18:33 +00:00
marker = MEM_callocN ( sizeof ( TimeMarker ) , " ActionMarker " ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
BLI_strncpy ( marker - > name , name , sizeof ( marker - > name ) ) ;
2012-05-08 20:18:33 +00:00
marker - > frame = frame ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
BLI_addtail ( & act - > markers , marker ) ;
2009-01-13 12:32:01 +00:00
}
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* validate name */
2013-03-25 08:29:06 +00:00
BLI_uniquename ( & act - > markers , marker , DATA_ ( " Pose " ) , ' . ' , offsetof ( TimeMarker , name ) , sizeof ( marker - > name ) ) ;
2018-06-04 09:31:30 +02:00
2011-02-15 11:47:09 +00:00
/* use Keying Set to determine what to store for the pose */
2016-09-28 13:54:57 +02:00
ks = ANIM_builtin_keyingset_get_named ( NULL , ANIM_KS_WHOLE_CHARACTER_SELECTED_ID ) ; /* this includes custom props :)*/
2011-02-15 11:47:09 +00:00
ANIM_apply_keyingset ( C , NULL , act , ks , MODIFYKEY_MODE_INSERT , ( float ) frame ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* store new 'active' pose number */
2014-11-16 13:57:58 +01:00
act - > active_marker = BLI_listbase_count ( & act - > markers ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* done */
return OPERATOR_FINISHED ;
2009-01-13 12:32:01 +00:00
}
2012-04-29 17:11:40 +00:00
void POSELIB_OT_pose_add ( wmOperatorType * ot )
2009-01-13 12:32:01 +00:00
{
2009-04-15 03:22:22 +00:00
/* identifiers */
2012-03-22 07:26:09 +00:00
ot - > name = " PoseLib Add Pose " ;
ot - > idname = " POSELIB_OT_pose_add " ;
ot - > description = " Add the current Pose to the active Pose Library " ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* api callbacks */
2012-03-22 07:26:09 +00:00
ot - > invoke = poselib_add_menu_invoke ;
ot - > exec = poselib_add_exec ;
2015-08-22 18:16:55 +12:00
ot - > poll = poselib_add_poll ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* flags */
2012-05-08 20:18:33 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* properties */
2011-09-15 13:20:18 +00:00
RNA_def_int ( ot - > srna , " frame " , 1 , 0 , INT_MAX , " Frame " , " Frame to store pose on " , 0 , INT_MAX ) ;
RNA_def_string ( ot - > srna , " name " , " Pose " , 64 , " Pose Name " , " Name of newly added Pose " ) ;
2009-04-15 03:22:22 +00:00
}
/* ----- */
2011-02-19 18:53:08 +00:00
/* can be called with C == NULL */
2017-10-18 15:07:26 +11:00
static const EnumPropertyItem * poselib_stored_pose_itemf ( bContext * C , PointerRNA * UNUSED ( ptr ) , PropertyRNA * UNUSED ( prop ) , bool * r_free )
2009-04-15 03:22:22 +00:00
{
2011-02-20 23:21:15 +00:00
Object * ob = get_poselib_object ( C ) ;
bAction * act = ( ob ) ? ob - > poselib : NULL ;
2009-04-15 03:22:22 +00:00
TimeMarker * marker ;
2012-05-08 20:18:33 +00:00
EnumPropertyItem * item = NULL , item_tmp = { 0 } ;
int totitem = 0 ;
int i = 0 ;
2009-10-13 05:50:26 +00:00
2011-02-16 06:18:20 +00:00
if ( C = = NULL ) {
2012-04-23 09:17:37 +00:00
return DummyRNA_NULL_items ;
2010-01-27 21:19:39 +00:00
}
2018-06-04 09:31:30 +02:00
2009-10-14 00:01:34 +00:00
/* check that the action exists */
if ( act ) {
/* add each marker to the list */
2012-05-08 20:18:33 +00:00
for ( marker = act - > markers . first , i = 0 ; marker ; marker = marker - > next , i + + ) {
item_tmp . identifier = item_tmp . name = marker - > name ;
item_tmp . icon = ICON_ARMATURE_DATA ;
item_tmp . value = i ;
2009-10-14 00:01:34 +00:00
RNA_enum_item_add ( & item , & totitem , & item_tmp ) ;
}
2009-10-13 05:50:26 +00:00
}
2009-04-15 03:22:22 +00:00
2009-10-14 19:19:43 +00:00
RNA_enum_item_end ( & item , & totitem ) ;
2014-01-04 18:08:43 +11:00
* r_free = true ;
2009-10-14 19:19:43 +00:00
return item ;
2009-10-13 05:50:26 +00:00
}
2009-04-15 03:22:22 +00:00
2012-05-08 20:18:33 +00:00
static int poselib_remove_exec ( bContext * C , wmOperator * op )
2009-04-15 03:22:22 +00:00
{
2012-05-08 20:18:33 +00:00
Object * ob = get_poselib_object ( C ) ;
bAction * act = ( ob ) ? ob - > poselib : NULL ;
2009-04-15 03:22:22 +00:00
TimeMarker * marker ;
2012-04-23 09:17:37 +00:00
int marker_index ;
2009-04-15 01:10:36 +00:00
FCurve * fcu ;
2012-04-23 09:17:37 +00:00
PropertyRNA * prop ;
2009-01-13 12:32:01 +00:00
/* check if valid poselib */
if ( act = = NULL ) {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Object does not have pose lib data " ) ;
2009-04-15 03:22:22 +00:00
return OPERATOR_CANCELLED ;
2009-01-13 12:32:01 +00:00
}
2012-04-23 09:17:37 +00:00
prop = RNA_struct_find_property ( op - > ptr , " pose " ) ;
if ( RNA_property_is_set ( op - > ptr , prop ) ) {
marker_index = RNA_property_enum_get ( op - > ptr , prop ) ;
}
else {
marker_index = act - > active_marker - 1 ;
}
2009-01-13 12:32:01 +00:00
/* get index (and pointer) of pose to remove */
2012-04-23 09:17:37 +00:00
marker = BLI_findlink ( & act - > markers , marker_index ) ;
2009-01-13 12:32:01 +00:00
if ( marker = = NULL ) {
2012-10-19 16:43:10 +00:00
BKE_reportf ( op - > reports , RPT_ERROR , " Invalid pose specified %d " , marker_index ) ;
2009-09-20 11:21:44 +00:00
return OPERATOR_CANCELLED ;
2009-01-13 12:32:01 +00:00
}
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* remove relevant keyframes */
2012-05-08 20:18:33 +00:00
for ( fcu = act - > curves . first ; fcu ; fcu = fcu - > next ) {
2009-01-13 12:32:01 +00:00
BezTriple * bezt ;
2011-02-27 08:31:10 +00:00
unsigned int i ;
2018-06-04 09:31:30 +02:00
2009-04-15 01:10:36 +00:00
if ( fcu - > bezt ) {
2012-05-08 20:18:33 +00:00
for ( i = 0 , bezt = fcu - > bezt ; i < fcu - > totvert ; i + + , bezt + + ) {
2009-04-15 01:10:36 +00:00
/* check if remove */
2013-11-10 12:56:50 +00:00
if ( IS_EQF ( bezt - > vec [ 1 ] [ 0 ] , ( float ) marker - > frame ) ) {
2009-04-15 01:10:36 +00:00
delete_fcurve_key ( fcu , i , 1 ) ;
2009-01-13 12:32:01 +00:00
break ;
}
2009-04-15 01:10:36 +00:00
}
2009-01-13 12:32:01 +00:00
}
}
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* remove poselib from list */
BLI_freelinkN ( & act - > markers , marker ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* fix active pose number */
2012-05-08 20:18:33 +00:00
act - > active_marker = 0 ;
2018-06-04 09:31:30 +02:00
/* send notifiers for this - using keyframe editing notifiers, since action
* may be being shown in anim editors as active action
2011-07-17 12:37:38 +00:00
*/
2012-05-08 20:18:33 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* done */
return OPERATOR_FINISHED ;
}
2012-04-29 17:11:40 +00:00
void POSELIB_OT_pose_remove ( wmOperatorType * ot )
2009-04-15 03:22:22 +00:00
{
2009-10-13 05:50:26 +00:00
PropertyRNA * prop ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* identifiers */
2012-03-22 07:26:09 +00:00
ot - > name = " PoseLib Remove Pose " ;
ot - > idname = " POSELIB_OT_pose_remove " ;
ot - > description = " Remove nth pose from the active Pose Library " ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* api callbacks */
2012-03-22 07:26:09 +00:00
ot - > invoke = WM_menu_invoke ;
ot - > exec = poselib_remove_exec ;
2015-08-22 18:16:55 +12:00
ot - > poll = has_poselib_pose_data_for_editing_poll ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* flags */
2012-05-08 20:18:33 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* properties */
2012-04-23 09:17:37 +00:00
prop = RNA_def_enum ( ot - > srna , " pose " , DummyRNA_NULL_items , 0 , " Pose " , " The pose to remove " ) ;
RNA_def_enum_funcs ( prop , poselib_stored_pose_itemf ) ;
2014-05-05 15:22:36 +10:00
RNA_def_property_flag ( prop , PROP_ENUM_NO_TRANSLATE ) ;
2012-03-22 07:26:09 +00:00
ot - > prop = prop ;
2009-01-13 12:32:01 +00:00
}
2013-03-13 09:03:46 +00:00
static int poselib_rename_invoke ( bContext * C , wmOperator * op , const wmEvent * event )
2009-10-13 05:50:26 +00:00
{
2012-05-08 20:18:33 +00:00
Object * ob = get_poselib_object ( C ) ;
bAction * act = ( ob ) ? ob - > poselib : NULL ;
2009-10-13 05:50:26 +00:00
TimeMarker * marker ;
2018-06-04 09:31:30 +02:00
2009-10-13 05:50:26 +00:00
/* check if valid poselib */
if ( act = = NULL ) {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Object does not have pose lib data " ) ;
2009-10-13 05:50:26 +00:00
return OPERATOR_CANCELLED ;
}
2018-06-04 09:31:30 +02:00
2009-10-13 05:50:26 +00:00
/* get index (and pointer) of pose to remove */
2012-05-08 20:18:33 +00:00
marker = BLI_findlink ( & act - > markers , act - > active_marker - 1 ) ;
2009-10-13 05:50:26 +00:00
if ( marker = = NULL ) {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Invalid index for pose " ) ;
2009-10-13 05:50:26 +00:00
return OPERATOR_CANCELLED ;
}
else {
/* use the existing name of the marker as the name, and use the active marker as the one to rename */
2012-05-08 20:18:33 +00:00
RNA_enum_set ( op - > ptr , " pose " , act - > active_marker - 1 ) ;
2009-10-13 05:50:26 +00:00
RNA_string_set ( op - > ptr , " name " , marker - > name ) ;
}
2018-06-04 09:31:30 +02:00
2009-10-13 05:50:26 +00:00
/* part to sync with other similar operators... */
2013-10-09 14:35:25 +00:00
return WM_operator_props_popup_confirm ( C , op , event ) ;
2009-10-13 05:50:26 +00:00
}
2009-04-15 03:22:22 +00:00
2012-05-08 20:18:33 +00:00
static int poselib_rename_exec ( bContext * C , wmOperator * op )
2009-01-13 12:32:01 +00:00
{
2012-05-08 20:18:33 +00:00
Object * ob = BKE_object_pose_armature_get ( CTX_data_active_object ( C ) ) ;
bAction * act = ( ob ) ? ob - > poselib : NULL ;
2009-01-13 12:32:01 +00:00
TimeMarker * marker ;
2009-04-15 03:22:22 +00:00
char newname [ 64 ] ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* check if valid poselib */
if ( act = = NULL ) {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Object does not have pose lib data " ) ;
2009-04-15 03:22:22 +00:00
return OPERATOR_CANCELLED ;
2009-01-13 12:32:01 +00:00
}
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* get index (and pointer) of pose to remove */
2013-02-13 15:03:36 +00:00
marker = BLI_findlink ( & act - > markers , RNA_enum_get ( op - > ptr , " pose " ) ) ;
2009-04-15 03:22:22 +00:00
if ( marker = = NULL ) {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Invalid index for pose " ) ;
2009-09-20 11:21:44 +00:00
return OPERATOR_CANCELLED ;
2009-04-15 03:22:22 +00:00
}
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* get new name */
RNA_string_get ( op - > ptr , " name " , newname ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* copy name and validate it */
2009-04-15 03:22:22 +00:00
BLI_strncpy ( marker - > name , newname , sizeof ( marker - > name ) ) ;
2013-03-25 08:29:06 +00:00
BLI_uniquename ( & act - > markers , marker , DATA_ ( " Pose " ) , ' . ' , offsetof ( TimeMarker , name ) , sizeof ( marker - > name ) ) ;
2018-06-04 09:31:30 +02:00
/* send notifiers for this - using keyframe editing notifiers, since action
* may be being shown in anim editors as active action
2011-07-17 12:37:38 +00:00
*/
2012-05-08 20:18:33 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* done */
return OPERATOR_FINISHED ;
2009-01-13 12:32:01 +00:00
}
2012-04-29 17:11:40 +00:00
void POSELIB_OT_pose_rename ( wmOperatorType * ot )
2009-04-15 03:22:22 +00:00
{
2009-10-13 05:50:26 +00:00
PropertyRNA * prop ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* identifiers */
2012-03-22 07:26:09 +00:00
ot - > name = " PoseLib Rename Pose " ;
ot - > idname = " POSELIB_OT_pose_rename " ;
ot - > description = " Rename specified pose from the active Pose Library " ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* api callbacks */
2012-03-22 07:26:09 +00:00
ot - > invoke = poselib_rename_invoke ;
ot - > exec = poselib_rename_exec ;
2015-08-22 18:16:55 +12:00
ot - > poll = has_poselib_pose_data_for_editing_poll ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* flags */
2012-05-08 20:18:33 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2018-06-04 09:31:30 +02:00
2009-04-15 03:22:22 +00:00
/* properties */
2012-05-08 20:18:33 +00:00
/* NOTE: name not pose is the operator's "main" property, so that it will get activated in the popup for easy renaming */
2012-03-22 07:26:09 +00:00
ot - > prop = RNA_def_string ( ot - > srna , " name " , " RenamedPose " , 64 , " New Pose Name " , " New name for pose " ) ;
2012-12-22 01:08:42 +00:00
prop = RNA_def_enum ( ot - > srna , " pose " , DummyRNA_NULL_items , 0 , " Pose " , " The pose to rename " ) ;
2012-05-08 20:18:33 +00:00
RNA_def_enum_funcs ( prop , poselib_stored_pose_itemf ) ;
2014-05-05 15:22:36 +10:00
RNA_def_property_flag ( prop , PROP_ENUM_NO_TRANSLATE ) ;
2009-04-15 03:22:22 +00:00
}
2009-01-13 12:32:01 +00:00
2016-09-16 15:07:23 +02:00
static int poselib_move_exec ( bContext * C , wmOperator * op )
{
Object * ob = get_poselib_object ( C ) ;
bAction * act = ( ob ) ? ob - > poselib : NULL ;
TimeMarker * marker ;
int marker_index ;
int dir ;
PropertyRNA * prop ;
/* check if valid poselib */
if ( act = = NULL ) {
BKE_report ( op - > reports , RPT_ERROR , " Object does not have pose lib data " ) ;
return OPERATOR_CANCELLED ;
}
prop = RNA_struct_find_property ( op - > ptr , " pose " ) ;
if ( RNA_property_is_set ( op - > ptr , prop ) ) {
marker_index = RNA_property_enum_get ( op - > ptr , prop ) ;
}
else {
marker_index = act - > active_marker - 1 ;
}
/* get index (and pointer) of pose to remove */
marker = BLI_findlink ( & act - > markers , marker_index ) ;
if ( marker = = NULL ) {
BKE_reportf ( op - > reports , RPT_ERROR , " Invalid pose specified %d " , marker_index ) ;
return OPERATOR_CANCELLED ;
}
dir = RNA_enum_get ( op - > ptr , " direction " ) ;
/* move pose */
2016-09-18 21:36:34 +02:00
if ( BLI_listbase_link_move ( & act - > markers , marker , dir ) ) {
act - > active_marker = marker_index + dir + 1 ;
2016-09-16 15:07:23 +02:00
2016-09-18 21:36:34 +02:00
/* send notifiers for this - using keyframe editing notifiers, since action
* may be being shown in anim editors as active action
*/
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2016-09-16 15:07:23 +02:00
}
2016-09-18 21:36:34 +02:00
else {
return OPERATOR_CANCELLED ;
2016-09-16 15:07:23 +02:00
}
/* done */
return OPERATOR_FINISHED ;
}
void POSELIB_OT_pose_move ( wmOperatorType * ot )
{
PropertyRNA * prop ;
2017-10-18 15:07:26 +11:00
static const EnumPropertyItem pose_lib_pose_move [ ] = {
2016-09-18 21:36:34 +02:00
{ - 1 , " UP " , 0 , " Up " , " " } ,
{ 1 , " DOWN " , 0 , " Down " , " " } ,
2016-09-16 15:07:23 +02:00
{ 0 , NULL , 0 , NULL , NULL }
} ;
/* identifiers */
ot - > name = " PoseLib Move Pose " ;
ot - > idname = " POSELIB_OT_pose_move " ;
ot - > description = " Move the pose up or down in the active Pose Library " ;
/* api callbacks */
ot - > invoke = WM_menu_invoke ;
ot - > exec = poselib_move_exec ;
ot - > poll = has_poselib_pose_data_for_editing_poll ;
/* flags */
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
/* properties */
prop = RNA_def_enum ( ot - > srna , " pose " , DummyRNA_NULL_items , 0 , " Pose " , " The pose to move " ) ;
RNA_def_enum_funcs ( prop , poselib_stored_pose_itemf ) ;
RNA_def_property_flag ( prop , PROP_ENUM_NO_TRANSLATE ) ;
ot - > prop = prop ;
2016-09-16 17:03:44 +02:00
RNA_def_enum ( ot - > srna , " direction " , pose_lib_pose_move , 0 , " Direction " ,
" Direction to move the chosen pose towards " ) ;
2016-09-16 15:07:23 +02:00
}
2009-01-13 12:32:01 +00:00
/* ************************************************************* */
2011-02-16 00:17:22 +00:00
/* Pose-Lib Browsing/Previewing Operator */
2009-01-13 12:32:01 +00:00
/* Simple struct for storing settings/data for use during PoseLib preview */
typedef struct tPoseLib_PreviewData {
2012-05-08 20:18:33 +00:00
ListBase backups ; /* tPoseLib_Backup structs for restoring poses */
ListBase searchp ; /* LinkData structs storing list of poses which match the current search-string */
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
Scene * scene ; /* active scene */
ScrArea * sa ; /* active area */
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
PointerRNA rna_ptr ; /* RNA-Pointer to Object 'ob' */
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 */
int totcount ; /* total number of elements to work on */
short state ; /* state of main loop */
short redraw ; /* redraw/update settings during main loop */
short flag ; /* flags for various settings */
short search_cursor ; /* position of cursor in searchstr (cursor occurs before the item at the nominated index) */
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 */
2018-06-04 09:31:30 +02:00
2016-05-14 10:00:52 +02:00
char headerstr [ UI_MAX_DRAW_STR ] ; /* Info-text to print in header */
2009-01-13 12:32:01 +00:00
} tPoseLib_PreviewData ;
/* defines for tPoseLib_PreviewData->state values */
enum {
PL_PREVIEW_ERROR = - 1 ,
PL_PREVIEW_RUNNING ,
PL_PREVIEW_CONFIRM ,
PL_PREVIEW_CANCEL ,
2018-06-04 09:31:30 +02:00
PL_PREVIEW_RUNONCE
2009-01-13 12:32:01 +00:00
} ;
/* defines for tPoseLib_PreviewData->redraw values */
enum {
PL_PREVIEW_NOREDRAW = 0 ,
PL_PREVIEW_REDRAWALL ,
PL_PREVIEW_REDRAWHEADER ,
} ;
/* defines for tPoseLib_PreviewData->flag values */
enum {
2012-05-08 20:18:33 +00:00
PL_PREVIEW_FIRSTTIME = ( 1 < < 0 ) ,
2018-03-09 19:03:29 +01:00
PL_PREVIEW_SHOWORIGINAL = ( 1 < < 1 ) ,
PL_PREVIEW_ANY_BONE_SELECTED = ( 1 < < 2 ) ,
2009-01-13 12:32:01 +00:00
} ;
/* ---------------------------- */
/* simple struct for storing backup info */
typedef struct tPoseLib_Backup {
struct tPoseLib_Backup * next , * prev ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
bPoseChannel * pchan ; /* pose channel backups are for */
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
bPoseChannel olddata ; /* copy of pose channel's old data (at start) */
IDProperty * oldprops ; /* copy (needs freeing) of pose channel's properties (at start) */
2009-01-13 12:32:01 +00:00
} tPoseLib_Backup ;
/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */
2012-05-08 20:18:33 +00:00
static void poselib_backup_posecopy ( tPoseLib_PreviewData * pld )
2009-01-13 12:32:01 +00:00
{
2009-04-16 00:33:40 +00:00
bActionGroup * agrp ;
2009-01-13 12:32:01 +00:00
bPoseChannel * pchan ;
2018-03-09 19:03:29 +01:00
bool selected = false ;
/* determine whether any bone is selected. */
LISTBASE_FOREACH ( bPoseChannel * , bchan , & pld - > pose - > chanbase ) {
selected = bchan - > bone ! = NULL & & bchan - > bone - > flag & BONE_SELECTED ;
if ( selected ) {
pld - > flag | = PL_PREVIEW_ANY_BONE_SELECTED ;
break ;
}
}
if ( ! selected ) {
pld - > flag & = ~ PL_PREVIEW_ANY_BONE_SELECTED ;
}
2009-01-13 12:32:01 +00:00
/* for each posechannel that has an actionchannel in */
2012-05-08 20:18:33 +00:00
for ( agrp = pld - > act - > groups . first ; agrp ; agrp = agrp - > next ) {
2009-01-13 12:32:01 +00:00
/* try to find posechannel */
2012-05-08 20:18:33 +00:00
pchan = BKE_pose_channel_find_name ( pld - > pose , agrp - > name ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* backup data if available */
if ( pchan ) {
tPoseLib_Backup * plb ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* store backup */
2012-05-08 20:18:33 +00:00
plb = MEM_callocN ( sizeof ( tPoseLib_Backup ) , " tPoseLib_Backup " ) ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
plb - > pchan = pchan ;
2009-01-13 12:32:01 +00:00
memcpy ( & plb - > olddata , plb - > pchan , sizeof ( bPoseChannel ) ) ;
2018-06-04 09:31:30 +02:00
2011-02-15 11:47:09 +00:00
if ( pchan - > prop )
2012-05-08 20:18:33 +00:00
plb - > oldprops = IDP_CopyProperty ( pchan - > prop ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
BLI_addtail ( & pld - > backups , plb ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* mark as being affected */
pld - > totcount + + ;
}
}
}
2011-02-15 11:47:09 +00:00
/* Restores original pose */
2012-05-08 20:18:33 +00:00
static void poselib_backup_restore ( tPoseLib_PreviewData * pld )
2009-01-13 12:32:01 +00:00
{
tPoseLib_Backup * plb ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
for ( plb = pld - > backups . first ; plb ; plb = plb - > next ) {
2011-02-15 11:47:09 +00:00
/* copy most of data straight back */
2009-01-13 12:32:01 +00:00
memcpy ( plb - > pchan , & plb - > olddata , sizeof ( bPoseChannel ) ) ;
2012-07-06 23:56:59 +00:00
2011-02-15 11:47:09 +00:00
/* just overwrite values of properties from the stored copies (there should be some) */
if ( plb - > oldprops )
IDP_SyncGroupValues ( plb - > pchan - > prop , plb - > oldprops ) ;
2012-07-06 23:56:59 +00:00
/* TODO: constraints settings aren't restored yet, even though these could change (though not that likely) */
2011-02-15 11:47:09 +00:00
}
}
/* Free list of backups, including any side data it may use */
2012-05-08 20:18:33 +00:00
static void poselib_backup_free_data ( tPoseLib_PreviewData * pld )
2011-02-15 11:47:09 +00:00
{
tPoseLib_Backup * plb , * plbn ;
2012-07-06 23:56:59 +00:00
2012-05-08 20:18:33 +00:00
for ( plb = pld - > backups . first ; plb ; plb = plbn ) {
plbn = plb - > next ;
2012-07-06 23:56:59 +00:00
2011-02-15 11:47:09 +00:00
/* free custom data */
if ( plb - > oldprops ) {
IDP_FreeProperty ( plb - > oldprops ) ;
MEM_freeN ( plb - > oldprops ) ;
}
2018-06-04 09:31:30 +02:00
2011-02-15 11:47:09 +00:00
/* free backup element now */
BLI_freelinkN ( & pld - > backups , plb ) ;
2009-01-13 12:32:01 +00:00
}
}
/* ---------------------------- */
/* Applies the appropriate stored pose from the pose-library to the current pose
* - assumes that a valid object , with a poselib has been supplied
* - gets the string to print in the header
2012-05-08 20:18:33 +00:00
* - this code is based on the code for extract_pose_from_action in blenkernel / action . c
2009-01-13 12:32:01 +00:00
*/
2012-05-08 20:18:33 +00:00
static void poselib_apply_pose ( tPoseLib_PreviewData * pld )
2009-01-13 12:32:01 +00:00
{
2012-05-08 20:18:33 +00:00
PointerRNA * ptr = & pld - > rna_ptr ;
bArmature * arm = pld - > arm ;
bPose * pose = pld - > pose ;
2009-01-13 12:32:01 +00:00
bPoseChannel * pchan ;
2012-05-08 20:18:33 +00:00
bAction * act = pld - > act ;
2009-04-15 01:10:36 +00:00
bActionGroup * agrp ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
KeyframeEditData ked = { { NULL } } ;
2010-04-02 12:02:39 +00:00
KeyframeEditFunc group_ok_cb ;
2012-05-08 20:18:33 +00:00
int frame = 1 ;
2018-03-09 19:03:29 +01:00
const bool any_bone_selected = pld - > flag & PL_PREVIEW_ANY_BONE_SELECTED ;
2018-06-04 09:31:30 +02:00
2009-04-15 01:10:36 +00:00
/* get the frame */
2009-01-13 12:32:01 +00:00
if ( pld - > marker )
2012-05-08 20:18:33 +00:00
frame = pld - > marker - > frame ;
2009-01-13 12:32:01 +00:00
else
2012-10-21 05:46:41 +00:00
return ;
2018-06-04 09:31:30 +02:00
2009-04-15 01:10:36 +00:00
/* init settings for testing groups for keyframes */
2012-05-08 20:18:33 +00:00
group_ok_cb = ANIM_editkeyframes_ok ( BEZT_OK_FRAMERANGE ) ;
ked . f1 = ( ( float ) frame ) - 0.5f ;
ked . f2 = ( ( float ) frame ) + 0.5f ;
2018-03-09 19:03:29 +01:00
2009-01-13 12:32:01 +00:00
/* start applying - only those channels which have a key at this point in time! */
2012-05-08 20:18:33 +00:00
for ( agrp = act - > groups . first ; agrp ; agrp = agrp - > next ) {
2009-04-15 01:10:36 +00:00
/* check if group has any keyframes */
2011-06-30 13:56:47 +00:00
if ( ANIM_animchanneldata_keyframes_loop ( & ked , NULL , agrp , ALE_GROUP , NULL , group_ok_cb , NULL ) ) {
2009-04-15 01:10:36 +00:00
/* has keyframe on this frame, so try to get a PoseChannel with this name */
2012-05-08 20:18:33 +00:00
pchan = BKE_pose_channel_find_name ( pose , agrp - > name ) ;
2018-06-04 09:31:30 +02:00
2012-10-21 05:46:41 +00:00
if ( pchan ) {
2014-04-11 11:25:41 +10:00
bool ok = 0 ;
2018-06-04 09:31:30 +02:00
2009-04-15 01:10:36 +00:00
/* check if this bone should get any animation applied */
2018-03-09 19:03:29 +01:00
if ( ! any_bone_selected ) {
2009-04-15 01:10:36 +00:00
/* if no bones are selected, then any bone is ok */
2012-05-08 20:18:33 +00:00
ok = 1 ;
2009-04-15 01:10:36 +00:00
}
else if ( pchan - > bone ) {
/* only ok if bone is visible and selected */
2012-04-28 06:31:57 +00:00
if ( ( pchan - > bone - > flag & BONE_SELECTED ) & &
( pchan - > bone - > flag & BONE_HIDDEN_P ) = = 0 & &
( pchan - > bone - > layer & arm - > layer ) )
{
2009-04-15 01:10:36 +00:00
ok = 1 ;
2012-04-28 06:31:57 +00:00
}
2009-01-13 12:32:01 +00:00
}
2018-03-09 19:03:29 +01:00
2018-06-04 09:31:30 +02:00
if ( ok )
2009-04-15 01:10:36 +00:00
animsys_evaluate_action_group ( ptr , act , agrp , NULL , ( float ) frame ) ;
2009-01-13 12:32:01 +00:00
}
}
}
}
/* Auto-keys/tags bones affected by the pose used from the poselib */
2012-05-08 20:18:33 +00:00
static void poselib_keytag_pose ( bContext * C , Scene * scene , tPoseLib_PreviewData * pld )
2009-01-13 12:32:01 +00:00
{
2012-05-08 20:18:33 +00:00
bPose * pose = pld - > pose ;
2009-01-13 12:32:01 +00:00
bPoseChannel * pchan ;
2012-05-08 20:18:33 +00:00
bAction * act = pld - > act ;
2009-04-15 12:04:10 +00:00
bActionGroup * agrp ;
2018-06-04 09:31:30 +02:00
2011-10-23 05:08:02 +00:00
KeyingSet * ks = ANIM_get_keyingset_for_autokeying ( scene , ANIM_KS_WHOLE_CHARACTER_ID ) ;
2011-02-15 11:47:09 +00:00
ListBase dsources = { NULL , NULL } ;
2014-11-20 20:23:13 +01:00
bool autokey = autokeyframe_cfra_can_key ( scene , & pld - > ob - > id ) ;
2018-03-09 19:03:29 +01:00
const bool any_bone_selected = pld - > flag & PL_PREVIEW_ANY_BONE_SELECTED ;
2009-01-13 12:32:01 +00:00
/* start tagging/keying */
2012-05-08 20:18:33 +00:00
for ( agrp = act - > groups . first ; agrp ; agrp = agrp - > next ) {
2011-08-21 13:25:56 +00:00
/* only for selected bones unless there aren't any selected, in which case all are included */
2012-05-08 20:18:33 +00:00
pchan = BKE_pose_channel_find_name ( pose , agrp - > name ) ;
2018-06-04 09:31:30 +02:00
2011-08-21 13:25:56 +00:00
if ( pchan ) {
2018-03-09 19:03:29 +01:00
if ( ! any_bone_selected | | ( ( pchan - > bone ) & & ( pchan - > bone - > flag & BONE_SELECTED ) ) ) {
2011-02-15 11:47:09 +00:00
if ( autokey ) {
/* add datasource override for the PoseChannel, to be used later */
2018-06-04 09:31:30 +02:00
ANIM_relative_keyingset_add_source ( & dsources , & pld - > ob - > id , & RNA_PoseBone , pchan ) ;
2009-01-13 12:32:01 +00:00
/* clear any unkeyed tags */
if ( pchan - > bone )
pchan - > bone - > flag & = ~ BONE_UNKEYED ;
}
else {
/* add unkeyed tags */
if ( pchan - > bone )
pchan - > bone - > flag | = BONE_UNKEYED ;
}
2009-04-15 12:04:10 +00:00
}
}
}
2018-06-04 09:31:30 +02:00
2011-02-15 11:47:09 +00:00
/* perform actual auto-keying now */
if ( autokey ) {
/* insert keyframes for all relevant bones in one go */
ANIM_apply_keyingset ( C , & dsources , NULL , ks , MODIFYKEY_MODE_INSERT , ( float ) CFRA ) ;
BLI_freelistN ( & dsources ) ;
}
2018-06-04 09:31:30 +02:00
2009-10-08 05:53:26 +00:00
/* send notifiers for this */
2012-05-08 20:18:33 +00:00
WM_event_add_notifier ( C , NC_ANIMATION | ND_KEYFRAME | NA_EDITED , NULL ) ;
2009-04-15 12:04:10 +00:00
}
/* Apply the relevant changes to the pose */
2012-05-08 20:18:33 +00:00
static void poselib_preview_apply ( bContext * C , wmOperator * op )
2009-04-15 12:04:10 +00:00
{
2012-05-08 20:18:33 +00:00
tPoseLib_PreviewData * pld = ( tPoseLib_PreviewData * ) op - > customdata ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* only recalc pose (and its dependencies) if pose has changed */
if ( pld - > redraw = = PL_PREVIEW_REDRAWALL ) {
/* don't clear pose if firsttime */
2012-05-08 20:18:33 +00:00
if ( ( pld - > flag & PL_PREVIEW_FIRSTTIME ) = = 0 )
2009-04-15 12:04:10 +00:00
poselib_backup_restore ( pld ) ;
else
pld - > flag & = ~ PL_PREVIEW_FIRSTTIME ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* pose should be the right one to draw (unless we're temporarily not showing it) */
2012-05-08 20:18:33 +00:00
if ( ( pld - > flag & PL_PREVIEW_SHOWORIGINAL ) = = 0 ) {
2009-04-16 00:53:22 +00:00
RNA_int_set ( op - > ptr , " pose_index " , BLI_findindex ( & pld - > act - > markers , pld - > marker ) ) ;
2009-04-15 12:04:10 +00:00
poselib_apply_pose ( pld ) ;
2009-04-16 00:53:22 +00:00
}
else
2012-05-08 20:18:33 +00:00
RNA_int_set ( op - > ptr , " pose_index " , - 2 ) ; /* -2 means don't apply any pose */
2018-06-04 09:31:30 +02:00
/* old optimize trick... this enforces to bypass the depgraph
2009-04-15 12:04:10 +00:00
* - note : code copied from transform_generics . c - > recalcData ( )
*/
// FIXME: shouldn't this use the builtin stuff?
2012-05-08 20:18:33 +00:00
if ( ( pld - > arm - > flag & ARM_DELAYDEFORM ) = = 0 )
2010-12-05 18:59:23 +00:00
DAG_id_tag_update ( & pld - > ob - > id , OB_RECALC_DATA ) ; /* sets recalc flags */
2009-04-15 12:04:10 +00:00
else
2012-05-05 16:03:57 +00:00
BKE_pose_where_is ( pld - > scene , pld - > ob ) ;
2009-04-15 12:04:10 +00:00
}
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* do header print - if interactively previewing */
if ( pld - > state = = PL_PREVIEW_RUNNING ) {
if ( pld - > flag & PL_PREVIEW_SHOWORIGINAL ) {
2012-01-11 12:33:51 +00:00
BLI_strncpy ( pld - > headerstr ,
2016-05-14 10:00:52 +02:00
IFACE_ ( " PoseLib Previewing Pose: [Showing Original Pose] | Use Tab to start previewing poses again " ) ,
2012-01-11 12:33:51 +00:00
sizeof ( pld - > headerstr ) ) ;
2009-04-15 12:04:10 +00:00
ED_area_headerprint ( pld - > sa , pld - > headerstr ) ;
}
else if ( pld - > searchstr [ 0 ] ) {
char tempstr [ 65 ] ;
char markern [ 64 ] ;
short index ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* get search-string */
2012-05-08 20:18:33 +00:00
index = pld - > search_cursor ;
2018-06-04 09:31:30 +02:00
2012-09-14 06:15:46 +00:00
if ( index > = 0 & & index < sizeof ( tempstr ) - 1 ) {
2009-04-15 12:04:10 +00:00
memcpy ( & tempstr [ 0 ] , & pld - > searchstr [ 0 ] , index ) ;
2012-05-08 20:18:33 +00:00
tempstr [ index ] = ' | ' ;
memcpy ( & tempstr [ index + 1 ] , & pld - > searchstr [ index ] , ( sizeof ( tempstr ) - 1 ) - index ) ;
2009-01-13 12:32:01 +00:00
}
2009-04-15 12:04:10 +00:00
else {
2011-09-26 18:51:10 +00:00
BLI_strncpy ( tempstr , pld - > searchstr , sizeof ( tempstr ) ) ;
2009-04-15 12:04:10 +00:00
}
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* get marker name */
2011-10-19 23:10:54 +00:00
BLI_strncpy ( markern , pld - > marker ? pld - > marker - > name : " No Matches " , sizeof ( markern ) ) ;
2012-01-11 12:33:51 +00:00
BLI_snprintf ( pld - > headerstr , sizeof ( pld - > headerstr ) ,
2016-05-14 10:00:52 +02:00
IFACE_ ( " PoseLib Previewing Pose: Filter - [%s] | "
" Current Pose - \" %s \" | "
" Use ScrollWheel or PageUp/Down to change " ) ,
2012-01-11 12:33:51 +00:00
tempstr , markern ) ;
2009-04-15 12:04:10 +00:00
ED_area_headerprint ( pld - > sa , pld - > headerstr ) ;
}
else {
2012-01-11 12:33:51 +00:00
BLI_snprintf ( pld - > headerstr , sizeof ( pld - > headerstr ) ,
2016-05-14 10:00:52 +02:00
IFACE_ ( " PoseLib Previewing Pose: \" %s \" | "
" Use ScrollWheel or PageUp/Down to change " ) ,
2012-01-11 12:33:51 +00:00
pld - > marker - > name ) ;
2009-04-15 12:04:10 +00:00
ED_area_headerprint ( pld - > sa , pld - > headerstr ) ;
2009-01-13 12:32:01 +00:00
}
}
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* request drawing of view + clear redraw flag */
2012-05-08 20:18:33 +00:00
WM_event_add_notifier ( C , NC_OBJECT | ND_POSE , pld - > ob ) ;
pld - > redraw = PL_PREVIEW_NOREDRAW ;
2009-01-13 12:32:01 +00:00
}
/* ---------------------------- */
2018-06-04 09:31:30 +02:00
/* This helper function is called during poselib_preview_poses to find the
2009-01-13 12:32:01 +00:00
* pose to preview next ( after a change event )
*/
2012-05-08 20:18:33 +00:00
static void poselib_preview_get_next ( tPoseLib_PreviewData * pld , int step )
2009-01-13 12:32:01 +00:00
{
2011-02-07 01:28:47 +00:00
/* stop if not going anywhere, as we assume that there is a direction to move in */
if ( step = = 0 )
return ;
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* search-string dictates a special approach */
if ( pld - > searchstr [ 0 ] ) {
TimeMarker * marker ;
LinkData * ld , * ldn , * ldc ;
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* free and rebuild if needed (i.e. if search-str changed) */
2015-01-26 16:03:11 +01:00
if ( ! STREQ ( pld - > searchstr , pld - > searchold ) ) {
2011-02-07 01:28:47 +00:00
/* free list of temporary search matches */
BLI_freelistN ( & pld - > searchp ) ;
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* generate a new list of search matches */
2012-05-08 20:18:33 +00:00
for ( marker = pld - > act - > markers . first ; marker ; marker = marker - > next ) {
2018-06-04 09:31:30 +02:00
/* does the name partially match?
2012-05-08 20:18:33 +00:00
* - don ' t worry about case , to make it easier for users to quickly input a name ( or
2011-02-07 01:28:47 +00:00
* 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 */
2012-05-08 20:18:33 +00:00
ld = MEM_callocN ( sizeof ( LinkData ) , " PoseMatch " ) ;
ld - > data = marker ;
2011-02-07 01:28:47 +00:00
BLI_addtail ( & pld - > searchp , ld ) ;
2009-01-13 12:32:01 +00:00
}
}
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* set current marker to NULL (so that we start from first) */
2012-05-08 20:18:33 +00:00
pld - > marker = NULL ;
2011-02-07 01:28:47 +00:00
}
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* check if any matches */
2014-02-08 06:07:10 +11:00
if ( BLI_listbase_is_empty ( & pld - > searchp ) ) {
2012-05-08 20:18:33 +00:00
pld - > marker = NULL ;
2011-02-07 01:28:47 +00:00
return ;
}
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* find first match */
2012-05-08 20:18:33 +00:00
for ( ldc = pld - > searchp . first ; ldc ; ldc = ldc - > next ) {
2011-02-07 01:28:47 +00:00
if ( ldc - > data = = pld - > marker )
break ;
}
if ( ldc = = NULL )
2012-05-08 20:18:33 +00:00
ldc = pld - > searchp . first ;
2018-06-04 09:31:30 +02:00
/* Loop through the matches in a cyclic fashion, incrementing/decrementing step as appropriate
2011-02-07 01:28:47 +00:00
* until step = = 0. At this point , marker should be the correct marker .
*/
if ( step > 0 ) {
2012-05-08 20:18:33 +00:00
for ( ld = ldc ; ld & & step ; ld = ldn , step - - )
ldn = ( ld - > next ) ? ld - > next : pld - > searchp . first ;
2009-01-13 12:32:01 +00:00
}
else {
2012-05-08 20:18:33 +00:00
for ( ld = ldc ; ld & & step ; ld = ldn , step + + )
ldn = ( ld - > prev ) ? ld - > prev : pld - > searchp . last ;
2009-01-13 12:32:01 +00:00
}
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* set marker */
if ( ld )
2012-05-08 20:18:33 +00:00
pld - > marker = ld - > data ;
2011-02-07 01:28:47 +00:00
}
else {
TimeMarker * marker , * next ;
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* if no marker, because we just ended searching, then set that to the start of the list */
if ( pld - > marker = = NULL )
2012-05-08 20:18:33 +00:00
pld - > marker = pld - > act - > markers . first ;
2018-06-04 09:31:30 +02:00
/* Loop through the markers in a cyclic fashion, incrementing/decrementing step as appropriate
2011-02-07 01:28:47 +00:00
* until step = = 0. At this point , marker should be the correct marker .
*/
if ( step > 0 ) {
2012-05-08 20:18:33 +00:00
for ( marker = pld - > marker ; marker & & step ; marker = next , step - - )
next = ( marker - > next ) ? marker - > next : pld - > act - > markers . first ;
2011-02-07 01:28:47 +00:00
}
else {
2012-05-08 20:18:33 +00:00
for ( marker = pld - > marker ; marker & & step ; marker = next , step + + )
next = ( marker - > prev ) ? marker - > prev : pld - > act - > markers . last ;
2011-02-07 01:28:47 +00:00
}
2018-06-04 09:31:30 +02:00
2011-02-07 01:28:47 +00:00
/* it should be fairly impossible for marker to be NULL */
if ( marker )
2012-05-08 20:18:33 +00:00
pld - > marker = marker ;
2009-01-13 12:32:01 +00:00
}
}
/* specially handle events for searching */
2012-05-08 20:18:33 +00:00
static void poselib_preview_handle_search ( tPoseLib_PreviewData * pld , unsigned short event , char ascii )
2009-01-13 12:32:01 +00:00
{
2009-04-15 12:04:10 +00:00
/* try doing some form of string manipulation first */
switch ( event ) {
case BACKSPACEKEY :
if ( pld - > searchstr [ 0 ] & & pld - > search_cursor ) {
2012-05-08 20:18:33 +00:00
short len = strlen ( pld - > searchstr ) ;
short index = pld - > search_cursor ;
2009-04-15 12:04:10 +00:00
short i ;
2018-06-04 09:31:30 +02:00
for ( i = index ; i < = len ; i + + )
2012-05-08 20:18:33 +00:00
pld - > searchstr [ i - 1 ] = pld - > searchstr [ i ] ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
pld - > search_cursor - - ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
poselib_preview_get_next ( pld , 1 ) ;
pld - > redraw = PL_PREVIEW_REDRAWALL ;
return ;
2012-10-21 05:46:41 +00:00
}
2009-04-15 12:04:10 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
case DELKEY :
if ( pld - > searchstr [ 0 ] & & pld - > searchstr [ 1 ] ) {
2012-05-08 20:18:33 +00:00
short len = strlen ( pld - > searchstr ) ;
short index = pld - > search_cursor ;
2009-04-15 12:04:10 +00:00
int i ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
if ( index < len ) {
2018-06-04 09:31:30 +02:00
for ( i = index ; i < len ; i + + )
2012-05-08 20:18:33 +00:00
pld - > searchstr [ i ] = pld - > searchstr [ i + 1 ] ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
poselib_preview_get_next ( pld , 1 ) ;
pld - > redraw = PL_PREVIEW_REDRAWALL ;
return ;
}
}
break ;
}
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
if ( ascii ) {
/* character to add to the string */
2012-05-08 20:18:33 +00:00
short index = pld - > search_cursor ;
short len = ( pld - > searchstr [ 0 ] ) ? strlen ( pld - > searchstr ) : 0 ;
2009-01-13 12:32:01 +00:00
short i ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
if ( len ) {
2018-06-04 09:31:30 +02:00
for ( i = len ; i > index ; i - - )
2012-05-08 20:18:33 +00:00
pld - > searchstr [ i ] = pld - > searchstr [ i - 1 ] ;
2009-01-13 12:32:01 +00:00
}
else
2012-05-08 20:18:33 +00:00
pld - > searchstr [ 1 ] = 0 ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
pld - > searchstr [ index ] = ascii ;
2009-01-13 12:32:01 +00:00
pld - > search_cursor + + ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
poselib_preview_get_next ( pld , 1 ) ;
pld - > redraw = PL_PREVIEW_REDRAWALL ;
}
}
/* handle events for poselib_preview_poses */
2013-03-13 09:03:46 +00:00
static int poselib_preview_handle_event ( bContext * UNUSED ( C ) , wmOperator * op , const wmEvent * event )
2009-01-13 12:32:01 +00:00
{
2012-05-08 20:18:33 +00:00
tPoseLib_PreviewData * pld = op - > customdata ;
2009-04-15 12:38:04 +00:00
int ret = OPERATOR_RUNNING_MODAL ;
2018-06-04 09:31:30 +02:00
2011-02-06 22:20:26 +00:00
/* only accept 'press' event, and ignore 'release', so that we don't get double actions */
if ( ELEM ( event - > val , KM_PRESS , KM_NOTHING ) = = 0 ) {
2015-07-03 15:07:46 +02:00
//printf("PoseLib: skipping event with type '%s' and val %d\n", WM_key_event_string(event->type, false), event->val);
2018-06-04 09:31:30 +02:00
return ret ;
2011-02-06 22:20:26 +00:00
}
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* backup stuff that needs to occur before every operation
* - make a copy of searchstr , so that we know if cache needs to be rebuilt
*/
2011-10-19 23:10:54 +00:00
BLI_strncpy ( pld - > searchold , pld - > searchstr , sizeof ( pld - > searchold ) ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* if we're currently showing the original pose, only certain events are handled */
if ( pld - > flag & PL_PREVIEW_SHOWORIGINAL ) {
2009-04-15 12:04:10 +00:00
switch ( event - > type ) {
2009-01-13 12:32:01 +00:00
/* exit - cancel */
case ESCKEY :
case RIGHTMOUSE :
2012-05-08 20:18:33 +00:00
pld - > state = PL_PREVIEW_CANCEL ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* exit - confirm */
case LEFTMOUSE :
case RETKEY :
case PADENTER :
case SPACEKEY :
2012-05-08 20:18:33 +00:00
pld - > state = PL_PREVIEW_CONFIRM ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* view manipulation */
2018-06-04 09:31:30 +02:00
/* we add pass through here, so that the operators responsible for these can still run,
2009-04-15 12:38:04 +00:00
* even though we still maintain control ( as RUNNING_MODAL flag is still set too )
*/
2009-01-13 12:32:01 +00:00
case PAD0 : case PAD1 : case PAD2 : case PAD3 : case PAD4 :
case PAD5 : case PAD6 : case PAD7 : case PAD8 : case PAD9 :
2018-06-04 09:31:30 +02:00
case PADPLUSKEY : case PADMINUS :
2011-02-06 22:20:26 +00:00
case MIDDLEMOUSE : case MOUSEMOVE :
2012-05-27 19:40:36 +00:00
//pld->redraw = PL_PREVIEW_REDRAWHEADER;
2011-02-06 22:20:26 +00:00
ret = OPERATOR_PASS_THROUGH ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:38:04 +00:00
/* quicky compare to original */
2009-01-13 12:32:01 +00:00
case TABKEY :
2011-02-06 22:20:26 +00:00
pld - > flag & = ~ PL_PREVIEW_SHOWORIGINAL ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
break ;
}
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* EXITS HERE... */
2009-04-15 12:38:04 +00:00
return ret ;
2009-01-13 12:32:01 +00:00
}
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* NORMAL EVENT HANDLING... */
/* searching takes priority over normal activity */
2009-04-15 12:04:10 +00:00
switch ( event - > type ) {
2009-01-13 12:32:01 +00:00
/* exit - cancel */
case ESCKEY :
case RIGHTMOUSE :
2012-05-08 20:18:33 +00:00
pld - > state = PL_PREVIEW_CANCEL ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* exit - confirm */
case LEFTMOUSE :
case RETKEY :
case PADENTER :
case SPACEKEY :
2012-05-08 20:18:33 +00:00
pld - > state = PL_PREVIEW_CONFIRM ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* toggle between original pose and poselib pose*/
case TABKEY :
2011-02-06 22:20:26 +00:00
pld - > flag | = PL_PREVIEW_SHOWORIGINAL ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* change to previous pose (cyclic) */
case PAGEUPKEY :
case WHEELUPMOUSE :
poselib_preview_get_next ( pld , - 1 ) ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* change to next pose (cyclic) */
case PAGEDOWNKEY :
case WHEELDOWNMOUSE :
poselib_preview_get_next ( pld , 1 ) ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* jump 5 poses (cyclic, back) */
case DOWNARROWKEY :
poselib_preview_get_next ( pld , - 5 ) ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* jump 5 poses (cyclic, forward) */
case UPARROWKEY :
poselib_preview_get_next ( pld , 5 ) ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* change to next pose or searching cursor control */
case RIGHTARROWKEY :
if ( pld - > searchstr [ 0 ] ) {
/* move text-cursor to the right */
if ( pld - > search_cursor < strlen ( pld - > searchstr ) )
pld - > search_cursor + + ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWHEADER ;
2009-01-13 12:32:01 +00:00
}
else {
/* change to next pose (cyclic) */
poselib_preview_get_next ( pld , 1 ) ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
}
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* change to next pose or searching cursor control */
case LEFTARROWKEY :
if ( pld - > searchstr [ 0 ] ) {
/* move text-cursor to the left */
if ( pld - > search_cursor )
pld - > search_cursor - - ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWHEADER ;
2009-01-13 12:32:01 +00:00
}
else {
/* change to previous pose (cyclic) */
poselib_preview_get_next ( pld , - 1 ) ;
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
}
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* change to first pose or start of searching string */
case HOMEKEY :
if ( pld - > searchstr [ 0 ] ) {
2012-05-08 20:18:33 +00:00
pld - > search_cursor = 0 ;
pld - > redraw = PL_PREVIEW_REDRAWHEADER ;
2009-01-13 12:32:01 +00:00
}
else {
/* change to first pose */
2012-05-08 20:18:33 +00:00
pld - > marker = pld - > act - > markers . first ;
pld - > act - > active_marker = 1 ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
}
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* change to last pose or start of searching string */
case ENDKEY :
if ( pld - > searchstr [ 0 ] ) {
2012-05-08 20:18:33 +00:00
pld - > search_cursor = strlen ( pld - > searchstr ) ;
pld - > redraw = PL_PREVIEW_REDRAWHEADER ;
2009-01-13 12:32:01 +00:00
}
else {
/* change to last pose */
2012-05-08 20:18:33 +00:00
pld - > marker = pld - > act - > markers . last ;
2014-11-16 13:57:58 +01:00
pld - > act - > active_marker = BLI_listbase_count ( & pld - > act - > markers ) ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-01-13 12:32:01 +00:00
}
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* view manipulation */
2018-06-04 09:31:30 +02:00
/* we add pass through here, so that the operators responsible for these can still run,
2009-04-15 12:38:04 +00:00
* even though we still maintain control ( as RUNNING_MODAL flag is still set too )
*/
2011-02-06 22:20:26 +00:00
case MIDDLEMOUSE : case MOUSEMOVE :
2012-05-27 19:40:36 +00:00
//pld->redraw = PL_PREVIEW_REDRAWHEADER;
2011-02-06 22:20:26 +00:00
ret = OPERATOR_PASS_THROUGH ;
2009-01-13 12:32:01 +00:00
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* view manipulation, or searching */
case PAD0 : case PAD1 : case PAD2 : case PAD3 : case PAD4 :
case PAD5 : case PAD6 : case PAD7 : case PAD8 : case PAD9 :
case PADPLUSKEY : case PADMINUS :
if ( pld - > searchstr [ 0 ] ) {
2009-04-15 12:38:04 +00:00
/* searching... */
poselib_preview_handle_search ( pld , event - > type , event - > ascii ) ;
2009-01-13 12:32:01 +00:00
}
else {
2009-04-15 12:38:04 +00:00
/* view manipulation (see above) */
2012-05-27 19:40:36 +00:00
//pld->redraw = PL_PREVIEW_REDRAWHEADER;
2011-02-06 22:20:26 +00:00
ret = OPERATOR_PASS_THROUGH ;
2009-01-13 12:32:01 +00:00
}
break ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* otherwise, assume that searching might be able to handle it */
default :
2009-04-15 12:04:10 +00:00
poselib_preview_handle_search ( pld , event - > type , event - > ascii ) ;
2009-01-13 12:32:01 +00:00
break ;
}
2018-06-04 09:31:30 +02:00
2009-04-15 12:38:04 +00:00
return ret ;
2009-01-13 12:32:01 +00:00
}
/* ---------------------------- */
/* Init PoseLib Previewing data */
2012-05-08 20:18:33 +00:00
static void poselib_preview_init_data ( bContext * C , wmOperator * op )
2009-01-13 12:32:01 +00:00
{
2009-04-15 12:04:10 +00:00
tPoseLib_PreviewData * pld ;
2012-05-08 20:18:33 +00:00
Object * ob = get_poselib_object ( C ) ;
2009-04-16 00:53:22 +00:00
int pose_index = RNA_int_get ( op - > ptr , " pose_index " ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* set up preview state info */
2012-05-08 20:18:33 +00:00
op - > customdata = pld = MEM_callocN ( sizeof ( tPoseLib_PreviewData ) , " PoseLib Preview Data " ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* get basic data */
2012-05-08 20:18:33 +00:00
pld - > ob = ob ;
pld - > arm = ( ob ) ? ( ob - > data ) : NULL ;
pld - > pose = ( ob ) ? ( ob - > pose ) : NULL ;
pld - > act = ( ob ) ? ( ob - > poselib ) : NULL ;
2018-06-04 09:31:30 +02:00
2012-05-08 20:18:33 +00:00
pld - > scene = CTX_data_scene ( C ) ;
pld - > sa = CTX_wm_area ( C ) ;
2018-06-04 09:31:30 +02:00
2009-04-16 00:53:22 +00:00
/* get starting pose based on RNA-props for this operator */
if ( pose_index = = - 1 )
2012-05-08 20:18:33 +00:00
pld - > marker = poselib_get_active_pose ( pld - > act ) ;
2009-04-16 00:53:22 +00:00
else if ( pose_index = = - 2 )
pld - > flag | = PL_PREVIEW_SHOWORIGINAL ;
else
2012-05-08 20:18:33 +00:00
pld - > marker = ( pld - > act ) ? BLI_findlink ( & pld - > act - > markers , pose_index ) : NULL ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* check if valid poselib */
2014-07-20 01:30:29 +10:00
if ( ELEM ( NULL , pld - > ob , pld - > pose , pld - > arm ) ) {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Pose lib is only for armatures in pose mode " ) ;
2012-05-08 20:18:33 +00:00
pld - > state = PL_PREVIEW_ERROR ;
2009-01-13 12:32:01 +00:00
return ;
}
if ( pld - > act = = NULL ) {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Object does not have a valid pose lib " ) ;
2012-05-08 20:18:33 +00:00
pld - > state = PL_PREVIEW_ERROR ;
2009-01-13 12:32:01 +00:00
return ;
}
if ( pld - > marker = = NULL ) {
2009-04-16 00:53:22 +00:00
if ( pld - > act - > markers . first ) {
2009-01-13 12:32:01 +00:00
/* just use first one then... */
2012-05-08 20:18:33 +00:00
pld - > marker = pld - > act - > markers . first ;
2018-06-04 09:31:30 +02:00
if ( pose_index > - 2 )
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_WARNING , " Pose lib had no active pose " ) ;
2009-01-13 12:32:01 +00:00
}
else {
2012-10-19 16:43:10 +00:00
BKE_report ( op - > reports , RPT_ERROR , " Pose lib has no poses to preview/apply " ) ;
2012-05-08 20:18:33 +00:00
pld - > state = PL_PREVIEW_ERROR ;
2009-01-13 12:32:01 +00:00
return ;
}
}
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* get ID pointer for applying poses */
RNA_id_pointer_create ( & ob - > id , & pld - > rna_ptr ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* make backups for restoring pose */
poselib_backup_posecopy ( pld ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* set flags for running */
2012-05-08 20:18:33 +00:00
pld - > state = PL_PREVIEW_RUNNING ;
pld - > redraw = PL_PREVIEW_REDRAWALL ;
2009-04-16 00:53:22 +00:00
pld - > flag | = PL_PREVIEW_FIRSTTIME ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* set depsgraph flags */
2012-05-08 20:18:33 +00:00
/* make sure the lock is set OK, unlock can be accidentally saved? */
2009-01-13 12:32:01 +00:00
pld - > pose - > flag | = POSE_LOCKED ;
pld - > pose - > flag & = ~ POSE_DO_UNLOCK ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* clear strings + search */
2012-05-08 20:18:33 +00:00
pld - > headerstr [ 0 ] = pld - > searchstr [ 0 ] = pld - > searchold [ 0 ] = ' \0 ' ;
pld - > search_cursor = 0 ;
2009-01-13 12:32:01 +00:00
}
/* After previewing poses */
2012-05-08 20:18:33 +00:00
static void poselib_preview_cleanup ( bContext * C , wmOperator * op )
2009-01-13 12:32:01 +00:00
{
2012-05-08 20:18:33 +00:00
tPoseLib_PreviewData * pld = ( tPoseLib_PreviewData * ) op - > customdata ;
Scene * scene = pld - > scene ;
Object * ob = pld - > ob ;
bPose * pose = pld - > pose ;
bArmature * arm = pld - > arm ;
bAction * act = pld - > act ;
TimeMarker * marker = pld - > marker ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* redraw the header so that it doesn't show any of our stuff anymore */
ED_area_headerprint ( pld - > sa , NULL ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* this signal does one recalc on pose, then unlocks, so ESC or edit will work */
pose - > flag | = POSE_DO_UNLOCK ;
2018-06-04 09:31:30 +02:00
2012-03-08 04:12:11 +00:00
/* clear pose if canceled */
2009-01-13 12:32:01 +00:00
if ( pld - > state = = PL_PREVIEW_CANCEL ) {
poselib_backup_restore ( pld ) ;
2018-06-04 09:31:30 +02:00
/* old optimize trick... this enforces to bypass the depgraph
2009-01-13 12:32:01 +00:00
* - note : code copied from transform_generics . c - > recalcData ( )
*/
2012-05-08 20:18:33 +00:00
if ( ( arm - > flag & ARM_DELAYDEFORM ) = = 0 )
2010-12-05 18:59:23 +00:00
DAG_id_tag_update ( & ob - > id , OB_RECALC_DATA ) ; /* sets recalc flags */
2009-01-13 12:32:01 +00:00
else
2012-05-05 16:03:57 +00:00
BKE_pose_where_is ( scene , ob ) ;
2009-01-13 12:32:01 +00:00
}
else if ( pld - > state = = PL_PREVIEW_CONFIRM ) {
/* tag poses as appropriate */
2009-09-13 12:34:00 +00:00
poselib_keytag_pose ( C , scene , pld ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* change active pose setting */
2012-05-08 20:18:33 +00:00
act - > active_marker = BLI_findindex ( & act - > markers , marker ) + 1 ;
2011-03-03 17:59:04 +00:00
action_set_activemarker ( act , marker , NULL ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* Update event for pose and deformation children */
2010-12-05 18:59:23 +00:00
DAG_id_tag_update ( & ob - > id , OB_RECALC_DATA ) ;
2018-06-04 09:31:30 +02:00
2009-01-13 12:32:01 +00:00
/* updates */
2009-02-16 03:01:56 +00:00
if ( IS_AUTOKEY_MODE ( scene , NORMAL ) ) {
2009-04-15 12:04:10 +00:00
//remake_action_ipos(ob->action);
2009-01-13 12:32:01 +00:00
}
2011-02-16 02:05:41 +00:00
else
2012-05-05 16:03:57 +00:00
BKE_pose_where_is ( scene , ob ) ;
2009-01-13 12:32:01 +00:00
}
2018-06-04 09:31:30 +02:00
2014-07-16 12:53:17 +02:00
/* Request final redraw of the view. */
WM_event_add_notifier ( C , NC_OBJECT | ND_POSE , pld - > ob ) ;
2018-06-04 09:31:30 +02:00
2011-02-15 11:47:09 +00:00
/* free memory used for backups and searching */
poselib_backup_free_data ( pld ) ;
2009-01-13 12:32:01 +00:00
BLI_freelistN ( & pld - > searchp ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* free temp data for operator */
MEM_freeN ( pld ) ;
2012-05-08 20:18:33 +00:00
op - > customdata = NULL ;
2009-01-13 12:32:01 +00:00
}
2009-04-15 12:04:10 +00:00
/* End previewing operation */
2012-05-08 20:18:33 +00:00
static int poselib_preview_exit ( bContext * C , wmOperator * op )
2009-04-15 12:04:10 +00:00
{
2012-05-08 20:18:33 +00:00
tPoseLib_PreviewData * pld = op - > customdata ;
2011-02-16 02:05:41 +00:00
int exit_state = pld - > state ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* finish up */
poselib_preview_cleanup ( C , op ) ;
2018-06-04 09:31:30 +02:00
2011-02-16 02:05:41 +00:00
if ( ELEM ( exit_state , PL_PREVIEW_CANCEL , PL_PREVIEW_ERROR ) )
2009-04-15 12:04:10 +00:00
return OPERATOR_CANCELLED ;
else
return OPERATOR_FINISHED ;
}
2009-01-13 12:32:01 +00:00
2009-04-15 12:04:10 +00:00
/* Cancel previewing operation (called when exiting Blender) */
2013-10-30 23:08:53 +00:00
static void poselib_preview_cancel ( bContext * C , wmOperator * op )
2009-04-15 12:04:10 +00:00
{
poselib_preview_exit ( C , op ) ;
}
2009-01-13 12:32:01 +00:00
2009-04-15 12:04:10 +00:00
/* main modal status check */
2013-03-13 09:03:46 +00:00
static int poselib_preview_modal ( bContext * C , wmOperator * op , const wmEvent * event )
2009-01-13 12:32:01 +00:00
{
2012-05-08 20:18:33 +00:00
tPoseLib_PreviewData * pld = op - > customdata ;
2009-04-15 12:38:04 +00:00
int ret ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* 1) check state to see if we're still running */
2009-04-16 00:53:22 +00:00
if ( pld - > state ! = PL_PREVIEW_RUNNING )
2009-04-15 12:04:10 +00:00
return poselib_preview_exit ( C , op ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:38:04 +00:00
/* 2) handle events */
2012-05-08 20:18:33 +00:00
ret = poselib_preview_handle_event ( C , op , event ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:38:04 +00:00
/* 3) apply changes and redraw, otherwise, confirming goes wrong */
if ( pld - > redraw )
poselib_preview_apply ( C , op ) ;
2018-06-04 09:31:30 +02:00
2009-04-16 00:53:22 +00:00
return ret ;
2009-04-15 12:04:10 +00:00
}
/* Modal Operator init */
2013-03-13 09:03:46 +00:00
static int poselib_preview_invoke ( bContext * C , wmOperator * op , const wmEvent * UNUSED ( event ) )
2009-04-15 12:04:10 +00:00
{
tPoseLib_PreviewData * pld ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* check if everything is ok, and init settings for modal operator */
poselib_preview_init_data ( C , op ) ;
2012-05-08 20:18:33 +00:00
pld = ( tPoseLib_PreviewData * ) op - > customdata ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
if ( pld - > state = = PL_PREVIEW_ERROR ) {
/* an error occurred, so free temp mem used */
poselib_preview_cleanup ( C , op ) ;
return OPERATOR_CANCELLED ;
}
2018-06-04 09:31:30 +02:00
2009-04-15 12:38:04 +00:00
/* do initial apply to have something to look at */
poselib_preview_apply ( C , op ) ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* add temp handler if we're running as a modal operator */
2009-09-18 12:43:36 +00:00
WM_event_add_modal_handler ( C , op ) ;
2009-04-15 12:04:10 +00:00
return OPERATOR_RUNNING_MODAL ;
}
2009-04-16 00:33:40 +00:00
/* Repeat operator */
2012-05-08 20:18:33 +00:00
static int poselib_preview_exec ( bContext * C , wmOperator * op )
2009-04-16 00:33:40 +00:00
{
tPoseLib_PreviewData * pld ;
2018-06-04 09:31:30 +02:00
2009-04-16 00:33:40 +00:00
/* check if everything is ok, and init settings for modal operator */
poselib_preview_init_data ( C , op ) ;
2012-05-08 20:18:33 +00:00
pld = ( tPoseLib_PreviewData * ) op - > customdata ;
2018-06-04 09:31:30 +02:00
2009-04-16 00:33:40 +00:00
if ( pld - > state = = PL_PREVIEW_ERROR ) {
/* an error occurred, so free temp mem used */
poselib_preview_cleanup ( C , op ) ;
return OPERATOR_CANCELLED ;
}
2018-06-04 09:31:30 +02:00
2009-04-16 00:53:22 +00:00
/* the exec() callback is effectively a 'run-once' scenario, so set the state to that
* so that everything draws correctly
*/
pld - > state = PL_PREVIEW_RUNONCE ;
2018-06-04 09:31:30 +02:00
2009-04-16 00:33:40 +00:00
/* apply the active pose */
poselib_preview_apply ( C , op ) ;
2018-06-04 09:31:30 +02:00
2009-04-16 00:53:22 +00:00
/* now, set the status to exit */
pld - > state = PL_PREVIEW_CONFIRM ;
2018-06-04 09:31:30 +02:00
2009-04-16 00:33:40 +00:00
/* cleanup */
return poselib_preview_exit ( C , op ) ;
}
2012-04-29 17:11:40 +00:00
void POSELIB_OT_browse_interactive ( wmOperatorType * ot )
2009-04-15 12:04:10 +00:00
{
/* identifiers */
2012-03-22 07:26:09 +00:00
ot - > name = " PoseLib Browse Poses " ;
ot - > idname = " POSELIB_OT_browse_interactive " ;
ot - > description = " Interactively browse poses in 3D-View " ;
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* callbacks */
2012-03-22 07:26:09 +00:00
ot - > invoke = poselib_preview_invoke ;
ot - > modal = poselib_preview_modal ;
ot - > cancel = poselib_preview_cancel ;
ot - > exec = poselib_preview_exec ;
ot - > poll = has_poselib_pose_data_poll ;
2018-06-04 09:31:30 +02:00
2009-04-15 12:04:10 +00:00
/* flags */
2012-05-08 20:18:33 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING ;
2018-06-04 09:31:30 +02:00
2012-10-21 05:46:41 +00:00
/* properties */
2012-05-08 20:18:33 +00:00
// TODO: make the pose_index into a proper enum instead of a cryptic int...
2012-03-22 07:26:09 +00:00
ot - > prop = RNA_def_int ( ot - > srna , " pose_index " , - 1 , - 2 , INT_MAX , " Pose " , " Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose) " , 0 , INT_MAX ) ;
2018-06-04 09:31:30 +02:00
2010-08-15 12:03:49 +00:00
// XXX: percentage vs factor?
/* not used yet */
/* RNA_def_float_factor(ot->srna, "blend_factor", 1.0f, 0.0f, 1.0f, "Blend Factor", "Amount that the pose is applied on top of the existing poses", 0.0f, 1.0f); */
2009-01-13 12:32:01 +00:00
}
2011-02-16 06:18:20 +00:00
2012-04-29 17:11:40 +00:00
void POSELIB_OT_apply_pose ( wmOperatorType * ot )
2011-02-16 06:18:20 +00:00
{
/* identifiers */
2011-09-15 13:20:18 +00:00
ot - > name = " Apply Pose Library Pose " ;
2011-02-16 06:18:20 +00:00
ot - > idname = " POSELIB_OT_apply_pose " ;
2011-09-15 13:20:18 +00:00
ot - > description = " Apply specified Pose Library pose to the rig " ;
2018-06-04 09:31:30 +02:00
2011-02-16 06:18:20 +00:00
/* callbacks */
2012-03-22 07:26:09 +00:00
ot - > exec = poselib_preview_exec ;
ot - > poll = has_poselib_pose_data_poll ;
2012-07-06 23:56:59 +00:00
2011-02-16 06:18:20 +00:00
/* flags */
2012-05-08 20:18:33 +00:00
ot - > flag = OPTYPE_REGISTER | OPTYPE_UNDO ;
2012-07-06 23:56:59 +00:00
/* properties */
/* TODO: make the pose_index into a proper enum instead of a cryptic int... */
2012-03-22 07:26:09 +00:00
ot - > prop = RNA_def_int ( ot - > srna , " pose_index " , - 1 , - 2 , INT_MAX , " Pose " , " Index of the pose to apply (-2 for no change to pose, -1 for poselib active pose) " , 0 , INT_MAX ) ;
2011-02-16 06:18:20 +00:00
}