LADXHD/Editor/AnimationScreen.cs
2023-12-14 17:21:22 -05:00

735 lines
39 KiB
C#

using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using ProjectZ.Base;
using ProjectZ.Base.UI;
using ProjectZ.InGame.GameObjects.Base;
using ProjectZ.InGame.SaveLoad;
using ProjectZ.InGame.Things;
#if WINDOWS
using System.Windows.Forms;
#endif
namespace ProjectZ.Editor
{
internal class AnimationScreen : InGame.Screens.Screen
{
private readonly EditorCamera _camera = new EditorCamera();
private Animator _animator = new Animator();
private Animator _overlayAnimator;
private Texture2D _sprAnimator;
private Point _currentPosition, _selectionStart, _selectionEnd;
private UiNumberInput _animationInput, _frameInput, _numberInputX, _numberInputY, _numberInputWidth, _numberInputHeight;
private UiNumberInput _niOffsetX, _niOffsetY, _niAnOffsetX, _niAnOffsetY, _fpsInput, _loopCountInput;
private UiTextInput _animationName, _nextAnimationName;
private UiLabel _animationUiLabel, _frameUiLabel;
private UiCheckBox _checkBoxLoop, _cbFrameMirroredV, _cbFrameMirroredH;
private string _sprPath;
private string _lastFileName;
private const float MinScale = 1;
private const float MaxScale = 10;
private const int LeftBarWidth = 200;
private const int RightBarWidth = 300;
private const int TileSize = 2;
private int _selectedAnimation, _selectedFrame;
private bool _selecting;
private bool _collisionRectangleMode;
private bool _isPlaying;
private bool _showAllSelections;
public AnimationScreen(string screenId) : base(screenId) { }
public override void Load(ContentManager content)
{
var buttonDist = 5;
var buttonWidth = LeftBarWidth - buttonDist * 2;
var buttonWidthHalf = (LeftBarWidth - buttonDist * 3) / 2;
var buttonHeight = 30;
var labelHeight = Resources.EditorFontHeight;
var buttonQWidth = LeftBarWidth - 15 - buttonHeight;
var posY = Values.ToolBarHeight + buttonDist;
var screenId = Values.EditorUiAnimation;
Game1.EditorUi.AddElement(new UiRectangle(new Rectangle(0, 0, 0, 0), "leftBackground", screenId, Values.ColorBackgroundLight, Color.White,
ui => { ui.Rectangle = new Rectangle(0, Values.ToolBarHeight, LeftBarWidth, Game1.WindowHeight - Values.ToolBarHeight); }));
Game1.EditorUi.AddElement(new UiRectangle(new Rectangle(0, 0, 0, 0), "rightBackground", screenId, Values.ColorBackgroundLight, Color.White,
ui => { ui.Rectangle = new Rectangle(Game1.WindowWidth - RightBarWidth, Values.ToolBarHeight, RightBarWidth, Game1.WindowHeight - Values.ToolBarHeight - RightBarWidth); }));
// animation background
Game1.EditorUi.AddElement(new UiRectangle(new Rectangle(0, 0, 0, 0), "rightAnimationBackground", screenId, Color.White * 0.5f, Color.White,
ui => { ui.Rectangle = new Rectangle(Game1.WindowWidth - RightBarWidth, Game1.WindowHeight - RightBarWidth, RightBarWidth, RightBarWidth); }));
// right toolbar
Game1.EditorUi.AddElement(new UiButton(Rectangle.Empty, Resources.EditorFont, "load overlay", "bt1", screenId,
ui => { ui.Rectangle = new Rectangle(Game1.WindowWidth - RightBarWidth + 5, Values.ToolBarHeight + buttonDist, buttonWidth, buttonHeight); },
ui => { LoadOverlayAnimation(); }));
Game1.EditorUi.AddElement(new UiButton(Rectangle.Empty, Resources.EditorFont, "play/pause", "bt1", screenId,
ui => { ui.Rectangle = new Rectangle(Game1.WindowWidth - RightBarWidth + 5, Values.ToolBarHeight + buttonDist * 2 + buttonHeight, buttonWidth, buttonHeight); },
ui => { _isPlaying = !_isPlaying; }));
posY = Values.ToolBarHeight + buttonDist;
// load button
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY, buttonWidth, buttonHeight), Resources.EditorFont,
"load", "bt1", screenId, null, ui => { LoadAnimation(); }));
// save button
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight), Resources.EditorFont,
"save as...", "bt1", screenId, null, ui => { SaveAnimationDialog(); }));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight), Resources.EditorFont,
"save...", "bt1", screenId, null, ui => { SaveAnimation(); }));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight), Resources.EditorFont,
"updated animations", "bt1", screenId, null, ui => { UpdateAnimations(); }));
// load image
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight), Resources.EditorFont,
"load image", "bt1", screenId, null, ui => { LoadImage(); }));
// clear animation
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight), Resources.EditorFont,
"clear animator", "bt1", screenId, null, ui => { CreateAnimator(); }));
Game1.EditorUi.AddElement(new UiCheckBox(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight),
Resources.EditorFont, "show all selections", "showAllSelections", screenId, false, null,
ui => { _showAllSelections = ((UiCheckBox)ui).CurrentState; }));
Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist * 3, buttonWidth, labelHeight),
Resources.EditorFont, "Animation", "frameHeader", screenId, null));
_animationUiLabel = new UiLabel(new Rectangle(buttonDist, posY += labelHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, "animation", "flable", screenId, ui => { ui.Label = "[" + (_selectedAnimation + 1) + "/" + _animator.Animations.Count + "]"; });
Game1.EditorUi.AddElement(_animationUiLabel);
_animationInput = new UiNumberInput(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 1, 1, 1, 1, "numberX", screenId,
ui => { ((UiNumberInput)ui).MaxValue = _animator.Animations.Count; },
ui => { ChangeAnimation((int)((UiNumberInput)ui).Value - 1); });
Game1.EditorUi.AddElement(_animationInput);
// add animation
Game1.EditorUi.AddElement(new UiButton(new Rectangle(buttonDist, posY += buttonHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, "add", "bt1", screenId, null, ui => { AddAnimation(); }));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, "remove", "bt1", screenId, null, ui => { RemoveAnimation(); }));
// animation name
var animationNameLabel = new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist, buttonWidth, labelHeight),
Resources.EditorFont, "name", "lableX", screenId, null);
Game1.EditorUi.AddElement(animationNameLabel);
_animationName = new UiTextInput(new Rectangle(buttonDist, posY += labelHeight, buttonWidth, buttonHeight),
Resources.EditorFontMonoSpace, 20, "animationName", screenId, null, ui => { _animator.Animations[_selectedAnimation].Id = ((UiTextInput)ui).StrValue; });
Game1.EditorUi.AddElement(_animationName);
// next animation
var nextAnimationLabel = new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist, buttonWidth, labelHeight),
Resources.EditorFont, "next animation", "lableX", screenId, null);
Game1.EditorUi.AddElement(nextAnimationLabel);
_nextAnimationName = new UiTextInput(new Rectangle(buttonDist, posY += labelHeight, buttonWidth, buttonHeight),
Resources.EditorFontMonoSpace, 20, "nextAnimationName", screenId, null,
ui => { _animator.Animations[_selectedAnimation].NextAnimation = ((UiTextInput)ui).StrValue; });
Game1.EditorUi.AddElement(_nextAnimationName);
// collision
Game1.EditorUi.AddElement(new UiButton(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight), Resources.EditorFont,
"collision mode", "bt1", screenId, ui => { ((UiButton)ui).Marked = _collisionRectangleMode; },
ui => { _collisionRectangleMode = !_collisionRectangleMode; }));
//// loop checkbox
//_checkBoxLoop = new CheckBox(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight), Resources.EditorFont,
// "loop", "cbloop", screenId, false, ui => { ((CheckBox)ui).CurrentState = _animator.CurrentAnimation.Looping; },
// ui => { _animator.CurrentAnimation.Looping = ((CheckBox)ui).CurrentState; });
//Game1.EditorUi.AddElement(_checkBoxLoop);
Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, "Loops", "flable", screenId, null));
_loopCountInput = new UiNumberInput(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 1, -1, 999, 1, "loopCount", screenId, null,
ui => _animator.Animations[_selectedAnimation].LoopCount = (int)((UiNumberInput)ui).Value);
Game1.EditorUi.AddElement(_loopCountInput);
Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist * 3, buttonWidth, labelHeight),
Resources.EditorFont, "Frame", "frameHeader", screenId, null));
// frame information
Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += labelHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, "frame", "flable", screenId,
ui => { ui.Label = "frame [" + (_selectedFrame + 1) + "/" + _animator.Animations[_selectedAnimation].Frames.Length + "]"; }));
_frameInput = new UiNumberInput(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 1, 1, 1, 1, "numberX", screenId,
ui => { ((UiNumberInput)ui).MaxValue = _animator.Animations[_selectedAnimation].Frames.Length; },
ui => { ChangeFrame((int)((UiNumberInput)ui).Value - 1); });
Game1.EditorUi.AddElement(_frameInput);
// add remove frame
Game1.EditorUi.AddElement(new UiButton(new Rectangle(buttonDist, posY += buttonHeight + buttonDist, buttonWidthHalf, buttonHeight), Resources.EditorFont,
"add", "addFrame", screenId, null, ui => { AddFrame(); }));
Game1.EditorUi.AddElement(new UiButton(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight), Resources.EditorFont,
"delete", "deleteFrame", screenId, null, ui => { DeleteFrame(); }));
_cbFrameMirroredV = (UiCheckBox)Game1.EditorUi.AddElement(new UiCheckBox(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight),
Resources.EditorFont, "mirrored V", "cbmirrored", screenId, false, null,
ui => { _animator.Animations[_selectedAnimation].Frames[_selectedFrame].MirroredV = ((UiCheckBox)ui).CurrentState; }));
_cbFrameMirroredH = (UiCheckBox)Game1.EditorUi.AddElement(new UiCheckBox(new Rectangle(5, posY += buttonHeight + buttonDist, buttonWidth, buttonHeight),
Resources.EditorFont, "mirrored H", "cbmirrored", screenId, false, null,
ui => { _animator.Animations[_selectedAnimation].Frames[_selectedFrame].MirroredH = ((UiCheckBox)ui).CurrentState; }));
Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist * 2, buttonWidth, labelHeight),
Resources.EditorFont, "fps", "flable", screenId, null));
_fpsInput = new UiNumberInput(new Rectangle(buttonDist, posY += labelHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 1, 1, 1000, 1, "numberX", screenId, null,
ui => { _animator.SetFrameFps(_selectedAnimation, _selectedFrame, (int)((UiNumberInput)ui).Value); });
Game1.EditorUi.AddElement(_fpsInput);
Game1.EditorUi.AddElement(new UiButton(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, "to all", "toall", screenId, null,
ui => { _animator.SetAnimationFps(_selectedAnimation, (int)_fpsInput.Value); }));
// animation offset
Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist,
buttonWidth, labelHeight), Resources.EditorFont, "animation offset", "lableX", screenId, null));
//Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += Resources.EditorFontHeight + buttonDist,
// buttonWidthHalf, labelHeight), Resources.EditorFont, "x", "lableX", screenId, null));
//Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY,
// buttonWidthHalf, labelHeight), Resources.EditorFont, "y", "lableX", screenId, null));
_niAnOffsetX = new UiNumberInput(new Rectangle(buttonDist, posY += labelHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 0, -100, 100, 1, "animationWidth", screenId, null,
ui => { _animator.Animations[_selectedAnimation].Offset.X = (int)((UiNumberInput)ui).Value; });
_niAnOffsetY = new UiNumberInput(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 0, -100, 100, 1, "animationWidth", screenId, null,
ui => { _animator.Animations[_selectedAnimation].Offset.Y = (int)((UiNumberInput)ui).Value; });
Game1.EditorUi.AddElement(_niAnOffsetX);
Game1.EditorUi.AddElement(_niAnOffsetY);
// rectangle
// labels
Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist,
buttonWidth, labelHeight), Resources.EditorFont, "rectangle", "rectangle", screenId, null));
//Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY,
// buttonWidthHalf, labelHeight), Resources.EditorFont, "y", "lableX", screenId, null));
// number picker
_numberInputX = new UiNumberInput(new Rectangle(buttonDist, posY += labelHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 0, 0, 1000, 1, "numberX", screenId, null,
ui =>
{
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.X = (int)((UiNumberInput)ui).Value;
UpdateCurrentFrame();
});
_numberInputY = new UiNumberInput(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 0, 0, 1000, 1, "numberY", screenId, null,
ui =>
{
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.Y = (int)((UiNumberInput)ui).Value;
UpdateCurrentFrame();
});
Game1.EditorUi.AddElement(_numberInputX);
Game1.EditorUi.AddElement(_numberInputY);
//// labels
//Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist,
// buttonWidthHalf, labelHeight), Resources.EditorFont, "width", "lableX", screenId, null));
//Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY,
// buttonWidthHalf, labelHeight), Resources.EditorFont, "height", "lableX", screenId, null));
// number picker
_numberInputWidth = new UiNumberInput(new Rectangle(buttonDist, posY += buttonHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 0, 0, 1000, 1, "numberWidth", screenId, null, ui =>
{
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.Width = (int)((UiNumberInput)ui).Value;
UpdateCurrentFrame();
});
_numberInputHeight = new UiNumberInput(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 0, 0, 1000, 1, "numberHeight", screenId, null, ui =>
{
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.Height = (int)((UiNumberInput)ui).Value;
UpdateCurrentFrame();
});
Game1.EditorUi.AddElement(_numberInputWidth);
Game1.EditorUi.AddElement(_numberInputHeight);
// offset
// labels
Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight + buttonDist,
buttonWidth, labelHeight), Resources.EditorFont, "frame offset", "lableX", screenId, null));
//Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist, posY += buttonHeight / 2,
// buttonWidthHalf, labelHeight), Resources.EditorFont, "x", "lableX", screenId, null));
//Game1.EditorUi.AddElement(new UiLabel(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY,
// buttonWidthHalf, labelHeight), Resources.EditorFont, "y", "lableX", screenId, null));
// number picker
_niOffsetX = new UiNumberInput(new Rectangle(buttonDist, posY += labelHeight + buttonDist, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 0, -100, 100, 1, "numberX", screenId, null, ui =>
{
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].Offset.X = (int)((UiNumberInput)ui).Value;
UpdateCurrentFrame();
});
_niOffsetY = new UiNumberInput(new Rectangle(buttonDist * 2 + buttonWidthHalf, posY, buttonWidthHalf, buttonHeight),
Resources.EditorFont, 0, -100, 100, 1, "numberY", screenId, null, ui =>
{
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].Offset.Y = (int)((UiNumberInput)ui).Value;
UpdateCurrentFrame();
});
Game1.EditorUi.AddElement(_niOffsetX);
Game1.EditorUi.AddElement(_niOffsetY);
// create empty animation
CreateAnimator();
}
public override void Update(GameTime gameTime)
{
Game1.EditorUi.CurrentScreen = Values.EditorUiAnimation;
if (_sprAnimator == null)
return;
var mousePosition = InputHandler.MousePosition();
if (_isPlaying && !_animator.IsPlaying)
{
_animator.Play(_selectedAnimation);
}
if (_isPlaying)
_animator.Update();
else
{
_animator.SetFrame(_selectedFrame);
}
// update tileset scale
if (InputHandler.MouseIntersect(new Rectangle(LeftBarWidth, Values.ToolBarHeight,
Game1.WindowWidth - LeftBarWidth - RightBarWidth, Game1.WindowHeight - Values.ToolBarHeight)))
{
_currentPosition = new Point(
(int)((InputHandler.MousePosition().X - _camera.Location.X) / _camera.Scale),
(int)((InputHandler.MousePosition().Y - _camera.Location.Y) / _camera.Scale));
if (InputHandler.MouseLeftStart())
{
_selecting = true;
_selectionStart = _currentPosition;
}
if (InputHandler.MouseLeftDown() && _selecting)
{
_selectionEnd = _currentPosition;
var selectionStart1 = new Point(Math.Min(_selectionStart.X, _selectionEnd.X), Math.Min(_selectionStart.Y, _selectionEnd.Y));
var selectionEnd1 = new Point(Math.Max(_selectionStart.X, _selectionEnd.X) + 1, Math.Max(_selectionStart.Y, _selectionEnd.Y) + 1);
if (_collisionRectangleMode)
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].CollisionRectangle =
new Rectangle(
selectionStart1.X - _animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.X,
selectionStart1.Y - _animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.Y,
selectionEnd1.X - selectionStart1.X, selectionEnd1.Y - selectionStart1.Y);
else
{
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle =
new Rectangle(selectionStart1.X, selectionStart1.Y, selectionEnd1.X - selectionStart1.X,
selectionEnd1.Y - selectionStart1.Y);
UpdateCurrentFrame();
}
UpdateInputUi();
}
if (InputHandler.MouseLeftReleased())
{
_selecting = false;
}
if (InputHandler.MouseRightPressed())
{
if (_collisionRectangleMode)
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].CollisionRectangle = Rectangle.Empty;
}
if (InputHandler.MouseWheelUp())
_camera.Zoom(1, mousePosition);
if (InputHandler.MouseWheelDown())
_camera.Zoom(-1, mousePosition);
}
if (!InputHandler.MouseMiddleStart() && InputHandler.MouseMiddleDown())
_camera.Location += mousePosition - InputHandler.LastMousePosition();
}
public override void Draw(SpriteBatch spriteBatch)
{
if (_sprAnimator == null)
return;
spriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.PointWrap, null, null, null, _camera.TransformMatrix);
// draw the tiled background
spriteBatch.Draw(Resources.SprTiledBlock, new Rectangle(0, 0, _sprAnimator.Width, _sprAnimator.Height),
new Rectangle(0, 0,
(int)(_sprAnimator.Width / (float)TileSize * 2),
(int)(_sprAnimator.Height / (float)TileSize * 2)), Color.White);
// draw the sprite
spriteBatch.Draw(_sprAnimator, new Rectangle(0, 0, _sprAnimator.Width, _sprAnimator.Height), Color.White);
// draw current position of the mouse
spriteBatch.Draw(Resources.SprWhite, new Rectangle(_currentPosition.X, _currentPosition.Y, 1, 1), Color.Red * 0.5f);
// show all source rectangles of all animations
if (_showAllSelections)
{
foreach (var animation in _animator.Animations)
for (var i = 0; i < animation.Frames.Length; i++)
spriteBatch.Draw(Resources.SprWhite, animation.Frames[i].SourceRectangle, Color.HotPink * 0.25f);
}
// draw the selection
for (var i = 0; i < _animator.Animations[_selectedAnimation].Frames.Length; i++)
{
spriteBatch.Draw(Resources.SprWhite, _animator.Animations[_selectedAnimation].Frames[i].SourceRectangle, _selectedFrame == i ? Color.Red * 0.5f : Color.Red * 0.25f);
}
spriteBatch.Draw(Resources.SprWhite, new Rectangle(
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].CollisionRectangle.X +
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.X,
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].CollisionRectangle.Y +
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.Y,
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].CollisionRectangle.Width,
_animator.Animations[_selectedAnimation].Frames[_selectedFrame].CollisionRectangle.Height), Color.Green * 0.5f);
spriteBatch.End();
}
public override void DrawTop(SpriteBatch spriteBatch)
{
if (_sprAnimator == null)
return;
float drawScale = 2;
if (_animator.CurrentAnimation.AnimationWidth > 0 && _animator.CurrentAnimation.AnimationHeight > 0)
{
if (_animator.CurrentAnimation.AnimationWidth > _animator.CurrentAnimation.AnimationHeight)
drawScale = (int)(RightBarWidth / (float)(_animator.CurrentAnimation.AnimationWidth + 2));
else
drawScale = (int)(RightBarWidth / (float)(_animator.CurrentAnimation.AnimationHeight + 2));
}
var drawOffsetX = Game1.WindowWidth - RightBarWidth / 2 -
(int)((_animator.CurrentAnimation.AnimationWidth + 2) * drawScale) / 2;
var drawOffsetY = Game1.WindowHeight - RightBarWidth / 2 -
(int)((_animator.CurrentAnimation.AnimationHeight + 2) * drawScale) / 2;
var drawPositionX = drawOffsetX + (int)drawScale +
(int)((_animator.CurrentFrame.Offset.X - _animator.CurrentAnimation.AnimationLeft) * drawScale);
var drawPositionY = drawOffsetY + (int)drawScale +
(int)((_animator.CurrentFrame.Offset.Y - _animator.CurrentAnimation.AnimationTop) * drawScale);
// draw the tiled background
spriteBatch.Draw(Resources.SprTiledBlock, new Rectangle(
drawOffsetX, drawOffsetY,
(int)((_animator.CurrentAnimation.AnimationWidth + 2) * drawScale),
(int)((_animator.CurrentAnimation.AnimationHeight + 2) * drawScale)),
new Rectangle(0, 0,
(int)((_animator.CurrentAnimation.AnimationWidth + 2) / (float)TileSize * 2),
(int)((_animator.CurrentAnimation.AnimationHeight + 2) / (float)TileSize * 2)), Color.White * 0.5f);
DrawOverlayAnimation(spriteBatch, drawOffsetX, drawOffsetY, drawScale);
// draw the current animation sprite
spriteBatch.Draw(_sprAnimator, new Rectangle(
drawPositionX, drawPositionY, (int)(drawScale * _animator.FrameWidth), (int)(drawScale * _animator.FrameHeight)),
_animator.CurrentFrame.SourceRectangle, Color.White, 0, Vector2.Zero,
(_animator.CurrentFrame.MirroredV ? SpriteEffects.FlipVertically : SpriteEffects.None) |
(_animator.CurrentFrame.MirroredH ? SpriteEffects.FlipHorizontally : SpriteEffects.None), 0);
// draw the origin xy axis
var originPosition = new Vector2(
drawPositionX + (-_animator.CurrentAnimation.Offset.X - _animator.CurrentFrame.Offset.X) * drawScale,
drawPositionY + (-_animator.CurrentAnimation.Offset.Y - _animator.CurrentFrame.Offset.Y) * drawScale);
spriteBatch.Draw(Resources.SprWhite, new Vector2(originPosition.X - 1, originPosition.Y - 10), new Rectangle(0, 0, 2, 20), Color.Green);
spriteBatch.Draw(Resources.SprWhite, new Vector2(originPosition.X - 10, originPosition.Y - 1), new Rectangle(0, 0, 20, 2), Color.Red);
}
private void DrawOverlayAnimation(SpriteBatch spriteBatch, int drawOffsetX, int drawOffsetY, float drawScale)
{
if (_overlayAnimator != null && _overlayAnimator.GetAnimationIndex(_animator.CurrentAnimation.Id) >= 0)
{
_overlayAnimator.Play(_animator.CurrentAnimation.Id);
// find the matching frame
var frameIndex = GetOverlayFrame();
_overlayAnimator.SetFrame(frameIndex);
var drawPositionX = drawOffsetX + (int)drawScale +
(int)((_overlayAnimator.CurrentFrame.Offset.X -
_animator.CurrentAnimation.AnimationLeft +
_overlayAnimator.CurrentAnimation.Offset.X -
_animator.CurrentAnimation.Offset.X) * drawScale);
var drawPositionY = drawOffsetY + (int)drawScale +
(int)((_overlayAnimator.CurrentFrame.Offset.Y -
_animator.CurrentAnimation.AnimationTop +
_overlayAnimator.CurrentAnimation.Offset.Y -
_animator.CurrentAnimation.Offset.Y) * drawScale);
spriteBatch.Draw(_overlayAnimator.SprTexture, new Rectangle(
drawPositionX, drawPositionY, (int)(drawScale * _overlayAnimator.FrameWidth),
(int)(drawScale * _overlayAnimator.FrameHeight)),
_overlayAnimator.CurrentFrame.SourceRectangle, Color.White, 0, Vector2.Zero,
(_overlayAnimator.CurrentFrame.MirroredV ? SpriteEffects.FlipVertically : SpriteEffects.None) |
(_overlayAnimator.CurrentFrame.MirroredH ? SpriteEffects.FlipHorizontally : SpriteEffects.None), 0);
}
}
private int GetOverlayFrame()
{
if (_overlayAnimator.CurrentAnimation.Frames.Length <= 0)
return 0;
// time to reach the selected frame
var frameTime = 0;
for (var i = 0; i < _animator.CurrentFrameIndex; i++)
frameTime += _animator.CurrentAnimation.Frames[i].FrameTime;
var index = 0;
while (frameTime >= 0)
{
frameTime -= _overlayAnimator.CurrentAnimation.Frames[index].FrameTime;
if (frameTime < 0)
return index;
if (_overlayAnimator.CurrentAnimation.Frames.Length > index + 1)
index++;
// loop animation
else
index = 0;
}
return 0;
}
private void UpdateCurrentFrame()
{
// update the size of the animation
_animator.RecalculateAnimationSize(_selectedAnimation);
}
public void CreateAnimator()
{
// create empty animator with one animation and frame
_animator = new Animator();
AddAnimation();
_animator.SpritePath = _sprPath;
}
public void AddAnimation()
{
var newAnimation = new Animation("a" + _animator.Animations.Count) { NextAnimation = "" };
_animator.AddAnimation(newAnimation);
_animator.AddFrame(_animator.Animations.Count - 1, 0, new Frame() { FrameTimeFps = 5 });
ChangeAnimation(_animator.Animations.Count - 1);
}
private void RemoveAnimation()
{
if (_animator.Animations.Count <= 1)
return;
_animator.Animations.Remove(_animator.Animations[_selectedAnimation]);
ChangeAnimation(_selectedAnimation % _animator.Animations.Count);
}
public void AddFrame()
{
var newFrame = new Frame()
{
SourceRectangle = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle,
Offset = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].Offset,
FrameTimeFps = 5
};
_animator.AddFrame(_selectedAnimation, _selectedFrame + 1, newFrame);
_selectedFrame++;
UpdateInputUi();
}
public void DeleteFrame()
{
// cant delete the last frame
if (_animator.Animations[_selectedAnimation].Frames.Length <= 1)
return;
_animator.Stop();
// create new frame array without the selected frame
var newFrames = new Frame[_animator.Animations[_selectedAnimation].Frames.Length - 1];
var newIndex = 0;
for (var i = 0; i < _animator.Animations[_selectedAnimation].Frames.Length; i++)
if (i != _selectedFrame)
{
newFrames[newIndex] = _animator.Animations[_selectedAnimation].Frames[i];
newIndex++;
}
_animator.Animations[_selectedAnimation].Frames = newFrames;
if (_selectedFrame > 0)
_selectedFrame--;
UpdateInputUi();
}
public void ChangeAnimation(int nextAnimation)
{
_selectedAnimation = nextAnimation;
_selectedFrame = 0;
_animator.Play(_selectedAnimation);
UpdateInputUi();
}
public void ChangeFrame(int nextFrame)
{
_selectedFrame = nextFrame;
UpdateInputUi();
}
public void UpdateInputUi()
{
_animationInput.Value = _selectedAnimation + 1;
_frameInput.Value = _selectedFrame + 1;
_loopCountInput.Value = _animator.Animations[_selectedAnimation].LoopCount;
_fpsInput.Value = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].FrameTimeFps;
_animationName.StrValue = _animator.Animations[_selectedAnimation].Id;
_nextAnimationName.StrValue = _animator.Animations[_selectedAnimation].NextAnimation;
_niAnOffsetX.Value = _animator.CurrentAnimation.Offset.X;
_niAnOffsetY.Value = _animator.CurrentAnimation.Offset.Y;
_numberInputX.Value = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.X;
_numberInputY.Value = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.Y;
_numberInputWidth.Value = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.Width;
_numberInputHeight.Value = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].SourceRectangle.Height;
_niOffsetX.Value = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].Offset.X;
_niOffsetY.Value = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].Offset.Y;
_cbFrameMirroredV.CurrentState = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].MirroredV;
_cbFrameMirroredH.CurrentState = _animator.Animations[_selectedAnimation].Frames[_selectedFrame].MirroredH;
}
public void SaveAnimationDialog()
{
#if WINDOWS
var saveFileDialog = new SaveFileDialog()
{
RestoreDirectory = true,
Filter = "animator files (*.ani)|*.ani",
};
if (_lastFileName != null)
{
saveFileDialog.FileName = Path.GetFileName(_lastFileName);
saveFileDialog.InitialDirectory = Path.GetFullPath(Path.GetDirectoryName(_lastFileName));
}
if (saveFileDialog.ShowDialog() == DialogResult.OK)
AnimatorSaveLoad.SaveAnimator(saveFileDialog.FileName, _animator);
#endif
}
public void SaveAnimation()
{
AnimatorSaveLoad.SaveAnimator(_lastFileName, _animator);
}
public void LoadAnimation()
{
#if WINDOWS
var openFileDialog = new OpenFileDialog()
{
Filter = "animator files (*.ani)|*.ani"
};
if (openFileDialog.ShowDialog() != DialogResult.OK)
return;
EditorLoadAnimation(openFileDialog.FileName);
#endif
}
public void EditorLoadAnimation(string filePath)
{
_selectedAnimation = 0;
_selectedFrame = 0;
_lastFileName = filePath;
_animator = AnimatorSaveLoad.LoadAnimatorFile(filePath);
_sprAnimator = _animator.SprTexture;
UpdateInputUi();
}
private void LoadOverlayAnimation()
{
#if WINDOWS
var openFileDialog = new OpenFileDialog()
{
Filter = "animator files (*.ani)|*.ani"
};
if (openFileDialog.ShowDialog() != DialogResult.OK) return;
_overlayAnimator = AnimatorSaveLoad.LoadAnimatorFile(openFileDialog.FileName);
#endif
}
public void UpdateAnimations()
{
#if WINDOWS
var openFileDialog = new OpenFileDialog()
{
Filter = "animator files (*.ani)|*.ani",
Multiselect = true
};
if (openFileDialog.ShowDialog() != DialogResult.OK) return;
foreach (var fileName in openFileDialog.FileNames)
{
_animator = AnimatorSaveLoad.LoadAnimatorFile(fileName);
AnimatorSaveLoad.SaveAnimator(fileName, _animator);
}
#endif
}
public void LoadImage()
{
#if WINDOWS
var openFileDialog = new OpenFileDialog()
{
Filter = "png files (*.png)|*.png"
};
if (openFileDialog.ShowDialog() != DialogResult.OK) return;
try
{
using (var stream = File.OpenRead(openFileDialog.FileName))
{
_sprAnimator = Texture2D.FromStream(Game1.Graphics.GraphicsDevice, stream);
_sprPath = Path.GetFileName(openFileDialog.FileName);
_animator.SpritePath = _sprPath;
}
}
catch { }
#endif
}
}
}