Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 40 additions & 15 deletions Godbert/ViewModels/MonstersViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,33 @@ private List<PapFile> SearchPaps(string modelPath, int m)
* a0002 animations are decided? */
string[] searchPaths =
{
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/ability",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/battle",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/blownaway",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/bnpc_gesture",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/bnpc_gimmickjump",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/bnpc_passmove",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/cr_mon",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/emote",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/event",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/event_base",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/gs_roulette/m{0:D4}",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/human_sp/c0101",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/idle_sp",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/lcut",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/loop_sp",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/minion",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/mon_sp/m{0:D4}",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/mon_sp/m{0:D4}/hide",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/mon_sp/m{0:D4}/show",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/event",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/minion",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/mount_sp/m{0:D4}",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/normal",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/parts_idle_sp",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/pc_contentsaction",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/resident",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/specialpop"
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/specialpop",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/trans_sp/m{0:D4}",
"chara/monster/m{0:D4}/animation/a{1:D4}/bt_common/warp",
};

SaintCoinach.IO.Directory d;
Expand Down Expand Up @@ -213,22 +233,27 @@ private IComponent CreateModel(Engine engine, Skeleton skeleton, ModelDefinition
var component = new AnimatedModel(engine, skeleton, variant, model, ModelQuality.High) {};
var papPath = string.Format(PapPathFormat, m, b);

SaintCoinach.IO.File papFileBase;
if (Parent.Realm.Packs.TryGetFile(papPath, out papFileBase)) {
var anim = new AnimationContainer(skeleton, new PapFile(papFileBase));

var allPaps = SearchPaps(model.File.Path, m);
if (allPaps.Any()) {
var hasAnim = false;
for(var i = 0; i < DefaultAnimationNames.Length && !hasAnim; ++i) {
var n = DefaultAnimationNames[i];
if (anim.AnimationNames.Contains(n)) {
component.AnimationPlayer.Animation = anim.Get(n);
hasAnim = true;

foreach (var pap in allPaps) {
var anim = new AnimationContainer(skeleton, pap);
foreach (var name in anim.AnimationNames) {
component.AnimationPlayer.AddAnimation(anim.Get(name));
if (!hasAnim && DefaultAnimationNames.Contains(name)) {
hasAnim = true;
component.AnimationPlayer.AnimationIndex = component.AnimationPlayer.Animations.Count - 1;
}
}
}

if (!hasAnim)
component.AnimationPlayer.Animation = anim.Get(0);

if (!hasAnim && component.AnimationPlayer.Animations.Any())
component.AnimationPlayer.AnimationIndex = 0;

component.AnimationPlayer.SortAnimationsByName();
}

return component;
}

Expand Down
2 changes: 1 addition & 1 deletion SaintCoinach.Graphics.Viewer/AnimatedModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public AnimatedModel(Engine engine, Skeleton skeleton, ModelVariantIdentifier va
: base(engine, variant, definition, quality) {

Skeleton = skeleton;
_AnimationPlayer = new AnimationPlayer();
_AnimationPlayer = new AnimationPlayer(engine);

var nameMap = new Dictionary<string, int>();
for (var i = 0; i < Skeleton.BoneNames.Length; ++i)
Expand Down
91 changes: 85 additions & 6 deletions SaintCoinach.Graphics.Viewer/AnimationPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SaintCoinach.Graphics.Viewer {
using SharpDX;
Expand All @@ -16,21 +17,26 @@ public class AnimationPlayer : IUpdateableComponent {
private bool _IsEnabled = true;
private bool _IsLooping = true;

private Animation _Animation;
private List<Animation> _Animations = new List<Animation>();
private int _AnimationIndex = -1;

private double _CurrentPlaybackPosition = 0f;

private bool _IsDirty = true;
private Matrix[] _BoneTransformationMatrices;

private Engine _Engine;
#endregion

#region Properties
public double PlaybackSpeed { get { return _PlaybackSpeed; } set { _PlaybackSpeed = value; } }
public bool IsLooping { get { return _IsLooping; } set { _IsLooping = value; _IsAnimating = true; } }
public Animation Animation {
get { return _Animation; }
public IList<Animation> Animations { get { return _Animations.AsReadOnly(); } }
public Animation Animation { get { return _AnimationIndex == -1 ? null : _Animations[_AnimationIndex]; } }
public int AnimationIndex {
get { return _AnimationIndex; }
set {
_Animation = value;
_AnimationIndex = value;
Reset();
}
}
Expand All @@ -39,6 +45,11 @@ public Animation Animation {
#endregion

#region Constructor
public AnimationPlayer(Engine engine) {
_Engine = engine;

Reset();
}
#endregion

#region Update
Expand All @@ -53,26 +64,94 @@ public Matrix[] GetPose() {

return _BoneTransformationMatrices;
}

public void Reset() {
_IsAnimating = true;
CurrentPlaybackPosition = 0f;
PlaybackSpeed = 1;
UpdateTitle();
}

public void UpdateTitle() {
if (Animation == null) {
_Engine.Subtitle = "";
return;
}

var sb = new StringBuilder();
sb.Append(_AnimationIndex + 1).Append("/").Append(_Animations.Count);
sb.Append(" - ").Append(Animation.Name);
sb.Append(" - ").AppendFormat("{0:0.00}x", PlaybackSpeed);
sb.Append(" - ").AppendFormat("{0:0.00}s/{1:0.00}s", CurrentPlaybackPosition, Animation.Duration);
sb.Append(" - ").AppendFormat("{0}/{1}", (int)Math.Floor(CurrentPlaybackPosition / Animation.FrameDuration) + 1, Animation.FrameCount);
if (!_IsAnimating)
sb.Append(" - Paused");
_Engine.Subtitle = sb.ToString();
}

public bool IsEnabled { get { return _IsEnabled; } set { _IsEnabled = value; } }

public void Update(EngineTime engineTime) {
if (!IsEnabled || !IsAnimating || Animation == null || Math.Abs(PlaybackSpeed) <= float.Epsilon)
if (!Animations.Any())
return;

var elapsedTime = IsAnimating ? engineTime.ElapsedTime.TotalSeconds : 0;
if (_Engine.Keyboard.IsKeyDown(Keys.R))
Reset();
if (_Engine.Keyboard.WasKeyPressedRepeatable(Keys.Oemcomma)) {
_AnimationIndex = (_AnimationIndex + _Animations.Count - 1) % _Animations.Count;
elapsedTime = 0;
_IsAnimating = true;
CurrentPlaybackPosition = 0f;
}
if (_Engine.Keyboard.WasKeyPressedRepeatable(Keys.OemPeriod)) {
_AnimationIndex = (_AnimationIndex + 1) % _Animations.Count;
elapsedTime = 0;
_IsAnimating = true;
CurrentPlaybackPosition = 0f;
}
if (_Engine.Keyboard.WasKeyPressedRepeatable(Keys.OemQuestion)) {
_IsAnimating = !_IsAnimating;
elapsedTime = 0;
}
if (_Engine.Keyboard.WasKeyPressedRepeatable(Keys.N)) {
_IsAnimating = false;
elapsedTime = 0;
_CurrentPlaybackPosition = (int)Math.Round((_CurrentPlaybackPosition + Animation.Duration - Animation.FrameDuration) / Animation.FrameDuration) % Animation.FrameCount * Animation.FrameDuration;
}
if (_Engine.Keyboard.WasKeyPressedRepeatable(Keys.M)) {
_IsAnimating = false;
elapsedTime = 0;
_CurrentPlaybackPosition = (int)Math.Round((_CurrentPlaybackPosition + Animation.FrameDuration) / Animation.FrameDuration) % Animation.FrameCount * Animation.FrameDuration;
}
if (_Engine.Keyboard.WasKeyPressedRepeatable(Keys.K))
PlaybackSpeed = Math.Max(1, Math.Round(PlaybackSpeed * 20) - 1) / 20;
if (_Engine.Keyboard.WasKeyPressedRepeatable(Keys.L))
PlaybackSpeed = Math.Min(80, Math.Round(PlaybackSpeed * 20) + 1) / 20;

_IsDirty = true;
_CurrentPlaybackPosition += engineTime.ElapsedTime.TotalSeconds * PlaybackSpeed;
_CurrentPlaybackPosition += elapsedTime * PlaybackSpeed;
if (IsLooping) {
while (_CurrentPlaybackPosition < 0)
_CurrentPlaybackPosition += Animation.Duration;
while (_CurrentPlaybackPosition > Animation.Duration)
_CurrentPlaybackPosition -= Animation.Duration;
} else if (_CurrentPlaybackPosition <= 0 || _CurrentPlaybackPosition > Animation.Duration)
_IsAnimating = false;

UpdateTitle();
}
#endregion

#region Misc
public void AddAnimation(Animation animation) {
_Animations.Add(animation);
}

public void SortAnimationsByName() {
var prev = Animation;
_Animations.Sort((x, y) => (x.Name.CompareTo(y.Name)));
AnimationIndex = Animations.IndexOf(prev);
}
#endregion
}
Expand Down
14 changes: 10 additions & 4 deletions SaintCoinach.Graphics.Viewer/Camera.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,20 @@ public void Update(EngineTime time) {
if (_Engine.Keyboard.IsKeyDown(Keys.Down))
_Pitch -= RotationSpeed * amount * 2;

if (_CurrentMouseState.LeftButton) {
if (_CurrentMouseState.LeftButton || _CurrentMouseState.RightButton) {
var mouseMove = _CurrentMouseState.AbsolutePosition - _PreviousMouseState.AbsolutePosition;
if (_CurrentMouseState.LeftButton) {
_Yaw -= mouseMove.X * MouseRotationSpeedYaw;
_Pitch -= mouseMove.Y * MouseRotationSpeedPitch;
}
if (_CurrentMouseState.RightButton)
moveVector += new Vector3(mouseMove.X / -16f, mouseMove.Y / 16f, 0);
if (_CurrentMouseState.LeftButton && _CurrentMouseState.RightButton)
moveVector += new Vector3(0, 0, -1);
var mouseMove = _CurrentMouseState.AbsolutePosition - _PreviousMouseState.AbsolutePosition;
_Yaw -= mouseMove.X * MouseRotationSpeedYaw;
_Pitch -= mouseMove.Y * MouseRotationSpeedPitch;
}

moveVector += new Vector3(0, 0, _CurrentMouseState.WheelDelta / -12f);

AddToCameraPosition(moveVector * amount);
}

Expand Down
2 changes: 2 additions & 0 deletions SaintCoinach.Graphics.Viewer/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public abstract class Engine : IDisposable {
private MaterialFactory _MaterialFactory;

private Size2 _ViewportSize;
private string _Subtitle;
#endregion

#region Properties
Expand All @@ -72,6 +73,7 @@ public abstract class Engine : IDisposable {
public MaterialFactory MaterialFactory { get { return _MaterialFactory; } }
public abstract IInputService InputService { get; }
public virtual Size2 ViewportSize { get { return _ViewportSize; } }
public virtual string Subtitle { get { return _Subtitle; } set { _Subtitle = value; } }
public abstract bool IsActive { get; }

public DepthStencilState DepthStencilState {
Expand Down
9 changes: 9 additions & 0 deletions SaintCoinach.Graphics.Viewer/FormEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ public override IInputService InputService {
get { return _InputService; }
}
public RenderForm Form { get { return _Form; } }
public override string Subtitle {
get {
return base.Subtitle;
}
set {
base.Subtitle = value;
_Form.Text = string.IsNullOrEmpty(value) ? _Title : _Title + " - " + value;
}
}
public override bool IsActive {
get { return Form.ContainsFocus; }
}
Expand Down
12 changes: 12 additions & 0 deletions SaintCoinach.Graphics.Viewer/FormInputService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class FormInputService : IInputService {
#region Fields
private List<Keys> _DownKeys = new List<Keys>();
private Point _MousePosition;
private int _MouseDelta;
private List<MouseButtons> _DownMouseButtons = new List<MouseButtons>();
#endregion

Expand All @@ -25,6 +26,7 @@ public FormInputService(Form form) {
form.KeyUp += Form_KeyUp;
form.MouseMove += Form_MouseMove;
form.MouseDown += Form_MouseDown;
form.MouseWheel += Form_MouseWheel;
form.MouseUp += Form_MouseUp;
form.LostFocus += Form_LostFocus;
}
Expand All @@ -43,6 +45,11 @@ public IEnumerable<MouseButtons> GetDownMouseButtons() {
buttons = _DownMouseButtons.ToArray();
return buttons;
}
public int GetNextWheelDelta() {
var v = _MouseDelta;
_MouseDelta = 0;
return v;
}
#endregion

#region Form events
Expand All @@ -67,6 +74,11 @@ void Form_MouseDown(object sender, MouseEventArgs e) {
void Form_MouseMove(object sender, MouseEventArgs e) {
_MousePosition = new Point(e.X, e.Y);
}

void Form_MouseWheel(object sender, MouseEventArgs e) {
_MouseDelta += e.Delta;
}

void Form_KeyUp(object sender, KeyEventArgs e) {
lock (_DownKeys)
_DownKeys.Remove(e.KeyCode);
Expand Down
1 change: 1 addition & 0 deletions SaintCoinach.Graphics.Viewer/IInputService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ public interface IInputService {
Point MousePosition { get; }
IEnumerable<Keys> GetDownKeys();
IEnumerable<MouseButtons> GetDownMouseButtons();
int GetNextWheelDelta();
}
}
4 changes: 4 additions & 0 deletions SaintCoinach.Graphics.Viewer/ImageRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public SharpDX.Point MousePosition {
yield break;
}

public int GetNextWheelDelta() {
return 0;
}

#endregion
}
#endregion
Expand Down
Loading