static void CacheAnimationFrame(ref AnimSequence AnimSeq, Transform root) { List <FMeshBoneInfo> frame = new List <FMeshBoneInfo>(); CacheSkeletonInfo(root, frame); AnimSeq.animationFames.Add(frame); }
static public AnimSequence CatchAnimationClip(AnimationClip InClip, Transform root) { float InCliplength = InClip.length; //InCliplength = 0; AnimSequence retAnimSequence = new AnimSequence(); retAnimSequence.NumFrames = (int)Mathf.Floor(InCliplength / (InClip.frameRate / 1000)) + 1; //if (retAnimSequence.NumFrames <= 1) // return null; retAnimSequence.SequenceLength = InClip.length; if (retAnimSequence.NumFrames - 1 != 0) { retAnimSequence.StepFrame = InClip.length / (retAnimSequence.NumFrames - 1); } else { retAnimSequence.StepFrame = 0; } retAnimSequence.animationFames = new List <List <FMeshBoneInfo> >(); for (int i = 0; i < retAnimSequence.NumFrames; i++) { float sampleTime = retAnimSequence.StepFrame * i; if (i == (retAnimSequence.NumFrames - 1)) { sampleTime = InClip.length; } InClip.SampleAnimation(root.gameObject, sampleTime); CacheAnimationFrame(ref retAnimSequence, root); } return(retAnimSequence); }
private void btn_addSequence_Click(object sender, EventArgs e) { // default name String name = "Default"; for(int i=0;i<1000; i++) { bool nameUsed = false; foreach(String seqName in lsb_animSequences.Items) { if (seqName == "Default" + i) { nameUsed = true; break; } } if (!nameUsed) { name = "Default" + i; break; } } AnimSequence animSeq = new AnimSequence(); animSeq.Name = name; anv_anim.AnimTexture.AnimSeqList.Add(animSeq); lsb_animSequences.Items.Add(name); }
public void Play(AnimSequence a) { if (a == null || (a.UseFrames && a.frames.Length == 0) || (!a.UseFrames && a.sprites.Length == 0)) { return; } isPlaying = true; CurrentSequence = a; CurrentFrameIndex = 0; #if UNITY_EDITOR if (Application.isPlaying) { animStart = Time.time; } else { animStart = (float)EditorApplication.timeSinceStartup; } #else if (Application.isPlaying) { animStart = Time.time; } #endif if (sr != null && !sr.enabled) { sr.enabled = true; } }
public static void SpritesToFrames(AnimSequence seq) { seq.frames = new AnimFrame[seq.sprites.Length]; for (int i = 0; i < seq.sprites.Length; i++) { seq.frames[i] = new AnimFrame(); seq.frames[i].sprite = seq.sprites[i]; } }
public override void OnInspectorGUI() { AnimSequence seq = target as AnimSequence; if (GUI.Button(EditorGUILayout.GetControlRect(), "Sprites to Frames")) { AnimSequence.SpritesToFrames(seq); } DrawDefaultInspector(); }
public FbxNode ExportAnimSequence(AnimSequence AnimSeq, List <FMeshBoneInfo> boneInfos) { if (Scene == null) { return(null); } List <FbxNode> BoneNodes = new List <FbxNode>(); FbxNode RootNode = Scene.GetRootNode(); FbxNode SkeletonRootNode = CreateSkeleton(boneInfos, ref BoneNodes); RootNode.AddChild(SkeletonRootNode); ExportAnimSequenceToFbx(AnimSeq, ref BoneNodes, AnimLayer, 0.0f, 0.0f, 1.0f, 0.0f); CorrectAnimTrackInterpolation(ref BoneNodes, AnimLayer); return(SkeletonRootNode); }
private void OnGUI() { if (GUI.Button(new Rect(10, 10, 150, 50), "动画加载")) { controller.OpenFromFile(Application.streamingAssetsPath, "pose"); anime.runtimeAnimatorController = controller.LoadAsset <RuntimeAnimatorController>("AC_Edit_F"); anime.Stop(); List <FMeshBoneInfo> SkeletonInfo = new List <FMeshBoneInfo>(); UnityBoneTransform.CatchSkeleton(gameObject.transform, ref SkeletonInfo); orginSkeletonInfo = SkeletonInfo; StatisticsGenerateDataBegin(SkeletonInfo); } if (GUI.Button(new Rect(170, 10, 150, 50), "动画导出")) { controller.OpenFromFile(Application.streamingAssetsPath, "pose"); anime.runtimeAnimatorController = controller.LoadAsset <RuntimeAnimatorController>("AC_Edit_F"); anime.Stop(); //anime.Play("tachi_pose_12"); AnimatorClipInfo [] acinfo = anime.GetCurrentAnimatorClipInfo(0); foreach (var v in acinfo) { Debug.Log(v.clip.name); } List <AnimationClip> aniList = new List <AnimationClip>(); foreach (var v in anime.runtimeAnimatorController.animationClips) { aniList.Add(v); Debug.Log(v + " " + v.length + " " + v.frameRate); } AnimSequence anim = UnityBoneTransform.CatchAnimationClip(aniList[8], gameObject.transform); List <FMeshBoneInfo> SkeletonInfo = new List <FMeshBoneInfo>(); UnityBoneTransform.CatchSkeleton(gameObject.transform, ref SkeletonInfo); MyExport aMyExport = new MyExport(); aMyExport.CreateDocument(); aMyExport.ExportAnimSequence(anim, SkeletonInfo); aMyExport.WriteToFile("E:/1.fbx"); } if (GUI.Button(new Rect(350, 10, 150, 50), "动画采样")) { List <AnimationClip> aniList = new List <AnimationClip>(); foreach (var v in anime.runtimeAnimatorController.animationClips) { aniList.Add(v); Debug.Log(v + " " + v.length + " " + v.frameRate); } aniList[0].SampleAnimation(gameObject, fSampleTime); List <FMeshBoneInfo> SkeletonInfo = new List <FMeshBoneInfo>(); UnityBoneTransform.CatchSkeleton(gameObject.transform, ref SkeletonInfo); StatisticsGenerateDataBegin(SkeletonInfo); Debug.Log(GameObject.Find("cf_J_Hips").transform.localRotation.eulerAngles); bSampleAniamtion = true; } if (GUI.Button(new Rect(620, 10, 150, 50), "重置T-Pose")) { UpdateTransformFromMeshBoneList(orginSkeletonInfo); } }
///<summary>Retrieves the Additive Base Pose type for the given Animation Sequence</summary> public static byte GetAdditiveBasePoseType(AnimSequence AnimationSequence) => AnimationBlueprintLibrary_methods.GetAdditiveBasePoseType_method.Invoke(AnimationSequence);
///<summary>Finds the Bone Path from the given Bone to the Root Bone</summary> public static IReadOnlyCollection <Name> FindBonePathToRoot(AnimSequence AnimationSequence, Name BoneName) => AnimationBlueprintLibrary_methods.FindBonePathToRoot_method.Invoke(AnimationSequence, BoneName);
///<summary>Apply all the changes made to Bone Tracks to Finalize. This triggers recompression. Note that this is expensive, but will require to get correct compressed data</summary> public static void FinalizeBoneAnimation(AnimSequence AnimationSequence) => AnimationBlueprintLibrary_methods.FinalizeBoneAnimation_method.Invoke(AnimationSequence);
///<summary>Sets whether or not Root Motion is Enabled for the given Animation Sequence</summary> public static void SetRootMotionEnabled(AnimSequence AnimationSequence, bool bEnabled) => AnimationBlueprintLibrary_methods.SetRootMotionEnabled_method.Invoke(AnimationSequence, bEnabled);
public static PSA CreateFrom(AnimSequence animSeq) => CreateFrom(new List <AnimSequence> { animSeq });
///<summary>Adds a multiple of Vector Keys to the specified Animation Curve inside of the given Animation Sequence</summary> public static void AddVectorCurveKeys(AnimSequence AnimationSequence, Name CurveName, byte Times /*TODO: array TArray */, byte Vectors /*TODO: array TArray */) => AnimationBlueprintLibrary_methods.AddVectorCurveKeys_method.Invoke(AnimationSequence, CurveName, Times, Vectors);
/// <summary> /// 播放动画 /// </summary> /// <param name="actionName">动画名称</param> public void PlaySeq(String seqName) { if (currentSeq == null || isIdle || currentSeq.enableDistrub) { foreach (AnimSequence animSeq in animSeqList) { if (seqName == animSeq.name) { isIdle = false; currentSeq = animSeq; currentFrame = currentSeq.startFrameId; // 重置播放时间 baseTimeMS = (int)GameMgr.gameTimeInMs; break; } } } }
///<summary>Adds a Transformation Key to the specified Animation Curve inside of the given Animation Sequence</summary> public static void AddTransformationCurveKey(AnimSequence AnimationSequence, Name CurveName, float Time, Transform Transform) => AnimationBlueprintLibrary_methods.AddTransformationCurveKey_method.Invoke(AnimationSequence, CurveName, Time, Transform);
///<summary>Adds a Vector Key to the specified Animation Curve inside of the given Animation Sequence</summary> public static void AddVectorCurveKey(AnimSequence AnimationSequence, Name CurveName, float Time, Vector Vector) => AnimationBlueprintLibrary_methods.AddVectorCurveKey_method.Invoke(AnimationSequence, CurveName, Time, Vector);
///<summary>Adds an instance of the specified MetaData Class to the given Animation Sequence (requires MetaDataObject's outer to be the Animation Sequence)</summary> public static void AddMetaDataObject(AnimSequence AnimationSequence, AnimMetaData MetaDataObject) => AnimationBlueprintLibrary_methods.AddMetaDataObject_method.Invoke(AnimationSequence, MetaDataObject);
///<summary>Creates and Adds an instance of the specified MetaData Class to the given Animation Sequence</summary> public static void AddMetaData(AnimSequence AnimationSequence, SubclassOf <AnimMetaData> MetaDataClass, AnimMetaData MetaDataInstance) => AnimationBlueprintLibrary_methods.AddMetaData_method.Invoke(AnimationSequence, MetaDataClass, MetaDataInstance);
///<summary>Sets the Root Motion Lock Type for the given Animation Sequence</summary> public static void SetRootMotionLockType(AnimSequence AnimationSequence, byte RootMotionLockType) => AnimationBlueprintLibrary_methods.SetRootMotionLockType_method.Invoke(AnimationSequence, RootMotionLockType);
///<summary>Sets whether or not Root Motion locking is Forced for the given Animation Sequence</summary> public static void SetIsRootMotionLockForced(AnimSequence AnimationSequence, bool bForced) => AnimationBlueprintLibrary_methods.SetIsRootMotionLockForced_method.Invoke(AnimationSequence, bForced);
/// <summary> /// 更新 /// 如果启用动画 -- 则更新帧 /// </summary> public override void Update() { base.Update(); // 如果启用动画,则更新帧 if (EnableAnim) { if (!isIdle) { if (currentFrameId >= currentSeq.EndFrameId) // 考虑单帧动画序列,使用“>”而不是“>=” { // 最后一帧也需要一段显示(静止)时间 if (BaseGame.TotalTimeMilliseconds - baseTimeMS > currentSeq.MsPerFrame + currentSeq.MsAllFrames) { if (currentSeq.looping) { currentFrameId = currentSeq.startFrameId; } else { isIdle = false; currentSeq = animSeqList[1]; // 切换回第一个动画序列 currentFrameId = currentSeq.startFrameId; // 默认0号是Free return; } } } else { int timeInCircle = (int)(BaseGame.TotalTimeMilliseconds - baseTimeMS) % currentSeq.MsAllFrames; currentFrameId = timeInCircle / currentSeq.MsPerFrame + currentSeq.startFrameId; } } } }
///<summary>Sets the Compression Scheme for the given Animation Sequence</summary> public static void SetCompressionScheme(AnimSequence AnimationSequence, AnimCompress CompressionScheme) => AnimationBlueprintLibrary_methods.SetCompressionScheme_method.Invoke(AnimationSequence, CompressionScheme);
internal void on_OnApply(AnimSequence AnimationSequence) => OnApply?.Invoke(AnimationSequence);
public List <AnimSequence> GetAnimSequences() { var animSeqs = new List <AnimSequence>(); List <string> boneNames = Bones.Select(b => b.Name).ToList(); int boneCount = boneNames.Count; foreach (var info in Infos) { var seq = new AnimSequence { Bones = boneNames, Name = info.Name, NumFrames = info.NumRawFrames, SequenceLength = info.TrackTime / info.AnimRate, RateScale = 1, RawAnimationData = new List <AnimTrack>() }; for (int boneIdx = 0; boneIdx < boneCount; boneIdx++) { var track = new AnimTrack { Positions = new List <Vector3>(), Rotations = new List <Quaternion>() }; for (int frameIdx = 0; frameIdx < seq.NumFrames; frameIdx++) { int srcIdx = ((info.FirstRawFrame + frameIdx) * boneCount) + boneIdx; var posVec = Keys[srcIdx].Position; var rotQuat = Keys[srcIdx].Rotation; track.Positions.Add(new Vector3(posVec.X, posVec.Y * -1, posVec.Z)); track.Rotations.Add(new Quaternion(rotQuat.X, rotQuat.Y * -1, rotQuat.Z, rotQuat.W * -1)); } //if all keys are identical, replace with a single key if (track.Positions.Count > 1) { var firstKey = track.Positions[0]; if (track.Positions.TrueForAll(key => key == firstKey)) { track.Positions.Clear(); track.Positions.Add(firstKey); } } if (track.Rotations.Count > 1) { var firstKey = track.Rotations[0]; if (track.Rotations.TrueForAll(key => key == firstKey)) { track.Rotations.Clear(); track.Rotations.Add(firstKey); } } seq.RawAnimationData.Add(track); } animSeqs.Add(seq); } return(animSeqs); }
///<summary>Adds an Animation Curve by Type and Name to the given Animation Sequence</summary> public static void AddCurve(AnimSequence AnimationSequence, Name CurveName, ERawCurveTrackTypes CurveType, bool bMetaDataCurve) => AnimationBlueprintLibrary_methods.AddCurve_method.Invoke(AnimationSequence, CurveName, CurveType, bMetaDataCurve);
///<summary>Adds a Virtual Bone between the Source and Target Bones to the given Animation Sequence</summary> public static Name AddVirtualBone(AnimSequence AnimationSequence, Name SourceBoneName, Name TargetBoneName) => AnimationBlueprintLibrary_methods.AddVirtualBone_method.Invoke(AnimationSequence, SourceBoneName, TargetBoneName);
///<summary>Sets the (Play) Rate Scale for the given Animation Sequence</summary> public static void SetRateScale(AnimSequence AnimationSequence, float RateScale) => AnimationBlueprintLibrary_methods.SetRateScale_method.Invoke(AnimationSequence, RateScale);
public byte[] BuildYcd() { YcdFile ycd = new YcdFile(); ycd.ClipDictionary = new ClipDictionary(); var clipmap = new List <ClipMapEntry>(); var animmap = new List <AnimationMapEntry>(); foreach (var onim in OnimFiles) { var anim = new Animation(); anim.Hash = JenkHash.GenHash(onim.Name.ToLowerInvariant()); anim.Frames = (ushort)onim.Frames; anim.SequenceFrameLimit = (ushort)onim.SequenceFrameLimit; anim.Duration = onim.Duration; JenkIndex.Ensure(onim.Name.ToLowerInvariant());//just to make it nicer to debug really bool isUV = false; bool hasRootMotion = false; var boneIds = new List <AnimationBoneId>(); var seqs = new List <Sequence>(); var aseqs = new List <List <AnimSequence> >(); foreach (var oseq in onim.SequenceList) { var boneid = new AnimationBoneId(); boneid.BoneId = (ushort)oseq.BoneID; //TODO: bone ID mapping boneid.Unk0 = 0; //what to use here? switch (oseq.Track) { case "BonePosition": boneid.Track = 0; break; case "BoneRotation": boneid.Track = 1; break; case "ModelPosition": boneid.Track = 5; hasRootMotion = true; break; case "ModelRotation": boneid.Track = 6; hasRootMotion = true; break; case "UV0": boneid.Track = 17; isUV = true; break; case "UV1": boneid.Track = 18; isUV = true; break; case "LightColor": boneid.Track = 0; //what should this be? break; case "LightRange": boneid.Track = 0; //what should this be? break; case "LightIntensity1": boneid.Track = 0; //what should this be? break; case "LightIntensity2": boneid.Track = 0; //what should this be? break; case "LightDirection": boneid.Track = 0; //what should this be? break; case "Type21": boneid.Track = 0; //what should this be? break; case "CameraPosition": boneid.Track = 7; break; case "CameraRotation": boneid.Track = 8; break; case "CameraFOV": boneid.Track = 0; //what should this be? break; case "CameraDof": boneid.Track = 0; //what should this be? break; case "CameraMatrixRotateFactor": boneid.Track = 0; //what should this be? break; case "CameraControl": boneid.Track = 0; //what should this be? break; case "ActionFlags": //not sure what this is for? just ignore it for now continue; default: break; } boneIds.Add(boneid); for (int i = 0; i < oseq.FramesData.Count; i++) { var framesData = oseq.FramesData[i]; if (i > 0) { } Sequence seq = null; List <AnimSequence> aseqlist = null; while (i >= seqs.Count) { seq = new Sequence(); seqs.Add(seq); aseqlist = new List <AnimSequence>(); aseqs.Add(aseqlist); } seq = seqs[i]; aseqlist = aseqs[i]; var chanlist = new List <AnimChannel>(); if (framesData.IsStatic) { var vals = (framesData.Channels.Count > 0) ? framesData.Channels[0].Values : null; if (vals != null) { if (vals.Length == 1) { var acsf = new AnimChannelStaticFloat(); acsf.Value = vals[0]; chanlist.Add(acsf); } else if (vals.Length == 3) { var acsv = new AnimChannelStaticVector3(); acsv.Value = new Vector3(vals[0], vals[1], vals[2]); chanlist.Add(acsv); } else if (vals.Length == 4) { var acsq = new AnimChannelStaticQuaternion(); acsq.Value = new Quaternion(vals[0], vals[1], vals[2], vals[3]); chanlist.Add(acsq); } else { } } else { } } else { int chanCount = framesData.Channels.Count; for (int c = 0; c < chanCount; c++) { var ochan = framesData.Channels[c]; var vals = ochan.Values; if (vals.Length == 1)//static channel... { var acsf = new AnimChannelStaticFloat(); acsf.Value = vals[0]; chanlist.Add(acsf); } else //if (vals.Length == onim.Frames) { float minval = float.MaxValue; float maxval = float.MinValue; float lastval = 0; float mindelta = float.MaxValue; foreach (var val in vals) { minval = Math.Min(minval, val); maxval = Math.Max(maxval, val); if (val != lastval) { float adelta = Math.Abs(val - lastval); mindelta = Math.Min(mindelta, adelta); } lastval = val; } if (mindelta == float.MaxValue) { mindelta = 0; } float range = maxval - minval; float minquant = range / 1048576.0f; float quantum = Math.Max(mindelta, minquant); var acqf = new AnimChannelQuantizeFloat(); acqf.Values = vals; acqf.Offset = minval; acqf.Quantum = quantum; chanlist.Add(acqf); } } if (chanCount == 4) { //assume it's a quaternion... add the extra quaternion channel var acq1 = new AnimChannelCachedQuaternion(AnimChannelType.CachedQuaternion2); acq1.QuatIndex = 3;//what else should it be? chanlist.Add(acq1); } } if (chanlist.Count == 4) { } //shouldn't happen AnimSequence aseq = new AnimSequence(); aseq.Channels = chanlist.ToArray(); aseqlist.Add(aseq); } } int remframes = anim.Frames; for (int i = 0; i < seqs.Count; i++) { var seq = seqs[i]; var aseqlist = aseqs[i]; seq.Unknown_00h = 0;//what to set this??? seq.NumFrames = (ushort)Math.Max(Math.Min(anim.SequenceFrameLimit, remframes), 0); seq.Sequences = aseqlist.ToArray(); seq.AssociateSequenceChannels(); remframes -= anim.SequenceFrameLimit; } anim.BoneIds = new ResourceSimpleList64_s <AnimationBoneId>(); anim.BoneIds.data_items = boneIds.ToArray(); anim.Sequences = new ResourcePointerList64 <Sequence>(); anim.Sequences.data_items = seqs.ToArray(); anim.Unknown_10h = hasRootMotion ? (byte)16 : (byte)0; anim.Unknown_1Ch = 0; //??? anim.AssignSequenceBoneIds(); var cliphash = anim.Hash; if (isUV) { var name = onim.Name.ToLowerInvariant(); var uvind = name.IndexOf("_uv_"); if (uvind < 0) { } var modelname = name.Substring(0, uvind); var geoindstr = name.Substring(uvind + 4); var geoind = 0u; uint.TryParse(geoindstr, out geoind); cliphash = JenkHash.GenHash(modelname) + geoind + 1; } else { } var clip = new ClipAnimation(); clip.Animation = anim; clip.StartTime = 0.0f; clip.EndTime = anim.Duration; clip.Rate = 1.0f; clip.Name = "pack:/" + onim.Name + ".clip"; //pack:/name.clip clip.Unknown_30h = 0; //what's this then? clip.Properties = new ClipPropertyMap(); clip.Properties.CreatePropertyMap(null); //TODO? clip.Tags = new ClipTagList(); //TODO? var cme = new ClipMapEntry(); cme.Clip = clip; cme.Hash = cliphash; clipmap.Add(cme); var ame = new AnimationMapEntry(); ame.Hash = anim.Hash;//is this right? what else to use? ame.Animation = anim; animmap.Add(ame); } ycd.ClipDictionary.CreateClipsMap(clipmap.ToArray()); ycd.ClipDictionary.CreateAnimationsMap(animmap.ToArray()); ycd.ClipDictionary.BuildMaps(); ycd.ClipDictionary.UpdateUsageCounts(); ycd.InitDictionaries(); byte[] data = ycd.Save(); return(data); }
///<summary>Checks whether or not the given Animation Sequences contains Meta Data Instance of the specified Meta Data Class</summary> public static bool ContainsMetaDataOfClass(AnimSequence AnimationSequence, SubclassOf <AnimMetaData> MetaDataClass) => AnimationBlueprintLibrary_methods.ContainsMetaDataOfClass_method.Invoke(AnimationSequence, MetaDataClass);
/// <summary> /// 播放动画 /// </summary> /// <param name="actionName">动画名称</param> public void PlaySeq(String seqName) { if (!EnableAnim) { throw new Exception("该Item未启用动画"); } if (currentSeq == null || isIdle || currentSeq.enableDistrub) { foreach (AnimSequence animSeq in animSeqList) { if (seqName == animSeq.name) { isIdle = false; currentSeq = animSeq; currentFrameId = currentSeq.startFrameId; // 重置播放时间 baseTimeMS = (int)BaseGame.TotalTimeMilliseconds; break; } } } }
///<summary>Checks whether or not the given Bone Name exist on the Skeleton referenced by the given Animation Sequence</summary> public static bool DoesBoneNameExist(AnimSequence AnimationSequence, Name BoneName) => AnimationBlueprintLibrary_methods.DoesBoneNameExist_method.Invoke(AnimationSequence, BoneName);
internal void on_OnRevert(AnimSequence AnimationSequence) => OnRevert?.Invoke(AnimationSequence);
///<summary>Checks whether or not the given Curve Name exist on the Skeleton referenced by the given Animation Sequence</summary> public static bool DoesCurveExist(AnimSequence AnimationSequence, Name CurveName, ERawCurveTrackTypes CurveType) => AnimationBlueprintLibrary_methods.DoesCurveExist_method.Invoke(AnimationSequence, CurveName, CurveType);