// 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& 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(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