AronaSlate/Source/Arona/UI/Widget/ChannelRack/ChannelRackMidiThumbnail.cpp
2024-01-25 11:21:15 +08:00

125 lines
3.6 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "ChannelRackMidiThumbnail.h"
#include "SImage.h"
#include "SInvalidationPanel.h"
#include "SlateApplication.h"
#include "SlateOptMacros.h"
#include "SScrollBox.h"
#include "SViewport.h"
#include "Midi/MidiMessageSequence.h"
#include "Singleton/MidiSequencer.h"
#include "UI/Widget/MainWindow.h"
#include "UI/Widget/SUpdatableImage.h"
#include "UI/Widget/Thumbnail.h"
#include "UI/Widget/WindowManager.h"
#include "UI/Widget/PianoRoll/SPianoRoll.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
SChannelRackMidiThumbnail::~SChannelRackMidiThumbnail()
{
SetPattern(nullptr);
}
void SChannelRackMidiThumbnail::SetPattern(FMidiPattern* InPattern)
{
if (CurrentPattern)
{
CurrentPattern->OnChanged.RemoveAll(this);
CurrentPattern->OnPlay.RemoveAll(this);
}
if (!InPattern)
return;
CurrentPattern = InPattern;
CurrentPattern->OnChanged_MainThread.AddRaw(this, &SChannelRackMidiThumbnail::OnChanged);
CurrentPattern->OnPlay.AddRaw(this, &SChannelRackMidiThumbnail::OnPatternPlay);
OnChanged(PluginHost, &InPattern->GetSequence(PluginHost));
}
void SChannelRackMidiThumbnail::Construct(const FArguments& InArgs, FPluginHost* InPluginHost)
{
PluginHost = InPluginHost;
SetPattern(InArgs._Pattern);
ChildSlot
[
SNew(SInvalidationPanel)
[
SAssignNew(UpdatableImage, SUpdatableImage)
.OnPostResize(this, &SChannelRackMidiThumbnail::UpdateMidiThumbnail)
.UpdateInterval(0)
]
];
if (InArgs._Pattern)
OnChanged(PluginHost, &InArgs._Pattern->GetSequence(InPluginHost));
}
FReply SChannelRackMidiThumbnail::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (!CurrentPattern)
return FReply::Unhandled();
FMidiMessageSequence* MidiSequence = &CurrentPattern->GetSequence(PluginHost);
TSharedPtr<SPianoRoll> PianoRoll = SNew(SPianoRoll, MidiSequence, PluginHost);
FWindowManager::Get().GetMainWindow()->CreateChildWindow(
FVector2D(100, 100),
TEXT(""),
PianoRoll.ToSharedRef()
);
PianoRoll->InitScrollBar();
return FReply::Unhandled();
}
int32 SChannelRackMidiThumbnail::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
LayerId = SCompoundWidget::OnPaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);
if (CurrentPattern)
{
const double EndTime = CurrentPattern->GetLength();
const double CurrentPercent = LastPatternPos / EndTime * (double)AllottedGeometry.Size.X;
TArray<FVector2f> Points;
Points.Add(FVector2f(CurrentPercent, 0));
Points.Add(FVector2f(CurrentPercent, AllottedGeometry.Size.Y));
FSlateDrawElement::MakeLines(
OutDrawElements,
++LayerId,
AllottedGeometry.ToPaintGeometry(),
Points,
ESlateDrawEffect::None,
FLinearColor::Red,
true,
1.f
);
}
return LayerId;
}
void SChannelRackMidiThumbnail::OnChanged(FPluginHost* Host, FMidiMessageSequence* Changed)
{
if (Host != PluginHost)
return;
UpdatableImage->NeedRedraw();
}
void SChannelRackMidiThumbnail::OnPatternPlay(FPatternInstance* PatternInstance, AudioFrame PatternTick, uint32 Length)
{
LastPatternPos = PatternTick;
}
void SChannelRackMidiThumbnail::UpdateMidiThumbnail(FImageData& ImageData)
{
if (!CurrentPattern)
return;
const FMidiMessageSequence* MidiSequence = &CurrentPattern->GetSequence(PluginHost);
ImageData.ClearColor(FColor::Black);
Thumbnail::GenerateMidiThumbnail(MidiSequence, ImageData);
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION