AronaSlate/Source/Arona/UI/Widget/Pattern/SPatternInstance.cpp

162 lines
4.1 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#include "SPatternInstance.h"
#include "SButton.h"
#include "SInvalidationPanel.h"
#include "SlateOptMacros.h"
#include "STextBlock.h"
#include "SViewport.h"
#include "Pattern/PatternInstance.h"
#include "Render/UpdatableTexture.h"
#include "UI/Widget/SUpdatableTexture.h"
#include "Widgets/SBoxPanel.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SPatternInstance::Construct(const FArguments& InArgs)
{
PatternInstance = InArgs._PatternInstance;
FrameToPixel = InArgs._FrameToPixel;
SnapFrame = InArgs._SnapFrame;
FrameViewRange = InArgs._FrameViewRange;
ChildSlot
[
SNew(SOverlay)
+SOverlay::Slot()
[
SNew(SBorder)
.BorderBackgroundColor(FLinearColor(0, 0, 0, 0.3f))
]
+SOverlay::Slot()
[
SNew(SVerticalBox)
+SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
+SHorizontalBox::Slot()
.AutoWidth()
[
SNew(SButton)
.Text(FText::FromString("X"))
.OnClicked(this, &SPatternInstance::OpenPatternMenu)
]
+SHorizontalBox::Slot()
.FillWidth(1.f)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString(PatternInstance->GetOwner()->Name))
.OverflowPolicy(ETextOverflowPolicy::Ellipsis)
.Justification(ETextJustify::Left)
]
]
+SVerticalBox::Slot()
.FillHeight(1.f)
[
GetViewWidget()
]
]
];
}
FReply SPatternInstance::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (ResizeDirection != ResizeDir::None)
{
FPatternSelector::Get().SelectPatternInstance(PatternInstance);
const TRange<AudioFrame>& Range = PatternInstance->TimeRange;
BeginPatternStart = Range.GetLowerBoundValue();
BeginPatternEnd = Range.GetUpperBoundValue();
MouseDownPos = MouseEvent.GetScreenSpacePosition();
BeginPatternPos = PatternInstance->Pos;
return FReply::Handled().CaptureMouse(AsShared());
}
return FReply::Unhandled();
}
FReply SPatternInstance::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
if (ResizeDirection != ResizeDir::None)
{
PatternInstance->RequestEndSetting();
return FReply::Handled().ReleaseMouseCapture();
}
return FReply::Unhandled();
}
FReply SPatternInstance::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
const FVector2f LocalMousePos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition());
if (MouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton))
{
const float MouseDelta = (MouseEvent.GetScreenSpacePosition().X - MouseDownPos.X) / MyGeometry.Scale;
const float Scaler = FrameToPixel.Get();
const bool NoSnap = MouseEvent.GetModifierKeys().IsAltDown();
double Delta = MouseDelta / Scaler;
if (!NoSnap)
Delta = FMath::GridSnap(Delta, SnapFrame.Get());
switch (ResizeDirection)
{
case ResizeDir::None: break;
case ResizeDir::Left:
{
AudioFrame NewRangeStart = BeginPatternStart + Delta;
AudioFrame NewPos = BeginPatternPos + Delta;
if (NewRangeStart.Pos < 0)
{
NewPos -= NewRangeStart;
NewRangeStart = 0;
}
if (NewPos.Pos < 0)
{
NewRangeStart -= NewPos;
NewPos = 0;
}
PatternInstance->TimeRange.SetLowerBoundValue(NewRangeStart);
PatternInstance->SetMidiPos(NewPos.Ticks());
return FReply::Handled();
}
case ResizeDir::Right:
{
const AudioFrame NewRangeEnd = FMath::Max<AudioFrame>(0, BeginPatternEnd + Delta);
PatternInstance->TimeRange.SetUpperBoundValue(NewRangeEnd);
return FReply::Handled();
}
default: ;
}
}
else
{
if (LocalMousePos.X <= ResizeHandleSize)
{
ResizeDirection = ResizeDir::Left;
}
else if (LocalMousePos.X >= MyGeometry.GetLocalSize().X - ResizeHandleSize)
{
ResizeDirection = ResizeDir::Right;
}
else
{
ResizeDirection = ResizeDir::None;
}
switch (ResizeDirection)
{
case ResizeDir::None: SetCursor(EMouseCursor::Default); break;
case ResizeDir::Left:
case ResizeDir::Right: SetCursor(EMouseCursor::ResizeLeftRight); break;
default: ;
}
}
return FReply::Unhandled();
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION