Exemple #1
0
/* can be called with C == NULL */
static EnumPropertyItem *poselib_stored_pose_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
{
	Object *ob = get_poselib_object(C);
	bAction *act = (ob) ? ob->poselib : NULL;
	TimeMarker *marker;
	EnumPropertyItem *item= NULL, item_tmp= {0};
	int totitem= 0;
	int i= 0;

	if (C == NULL) {
		return DummyRNA_DEFAULT_items;
	}
	
	/* check that the action exists */
	if (act) {
		/* add each marker to the list */
		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;
			RNA_enum_item_add(&item, &totitem, &item_tmp);
		}
	}

	RNA_enum_item_end(&item, &totitem);
	*free= 1;

	return item;
}
Exemple #2
0
static int poselib_rename_invoke (bContext *C, wmOperator *op, wmEvent *evt)
{
	Object *ob= get_poselib_object(C);
	bAction *act= (ob) ? ob->poselib : NULL;
	TimeMarker *marker;
	
	/* check if valid poselib */
	if (act == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Object doesn't have PoseLib data");
		return OPERATOR_CANCELLED;
	}
	
	/* get index (and pointer) of pose to remove */
	marker= BLI_findlink(&act->markers, act->active_marker-1);
	if (marker == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Invalid index for Pose");
		return OPERATOR_CANCELLED;
	}
	else {
		/* use the existing name of the marker as the name, and use the active marker as the one to rename */
		RNA_enum_set(op->ptr, "pose", act->active_marker-1);
		RNA_string_set(op->ptr, "name", marker->name);
	}
	
	/* part to sync with other similar operators... */
	return WM_operator_props_popup(C, op, evt);
}
Exemple #3
0
static int poselib_add_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
{
	Scene *scene= CTX_data_scene(C);
	Object *ob= get_poselib_object(C);
	bPose *pose= (ob) ? ob->pose : NULL;
	uiPopupMenu *pup;
	uiLayout *layout;
	
	/* sanity check */
	if (ELEM(NULL, ob, pose)) 
		return OPERATOR_CANCELLED;
	
	/* start building */
	pup= uiPupMenuBegin(C, op->type->name, ICON_NONE);
	layout= uiPupMenuLayout(pup);
	uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
	
	/* add new (adds to the first unoccupied frame) */
	uiItemIntO(layout, IFACE_("Add New"), ICON_NONE, "POSELIB_OT_pose_add", "frame", poselib_get_free_index(ob->poselib));
	
	/* 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) */
		uiItemIntO(layout, IFACE_("Add New (Current Frame)"), ICON_NONE, "POSELIB_OT_pose_add", "frame", CFRA);
		
		/* replace existing - submenu */
		uiItemMenuF(layout, IFACE_("Replace Existing..."), 0, poselib_add_menu_invoke__replacemenu, NULL);
	}
	
	uiPupMenuEnd(C, pup);
	
	/* this operator is only for a menu, not used further */
	return OPERATOR_CANCELLED;
}
Exemple #4
0
static int poselib_remove_exec(bContext *C, wmOperator *op)
{
	Object *ob = get_poselib_object(C);
	bAction *act = (ob) ? ob->poselib : NULL;
	TimeMarker *marker;
	int marker_index;
	FCurve *fcu;
	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;
	}
	
	/* remove relevant keyframes */
	for (fcu = act->curves.first; fcu; fcu = fcu->next) {
		BezTriple *bezt;
		unsigned int i;
		
		if (fcu->bezt) {
			for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
				/* check if remove */
				if (IS_EQF(bezt->vec[1][0], (float)marker->frame)) {
					delete_fcurve_key(fcu, i, 1);
					break;
				}
			}
		}
	}
	
	/* remove poselib from list */
	BLI_freelinkN(&act->markers, marker);
	
	/* fix active pose number */
	act->active_marker = 0;
	
	/* 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);
	
	/* done */
	return OPERATOR_FINISHED;
}
Exemple #5
0
static void poselib_add_menu_invoke__replacemenu (bContext *C, uiLayout *layout, void *UNUSED(arg))
{
	Object *ob= get_poselib_object(C);
	bAction *act= ob->poselib; /* never NULL */
	TimeMarker *marker;
	
	wmOperatorType *ot = WM_operatortype_find("POSELIB_OT_pose_add", 1);

	BLI_assert(ot != NULL);

	/* set the operator execution context correctly */
	uiLayoutSetOperatorContext(layout, WM_OP_EXEC_DEFAULT);
	
	/* add each marker to this menu */
	for (marker= act->markers.first; marker; marker= marker->next) {
		PointerRNA props_ptr;
		
		props_ptr = uiItemFullO_ptr(layout, ot,
		                            marker->name, ICON_ARMATURE_DATA, NULL,
		                            WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
		
		RNA_int_set(&props_ptr, "frame", marker->frame);
		RNA_string_set(&props_ptr, "name", marker->name);
	}
}
Exemple #6
0
static int poselib_add_exec (bContext *C, wmOperator *op)
{
	Object *ob= get_poselib_object(C);
	bAction *act = poselib_validate(ob);
	bPose *pose= (ob) ? ob->pose : NULL;
	TimeMarker *marker;
	KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_WHOLE_CHARACTER_ID); /* this includes custom props :)*/
	int frame= RNA_int_get(op->ptr, "frame");
	char name[64];
	
	/* sanity check (invoke should have checked this anyway) */
	if (ELEM(NULL, ob, pose)) 
		return OPERATOR_CANCELLED;
	
	/* get name to give to pose */
	RNA_string_get(op->ptr, "name", name);
	
	/* add pose to poselib - replaces any existing pose there
	 *	- for the 'replace' option, this should end up finding the appropriate marker,
	 *	  so no new one will be added
	 */
	for (marker= act->markers.first; marker; marker= marker->next) {
		if (marker->frame == frame) {
			BLI_strncpy(marker->name, name, sizeof(marker->name));
			break;
		}
	}
	if (marker == NULL) {
		marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
		
		BLI_strncpy(marker->name, name, sizeof(marker->name));
		marker->frame= frame;
		
		BLI_addtail(&act->markers, marker);
	}
	
	/* validate name */
	BLI_uniquename(&act->markers, marker, "Pose", '.', offsetof(TimeMarker, name), sizeof(marker->name));
	
	/* use Keying Set to determine what to store for the pose */
	// FIXME: in the past, the Keying Set respected selections (LocRotScale), but the current one doesn't (Whole Character)
	// so perhaps we need either a new Keying Set, or just to add overrides here...
	ANIM_apply_keyingset(C, NULL, act, ks, MODIFYKEY_MODE_INSERT, (float)frame);
	
	/* store new 'active' pose number */
	act->active_marker= BLI_countlist(&act->markers);
	
	/* done */
	return OPERATOR_FINISHED;
}
Exemple #7
0
static int poselib_new_exec (bContext *C, wmOperator *UNUSED(op))
{
	Object *ob = get_poselib_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;
}
Exemple #8
0
static int poselib_unlink_exec (bContext *C, wmOperator *UNUSED(op))
{
	Object *ob = get_poselib_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;
}
Exemple #9
0
/* This tool automagically generates/validates poselib data so that it corresponds to the data 
 * in the action. This is for use in making existing actions usable as poselibs.
 */
