mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-15 15:09:29 +00:00
a501f76162
* Add file header * Refator to file-scoped namespace * Least complex to most complext method ordering * Refactor: Group properties at top before constructor * Use the new UV properties from Texture2DRegion. This removes the dependency on the texture size in the calculations if the TextureRegion property is changed. * No longer need to cache normalized origin to preserve it * Use ArgumentNullException instead * Use ArgumentNullException.ThrowIfNull * Refactor: Use brackets for readability * Add xml documentation * Add check for disposed texture * Moved `Sprite` to `MonoGame.Extended.Graphics` * Moved extension methods for rendering sprite into `SpriteBatch.Extensions` * `ISpriteBatchDrawable` is not used by anything It was originally part of the ScreneGraph implementation in MonoGame.Extended which was replaced by the ECS system. It appears that this interface was forgotten to be removed and is not used for anything anymore. * Add `CreateSprite` methods * Add file header * Moved `SpriteSheetAnimationFrame` to `MonoGame.Extended.Graphics` * Move properties before constructor. * Changed `Duration` to `TimeSpan` type * Renamed `Index` to `FrameIndex` * Add `TextureRegion` property * Make property get only * Cleanup whitespace * Remove `SpriteSheetAnimationFrameJsonConverter` * Cleanup unused namespaces * Make file-scoped namespace * Added xml documentation * Added file header * marked constructor as internal. This will be created from a spritesheet itself * Move `SpriteSheetAnimationCycle` to `MonoGame.Extended.Graphcis` * File scoped namespace * Add file header * Reorganize: Move properties above constructor * Make `Frames` property a read-only span * Remove duration, this is being moved to the frame itself * Add `Name` property * Set looping, reversed, and ping pong properties in ctor * Make ctor internal This will be an object created by a spritesheet instane itself. * Cleanup: Whitespace * Add `FrameCount` property * Add `GetFrame` method and accompanying `this[int]` method. * Documentation: Added missing documentation. * WIP: Temporary commit for workstation change * WIP: Temporary commit for workstation change * WIP: Temporary commit for workstation change * WIP: Temporary commit for workstation change * Refactor: Animation Refactor Completed * Refactor: Sprite stuff finished * Remove tests that can't be run on GitHub CI Need to find alternative * Make optional name param the last param in Texture2DRegion ctors * Resolve merge conflicts
221 lines
6.1 KiB
C#
221 lines
6.1 KiB
C#
// Copyright (c) Craftwork Games. All rights reserved.
|
|
// Licensed under the MIT license.
|
|
// See LICENSE file in the project root for full license information.
|
|
|
|
using System;
|
|
using Microsoft.Xna.Framework;
|
|
using Xunit;
|
|
using MonoGame.Extended.Animations;
|
|
|
|
namespace MonoGame.Extended.Tests.Animations;
|
|
|
|
|
|
public class AnimationTests
|
|
{
|
|
private class TestAnimationFrame : IAnimationFrame
|
|
{
|
|
public int FrameIndex { get; set; }
|
|
public TimeSpan Duration { get; set; }
|
|
}
|
|
|
|
private class TestAnimationDefinition : IAnimationDefinition
|
|
{
|
|
private readonly IAnimationFrame[] _frames;
|
|
public string Name { get; set; }
|
|
public ReadOnlySpan<IAnimationFrame> Frames => _frames;
|
|
public int FrameCount { get; set; }
|
|
public bool IsLooping { get; set; }
|
|
public bool IsReversed { get; set; }
|
|
public bool IsPingPong { get; set; }
|
|
|
|
public TestAnimationDefinition(IAnimationFrame[] frames) => _frames = frames;
|
|
}
|
|
|
|
private readonly IAnimationDefinition _definition;
|
|
private readonly Animation _animation;
|
|
|
|
public AnimationTests()
|
|
{
|
|
var frames = new IAnimationFrame[]
|
|
{
|
|
new TestAnimationFrame { FrameIndex = 0, Duration = TimeSpan.FromSeconds(1) },
|
|
new TestAnimationFrame { FrameIndex = 1, Duration = TimeSpan.FromSeconds(1) }
|
|
};
|
|
_definition = new TestAnimationDefinition(frames)
|
|
{
|
|
FrameCount = frames.Length,
|
|
IsLooping = false,
|
|
IsReversed = false,
|
|
IsPingPong = false
|
|
};
|
|
_animation = new Animation(_definition);
|
|
}
|
|
|
|
[Fact]
|
|
public void Play_ShouldStartAnimation()
|
|
{
|
|
var result = _animation.Play();
|
|
|
|
Assert.True(result);
|
|
Assert.True(_animation.IsAnimating);
|
|
Assert.Equal(0, _animation.CurrentFrame);
|
|
}
|
|
|
|
[Fact]
|
|
public void Play_ShouldThrowException_ForInvalidFrame()
|
|
{
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => _animation.Play(-1));
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => _animation.Play(10));
|
|
}
|
|
|
|
[Fact]
|
|
public void Pause_ShouldPauseAnimation()
|
|
{
|
|
_animation.Play();
|
|
var result = _animation.Pause();
|
|
|
|
Assert.True(result);
|
|
Assert.True(_animation.IsPaused);
|
|
}
|
|
|
|
[Fact]
|
|
public void Pause_ShouldResetFrameDuration_WhenSpecified()
|
|
{
|
|
_animation.Play();
|
|
_animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(0.5)));
|
|
|
|
var result = _animation.Pause(true);
|
|
|
|
Assert.True(result);
|
|
Assert.Equal(_definition.Frames[0].Duration, _animation.CurrentFrameTimeRemaining);
|
|
}
|
|
|
|
[Fact]
|
|
public void UnPause_ShouldResumeAnimation()
|
|
{
|
|
_animation.Play();
|
|
_animation.Pause();
|
|
var result = _animation.Unpause();
|
|
|
|
Assert.True(result);
|
|
Assert.False(_animation.IsPaused);
|
|
}
|
|
|
|
[Fact]
|
|
public void UnPause_ShouldAdvanceFrame_WhenSpecified()
|
|
{
|
|
_animation.Play();
|
|
_animation.Pause();
|
|
var result = _animation.Unpause(true);
|
|
|
|
Assert.True(result);
|
|
Assert.Equal(1, _animation.CurrentFrame);
|
|
}
|
|
|
|
[Fact]
|
|
public void Stop_ShouldStopAnimation()
|
|
{
|
|
_animation.Play();
|
|
var result = _animation.Stop();
|
|
|
|
Assert.True(result);
|
|
Assert.False(_animation.IsAnimating);
|
|
}
|
|
|
|
[Fact]
|
|
public void Update_ShouldAdvanceFrame()
|
|
{
|
|
_animation.Play();
|
|
_animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1)));
|
|
|
|
Assert.Equal(1, _animation.CurrentFrame);
|
|
}
|
|
|
|
[Fact]
|
|
public void Update_ShouldTriggerAnimationEvents()
|
|
{
|
|
bool frameBeginTriggered = false;
|
|
bool frameEndTriggered = false;
|
|
bool animationLoopTriggered = false;
|
|
bool animationCompletedTriggered = false;
|
|
|
|
_animation.OnAnimationEvent += (anim, trigger) =>
|
|
{
|
|
switch (trigger)
|
|
{
|
|
case AnimationEventTrigger.FrameBegin:
|
|
frameBeginTriggered = true;
|
|
break;
|
|
case AnimationEventTrigger.FrameEnd:
|
|
frameEndTriggered = true;
|
|
break;
|
|
case AnimationEventTrigger.AnimationLoop:
|
|
animationLoopTriggered = true;
|
|
break;
|
|
case AnimationEventTrigger.AnimationCompleted:
|
|
animationCompletedTriggered = true;
|
|
break;
|
|
}
|
|
};
|
|
|
|
_animation.Play();
|
|
_animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1)));
|
|
|
|
Assert.True(frameBeginTriggered);
|
|
Assert.True(frameEndTriggered);
|
|
|
|
_animation.IsLooping = true;
|
|
_animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(1.1)));
|
|
Assert.True(animationLoopTriggered);
|
|
|
|
_animation.IsLooping = false;
|
|
_animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(2)));
|
|
Assert.True(animationCompletedTriggered);
|
|
}
|
|
|
|
[Fact]
|
|
public void Update_ShouldLoopAnimation()
|
|
{
|
|
_animation.IsLooping = true;
|
|
_animation.Play();
|
|
_animation.Update(new GameTime(TimeSpan.Zero, TimeSpan.FromSeconds(2.1)));
|
|
|
|
Assert.Equal(0, _animation.CurrentFrame);
|
|
}
|
|
|
|
[Fact]
|
|
public void Reset_ShouldResetAnimation()
|
|
{
|
|
_animation.Play();
|
|
_animation.Reset();
|
|
|
|
Assert.False(_animation.IsAnimating);
|
|
Assert.True(_animation.IsPaused);
|
|
Assert.Equal(0, _animation.CurrentFrame);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetFrame_ShouldChangeCurrentFrame()
|
|
{
|
|
_animation.SetFrame(1);
|
|
|
|
Assert.Equal(1, _animation.CurrentFrame);
|
|
Assert.Equal(_definition.Frames[1].Duration, _animation.CurrentFrameTimeRemaining);
|
|
}
|
|
|
|
[Fact]
|
|
public void SetFrame_ShouldThrowException_ForInvalidFrame()
|
|
{
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => _animation.SetFrame(-1));
|
|
Assert.Throws<ArgumentOutOfRangeException>(() => _animation.SetFrame(10));
|
|
}
|
|
|
|
[Fact]
|
|
public void Dispose_ShouldDisposeAnimation()
|
|
{
|
|
_animation.Dispose();
|
|
|
|
Assert.True(_animation.IsDisposed);
|
|
}
|
|
}
|