Ejemplo n.º 1
0
/* Criteria:
 *  1) There must be an dopesheet/action editor, and it must be in a mode which uses actions 
 *  2) The associated AnimData block must not be in tweakmode
 */
static int action_stash_create_poll(bContext *C)
{
	if (ED_operator_action_active(C)) {
		AnimData *adt = ED_actedit_animdata_from_context(C);
		
		/* Check tweakmode is off (as you don't want to be tampering with the action in that case) */
		/* NOTE: unlike for pushdown, this operator needs to be run when creating an action from nothing... */
		if (adt) {
			if (!(adt->flag & ADT_NLA_EDIT_ON))
				return true;
		}
		else {
			/* There may not be any action/animdata yet, so, just fallback to the global setting
			 * (which may not be totally valid yet if the action editor was used and things are 
			 * now in an inconsistent state)
			 */
			SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
			Scene *scene = CTX_data_scene(C);
			
			if (!(scene->flag & SCE_NLA_EDIT_ON)) {
				/* For now, actions are only for the active object, and on object and shapekey levels... */
				return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
			}
		}
	}
	
	/* something failed... */
	return false;
}
Ejemplo n.º 2
0
static int action_layer_prev_poll(bContext *C)
{
	/* Action Editor's action editing modes only */
	if (ED_operator_action_active(C)) {
		AnimData *adt = ED_actedit_animdata_from_context(C);
		if (adt) {
			if (adt->flag & ADT_NLA_EDIT_ON) {
				/* Tweak Mode: We need to check if there are any tracks below the active one that we can move to */
				if (adt->nla_tracks.first) {
					NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
					
					/* Since the first disabled track is the track being tweaked/edited,
					 * we can simplify things by only checking the first track:
					 *    - If it is disabled, this is the track being tweaked,
					 *      so there can't be anything below it
					 *    - Otherwise, there is at least 1 track below the tweaking
					 *      track that we can descend to
					 */
					if ((nlt->flag & NLATRACK_DISABLED) == 0) {
						/* not disabled = there are actions below the one being tweaked */
						return true;
					}
				}
			}
			else {
				/* Normal Mode: If there are any tracks, we can try moving to those */
				return (adt->nla_tracks.first != NULL);
			}
		}
	}
	
	/* something failed... */
	return false;
}
Ejemplo n.º 3
0
static int action_layer_next_poll(bContext *C)
{
	/* Action Editor's action editing modes only */
	if (ED_operator_action_active(C)) {
		AnimData *adt = ED_actedit_animdata_from_context(C);
		if (adt) {
			/* only allow if we're in tweakmode, and there's something above us... */
			if (adt->flag & ADT_NLA_EDIT_ON) {
				/* We need to check if there are any tracks above the active one
				 * since the track the action comes from is not stored in AnimData
				 */
				if (adt->nla_tracks.last) {
					NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
					
					if (nlt->flag & NLATRACK_DISABLED) {
						/* A disabled track will either be the track itself,
						 * or one of the ones above it.
						 *
						 * If this is the top-most one, there is the possibility
						 * that there is no active action. For now, we let this
						 * case return true too, so that there is a natural way
						 * to "move to an empty layer", even though this means
						 * that we won't actually have an action.
						 */
						// return (adt->tmpact != NULL);
						return true;
					}
				}
			}
		}
	}
	
	/* something failed... */
	return false;
}
Ejemplo n.º 4
0
static int action_pushdown_exec(bContext *C, wmOperator *op)
{
	SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
	AnimData *adt = ED_actedit_animdata_from_context(C);
	
	/* Do the deed... */
	if (adt) {
		/* Perform the pushdown operation
		 * - This will deal with all the AnimData-side usercounts
		 */
		if (action_has_motion(adt->action) == 0) {
			/* action may not be suitable... */
			BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
			return OPERATOR_CANCELLED;
		}
		else {
			/* action can be safely added */
			BKE_nla_action_pushdown(adt);
		}
		
		/* Stop displaying this action in this editor
		 * NOTE: The editor itself doesn't set a user...
		 */
		saction->action = NULL;
	}
	
	/* Send notifiers that stuff has changed */
	WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
	return OPERATOR_FINISHED;
}
Ejemplo n.º 5
0
static int action_layer_next_exec(bContext *C, wmOperator *op)
{
	AnimData *adt = ED_actedit_animdata_from_context(C);
	NlaTrack *act_track;
	
	Scene *scene = CTX_data_scene(C);
	float ctime = BKE_scene_frame_get(scene);
	
	/* Get active track */
	act_track = BKE_nlatrack_find_tweaked(adt);
	
	if (act_track == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
		return OPERATOR_CANCELLED;
	}
	
	/* Find next action, and hook it up */
	if (act_track->next) {
		NlaTrack *nlt;
		
		/* Find next action to use */
		for (nlt = act_track->next; nlt; nlt = nlt->next) {
			NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
			
			if (strip) {
				action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
				break;
			}
		}
	}
	else {
		/* No more actions (strips) - Go back to editing the original active action
		 * NOTE: This will mean exiting tweakmode...
		 */
		BKE_nla_tweakmode_exit(adt);
		
		/* Deal with solo flags...
		 * Assume: Solo Track == NLA Muting
		 */
		if (adt->flag & ADT_NLA_SOLO_TRACK) {
			/* turn off solo flags on tracks */
			act_track->flag &= ~NLATRACK_SOLO;
			adt->flag &= ~ADT_NLA_SOLO_TRACK;
			
			/* turn on NLA muting (to keep same effect) */
			adt->flag |= ADT_NLA_EVAL_OFF;
			
			// TODO: Needs restpose flushing (when we get reference track)
		}
	}
	
	/* Update the action that this editor now uses
	 * NOTE: The calls above have already handled the usercount/animdata side of things
	 */
	actedit_change_action(C, adt->action);
	return OPERATOR_FINISHED;
}
Ejemplo n.º 6
0
static int action_unlink_exec(bContext *C, wmOperator *op)
{
	AnimData *adt = ED_actedit_animdata_from_context(C);
	
	if (adt && adt->action) {
		ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports);
	}
	
	return OPERATOR_FINISHED;
}
Ejemplo n.º 7
0
static int action_unlink_exec(bContext *C, wmOperator *op)
{
	AnimData *adt = ED_actedit_animdata_from_context(C);
	bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
	
	if (adt && adt->action) {
		ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
	}
	
	return OPERATOR_FINISHED;
}
Ejemplo n.º 8
0
static int action_unlink_poll(bContext *C)
{
	if (ED_operator_action_active(C)) {
		SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
		AnimData *adt = ED_actedit_animdata_from_context(C);
		
		/* Only when there's an active action, in the right modes... */
		if (saction->action && adt)
			return true;
	}
	
	/* something failed... */
	return false;
}
Ejemplo n.º 9
0
static int action_stash_create_exec(bContext *C, wmOperator *op)
{
	SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
	AnimData *adt = ED_actedit_animdata_from_context(C);
	
	/* Check for no action... */
	if (saction->action == NULL) {
		/* just create a new action */
		bAction *action = action_create_new(C, NULL);
		actedit_change_action(C, action);
	}
	else if (adt) {
		/* Perform stashing operation */
		if (action_has_motion(adt->action) == 0) {
			/* don't do anything if this action is empty... */
			BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
			return OPERATOR_CANCELLED;
		}
		else {
			/* stash the action */
			if (BKE_nla_action_stash(adt)) {
				bAction *new_action = NULL;
				
				/* create new action not based on the old one (since the "new" operator already does that) */
				new_action = action_create_new(C, NULL);
				
				/* The stash operation will remove the user already,
				 * so the flushing step later shouldn't double up
				 * the usercount fixes. Hence, we must unset this ref
				 * first before setting the new action.
				 */
				saction->action = NULL;
				actedit_change_action(C, new_action);
			}
			else {
				/* action has already been added - simply warn about this, and clear */
				BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
				actedit_change_action(C, NULL);
			}
		}
	}
	
	/* Send notifiers that stuff has changed */
	WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
	return OPERATOR_FINISHED;
}
Ejemplo n.º 10
0
static int action_layer_prev_exec(bContext *C, wmOperator *op)
{
	AnimData *adt = ED_actedit_animdata_from_context(C);
	NlaTrack *act_track;
	NlaTrack *nlt;
	
	Scene *scene = CTX_data_scene(C);
	float ctime = BKE_scene_frame_get(scene);
	
	/* Sanity Check */
	if (adt == NULL) {
		BKE_report(op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
		return OPERATOR_CANCELLED;
	}
	
	/* Get active track */
	act_track = BKE_nlatrack_find_tweaked(adt);
	
	/* If there is no active track, that means we are using the active action... */
	if (act_track) {
		/* Active Track - Start from the one below it */
		nlt = act_track->prev;
	}
	else {
		/* Active Action - Use the top-most track */
		nlt = adt->nla_tracks.last;
	}
	
	/* Find previous action and hook it up */
	for (; nlt; nlt = nlt->prev) {
		NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
		
		if (strip) {
			action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
			break;
		}
	}
	
	/* Update the action that this editor now uses
	 * NOTE: The calls above have already handled the usercount/animdata side of things
	 */
	actedit_change_action(C, adt->action);
	return OPERATOR_FINISHED;
}
Ejemplo n.º 11
0
/* Criteria:
 *  1) There must be an dopesheet/action editor, and it must be in a mode which uses actions 
 *  2) There must be an action active
 *  3) The associated AnimData block must not be in tweakmode
 */
static int action_pushdown_poll(bContext *C)
{
	if (ED_operator_action_active(C)) {
		SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
		AnimData *adt = ED_actedit_animdata_from_context(C);
		
		/* Check for AnimData, Actions, and that tweakmode is off */
		if (adt && saction->action) {
			/* NOTE: We check this for the AnimData block in question and not the global flag,
			 *       as the global flag may be left dirty by some of the browsing ops here.
			 */
			if (!(adt->flag & ADT_NLA_EDIT_ON))
				return true;
		}
	}
	
	/* something failed... */
	return false;
}
Ejemplo n.º 12
0
static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
{
	PointerRNA ptr, idptr;
	PropertyRNA *prop;
	
	/* hook into UI */
	UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
	
	if (prop) {
		bAction *action = NULL, *oldact = NULL;
		AnimData *adt = NULL;
		PointerRNA oldptr;
		
		oldptr = RNA_property_pointer_get(&ptr, prop);
		oldact = (bAction *)oldptr.id.data;
		
		/* stash the old action to prevent it from being lost */
		if (ptr.type == &RNA_AnimData) {
			adt = ptr.data;
		}
		else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
			adt = ED_actedit_animdata_from_context(C);
		}
		
		/* Perform stashing operation - But only if there is an action */
		if (adt && oldact) {
			/* stash the action */
			if (BKE_nla_action_stash(adt)) {
				/* The stash operation will remove the user already
				 * (and unlink the action from the AnimData action slot).
				 * Hence, we must unset the ref to the action in the
				 * action editor too (if this is where we're being called from)
				 * first before setting the new action once it is created,
				 * or else the user gets decremented twice!
				 */
				if (ptr.type == &RNA_SpaceDopeSheetEditor) {
					SpaceAction *saction = (SpaceAction *)ptr.data;
					saction->action = NULL;
				}
			}
			else {
				//printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n", oldact->id.name);
			}
		}
		
		/* create action */
		action = action_create_new(C, oldact);
		
		/* set this new action
		 * NOTE: we can't use actedit_change_action, as this function is also called from the NLA
		 */
		RNA_id_pointer_create(&action->id, &idptr);
		RNA_property_pointer_set(&ptr, prop, idptr);
		RNA_property_update(C, &ptr, prop);
	}
	
	/* set notifier that keyframes have changed */
	WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
	
	return OPERATOR_FINISHED;
}