Download

Setting Notifies/Curves on AnimSequence through code?

Hey there,

I’ve been making the switch from Unity3D to Unreal and its been going pretty smoothly up to this point. I am having a bit of an issue understanding how to insert notifies and “Curves” through code (C++).

I’m sure I’ll figure it out if let on my own but was curious if anyone else has the knowledge of the proper way to go about this.

My setup right now involves DataAsset(s) outside of animations holding relevant shared setup information, and a AnimMetaData on each animation using the configuration which can overwrite settings in the text asset (but more importantly inherit everything else).

Right now the UAnimMeta derivative class is picking up on changes through Modify() and obtaining the animation itself via GetOuter() within PostEditChangeProperty(). It’s (somewhat) successfully inserting the SyncMarker points in the image, though its implementation has crashed the editor when there are previously existing sync markers.



FORCEINLINE constexpr const FAnimationBatchTime& GetFootTime(const FAnimationBatchFoot&Foot, const int32 index) {
	return (!(index & 2))?
		(!(index & 1))?
		Foot.Pass:
		Foot.High:
		(!(index & 1))?
		Foot.Contact:
		Foot.Recoil;
}

FORCEINLINE constexpr const FAnimationBatchFoot& GetFoot(const FAnimationBatchFooting&Footing, const int32 index) {
	return (!(index & 1))?Footing.Left:Footing.Right;
}


FORCEINLINE constexpr const FAnimationBatchTime& GetFootTime(const FAnimationBatchFooting&Footing, const int32 index) {
	return GetFootTime(GetFoot(Footing, index >> 2),index);
}

bool FAnimationBatchConfiguration::BIND(UAnimSequence*seq, const FAnimationBatchConfiguration &cfg) {

	static const FName FootNames[8] = {
		FName("PssL"),
		FName("HghL"),
		FName("CnctL"),
		FName("RclL"),
		FName("PssR"),
		FName("HghR"),
		FName("CnctR"),
		FName("RclR"),
	};

	if (!seq)
		return false;

	const int8 numFootMarkersLeft = cfg.Footing.Left.GetNumValid();
	const int8 numFootMarkersRight = cfg.Footing.Right.GetNumValid();
	const int8 numFootMarkers = numFootMarkersLeft + numFootMarkersRight;
	const int8 numFoot = numFootMarkersLeft ? numFootMarkersRight ? 2 : 1 : numFootMarkersRight ? 1 : 0;


	if (numFoot) {
		auto &Markers = seq->AuthoredSyncMarkers;

		for (int32 i = Markers.Num() - 1; i >= 0; i--) {
			auto &Marker = Markers*;
			for (int32 n = 0;n < 8;n++) {
				if (Marker.MarkerName == FootNames[n]) {
					Markers.RemoveAt(i);
					break;
				}
			}
		}
		seq->SortSyncMarkers();

		for (int32 i = 0; i < 8; i++) {
			const FAnimationBatchTime &footTime = GetFootTime(cfg.Footing, i);
			if (footTime.IsModeValid()) {
				FAnimSyncMarker marker{};
				marker.MarkerName = FootNames*;
				marker.Time = (footTime.FrameNumber* seq->GetPlayLength()) / (float)seq->NumFrames;
				Markers.Add(marker);
			}
		}

		seq->SortSyncMarkers();

	}

	return false;
}

However, I’m struggling a bit to see the proper way one would insert curves or non-sync-marker notifies.

I’m still somewhat unaware of how to find the editor code that does it. If anyone would point me in the right direction or has any insight I would greatly appreciate it.

Thanks

I’ve located and have gone over the Persona editor code that does these operations. However doing similar operations outside of what persona does results in a crash when persona is not aware of the changes. I’m guessing because firing off the OnUpdated or whatever event/delegate on the persona window is not happening from manually calling Modify() then MarkPackageDirty / MarkRawDataAsModified / PostEditChange on the UAnimSequence.

This is a problem for me because I’m doing the modifications to the animation from a UAnimMetaData implementation, so Persona is going to be viewing the thing altering it always.

So in addition to the original question about finding the proper way to do this (If anyone knows of a better way), I’m also curious if there is anyway to get a handle / pointer to the persona window showing previewing the mesh/animation in order to fire off the update listeners to prevent the crash. I’m hesitant to edit engine code, but will likely end up having persona forward itself to UAnimMetaData instances after another day of searching for a better solution. Again, I would rather not make edits but am about ready to drop the hammer since this is unfortunately becoming a time drain.

Thanks!