2011-02-23 10:52:22 +00:00
/*
2009-01-13 12:32:01 +00:00
* 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
*/
2011-02-27 20:29:51 +00:00
2019-02-06 15:42:22 +11:00
/** \file \ingroup edarmature
2011-02-27 20:29:51 +00:00
*/
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"
# include "BKE_action.h"
2018-11-07 18:00:24 +01:00
# include "BKE_animsys.h"
2009-01-13 12:32:01 +00:00
# include "BKE_armature.h"
2011-02-15 11:47:09 +00:00
# include "BKE_idprop.h"
2011-02-16 00:17:22 +00:00
# include "BKE_library.h"
2018-11-07 18:00:24 +01:00
# include "BKE_main.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
2017-06-08 10:14:53 +02:00
# include "DEG_depsgraph.h"
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 :
2018-11-14 12:53:15 +11:00
* - 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
2009-01-13 12:32:01 +00:00
*/
/* ************************************************************* */
2018-06-04 09:31:30 +02:00
/* gets the first available frame in poselib to store a pose on
2018-11-14 12:53:15 +11:00
* - frames start from 1 , and a pose should occur on every frame . . . 0 is error !
2009-01-13 12:32:01 +00:00
*/
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
2019-02-16 10:44:15 +11:00
if ( sa & & ( sa - > spacetype = = SPACE_PROPERTIES ) )
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 ) ;
Dope Sheet: new option to display keyframe interpolation mode and extremes.
With the new automatic handle algorithm, it is possible to do a lot
of the animation via keyframes without touching the curves. It is
however necessary to change the keyframe interpolation and handle
types in certain cases. Currently the dopesheet/action editor
allows changing the types, but does not show them in any way.
To fix, add a new menu option to display this information. For handle
type, it is represented using the shape of the key icons: diamond for
Free, clipped diamond for Aligned, square for Vector, circle for Auto
Clamp, and cirle with dot for Automatic.
Non-bezier interpolation is a property of intervals between keys,
so it is marked by drawing lines, similar to holds. In this initial
version, only the fact of non-bezier interpolation is displayed,
without distinguishing types. For summaries, the line is drawn at
half alpha if not all curves in the group are non-bezier.
In addition, it is sometimes helpful to know the general direction
of change of the curve, and which keys are extremes. This commit
also adds an option to highlight extremes, based on comparing the
keyed values with adjacent keys. Half-intensity display is used
for overshot bezier extremes, or non-uniform summaries.
Reviewers: brecht, aligorith, billreynish
Differential Revision: https://developer.blender.org/D3788
2018-10-19 18:55:19 +03:00
action_to_keylist ( NULL , act , & keys , 0 ) ;
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
2018-11-14 12:53:15 +11:00
* - for the ' replace ' option , this should end up finding the appropriate marker ,
* so no new one will be added
2009-04-15 03:22:22 +00:00
*/
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 */
2019-01-15 23:24:20 +11:00
/* this includes custom props :)*/
ks = ANIM_builtin_keyingset_get_named ( NULL , ANIM_KS_WHOLE_CHARACTER_SELECTED_ID ) ;
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-12-06 17:52:37 +01:00
DEG_id_tag_update ( & act - > id , ID_RECALC_COPY_ON_WRITE ) ;
2018-05-31 12:38:56 +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-12-06 17:52:37 +01:00
DEG_id_tag_update ( & act - > id , ID_RECALC_COPY_ON_WRITE ) ;
2018-05-31 12:38:56 +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 */
2019-01-15 23:24:20 +11: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 " , " " } ,
2019-02-03 14:01:45 +11:00
{ 0 , NULL , 0 , NULL , NULL } ,
2016-09-16 15:07:23 +02:00
} ;
/* 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 {
2019-01-08 10:28:20 +11:00
/** tPoseLib_Backup structs for restoring poses. */
ListBase backups ;
/** LinkData structs storing list of poses which match the current search-string. */
ListBase searchp ;
/** active scene. */
Scene * scene ;
/** active area. */
ScrArea * sa ;
2012-05-08 20:18:33 +00:00
2019-01-08 10:28:20 +11:00
/** RNA-Pointer to Object 'ob' .*/
PointerRNA rna_ptr ;
/** object to work on. */
Object * ob ;
/** object's armature data. */
bArmature * arm ;
/** object's pose. */
bPose * pose ;
/** poselib to use. */
bAction * act ;
/** 'active' pose. */
TimeMarker * marker ;
2018-06-04 09:31:30 +02:00
2019-01-08 10:28:20 +11:00
/** total number of elements to work on. */
int totcount ;
/** state of main loop. */
short state ;
/** redraw/update settings during main loop. */
short redraw ;
/** flags for various settings. */
short flag ;
/** position of cursor in searchstr (cursor occurs before the item at the nominated index) */
short search_cursor ;
/** (Part of) Name to search for to filter poses that get shown. */
char searchstr [ 64 ] ;
/** Previously set searchstr (from last loop run),
* so that we can detected when to rebuild searchp . */
char searchold [ 64 ] ;
/** Info-text to print in header. */
char headerstr [ UI_MAX_DRAW_STR ] ;
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 ,
2019-02-03 14:01:45 +11: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
2019-01-15 23:24:20 +11: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
2018-11-14 12:53:15 +11:00
* - assumes that a valid object , with a poselib has been supplied
* - gets the string to print in the header
* - 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 )
2018-11-12 19:30:25 +03:00
animsys_evaluate_action_group ( ptr , act , agrp , ( 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
2018-11-14 12:53:15 +11:00
* - note : code copied from transform_generics . c - > recalcData ( )
2009-04-15 12:04:10 +00:00
*/
// FIXME: shouldn't this use the builtin stuff?
2012-05-08 20:18:33 +00:00
if ( ( pld - > arm - > flag & ARM_DELAYDEFORM ) = = 0 )
2018-12-06 17:52:37 +01:00
DEG_id_tag_update ( & pld - > ob - > id , ID_RECALC_GEOMETRY ) ; /* sets recalc flags */
2009-04-15 12:04:10 +00:00
else
2018-04-06 12:07:27 +02:00
BKE_pose_where_is ( CTX_data_depsgraph ( C ) , 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 ) {
2018-06-28 12:06:00 +02:00
ED_area_status_text ( pld - > sa , IFACE_ ( " PoseLib Previewing Pose: [Showing Original Pose] " ) ) ;
ED_workspace_status_text ( C , IFACE_ ( " Use Tab to start previewing poses again " ) ) ;
2009-04-15 12:04:10 +00:00
}
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] | "
2018-06-28 12:06:00 +02:00
" Current Pose - \" %s \" " ) ,
2012-01-11 12:33:51 +00:00
tempstr , markern ) ;
2018-06-28 12:06:00 +02:00
ED_area_status_text ( pld - > sa , pld - > headerstr ) ;
ED_workspace_status_text ( C , IFACE_ ( " Use ScrollWheel or PageUp/Down to change pose " ) ) ;
2009-04-15 12:04:10 +00:00
}
else {
2012-01-11 12:33:51 +00:00
BLI_snprintf ( pld - > headerstr , sizeof ( pld - > headerstr ) ,
2018-06-28 12:06:00 +02:00
IFACE_ ( " PoseLib Previewing Pose: \" %s \" " ) ,
2012-01-11 12:33:51 +00:00
pld - > marker - > name ) ;
2018-06-28 12:06:00 +02:00
ED_area_status_text ( pld - > sa , pld - > headerstr ) ;
ED_workspace_status_text ( C , NULL ) ;
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?
2018-11-14 12:53:15 +11:00
* - don ' t worry about case , to make it easier for users to quickly input a name ( or
* part of one ) , which is the whole point of this feature
2011-02-07 01:28:47 +00:00
*/
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
2018-11-14 12:53:15 +11:00
* - make a copy of searchstr , so that we know if cache needs to be rebuilt
2009-01-13 12:32:01 +00:00
*/
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 */
2018-06-28 12:06:00 +02:00
ED_area_status_text ( pld - > sa , NULL ) ;
2018-06-26 17:19:25 +02:00
ED_workspace_status_text ( C , 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
2018-11-14 12:53:15 +11:00
* - note : code copied from transform_generics . c - > recalcData ( )
2009-01-13 12:32:01 +00:00
*/
2012-05-08 20:18:33 +00:00
if ( ( arm - > flag & ARM_DELAYDEFORM ) = = 0 )
2018-12-06 17:52:37 +01:00
DEG_id_tag_update ( & ob - > id , ID_RECALC_GEOMETRY ) ; /* sets recalc flags */
2009-01-13 12:32:01 +00:00
else
2018-04-06 12:07:27 +02:00
BKE_pose_where_is ( CTX_data_depsgraph ( C ) , 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 */
2018-12-06 17:52:37 +01:00
DEG_id_tag_update ( & ob - > id , ID_RECALC_GEOMETRY ) ;
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
2018-04-06 12:07:27 +02:00
BKE_pose_where_is ( CTX_data_depsgraph ( C ) , 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 */
2019-01-15 23:24:20 +11:00
#if 0
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 ) ;
# endif
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
}