Example #1
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;
}
Example #2
0
void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports)
{
	ScrArea *sa = CTX_wm_area(C);
	
	/* If the old action only has a single user (that it's about to lose),
	 * warn user about it
	 *
	 * TODO: Maybe we should just save it for them? But then, there's the problem of
	 *       trying to get rid of stuff that's actually unwanted!
	 */
	if (act->id.us == 1) {
		BKE_reportf(reports, RPT_WARNING,
		            "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
		            act->id.name + 2);
	}
	
	/* If in Tweak Mode, don't unlink. Instead, this 
	 * becomes a shortcut to exit Tweak Mode instead
	 */
	if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
		/* Exit Tweak Mode */
		BKE_nla_tweakmode_exit(adt);
		
		/* Flush this to the Action Editor (if that's where this change was initiated) */
		if (sa->spacetype == SPACE_ACTION) {
			actedit_change_action(C, NULL);
		}
	}
	else {
		/* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
		if (sa->spacetype == SPACE_ACTION) {
			/* clear action editor -> action */
			actedit_change_action(C, NULL);
		}
		else {
			/* clear AnimData -> action */
			PointerRNA ptr;
			PropertyRNA *prop;
			
			/* create AnimData RNA pointers */
			RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
			prop = RNA_struct_find_property(&ptr, "action");
			
			/* clear... */
			RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL);
			RNA_property_update(C, &ptr, prop);
		}
	}
}
Example #3
0
static void rna_AnimData_tweakmode_set(PointerRNA *ptr, const int value)
{
	AnimData *adt = (AnimData *)ptr->data;

	/* NOTE: technically we should also set/unset SCE_NLA_EDIT_ON flag on the
	 * scene which is used to make polling tests faster, but this flag is weak
	 * and can easily break e.g. by changing layer visibility. This needs to be
	 * dealt with at some point. */

	if (value) {
		BKE_nla_tweakmode_enter(adt);
	}
	else {
		BKE_nla_tweakmode_exit(adt);
	}
}
Example #4
0
/* Switch NLA Strips/Actions  */
static void action_layer_switch_strip(AnimData *adt,
                                      NlaTrack *old_track, NlaStrip *old_strip,
                                      NlaTrack *nlt, NlaStrip *strip)
{
	/* Exit tweakmode on old strip
	 * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it
	 */
	BKE_nla_tweakmode_exit(adt);
	
	if (old_strip) {
		old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
	}
	if (old_track) {
		old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
	}
	
	/* Make this one the active one instead */
	strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
	nlt->flag |= NLATRACK_ACTIVE;
	
	/* Copy over "solo" flag - This is useful for stashed actions... */
	if (old_track) {
		if (old_track->flag & NLATRACK_SOLO) {
			old_track->flag &= ~NLATRACK_SOLO;
			nlt->flag |= NLATRACK_SOLO;
		}
	}
	else {
		/* NLA muting <==> Solo Tracks */
		if (adt->flag & ADT_NLA_EVAL_OFF) {
			/* disable NLA muting */
			adt->flag &= ~ADT_NLA_EVAL_OFF;
			
			/* mark this track as being solo */
			adt->flag |= ADT_NLA_SOLO_TRACK;
			nlt->flag |= NLATRACK_SOLO;
			
			// TODO: Needs restpose flushing (when we get reference track)
		}
	}
	
	/* Enter tweakmode again - hopefully we're now "it" */
	BKE_nla_tweakmode_enter(adt);
	BLI_assert(adt->actstrip == strip);
}
Example #5
0
void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
{
	ScrArea *sa = CTX_wm_area(C);
	
	/* If the old action only has a single user (that it's about to lose),
	 * warn user about it
	 *
	 * TODO: Maybe we should just save it for them? But then, there's the problem of
	 *       trying to get rid of stuff that's actually unwanted!
	 */
	if (act->id.us == 1) {
		BKE_reportf(reports, RPT_WARNING,
		            "Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
		            act->id.name + 2);
	}
	
	/* Clear Fake User and remove action stashing strip (if present) */
	if (force_delete) {
		/* Remove stashed strip binding this action to this datablock */
		/* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
		 * but GE users only seem to use/care about single-object binding for now so this
		 * should be fine
		 */
		if (adt) {
			NlaTrack *nlt, *nlt_next;
			NlaStrip *strip, *nstrip;
			
			for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
				nlt_next = nlt->next;
				
				if (strstr(nlt->name, DATA_("[Action Stash]"))) {
					for (strip = nlt->strips.first; strip; strip = nstrip) {
						nstrip = strip->next;
						
						if (strip->act == act) {
							/* Remove this strip, and the track too if it doesn't have anything else */
							free_nlastrip(&nlt->strips, strip);
							
							if (nlt->strips.first == NULL) {
								BLI_assert(nstrip == NULL);
								free_nlatrack(&adt->nla_tracks, nlt);
							}
						}
					}
				}
			}
		}
		
		/* Clear Fake User */
		id_fake_user_clear(&act->id);
	}
	
	/* If in Tweak Mode, don't unlink. Instead, this 
	 * becomes a shortcut to exit Tweak Mode instead
	 */
	if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
		/* Exit Tweak Mode */
		BKE_nla_tweakmode_exit(adt);
		
		/* Flush this to the Action Editor (if that's where this change was initiated) */
		if (sa->spacetype == SPACE_ACTION) {
			actedit_change_action(C, NULL);
		}
	}
	else {
		/* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
		if (sa->spacetype == SPACE_ACTION) {
			/* clear action editor -> action */
			actedit_change_action(C, NULL);
		}
		else {
			/* clear AnimData -> action */
			PointerRNA ptr;
			PropertyRNA *prop;
			
			/* create AnimData RNA pointers */
			RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
			prop = RNA_struct_find_property(&ptr, "action");
			
			/* clear... */
			RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL);
			RNA_property_update(C, &ptr, prop);
		}
	}
}