252 lines
7.4 KiB
C#
252 lines
7.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using JD.Application.View.Timeline;
|
|
using JD.Audio.Annotations;
|
|
using JD.Collections.Extensions;
|
|
using JD.Maths.Utils;
|
|
using JD.VideoPlayer.Project;
|
|
using TeaBox;
|
|
using JD.Serialization;
|
|
|
|
namespace JD.Timeline.View.ClipView.Widgets
|
|
{
|
|
public class DanceEditorClipWidget : ClipWidget
|
|
{
|
|
#region Variables
|
|
|
|
private List<ToolbarItem> _toolbarItems = new List<ToolbarItem>();
|
|
protected static readonly Color SelectionBorderColor = Color.FromArgb(255, 200, 0);
|
|
protected static readonly Color SelectionFillColor = Color.FromArgb(100, SelectionBorderColor);
|
|
protected static readonly Pen SelectionBorderPen = new Pen(SelectionBorderColor, 2);
|
|
protected static readonly Pen PlayingBorderPen = new Pen(Color.Firebrick, 2);
|
|
protected static readonly Color WarningFillColor = Color.FromArgb(255, 255, 0);
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
public DanceEditorClipWidget(Clip model)
|
|
: base(model)
|
|
{
|
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
public List<ToolbarItem> ToolbarItems
|
|
{
|
|
get { return _toolbarItems; }
|
|
set { _toolbarItems = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Whether the timeline cursors is currently over the clip.
|
|
/// </summary>
|
|
protected bool IsPlaying
|
|
{
|
|
get
|
|
{
|
|
var currentBeat = Timeline.BeatFromTimeUnit(Timeline.TimeCursor.Time).Value;
|
|
return currentBeat.IsBetween(Model.StartBeat, Model.StopBeat);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// Default painting for Dance Editor clips
|
|
/// </summary>
|
|
protected override void OnPaint(PaintEventArgs e)
|
|
{
|
|
SetupBounds();
|
|
|
|
var graphics = e.Graphics;
|
|
|
|
if (Model.CollisionsWithOther)
|
|
{
|
|
DrawClipWithWarning(graphics);
|
|
return;
|
|
}
|
|
|
|
FillBackground(graphics, Bounds, BackgroundColor);
|
|
DrawClipType(Model.Type, graphics);
|
|
|
|
if (Selected)
|
|
{
|
|
FillBackground(graphics, Bounds, SelectionFillColor);
|
|
DrawRectangle(graphics, Bounds, SelectionBorderPen);
|
|
}
|
|
else
|
|
{
|
|
DrawEdge(graphics, Bounds);
|
|
}
|
|
|
|
OnPaintChildControls(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Method used to draw clip when there is a warning
|
|
/// </summary>
|
|
protected void DrawClipWithWarning(Graphics graphics, int additionalOffsetX = 0, int additionalOffsetY = 0)
|
|
{
|
|
var image = Properties.Resources.Icon_16x16_warning;
|
|
var imageBounds = new Rectangle(Bounds.X + 2 + additionalOffsetX, Bounds.Top + 2 + additionalOffsetY, image.Width, image.Height); ;
|
|
|
|
int right = Bounds.Right;
|
|
if (imageBounds.Right > right)
|
|
{
|
|
imageBounds.Width -= imageBounds.Right - right;
|
|
}
|
|
if (image != null)
|
|
{
|
|
graphics.DrawImageUnscaledAndClipped(image, imageBounds);
|
|
}
|
|
|
|
DrawNotificationIcons(graphics);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Drawing of notification icons
|
|
/// </summary>
|
|
protected void DrawNotificationIcons(Graphics graphics)
|
|
{
|
|
foreach (var icon in ToolbarItems.Where(x => x.IsVisible()))
|
|
{
|
|
var bounds = GetBounds(icon);
|
|
if (bounds.Width > 0)
|
|
{
|
|
graphics.DrawImage(icon.Bitmap(), bounds);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the bounds of the notification icon. Used for drawing and mouse interaction.
|
|
/// </summary>
|
|
protected Rectangle GetBounds(ToolbarItem icon)
|
|
{
|
|
var icons = ToolbarItems.Where(x => x.IsVisible()).ToList();
|
|
while (icons.Count > 0 && icons.Sum(x => x.Width) > Bounds.Width)
|
|
{
|
|
var iconToRemove = icons.MaxElement(x => x.Priority);
|
|
if (iconToRemove != null)
|
|
{
|
|
icons.Remove(iconToRemove);
|
|
}
|
|
}
|
|
|
|
if (!icons.Contains(icon))
|
|
return new Rectangle(0,0,0,0);
|
|
|
|
int left = Bounds.Right;
|
|
foreach (var notificationIcon in icons)
|
|
{
|
|
left -= notificationIcon.Width;
|
|
if (notificationIcon == icon)
|
|
break;
|
|
}
|
|
return new Rectangle(left, Bounds.Top, icon.Width, icon.Height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handles click on notification icons
|
|
/// </summary>
|
|
public override void OnMouseClick(MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Left)
|
|
{
|
|
foreach (var notificationIcon in ToolbarItems)
|
|
{
|
|
if (GetBounds(notificationIcon).Contains(e.Location))
|
|
{
|
|
ToolbarItem icon = notificationIcon;
|
|
if (icon.OnClick != null)
|
|
{
|
|
TeaBox.ObjectModel.Application.Main.Dispatcher.DispatchAsync(() => icon.OnClick(),forceAsync: true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
base.OnMouseClick(e);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Video Preview
|
|
|
|
private float _lastPaintBeat;
|
|
|
|
protected void PaintPictogram(Graphics graphics)
|
|
{
|
|
var destBounds = Bounds;
|
|
destBounds.Height -= 10;
|
|
destBounds.Y += 5;
|
|
|
|
var currentBeat = Timeline.BeatFromTimeUnit(Timeline.TimeCursor.Time).Value;
|
|
var isPlaying = IsPlaying;
|
|
var wasPlaying = _lastPaintBeat.IsBetween(Model.StartBeat, Model.StopBeat);
|
|
|
|
// While playing, refresh the cursor when moving over the clip.
|
|
if (Math.Abs(_lastPaintBeat - currentBeat) > 0.001 && (isPlaying || wasPlaying))
|
|
{
|
|
Invalidate();
|
|
}
|
|
|
|
_lastPaintBeat = currentBeat;
|
|
|
|
var beatToPaint = GetBeatToPaint(currentBeat);
|
|
|
|
Model.Tape.VideoSpriteSheet().Paint(graphics, new BeatUnit(beatToPaint), destBounds);
|
|
}
|
|
|
|
protected virtual float GetBeatToPaint(float currentBeat)
|
|
{
|
|
if (currentBeat.IsBetween(Model.StartBeat, Model.StopBeat) && !IsDragging)
|
|
{
|
|
return currentBeat;
|
|
}
|
|
|
|
return Model.StartBeat;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
#region NotificationIcon
|
|
|
|
/// <summary>
|
|
/// Represents a notification icon on widget's top-right corner
|
|
/// </summary>
|
|
public class ToolbarItem
|
|
{
|
|
private Func<Bitmap> _bitmap;
|
|
|
|
public Func<Bitmap> Bitmap
|
|
{
|
|
get { return _bitmap; }
|
|
set
|
|
{
|
|
_bitmap = value;
|
|
Width = value().Width;
|
|
Height = value().Height;
|
|
}
|
|
}
|
|
|
|
public int Width { get; private set; }
|
|
public int Height { get; private set; }
|
|
|
|
public Func<bool> IsVisible = () => true;
|
|
public System.Action OnClick = () => { };
|
|
|
|
public uint Priority { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
}
|