diff --git a/Z64Utils/Forms/SkeletonViewerForm.cs b/Z64Utils/Forms/SkeletonViewerForm.cs index 39d52e0..6b4a864 100644 --- a/Z64Utils/Forms/SkeletonViewerForm.cs +++ b/Z64Utils/Forms/SkeletonViewerForm.cs @@ -23,6 +23,125 @@ enum PlayState Backward, } + interface ISkeletonViewerAnimationEntry + { + string GetName(); + } + + interface ISkeletonViewerRegularAnimationEntry : ISkeletonViewerAnimationEntry + { + AnimationHolder GetAnim(); + } + + interface ISkeletonViewerPlayerAnimationEntry : ISkeletonViewerAnimationEntry + { + PlayerAnimationHolder GetPlayerAnim(); + } + + interface ISkeletonViewerExternalAnimationEntry : ISkeletonViewerAnimationEntry + { + int GetExternalSegment(); + F3DZEX.Memory.Segment GetExternalData(); + } + + class SkeletonViewerRegularAnimationEntry : ISkeletonViewerRegularAnimationEntry + { + private AnimationHolder _anim; + + public SkeletonViewerRegularAnimationEntry(AnimationHolder anim) + { + _anim = anim; + } + + public string GetName() + { + return _anim.Name; + } + + public AnimationHolder GetAnim() + { + return _anim; + } + } + + class SkeletonViewerPlayerAnimationEntry : ISkeletonViewerPlayerAnimationEntry + { + private PlayerAnimationHolder _playerAnim; + + public SkeletonViewerPlayerAnimationEntry(PlayerAnimationHolder playerAnim) + { + _playerAnim = playerAnim; + } + + public string GetName() + { + return _playerAnim.Name; + } + + public PlayerAnimationHolder GetPlayerAnim() + { + return _playerAnim; + } + } + + class SkeletonViewerExternalRegularAnimationEntry + : SkeletonViewerRegularAnimationEntry, + ISkeletonViewerExternalAnimationEntry + { + private int _segment; + private F3DZEX.Memory.Segment _data; + + public SkeletonViewerExternalRegularAnimationEntry( + AnimationHolder anim, + int segment, + F3DZEX.Memory.Segment data + ) + : base(anim) + { + _segment = segment; + _data = data; + } + + public int GetExternalSegment() + { + return _segment; + } + + public F3DZEX.Memory.Segment GetExternalData() + { + return _data; + } + } + + class SkeletonViewerExternalPlayerAnimationEntry + : SkeletonViewerPlayerAnimationEntry, + ISkeletonViewerExternalAnimationEntry + { + private int _segment; + private F3DZEX.Memory.Segment _data; + + public SkeletonViewerExternalPlayerAnimationEntry( + PlayerAnimationHolder playerAnim, + int segment, + F3DZEX.Memory.Segment data + ) + : base(playerAnim) + { + _segment = segment; + _data = data; + } + + public int GetExternalSegment() + { + return _segment; + } + + public F3DZEX.Memory.Segment GetExternalData() + { + return _data; + } + } + bool _formClosing = false; System.Timers.Timer _timer; PlayState _playState; @@ -35,26 +154,22 @@ enum PlayState SettingsForm? _settingsForm; F3DZEX.Render.Renderer.Config _rendererCfg; + int _curSegment; SkeletonHolder _skel; - List _anims; - List _playerAnims; + List _animations; List _limbs; List _limbDlists; List _limbDlistRenderFlags; - AnimationHolder? _curAnim; + ISkeletonViewerAnimationEntry? _curAnimation; + short[]? _frameData; AnimationJointIndicesHolder.JointIndex[]? _curJoints; - PlayerAnimationHolder? _curPlayerAnim; PlayerAnimationJointTableHolder.JointTableEntry[,]? _curPlayerJointTable; string? _animationError; - byte[]? _animFile; - int _curSegment = 6; - int _extAnimSegment = 6; - public SkeletonViewerForm( Z64Game? game, int curSegment, @@ -113,7 +228,16 @@ List anims _playState = PlayState.Pause; SetSegment(curSegment, curSegmentData); - SetSkeleton(skel, anims); + + _skel = skel; + _animations = new(); + anims.ForEach(ah => _animations.Add(new SkeletonViewerRegularAnimationEntry(ah))); + + listBox_anims.Items.Clear(); + _animations.ForEach(a => listBox_anims.Items.Add(a.GetName())); + + UpdateSkeleton(); + NewRender(); } void RenderLimb(int limbIdx, bool overlay = false) @@ -132,7 +256,7 @@ void RenderLimb(int limbIdx, bool overlay = false) { Vector3 childPos; - if (_curAnim != null && _curJoints != null) + if (_curAnimation != null && _curJoints != null) childPos = GetLimbPos(_limbs[limbIdx].Child); else childPos = new Vector3(0, 0, 0); @@ -238,22 +362,6 @@ private void NewRender(object? sender = null, EventArgs? e = null) modelViewer.Render(); } - [MemberNotNull(nameof(_skel), nameof(_anims), nameof(_playerAnims))] - [MemberNotNull(nameof(_limbs), nameof(_limbDlistRenderFlags))] - [MemberNotNull(nameof(_limbDlists))] - public void SetSkeleton(SkeletonHolder skel, List anims) - { - _skel = skel; - _anims = anims; - _playerAnims = new List(); - - listBox_anims.Items.Clear(); - _anims.ForEach(a => listBox_anims.Items.Add(a.Name)); - - UpdateSkeleton(); - NewRender(); - } - [MemberNotNull(nameof(_limbDlists))] void UpdateLimbsDlists() { @@ -348,9 +456,10 @@ void AddLimbRoutine(TreeNode parent, int i, int x, int y, int z) short GetFrameData(int frameDataIdx) { Debug.Assert(_frameData != null); - Debug.Assert(_curAnim != null); + var curRegularAnimation = _curAnimation as ISkeletonViewerRegularAnimationEntry; + Debug.Assert(curRegularAnimation != null); return _frameData[ - frameDataIdx < _curAnim.StaticIndexMax + frameDataIdx < curRegularAnimation.GetAnim().StaticIndexMax ? frameDataIdx : frameDataIdx + trackBar_anim.Value ]; @@ -358,7 +467,7 @@ short GetFrameData(int frameDataIdx) Vector3 GetLimbPos(int limbIdx) { - if (_curPlayerAnim != null) + if (_curAnimation is ISkeletonViewerPlayerAnimationEntry) { return new Vector3( _limbs[limbIdx].JointX, @@ -382,26 +491,30 @@ Vector3 GetLimbPos(int limbIdx) } // Update anims -> matrices - void UpdateAnim() + void UpdateRegularAnim() { - Debug.Assert(_curAnim != null); + var curRegularAnimation = _curAnimation as ISkeletonViewerRegularAnimationEntry; + Debug.Assert(curRegularAnimation != null); + var curAH = curRegularAnimation.GetAnim(); + trackBar_anim.Minimum = 0; - trackBar_anim.Maximum = _curAnim.FrameCount - 1; + trackBar_anim.Maximum = curAH.FrameCount - 1; trackBar_anim.Value = 0; - var Saved = _renderer.Memory.Segments[_curSegment]; + int? savedSegment = null; + F3DZEX.Memory.Segment? savedData = null; - if (_curAnim.extAnim) + if (_curAnimation is ISkeletonViewerExternalAnimationEntry curExternalAnimation) { - Debug.Assert(_animFile != null); // extAnim = true is only set with _animFile set - _renderer.Memory.Segments[_extAnimSegment] = F3DZEX.Memory.Segment.FromBytes( - "", - _animFile - ); + savedSegment = curExternalAnimation.GetExternalSegment(); + savedData = _renderer.Memory.Segments[curExternalAnimation.GetExternalSegment()]; + + _renderer.Memory.Segments[curExternalAnimation.GetExternalSegment()] = + curExternalAnimation.GetExternalData(); } byte[] buff = _renderer.Memory.ReadBytes( - _curAnim.JointIndices, + curAH.JointIndices, (_limbs.Count + 1) * AnimationJointIndicesHolder.ENTRY_SIZE ); _curJoints = new AnimationJointIndicesHolder("joints", buff).JointIndices; @@ -414,14 +527,13 @@ void UpdateAnim() max = Math.Max(max, joint.Z); } - int bytesToRead = - (max < _curAnim.StaticIndexMax ? max + 1 : _curAnim.FrameCount + max) * 2; + int bytesToRead = (max < curAH.StaticIndexMax ? max + 1 : curAH.FrameCount + max) * 2; - var curSegmentData = _renderer.Memory.Segments[_curSegment].Data; + var curSegmentData = _renderer.Memory.Segments[curAH.FrameData.SegmentId].Data; Debug.Assert(curSegmentData != null); - if (bytesToRead + _curAnim.FrameData.SegmentOff > curSegmentData.Length) + if (bytesToRead + curAH.FrameData.SegmentOff > curSegmentData.Length) { - _curAnim = null; + _curAnimation = null; _curJoints = null; _frameData = null; _animationError = @@ -429,56 +541,69 @@ void UpdateAnim() } else { - buff = _renderer.Memory.ReadBytes(_curAnim.FrameData, bytesToRead); + buff = _renderer.Memory.ReadBytes(curAH.FrameData, bytesToRead); _frameData = new AnimationFrameDataHolder("framedata", buff).FrameData; _animationError = ""; } - _renderer.Memory.Segments[_curSegment] = Saved; + if (savedSegment != null) + { + Debug.Assert(savedData != null); + _renderer.Memory.Segments[(int)savedSegment] = savedData; + } + UpdateMatrixBuf(); } void UpdatePlayerAnim() { - Debug.Assert(_curPlayerAnim != null); + var curPlayerAnimation = _curAnimation as ISkeletonViewerPlayerAnimationEntry; + Debug.Assert(curPlayerAnimation != null); + var curPAH = curPlayerAnimation.GetPlayerAnim(); trackBar_anim.Minimum = 0; - trackBar_anim.Maximum = _curPlayerAnim.FrameCount - 1; + trackBar_anim.Maximum = curPAH.FrameCount - 1; trackBar_anim.Value = 0; if (_game == null) return; - var Saved = _renderer.Memory.Segments[_curPlayerAnim.PlayerAnimationSegment.SegmentId]; + var Saved = _renderer.Memory.Segments[curPAH.PlayerAnimationSegment.SegmentId]; var link_animetionFile = _game.GetFileByName("link_animetion"); Debug.Assert(link_animetionFile != null); Debug.Assert(link_animetionFile.Valid()); - _renderer.Memory.Segments[_curPlayerAnim.PlayerAnimationSegment.SegmentId] = + _renderer.Memory.Segments[curPAH.PlayerAnimationSegment.SegmentId] = F3DZEX.Memory.Segment.FromBytes("link_animetion", link_animetionFile.Data); byte[] buff = _renderer.Memory.ReadBytes( - _curPlayerAnim.PlayerAnimationSegment, - ((PlayerAnimationHolder.PLAYER_LIMB_COUNT * 3) + 1) * _curPlayerAnim.FrameCount * 2 + curPAH.PlayerAnimationSegment, + ((PlayerAnimationHolder.PLAYER_LIMB_COUNT * 3) + 1) * curPAH.FrameCount * 2 ); _curPlayerJointTable = new PlayerAnimationJointTableHolder("joints", buff).JointTable; - _renderer.Memory.Segments[_curPlayerAnim.PlayerAnimationSegment.SegmentId] = Saved; + _renderer.Memory.Segments[curPAH.PlayerAnimationSegment.SegmentId] = Saved; UpdateMatrixBuf(); } Matrix4 CalcMatrix(Matrix4 src, int limbIdx) { - if (_curPlayerAnim != null) + if (_curAnimation == null) + return src; + + if (_curAnimation is ISkeletonViewerPlayerAnimationEntry) { return CalcMatrixPlayer(src, limbIdx); } - - return CalcMatrixNormal(src, limbIdx); + else + { + Debug.Assert(_curAnimation is ISkeletonViewerRegularAnimationEntry); + return CalcMatrixRegular(src, limbIdx); + } } - Matrix4 CalcMatrixNormal(Matrix4 src, int limbIdx) + Matrix4 CalcMatrixRegular(Matrix4 src, int limbIdx) { - if (_curAnim == null || _curJoints == null) + if (_curAnimation == null || _curJoints == null) return src; Vector3 pos = GetLimbPos(limbIdx); @@ -652,18 +777,17 @@ private void listBox_anims_SelectedIndexChanged(object sender, EventArgs e) trackBar_anim.Enabled = listBox_anims.SelectedIndex >= 0; - _curAnim = null; - _curPlayerAnim = null; + _curAnimation = null; if (listBox_anims.SelectedIndex >= 0) { - if (listBox_anims.SelectedIndex < _anims.Count) + _curAnimation = _animations[listBox_anims.SelectedIndex]; + if (_curAnimation is ISkeletonViewerRegularAnimationEntry) { - _curAnim = _anims[listBox_anims.SelectedIndex]; - UpdateAnim(); + UpdateRegularAnim(); } else { - _curPlayerAnim = _playerAnims[listBox_anims.SelectedIndex - _anims.Count]; + Debug.Assert(_curAnimation is ISkeletonViewerPlayerAnimationEntry); UpdatePlayerAnim(); } @@ -761,55 +885,72 @@ private void listBox_anims_DoubleClick(object sender, EventArgs e) button_playAnim.BackgroundImage = Properties.Resources.play_icon; button_playbackAnim.BackgroundImage = Properties.Resources.playback_icon; - OpenFileDialog of = new OpenFileDialog(); - DialogResult DR = of.ShowDialog(); + OpenFileDialog openFileDialog = new(); - if (DR == DialogResult.OK) + if (openFileDialog.ShowDialog() == DialogResult.OK) { - _animFile = File.ReadAllBytes(of.FileName); + var animFileData = File.ReadAllBytes(openFileDialog.FileName); int segment = _curSegment; - if (of.FileName.Contains("gameplay_keep")) + if (openFileDialog.FileName.Contains("gameplay_keep")) { segment = 4; } else if ( - of.FileName.Contains("gameplay_dangeon_keep") - || of.FileName.Contains("gameplay_field_keep") + openFileDialog.FileName.Contains("gameplay_dangeon_keep") + || openFileDialog.FileName.Contains("gameplay_field_keep") ) { segment = 5; } - else if ((segment == 4 || segment == 5) && !of.FileName.Contains("keep")) + else if ( + (segment == 4 || segment == 5) && !openFileDialog.FileName.Contains("keep") + ) { segment = 6; } - _extAnimSegment = segment; - using (var form = new ObjectAnalyzerForm(_game, _animFile, of.FileName, segment)) + var data = F3DZEX.Memory.Segment.FromBytes("", animFileData); + + using ( + var form = new ObjectAnalyzerForm( + _game, + animFileData, + openFileDialog.FileName, + segment + ) + ) { - _anims.Clear(); - _playerAnims.Clear(); + _animations.Clear(); form._obj.Entries.ForEach(e => { if (e is Z64Object.AnimationHolder eAnim) { - eAnim.extAnim = true; eAnim.Name = "ext_" + eAnim.Name; - _anims.Add(eAnim); + _animations.Add( + new SkeletonViewerExternalRegularAnimationEntry( + eAnim, + segment, + data + ) + ); } if (e is Z64Object.PlayerAnimationHolder ePlayerAnim) { - ePlayerAnim.extAnim = true; ePlayerAnim.Name = "ext_" + ePlayerAnim.Name; - _playerAnims.Add(ePlayerAnim); + _animations.Add( + new SkeletonViewerExternalPlayerAnimationEntry( + ePlayerAnim, + segment, + data + ) + ); } }); } listBox_anims.Items.Clear(); - _anims.ForEach(a => listBox_anims.Items.Add(a.Name)); - _playerAnims.ForEach(a => listBox_anims.Items.Add(a.Name)); + _animations.ForEach(a => listBox_anims.Items.Add(a.GetName())); } } } diff --git a/Z64Utils/Z64/Z64Object.cs b/Z64Utils/Z64/Z64Object.cs index ab31163..8ce2065 100644 --- a/Z64Utils/Z64/Z64Object.cs +++ b/Z64Utils/Z64/Z64Object.cs @@ -511,8 +511,6 @@ public class AnimationHolder : ObjectHolder public SegmentedAddress JointIndices { get; set; } public ushort StaticIndexMax { get; set; } - public bool extAnim { get; set; } - public AnimationHolder(string name, byte[] data) : base(name) { @@ -668,7 +666,6 @@ public class PlayerAnimationHolder : ObjectHolder public short FrameCount { get; set; } public SegmentedAddress PlayerAnimationSegment { get; set; } - public bool extAnim { get; set; } public PlayerAnimationHolder(string name, byte[] data) : base(name)