static int poselib_sanitise_exec (bContext *C, wmOperator *op)
{
	Object *ob = get_poselib_object(C);
	bAction *act = (ob)? ob->poselib : NULL;
	DLRBT_Tree keys;
	ActKeyColumn *ak;
	TimeMarker *marker, *markern;
	
	/* validate action */
	if (act == NULL)  {
		BKE_report(op->reports, RPT_WARNING, "No Action to validate");
		return OPERATOR_CANCELLED;
	}
	
	/* determine which frames have keys */
	BLI_dlrbTree_init(&keys);
		action_to_keylist(NULL, act, &keys, NULL);
	BLI_dlrbTree_linkedlist_sync(&keys);
	
	/* for each key, make sure there is a corresponding pose */
	for (ak= keys.first; ak; ak= ak->next) {
		/* check if any pose matches this */
		// TODO: don't go looking through the list like this every time...
		for (marker= act->markers.first; marker; marker= marker->next) {
			if (IS_EQ(marker->frame, (double)ak->cfra)) {
				marker->flag = -1;
				break;
			}
		}
		
		/* add new if none found */
		if (marker == NULL) {
			/* add pose to poselib */
			marker= MEM_callocN(sizeof(TimeMarker), "ActionMarker");
			
			BLI_strncpy(marker->name, "Pose", sizeof(marker->name));
			
			marker->frame= (int)ak->cfra;
			marker->flag= -1;
			
			BLI_addtail(&act->markers, marker);
		}
	}
	
	/* remove all untagged poses (unused), and remove all tags */
	for (marker= act->markers.first; marker; marker= markern) {
		markern= marker->next;
		
		if (marker->flag != -1)
			BLI_freelinkN(&act->markers, marker);
		else
			marker->flag = 0;
	}
	
	/* free temp memory */
	BLI_dlrbTree_free(&keys);
	
	/* 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);
	
	return OPERATOR_FINISHED;
}
Exemple #10
0
/* Poll callback for operators that require existing PoseLib data (with poses) to work */
static int has_poselib_pose_data_poll (bContext *C)
{
	Object *ob = get_poselib_object(C);
	return (ob && ob->poselib);
}
Exemple #11
0
/* Init PoseLib Previewing data */
static void poselib_preview_init_data (bContext *C, wmOperator *op)
{
	tPoseLib_PreviewData *pld;
	Object *ob= get_poselib_object(C);
	int pose_index = RNA_int_get(op->ptr, "pose_index");
	
	/* set up preview state info */
	op->customdata= pld= MEM_callocN(sizeof(tPoseLib_PreviewData), "PoseLib Preview Data");
	
	/* get basic data */
	pld->ob= ob;
	pld->arm= (ob) ? (ob->data) : NULL;
	pld->pose= (ob) ? (ob->pose) : NULL;
	pld->act= (ob) ? (ob->poselib) : NULL;
	
	pld->scene= CTX_data_scene(C);
	pld->sa= CTX_wm_area(C);
	
	/* get starting pose based on RNA-props for this operator */
	if (pose_index == -1)
		pld->marker= poselib_get_active_pose(pld->act);
	else if (pose_index == -2)
		pld->flag |= PL_PREVIEW_SHOWORIGINAL;
	else
		pld->marker= (pld->act) ? BLI_findlink(&pld->act->markers, pose_index) : NULL;
	
	/* check if valid poselib */
	if (ELEM3(NULL, pld->ob, pld->pose, pld->arm)) {
		BKE_report(op->reports, RPT_ERROR, "PoseLib is only for Armatures in PoseMode");
		pld->state= PL_PREVIEW_ERROR;
		return;
	}
	if (pld->act == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Object doesn't have a valid PoseLib");
		pld->state= PL_PREVIEW_ERROR;
		return;
	}
	if (pld->marker == NULL) {
		if (pld->act->markers.first) {
			/* just use first one then... */
			pld->marker= pld->act->markers.first;
			if (pose_index > -2) 
				BKE_report(op->reports, RPT_WARNING, "PoseLib had no active pose");
		}
		else {
			BKE_report(op->reports, RPT_ERROR, "PoseLib has no poses to preview/apply");
			pld->state= PL_PREVIEW_ERROR;
			return;
		}
	}
	
	/* get ID pointer for applying poses */
	RNA_id_pointer_create(&ob->id, &pld->rna_ptr);
	
	/* make backups for restoring pose */
	poselib_backup_posecopy(pld);
	
	/* set flags for running */
	pld->state= PL_PREVIEW_RUNNING;
	pld->redraw= PL_PREVIEW_REDRAWALL;
	pld->flag |= PL_PREVIEW_FIRSTTIME;
	
	/* set depsgraph flags */
		/* make sure the lock is set OK, unlock can be accidentally saved? */
	pld->pose->flag |= POSE_LOCKED;
	pld->pose->flag &= ~POSE_DO_UNLOCK;
	
	/* clear strings + search */
	pld->headerstr[0]= pld->searchstr[0]= pld->searchold[0]= '\0';
	pld->search_cursor= 0;
}