forked from bartvdbraak/blender
Pose Lib: Start of PoseLib UI in Armature buttons
This presents a UI from which PoseLibs can be assigned/removed from Objects. From here, it is also possible to see the list of poses and add/remove poses from this list. Known Issues: - [Py/RNA/Operators BUG ALERT!] If after immediately starting Blender you try to remove a pose from the PoseLib using the UI buttons, you'll get a an error the first time you do so (but not for subsequent attempts). This seems to be caused by the "pose" enum (dynamically generated) of the POSELIB_OT_pose_remove operator, which does not seem to be getting initialised when the operator's exec gets called without the invoke having been called previously - Changing the active Pose Library still seems to be broken (to be fixed soon) Todos: - Operator button to make the selected pose get shown in the 3d view - Restore the "validate action" operator and add that to this panel - Rename pose access
This commit is contained in:
parent
c195e68e8e
commit
147309e3c5
@ -154,6 +154,51 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel):
|
||||
sub.operator("pose.group_deselect", text="Deselect")
|
||||
|
||||
|
||||
class DATA_PT_pose_library(ArmatureButtonsPanel, bpy.types.Panel):
|
||||
bl_label = "Pose Library"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (context.object and context.object.type == 'ARMATURE' and context.object.pose)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
ob = context.object
|
||||
poselib = ob.pose_library
|
||||
|
||||
row = layout.row()
|
||||
row.template_ID(ob, "pose_library", new="poselib.new", unlink="poselib.unlink")
|
||||
|
||||
if poselib:
|
||||
activePoseIndex = poselib.pose_markers.active_index
|
||||
if len(poselib.pose_markers):
|
||||
activePose = poselib.pose_markers[activePoseIndex]
|
||||
activePoseName = activePose.name if activePose else None
|
||||
else:
|
||||
activePose = None
|
||||
activePoseName = None
|
||||
|
||||
row = layout.row()
|
||||
row.template_list(poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.active = (poselib.library is None)
|
||||
|
||||
# invoke should still be used for 'add', as it is needed to allow
|
||||
# add/replace options to be used properly
|
||||
col.operator("poselib.pose_add", icon='ZOOMIN', text="")
|
||||
|
||||
col.operator_context = 'EXEC_DEFAULT' # exec not invoke, so that menu doesn't need showing
|
||||
col.operator("poselib.pose_remove", icon='ZOOMOUT', text="").pose = activePoseName
|
||||
|
||||
# TODO:
|
||||
# - show selected pose in 3d-view using browse op...
|
||||
# - rename selected pose...
|
||||
|
||||
# TODO: "validate action" operator to be restored
|
||||
|
||||
# TODO: this panel will soon be depreceated too
|
||||
class DATA_PT_ghost(ArmatureButtonsPanel, bpy.types.Panel):
|
||||
bl_label = "Ghost"
|
||||
|
@ -171,9 +171,13 @@ LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, cha
|
||||
/* PoseLib */
|
||||
/* poselib.c */
|
||||
|
||||
void POSELIB_OT_new(struct wmOperatorType *ot);
|
||||
void POSELIB_OT_unlink(struct wmOperatorType *ot);
|
||||
|
||||
void POSELIB_OT_pose_add(struct wmOperatorType *ot);
|
||||
void POSELIB_OT_pose_remove(struct wmOperatorType *ot);
|
||||
void POSELIB_OT_pose_rename(struct wmOperatorType *ot);
|
||||
|
||||
void POSELIB_OT_browse_interactive(struct wmOperatorType *ot);
|
||||
|
||||
/* ******************************************************* */
|
||||
|
@ -147,6 +147,9 @@ void ED_operatortypes_armature(void)
|
||||
WM_operatortype_append(POSELIB_OT_pose_remove);
|
||||
WM_operatortype_append(POSELIB_OT_pose_rename);
|
||||
|
||||
WM_operatortype_append(POSELIB_OT_new);
|
||||
WM_operatortype_append(POSELIB_OT_unlink);
|
||||
|
||||
/* POSE SLIDING */
|
||||
WM_operatortype_append(POSE_OT_push);
|
||||
WM_operatortype_append(POSE_OT_relax);
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_idprop.h"
|
||||
#include "BKE_library.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_report.h"
|
||||
@ -180,7 +181,7 @@ static bAction *poselib_init_new (Object *ob)
|
||||
|
||||
/* init object's poselib action (unlink old one if there) */
|
||||
if (ob->poselib)
|
||||
ob->poselib->id.us--;
|
||||
id_us_min(&ob->poselib->id);
|
||||
ob->poselib= add_empty_action("PoseLib");
|
||||
|
||||
return ob->poselib;
|
||||
@ -232,13 +233,10 @@ static void poselib_validate_act (bAction *act)
|
||||
|
||||
/* add new if none found */
|
||||
if (marker == NULL) {
|
||||
char name[64];
|
||||
|
||||
/* add pose to poselib */
|
||||
marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
|
||||
|
||||
strcpy(name, "Pose");
|
||||
BLI_strncpy(marker->name, name, sizeof(marker->name));
|
||||
BLI_strncpy(marker->name, "Pose", sizeof(marker->name));
|
||||
|
||||
marker->frame= (int)ak->cfra;
|
||||
marker->flag= -1;
|
||||
@ -264,6 +262,107 @@ static void poselib_validate_act (bAction *act)
|
||||
}
|
||||
|
||||
/* ************************************************************* */
|
||||
/* Pose Lib UI Operators */
|
||||
|
||||
static int poselib_new_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
Object *ob;
|
||||
|
||||
/* get object to add Pose Lib to */
|
||||
if (sa->spacetype == SPACE_BUTS)
|
||||
ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
|
||||
else
|
||||
ob= ED_object_pose_armature(CTX_data_active_object(C));
|
||||
|
||||
/* sanity checks */
|
||||
if (ob == NULL)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* new method here deals with the rest... */
|
||||
poselib_init_new(ob);
|
||||
|
||||
/* notifier here might evolve? */
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void POSELIB_OT_new (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "New Pose Library";
|
||||
ot->idname = "POSELIB_OT_new";
|
||||
ot->description = "Add New Pose Library to active Object";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = poselib_new_exec;
|
||||
ot->poll= ED_operator_posemode;
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------ */
|
||||
|
||||
static int poselib_unlink_poll (bContext *C)
|
||||
{
|
||||
/* object must exist, and so must a poselib */
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
Object *ob;
|
||||
|
||||
/* get object to add Pose Lib to */
|
||||
if (sa->spacetype == SPACE_BUTS)
|
||||
ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
|
||||
else
|
||||
ob= ED_object_pose_armature(CTX_data_active_object(C));
|
||||
|
||||
/* sanity checks */
|
||||
return (ob && ob->poselib);
|
||||
}
|
||||
|
||||
static int poselib_unlink_exec (bContext *C, wmOperator *op)
|
||||
{
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
Object *ob;
|
||||
|
||||
/* get object to add Pose Lib to */
|
||||
if (sa->spacetype == SPACE_BUTS)
|
||||
ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
|
||||
else
|
||||
ob= ED_object_pose_armature(CTX_data_active_object(C));
|
||||
|
||||
/* sanity checks */
|
||||
if (ELEM(NULL, ob, ob->poselib))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* notifier here might evolve? */
|
||||
WM_event_add_notifier(C, NC_OBJECT|ND_POSE, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void POSELIB_OT_unlink (wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Unlink Pose Library";
|
||||
ot->idname = "POSELIB_OT_unlink";
|
||||
ot->description = "Remove Pose Library from active Object";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = poselib_unlink_exec;
|
||||
ot->poll= ED_operator_posemode; // TODO: this here should require that a poselib exists!
|
||||
|
||||
/* flags */
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ************************************************************* */
|
||||
/* Pose Editing Operators */
|
||||
|
||||
static void poselib_add_menu_invoke__replacemenu (bContext *C, uiLayout *layout, void *UNUSED(arg))
|
||||
{
|
||||
@ -370,7 +469,7 @@ static int poselib_add_exec (bContext *C, wmOperator *op)
|
||||
ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame);
|
||||
|
||||
/* store new 'active' pose number */
|
||||
act->active_marker= BLI_countlist(&act->markers);
|
||||
act->active_marker= BLI_countlist(&act->markers) - 1;
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
@ -444,7 +543,7 @@ static int poselib_remove_exec (bContext *C, wmOperator *op)
|
||||
/* get index (and pointer) of pose to remove */
|
||||
marker= BLI_findlink(&act->markers, RNA_int_get(op->ptr, "pose"));
|
||||
if (marker == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose");
|
||||
BKE_reportf(op->reports, RPT_ERROR, "Invalid Pose specified %d", RNA_int_get(op->ptr, "pose"));
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
@ -583,6 +682,7 @@ void POSELIB_OT_pose_rename (wmOperatorType *ot)
|
||||
}
|
||||
|
||||
/* ************************************************************* */
|
||||
/* Pose-Lib Browsing/Previewing Operator */
|
||||
|
||||
/* Simple struct for storing settings/data for use during PoseLib preview */
|
||||
typedef struct tPoseLib_PreviewData {
|
||||
|
@ -149,6 +149,15 @@ static void rna_Action_pose_markers_remove(bAction *act, ReportList *reports, Ti
|
||||
MEM_freeN(marker);
|
||||
}
|
||||
|
||||
static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min, int *max)
|
||||
{
|
||||
bAction *act= (bAction *)ptr->data;
|
||||
|
||||
*min= 0;
|
||||
*max= BLI_countlist(&act->markers)-1;
|
||||
*max= MAX2(0, *max);
|
||||
}
|
||||
|
||||
static void rna_Action_frame_range_get(PointerRNA *ptr,float *values)
|
||||
{
|
||||
calc_action_range(ptr->id.data, values, values+1, 1);
|
||||
@ -422,6 +431,7 @@ static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
static void rna_def_action_pose_markers(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
@ -445,6 +455,11 @@ static void rna_def_action_pose_markers(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
parm= RNA_def_pointer(func, "marker", "TimelineMarker", "", "Timeline marker to remove.");
|
||||
RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL);
|
||||
|
||||
prop= RNA_def_property(srna, "active_index", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "active_marker");
|
||||
RNA_def_property_int_funcs(prop, NULL, NULL, "rna_Action_active_pose_marker_index_range");
|
||||
RNA_def_property_ui_text(prop, "Active Pose Marker Index", "Index of active pose marker");
|
||||
}
|
||||
|
||||
static void rna_def_action(BlenderRNA *brna)
|
||||
|
Loading…
Reference in New Issue
Block a user