112 lines
3.6 KiB
C++
112 lines
3.6 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "SPlayListTimeLine.h"
|
|
|
|
#include "SlateOptMacros.h"
|
|
#include "Singleton/MidiSequencer.h"
|
|
|
|
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
|
|
void SPlayListTimeLine::Construct(const FArguments& InArgs)
|
|
{
|
|
FrameRange = InArgs._FrameRange;
|
|
/*
|
|
ChildSlot
|
|
[
|
|
// Populate the widget
|
|
];
|
|
*/
|
|
MainStepColor = FLinearColor(0.2f, 0.2f, 0.2f, 1.f);
|
|
SubStepColor = FLinearColor(0.1f, 0.1f, 0.1f, 1.f);
|
|
}
|
|
|
|
int32 SPlayListTimeLine::OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
|
|
{
|
|
const AudioFrame Step = FMidiSequencer::Get().GetBar().Frames();
|
|
const AudioFrame SubStep = FMidiSequencer::Get().GetBeat().Frames();
|
|
|
|
const TRange<AudioFrame> Range = FrameRange.Get();
|
|
|
|
const auto& Size = AllottedGeometry.Size;
|
|
const float FrameToPixelScaler = Size.X / Range.Size<float>();
|
|
const int32 StepRate = FMath::FloorToInt(Step / SubStep);
|
|
if (StepRate < 0)
|
|
return LayerId;
|
|
|
|
const int32 MakerCount = FMath::CeilToInt(Range.Size<float>() / Step) + 1;
|
|
const int32 SubMakerLineCount = StepRate * MakerCount + 1;
|
|
|
|
const float Offset = FMath::Fmod(Range.GetLowerBoundValue(), Step);
|
|
|
|
// Push clip rect
|
|
FSlateClippingZone ClippingZone(AllottedGeometry);
|
|
OutDrawElements.PushClip(ClippingZone);
|
|
|
|
++LayerId;
|
|
// const float SubLinePadding = AllottedGeometry.Size.Y * 0.4f;
|
|
const FPaintGeometry LinePaintGeometry = AllottedGeometry.ToPaintGeometry();
|
|
for (int i = 0; i < SubMakerLineCount; ++i)
|
|
{
|
|
const bool bIsSubMaker = i % StepRate != 0;
|
|
|
|
const float X = (i * SubStep - Offset) * FrameToPixelScaler;
|
|
// const float YPadding = bIsSubMaker ? SubLinePadding : 0;
|
|
TArray<FVector2D> Points;
|
|
Points.Add(FVector2D(X, 0));
|
|
Points.Add(FVector2D(X, AllottedGeometry.Size.Y));
|
|
|
|
FSlateDrawElement::MakeLines(OutDrawElements, LayerId, LinePaintGeometry, Points, ESlateDrawEffect::None, bIsSubMaker ? SubStepColor : MainStepColor, true, 1.f);
|
|
}
|
|
OutDrawElements.PopClip();
|
|
|
|
return LayerId;
|
|
}
|
|
|
|
FReply SPlayListTimeLine::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
|
{
|
|
if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton)
|
|
{
|
|
SetTimePos(MyGeometry, MouseEvent);
|
|
return FReply::Handled().CaptureMouse(AsShared());
|
|
}
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
FReply SPlayListTimeLine::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
|
{
|
|
if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton)
|
|
return FReply::Handled().ReleaseMouseCapture();
|
|
return FReply::Unhandled();
|
|
}
|
|
|
|
FReply SPlayListTimeLine::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
|
{
|
|
if (MouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton))
|
|
{
|
|
SetTimePos(MyGeometry, MouseEvent);
|
|
}
|
|
return FReply::Handled();
|
|
}
|
|
|
|
void SPlayListTimeLine::SetTimePos(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
|
|
{
|
|
const auto& Size = MyGeometry.Size;
|
|
const TRange<AudioFrame> Range = FrameRange.Get();
|
|
const float FrameToPixelScaler = Size.X / Range.Size<float>();
|
|
|
|
const float X = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()).X;
|
|
const bool NoSnap = MouseEvent.GetModifierKeys().IsAltDown();
|
|
AudioFrame Frame = X / FrameToPixelScaler + Range.GetLowerBoundValue();
|
|
if (!NoSnap)
|
|
Frame = FMath::GridSnap(Frame.Pos, FMidiSequencer::Get().GetBeat().Frames());
|
|
if (Frame.Pos < 0)
|
|
Frame = 0;
|
|
if (LastFrame == Frame)
|
|
return;
|
|
|
|
LastFrame = Frame;
|
|
FMidiSequencer::Get().FramePos = Frame;
|
|
}
|
|
|
|
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
|