private void PlayAttriubteAnim(HSFMotionAnimation anim) { foreach (AnimationNode node in anim.AnimGroups) { if (node.Mode == TrackMode.Attriubute) { int index = (int)node.ValueIndex; if (!Header.AttributeAnimControllers.ContainsKey(index)) { Header.AttributeAnimControllers.Add(index, new AttributeAnimController()); } var controller = Header.AttributeAnimControllers[index]; foreach (AnimTrack track in node.GetTracks()) { switch (track.TrackEffect) { case TrackEffect.TranslateX: controller.TranslateX = track.GetFrameValue(anim.Frame); break; case TrackEffect.TranslateY: controller.TranslateY = track.GetFrameValue(anim.Frame); break; case TrackEffect.TranslateZ: controller.TranslateZ = track.GetFrameValue(anim.Frame); break; case TrackEffect.RotationX: controller.RotateX = track.GetFrameValue(anim.Frame); break; case TrackEffect.RotationY: controller.RotateY = track.GetFrameValue(anim.Frame); break; case TrackEffect.RotationZ: controller.RotateZ = track.GetFrameValue(anim.Frame); break; case TrackEffect.ScaleX: controller.ScaleX = track.GetFrameValue(anim.Frame); break; case TrackEffect.ScaleY: controller.ScaleY = track.GetFrameValue(anim.Frame); break; case TrackEffect.ScaleZ: controller.ScaleZ = track.GetFrameValue(anim.Frame); break; } } } } }
public HSFMotionDataText(HSFMotionAnimation anim) { Name = anim.Name; FrameCount = anim.FrameCount; foreach (AnimationNode group in anim.AnimGroups) { Groups.Add(new HSFMotionGroupText(group)); } }
private void OnAnimationNextFrame(object sender, EventArgs e) { HSFMotionAnimation anim = (HSFMotionAnimation)sender; PlayAttriubteAnim(anim); PlayMaterialAnim(anim); PlaySkeletalAnim(anim); Console.WriteLine($"OnAnimationNextFrame {anim.Name}"); }
private void PlaySkeletalAnim(HSFMotionAnimation anim) { STSkeleton skeleton = Renderer.Scene.Models[0].Skeleton; foreach (var container in Runtime.ModelContainers) { var skel = container.SearchActiveSkeleton(); if (skel != null) { skeleton = skel; } } Console.WriteLine($"skeleton {skeleton != null}"); if (skeleton == null) { return; } if (anim.Frame == 0) { skeleton.Reset(); } bool Updated = false; // no need to update skeleton of animations that didn't change foreach (AnimationNode node in anim.AnimGroups) { var b = skeleton.SearchBone(node.Name); if (b == null) { continue; } Updated = true; Vector3 position = b.Position; Vector3 scale = b.Scale; Quaternion rotation = b.Rotation; if (node.TranslateX.HasKeys) { position.X = node.TranslateX.GetFrameValue(anim.Frame) * HSF_Renderer.PreviewScale; } if (node.TranslateY.HasKeys) { position.Y = node.TranslateY.GetFrameValue(anim.Frame) * HSF_Renderer.PreviewScale; } if (node.TranslateZ.HasKeys) { position.Z = node.TranslateZ.GetFrameValue(anim.Frame) * HSF_Renderer.PreviewScale; } if (node.ScaleX.HasKeys) { scale.X = node.ScaleX.GetFrameValue(anim.Frame); } if (node.ScaleY.HasKeys) { scale.Y = node.ScaleY.GetFrameValue(anim.Frame); } if (node.ScaleZ.HasKeys) { scale.Z = node.ScaleZ.GetFrameValue(anim.Frame); } if (node.RotationX.HasKeys || node.RotationY.HasKeys || node.RotationZ.HasKeys) { float x = node.RotationX.HasKeys ? MathHelper.DegreesToRadians(node.RotationX.GetFrameValue(anim.Frame)) : b.EulerRotation.X; float y = node.RotationY.HasKeys ? MathHelper.DegreesToRadians(node.RotationY.GetFrameValue(anim.Frame)) : b.EulerRotation.Y; float z = node.RotationZ.HasKeys ? MathHelper.DegreesToRadians(node.RotationZ.GetFrameValue(anim.Frame)) : b.EulerRotation.Z; rotation = STMath.FromEulerAngles(new Vector3(x, y, z)); } b.AnimationController.Position = position; b.AnimationController.Scale = scale; b.AnimationController.Rotation = rotation; } if (Updated) { skeleton.Update(); } }
private void PlayMaterialAnim(HSFMotionAnimation anim) { foreach (AnimationNode node in anim.AnimGroups) { if (node.Mode == TrackMode.Material) { int index = (int)node.ValueIndex; if (!Header.MatAnimControllers.ContainsKey(index)) { Header.MatAnimControllers.Add(index, new MatAnimController()); } var controller = Header.MatAnimControllers[index]; controller.AmbientColorB = 1; controller.AmbientColorG = 1; controller.AmbientColorR = 1; foreach (AnimTrack track in node.GetTracks()) { switch ((MaterialTrackEffect)track.TrackEffect) { case MaterialTrackEffect.AmbientColorR: controller.AmbientColorR = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.AmbientColorG: controller.AmbientColorG = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.AmbientColorB: controller.AmbientColorB = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.LitAmbientColorR: controller.LitAmbientColorR = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.LitAmbientColorG: controller.LitAmbientColorG = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.LitAmbientColorB: controller.LitAmbientColorB = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.ShadowColorR: controller.ShadowColorR = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.ShadowColorG: controller.ShadowColorG = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.ShadowColorB: controller.ShadowColorB = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.HiliteScale: controller.HiliteScale = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.ReflectionBrightness: controller.ReflectionIntensity = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.Transparency: controller.TransparencyInverted = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.MatUnknown3: controller.Unknown3 = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.MatUnknown4: controller.Unknown4 = track.GetFrameValue(anim.Frame); break; case MaterialTrackEffect.MatUnknown5: controller.Unknown5 = track.GetFrameValue(anim.Frame); break; } } } } }
public override void Read(FileReader reader, HsfFile header) { List <MotionData> anims = reader.ReadMultipleStructs <MotionData>(this.Count); long pos = reader.Position; for (int i = 0; i < anims.Count; i++) { HSFMotionAnimation anm = new HSFMotionAnimation(); Animations.Add(anm); anm.Name = header.GetString(reader, anims[i].NameOffset); anm.FrameCount = anims[i].MotionLength; reader.SeekBegin(pos + anims[i].TrackDataOffset); for (int j = 0; j < anims[i].TrackCount; j++) { TrackData track = new TrackData(); track.mode = (TrackMode)reader.ReadByte(); track.unk = reader.ReadByte(); track.stringOffset = reader.ReadInt16(); track.valueIndex = reader.ReadInt16(); //Used if no string (stringOffset = -1) track.effect = (TrackEffect)reader.ReadInt16(); track.interpolate_type = (InterpolationMode)reader.ReadInt16(); track.keyframe_count = reader.ReadInt16(); if (track.keyframe_count > 0 && track.interpolate_type != InterpolationMode.Constant) { track.keyframe_offset = reader.ReadInt32(); } else { track.Constant = reader.ReadSingle(); } Console.WriteLine($"{j} TrackMode {track.mode} valueIndex {track.valueIndex} effect {track.effect} interp {track.interpolate_type} Constant {track.Constant}"); if (track.valueIndex != 0) { //Console.WriteLine($"valueIndex {track.valueIndex} str {track.stringOffset}"); } anm.trackInfo.Add(track); } } Dictionary <string, AnimationNode> animationNodes = new Dictionary <string, AnimationNode>(); long dataStart = reader.Position; for (int i = 0; i < Animations.Count; i++) { var anim = Animations[i]; for (int j = 0; j < anim.trackInfo.Count; j++) { var track = anim.trackInfo[j]; string name = header.GetString(reader, (uint)track.stringOffset); if (track.stringOffset == -1) { name = $"{track.mode}_{track.valueIndex}"; } else if (track.valueIndex > 0) { name = $"{name}_{track.valueIndex}"; } if (!animationNodes.ContainsKey(name)) { animationNodes.Add(name, new AnimationNode() { Name = name, Mode = track.mode, ValueIndex = track.valueIndex, }); } AnimationNode currentGroup = animationNodes[name]; List <STKeyFrame> keyFrames = new List <STKeyFrame>(); if (track.keyframe_count > 0 && track.interpolate_type != InterpolationMode.Constant) { reader.SeekBegin(dataStart + track.keyframe_offset); for (int key = 0; key < track.keyframe_count; key++) { switch (track.interpolate_type) { //8 bytes case InterpolationMode.Step: { keyFrames.Add(new STKeyFrame() { Frame = reader.ReadSingle(), Value = reader.ReadSingle(), }); } break; //8 bytes case InterpolationMode.Bitmap: { keyFrames.Add(new STKeyFrame() { Frame = reader.ReadSingle(), Value = reader.ReadInt32(), }); } break; //16 bytes case InterpolationMode.Bezier: { keyFrames.Add(new STBezierKeyFrame() { Frame = reader.ReadSingle(), Value = reader.ReadSingle(), SlopeIn = reader.ReadSingle(), SlopeOut = reader.ReadSingle(), }); } break; case InterpolationMode.Linear: { keyFrames.Add(new STKeyFrame() { Frame = reader.ReadSingle(), Value = reader.ReadSingle(), }); } break; default: throw new Exception($"Unsupported interpolation mode! track {j} " + track.interpolate_type); } } } currentGroup.TrackList.Add(new AnimTrack(currentGroup) { ConstantUnk = track.keyframe_count, //When constant used, value is used for something else? KeyFrames = keyFrames, TrackEffect = track.effect, TrackMode = track.mode, ValueIdx = track.valueIndex, Unknown = track.unk, Constant = track.Constant, InterpolationType = ConvertType(track.interpolate_type), }); } foreach (var group in animationNodes) { anim.AnimGroups.Add(group.Value); } } }
public static string Export(HSFMotionAnimation anim) { return(TextConverter(anim)); }
private static string TextConverter(HSFMotionAnimation anim) { StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); using (JsonWriter writer = new JsonTextWriter(sw)) { writer.Formatting = Formatting.Indented; writer.WriteStartObject(); writer.WritePropertyName("Name"); writer.WriteValue(anim.Name); writer.WritePropertyName("FrameCount"); writer.WriteValue(anim.FrameCount); writer.WritePropertyName("Groups"); writer.WriteStartObject(); foreach (AnimationNode group in anim.AnimGroups) { writer.WritePropertyName("Group"); writer.WriteValue(group.Name); writer.Formatting = Formatting.None; writer.WritePropertyName("Id"); writer.WriteValue(group.ValueIndex); writer.WritePropertyName("Mode"); writer.WriteValue(group.Mode); writer.WritePropertyName("Tracks"); writer.WriteStartObject(); writer.Formatting = Formatting.Indented; var tracks = group.GetTracks().OrderBy(x => x.InterpolationType); foreach (AnimTrack track in tracks) { writer.WritePropertyName($"Track_{track.InterpolationType}"); switch (track.TrackMode) { case TrackMode.Material: writer.WriteValue($"{(MaterialTrackEffect)track.TrackEffect}"); break; writer.WriteValue($"{(AttributeTrackEffect)track.TrackEffect}"); break; default: writer.WriteValue($"{track.TrackEffect}"); break; } // writer.WritePropertyName("Unk"); // writer.WriteValue(track.Unknown); writer.Formatting = Formatting.None; if (track.InterpolationType == STInterpoaltionType.Constant) { writer.WritePropertyName("Value"); writer.WriteValue(track.Constant); writer.WritePropertyName("Flags"); writer.WriteValue($"0x{track.ConstantUnk.ToString("X")}"); } writer.Formatting = Formatting.Indented; if (track.HasKeys) { writer.WritePropertyName("KeyFrames"); writer.WriteStartObject(); } foreach (var key in track.KeyFrames) { switch (track.InterpolationType) { case STInterpoaltionType.Bezier: writer.WritePropertyName("Frame"); writer.WriteValue(key.Frame); writer.Formatting = Formatting.None; writer.WritePropertyName("Value"); writer.WriteValue((float)Math.Round(key.Value, 5)); writer.WritePropertyName("in"); writer.WriteValue((float)Math.Round(((STBezierKeyFrame)key).SlopeIn, 5)); writer.WritePropertyName("out"); writer.WriteValue((float)Math.Round(((STBezierKeyFrame)key).SlopeOut, 5)); writer.Formatting = Formatting.Indented; break; default: writer.WritePropertyName("Frame"); writer.WriteValue(key.Frame); writer.Formatting = Formatting.None; writer.WritePropertyName("Value"); writer.WriteValue(key.Value); writer.Formatting = Formatting.Indented; break; } } if (track.HasKeys) { writer.WriteEndObject(); } } writer.WriteEndObject(); } writer.WriteEndObject(); writer.WriteEndObject(); } return(sb.ToString()); }
private static HSFMotionAnimation TextConverter(string text) { HSFMotionAnimation anim = new HSFMotionAnimation(); StringReader sr = new StringReader(text); using (JsonReader reader = new JsonTextReader(sr)) { AnimationNode group = null; while (reader.Read()) { if (reader.Value == null) { continue; } if (reader.Value.Equals("Name")) { anim.Name = reader.ReadAsString(); } else if (reader.Value.Equals("FrameCount")) { anim.FrameCount = (float)reader.ReadAsDecimal(); } else if (reader.Value.Equals("Group")) { group = new AnimationNode(); anim.AnimGroups.Add(group); string name = reader.ReadAsString(); reader.Read(); //ID group.ValueIndex = (short)reader.ReadAsInt32(); //index reader.Read(); //mode group.Mode = (TrackMode)reader.ReadAsInt32(); if (group.Mode == TrackMode.Normal || group.Mode == TrackMode.Object) { group.Name = name; } else { group.Name = ""; } } else if (reader.Value.Equals("Track_Constant")) { string effect = reader.ReadAsString(); reader.Read(); //Value float value = (float)reader.ReadAsDecimal(); reader.Read(); //Flags string flags = reader.ReadAsString().Replace("0x", string.Empty); AnimTrack track = new AnimTrack(group); track.ValueIdx = group.ValueIndex; track.TrackMode = group.Mode; track.TrackEffect = ParseEffect(group.Mode, effect); track.Constant = value; track.ConstantUnk = short.Parse(flags, System.Globalization.NumberStyles.HexNumber); track.InterpolationType = STInterpoaltionType.Constant; track.KeyFrames = new List <STKeyFrame>(); track.Unknown = 0; group.TrackList.Add(track); } else if (reader.Value.Equals("Track_Bezier")) { group.TrackList.Add(ParseAnimTrack(reader, group, STInterpoaltionType.Bezier)); } else if (reader.Value.Equals("Track_Linear")) { group.TrackList.Add(ParseAnimTrack(reader, group, STInterpoaltionType.Linear)); } else if (reader.Value.Equals("Track_Bezier")) { group.TrackList.Add(ParseAnimTrack(reader, group, STInterpoaltionType.Bezier)); } else if (reader.Value.Equals("Track_Bitmap")) { group.TrackList.Add(ParseAnimTrack(reader, group, STInterpoaltionType.Bitmap)); } else if (reader.Value.Equals("Track_Step")) { group.TrackList.Add(ParseAnimTrack(reader, group, STInterpoaltionType.Step)); } } } return(anim); }