324 lines
13 KiB
C#
324 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace BAKKA_Editor
|
|
{
|
|
public partial class LinearViewForm : Form
|
|
{
|
|
// Chart
|
|
Chart _chart;
|
|
internal Chart Chart
|
|
{
|
|
get => _chart;
|
|
set
|
|
{
|
|
_chart = value;
|
|
linearPanel.Invalidate();
|
|
}
|
|
}
|
|
|
|
// Graphics
|
|
BufferedGraphicsContext gfxContext;
|
|
BufferedGraphics bufGraphics;
|
|
LinearView linearView;
|
|
|
|
public LinearViewForm()
|
|
{
|
|
InitializeComponent();
|
|
|
|
// Form events
|
|
linearPanel.MouseWheel += LinearPanel_MouseWheel;
|
|
|
|
// Setup graphics
|
|
gfxContext = BufferedGraphicsManager.Current;
|
|
SetBufferedGraphicsContext();
|
|
linearView = new LinearView(linearPanel.Size);
|
|
|
|
// Force double buffering on linearPanel
|
|
Type controlType = linearPanel.GetType();
|
|
PropertyInfo pi = controlType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
pi.SetValue(linearPanel, true);
|
|
}
|
|
|
|
private void SetBufferedGraphicsContext()
|
|
{
|
|
if (linearPanel.Width == 0 || linearPanel.Height == 0)
|
|
return;
|
|
|
|
gfxContext.MaximumBuffer = new Size(linearPanel.Width + 1, linearPanel.Height + 1);
|
|
bufGraphics = gfxContext.Allocate(linearPanel.CreateGraphics(),
|
|
new Rectangle(0, 0, linearPanel.Width, linearPanel.Height));
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
linearPanel.Invalidate(true);
|
|
}
|
|
|
|
private void linearPanel_Paint(object sender, PaintEventArgs e)
|
|
{
|
|
Rectangle panelRect = new Rectangle(0, 0, linearPanel.Width, linearPanel.Height);
|
|
|
|
// Set drawing mode
|
|
bufGraphics.Graphics.SmoothingMode = SmoothingMode.HighSpeed;
|
|
|
|
// Draw background
|
|
bufGraphics.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(160, 160, 160)), panelRect);
|
|
|
|
// Ref Points
|
|
float startingRemainder = (float)Math.Ceiling(linearView.StartingMeasure) - linearView.StartingMeasure;
|
|
float startingPoint = startingRemainder * linearView.QuarterNoteHeight * 4;
|
|
|
|
// Draw Masks
|
|
var masks = Chart.Notes.Where(x => x.IsMask && x.NoteType == NoteType.MaskAdd && x.Measure < linearView.EndMeasure);
|
|
foreach (var mask in masks)
|
|
{
|
|
float measureOffset = mask.Measure - (float)Math.Ceiling(linearView.StartingMeasure);
|
|
float maskPoint = measureOffset * linearView.QuarterNoteHeight * 4;
|
|
float endPoint = 0;
|
|
|
|
var addNote = new NoteInfo(mask.Position, mask.Size);
|
|
|
|
var removeNote = Chart.Notes.FirstOrDefault(x => x.NoteType == NoteType.MaskRemove && x.Measure > mask.Measure && x.Position == mask.Position && x.Size == mask.Size);
|
|
if (removeNote != null)
|
|
{
|
|
endPoint = linearView.PanelSize.Height - startingPoint - (removeNote.Measure - (float)Math.Ceiling(linearView.StartingMeasure)) * linearView.QuarterNoteHeight * 4;
|
|
if (endPoint < 0)
|
|
endPoint = 0;
|
|
}
|
|
|
|
bufGraphics.Graphics.FillRectangle(
|
|
new SolidBrush(mask.Color),
|
|
linearView.LeftMargin + linearView.LaneWidth * addNote.StartLane + 1.0f,
|
|
endPoint,
|
|
linearView.LaneWidth * addNote.Size - 1.0f,
|
|
linearView.PanelSize.Height - startingPoint - maskPoint);
|
|
|
|
if (addNote.StartLane2 != null && addNote.Size2 != null)
|
|
{
|
|
bufGraphics.Graphics.FillRectangle(
|
|
new SolidBrush(mask.Color),
|
|
linearView.LeftMargin + linearView.LaneWidth * (int)addNote.StartLane2 + 1.0f,
|
|
endPoint,
|
|
linearView.LaneWidth * (int)addNote.Size2 - 1.0f,
|
|
linearView.PanelSize.Height - startingPoint - maskPoint);
|
|
}
|
|
}
|
|
|
|
// Draw Lanes
|
|
for (int i = 0; i < (linearView.NumLanes + 1); i++)
|
|
{
|
|
Pen lanePen;
|
|
if (i % 15 == 0)
|
|
lanePen = linearView.MajorLanePen;
|
|
else if (i % 5 == 0)
|
|
lanePen = linearView.MediumLanePen;
|
|
else
|
|
lanePen = linearView.MinorLanePen;
|
|
|
|
bufGraphics.Graphics.DrawLine(
|
|
lanePen,
|
|
linearView.LeftMargin + i * linearView.LaneWidth,
|
|
0,
|
|
linearView.LeftMargin + i * linearView.LaneWidth,
|
|
linearView.PanelSize.Height);
|
|
}
|
|
|
|
// Draw Measure Lines
|
|
for (int i = 0; i <= (int)(linearView.EndMeasure - linearView.StartingMeasure); i++)
|
|
{
|
|
bufGraphics.Graphics.DrawLine(
|
|
linearView.MeasurePen,
|
|
linearView.LeftMargin,
|
|
linearView.PanelSize.Height - startingPoint - i * linearView.QuarterNoteHeight * 4,
|
|
linearView.LeftMargin + linearView.AllLaneWidth,
|
|
linearView.PanelSize.Height - startingPoint - i * linearView.QuarterNoteHeight * 4);
|
|
|
|
bufGraphics.Graphics.DrawString(
|
|
$"{(Math.Ceiling(linearView.StartingMeasure) + i):F0}",
|
|
linearView.GimmickFont,
|
|
linearView.LabelBrush,
|
|
linearView.LeftMargin - 8.0f,
|
|
linearView.PanelSize.Height - startingPoint - i * linearView.QuarterNoteHeight * 4 - 18.0f,
|
|
linearView.RightAlign);
|
|
}
|
|
|
|
// Draw Hi-Speed
|
|
var hispeed = Chart.Gimmicks.Where(
|
|
x => x.GimmickType == GimmickType.HiSpeedChange
|
|
&& x.Measure >= linearView.StartingMeasure
|
|
&& x.Measure <= linearView.EndMeasure);
|
|
foreach (var evt in hispeed)
|
|
{
|
|
float measureOffset = evt.Measure - (float)Math.Ceiling(linearView.StartingMeasure);
|
|
float eventPoint = measureOffset * linearView.QuarterNoteHeight * 4;
|
|
|
|
bufGraphics.Graphics.DrawLine(
|
|
linearView.HiSpeedPen,
|
|
linearView.LeftMargin + linearView.AllLaneWidth,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint,
|
|
linearView.LeftMargin + linearView.AllLaneWidth + linearView.BpmMargin + linearView.TimeSigMargin + linearView.HiSpeedMargin,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint);
|
|
|
|
bufGraphics.Graphics.DrawString(
|
|
$"x {evt.HiSpeed:F3}",
|
|
linearView.GimmickFont,
|
|
linearView.HiSpeedBrush,
|
|
linearView.LeftMargin + linearView.AllLaneWidth + linearView.BpmMargin + linearView.TimeSigMargin + 8.0f,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint - 18.0f);
|
|
}
|
|
|
|
// Draw Time Signature
|
|
var timesig = Chart.Gimmicks.Where(
|
|
x => x.GimmickType == GimmickType.TimeSignatureChange
|
|
&& x.Measure >= linearView.StartingMeasure
|
|
&& x.Measure <= linearView.EndMeasure);
|
|
foreach (var evt in timesig)
|
|
{
|
|
float measureOffset = evt.Measure - (float)Math.Ceiling(linearView.StartingMeasure);
|
|
float eventPoint = measureOffset * linearView.QuarterNoteHeight * 4;
|
|
|
|
bufGraphics.Graphics.DrawLine(
|
|
linearView.TimeSigPen,
|
|
linearView.LeftMargin + linearView.AllLaneWidth,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint,
|
|
linearView.LeftMargin + linearView.AllLaneWidth + linearView.BpmMargin + linearView.TimeSigMargin,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint);
|
|
|
|
bufGraphics.Graphics.DrawString(
|
|
$"{evt.TimeSig.Upper}/{evt.TimeSig.Lower}",
|
|
linearView.GimmickFont,
|
|
linearView.TimeSigBrush,
|
|
linearView.LeftMargin + linearView.AllLaneWidth + linearView.BpmMargin + 8.0f,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint - 18.0f);
|
|
}
|
|
|
|
// Draw BPM
|
|
var bpm = Chart.Gimmicks.Where(
|
|
x => x.GimmickType == GimmickType.BpmChange
|
|
&& x.Measure >= linearView.StartingMeasure
|
|
&& x.Measure <= linearView.EndMeasure);
|
|
foreach (var evt in bpm)
|
|
{
|
|
float measureOffset = evt.Measure - (float)Math.Ceiling(linearView.StartingMeasure);
|
|
float eventPoint = measureOffset * linearView.QuarterNoteHeight * 4;
|
|
|
|
bufGraphics.Graphics.DrawLine(
|
|
linearView.BpmPen,
|
|
linearView.LeftMargin + linearView.AllLaneWidth,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint,
|
|
linearView.LeftMargin + linearView.AllLaneWidth + linearView.BpmMargin,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint);
|
|
|
|
bufGraphics.Graphics.DrawString(
|
|
evt.BPM.ToString("F2"),
|
|
linearView.GimmickFont,
|
|
linearView.BpmBrush,
|
|
linearView.LeftMargin + linearView.AllLaneWidth + 8.0f,
|
|
linearView.PanelSize.Height - startingPoint - eventPoint - 18.0f);
|
|
}
|
|
|
|
// Draw Selection Line
|
|
float selectionOffset = linearView.SelectedMeasure - (float)Math.Ceiling(linearView.StartingMeasure);
|
|
float selectionPoint = selectionOffset * linearView.QuarterNoteHeight * 4;
|
|
|
|
bufGraphics.Graphics.DrawLine(
|
|
linearView.SelectionPen,
|
|
linearView.LeftMargin - 10.0f,
|
|
linearView.PanelSize.Height - startingPoint - selectionPoint,
|
|
linearView.LeftMargin + linearView.AllLaneWidth,
|
|
linearView.PanelSize.Height - startingPoint - selectionPoint);
|
|
|
|
// Draw Holds
|
|
// First, draw holds that start before the viewpoint and end after
|
|
|
|
// Second, draw all notes on-screen
|
|
var holdNotes = Chart.Notes.Where(
|
|
x => x.Measure >= linearView.StartingMeasure
|
|
&& x.Measure <= linearView.EndMeasure
|
|
&& x.IsHold).ToList();
|
|
foreach (var note in holdNotes)
|
|
{
|
|
linearView.DrawNote(bufGraphics.Graphics, note, startingPoint);
|
|
}
|
|
|
|
// Draw Notes
|
|
var drawNotes = Chart.Notes.Where(
|
|
x => x.Measure >= linearView.StartingMeasure
|
|
&& x.Measure <= linearView.EndMeasure
|
|
&& !x.IsHold
|
|
&& !x.IsMask).ToList();
|
|
foreach (var note in drawNotes)
|
|
{
|
|
linearView.DrawNote(bufGraphics.Graphics, note, startingPoint);
|
|
}
|
|
|
|
bufGraphics.Render(e.Graphics);
|
|
}
|
|
|
|
private void LinearViewForm_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
if (e.CloseReason == CloseReason.UserClosing)
|
|
{
|
|
Hide();
|
|
e.Cancel = true;
|
|
}
|
|
}
|
|
|
|
private void linearPanel_Click(object sender, EventArgs e)
|
|
{
|
|
linearPanel.Invalidate();
|
|
}
|
|
|
|
private void LinearViewForm_Resize(object sender, EventArgs e)
|
|
{
|
|
SetBufferedGraphicsContext();
|
|
linearView.Update(linearPanel.Size);
|
|
linearPanel.Invalidate();
|
|
}
|
|
|
|
private void LinearPanel_MouseWheel(object? sender, MouseEventArgs e)
|
|
{
|
|
if (Control.ModifierKeys == Keys.Control)
|
|
{
|
|
if (e.Delta > 0)
|
|
linearView.QuarterNoteHeight += 50;
|
|
else if (linearView.QuarterNoteHeight > 50)
|
|
linearView.QuarterNoteHeight -= 50;
|
|
linearPanel.Invalidate();
|
|
}
|
|
else if (Control.ModifierKeys == Keys.Alt)
|
|
{ }
|
|
else if (Control.ModifierKeys == Keys.Shift)
|
|
{ }
|
|
else
|
|
{
|
|
if (e.Delta > 0)
|
|
{
|
|
linearView.StartingMeasure += 0.25f * (50.0f / linearView.QuarterNoteHeight);
|
|
}
|
|
else
|
|
{
|
|
if (linearView.StartingMeasure > -0.25f)
|
|
linearView.StartingMeasure = Math.Max(-0.25f, linearView.StartingMeasure - 0.25f * ( 50.0f / linearView.QuarterNoteHeight));
|
|
}
|
|
}
|
|
linearPanel.Invalidate();
|
|
}
|
|
|
|
private void linearPanel_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
// Check all notes to determine if we are over one
|
|
}
|
|
}
|
|
}
|