FReply SInlineEditableTextBlock::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if( !MouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton) || MouseEvent.IsControlDown() || MouseEvent.IsShiftDown()) { return FReply::Unhandled(); } if(IsSelected.IsBound()) { if(IsSelected.Execute() && !bIsReadOnly.Get() && !ActiveTimerHandle.IsValid()) { RegisterActiveTimer(0.5f, FWidgetActiveTimerDelegate::CreateSP(this, &SInlineEditableTextBlock::TriggerEditMode)); } } else { // The widget is not managed by another widget, so handle the mouse input and enter edit mode if ready. if(HasKeyboardFocus()) { EnterEditingMode(); } return FReply::Handled(); } // Do not handle the mouse input, this will allow for drag and dropping events to trigger. return FReply::Unhandled(); }
FReply SAnimationOutlinerTreeNode::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if( MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && DisplayNode->IsSelectable() ) { bool bSelected = DisplayNode->IsSelected(); if( MouseEvent.IsControlDown() ) { const bool bDeselectOtherNodes = false; // Select the node if we were clicked on DisplayNode->SetSelectionState( !bSelected, bDeselectOtherNodes ); } else { const bool bDeselectOtherNodes = true; // Select the node if we were clicked on DisplayNode->SetSelectionState( true, bDeselectOtherNodes ); } OnSelectionChanged.ExecuteIfBound( DisplayNode ); return FReply::Handled(); } else if( MouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) { return FReply::Handled().CaptureMouse(SharedThis(this)); } return FReply::Unhandled(); }
FReply SSequencerSectionAreaView::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { // Clear selected sections if( !MouseEvent.IsControlDown() ) { GetSequencer().ClearSectionSelection(); } return FReply::Handled(); }
void SSection::HandleSectionSelection( const FPointerEvent& MouseEvent ) { if( !MouseEvent.IsControlDown() ) { GetSequencer().GetSelection().EmptySelectedSections(); } // handle selecting sections UMovieSceneSection* Section = SectionInterface->GetSectionObject(); GetSequencer().GetSelection().AddToSelection(Section); }
void SSection::HandleKeySelection( const FSelectedKey& Key, const FPointerEvent& MouseEvent, bool bSelectDueToDrag ) { if( Key.IsValid() ) { // Clear previous key selection if: // we are selecting due to drag and the key being dragged is not selected or control is not down bool bShouldClearSelectionDueToDrag = bSelectDueToDrag ? !GetSequencer().GetSelection().IsSelected( Key ) : true; // Keep key selection if right clicking to bring up a menu and the current key is selected bool bKeepKeySelection = MouseEvent.GetEffectingButton() == EKeys::RightMouseButton && GetSequencer().GetSelection().IsSelected( Key ); if( (!MouseEvent.IsControlDown() && bShouldClearSelectionDueToDrag) && !bKeepKeySelection ) { GetSequencer().GetSelection().EmptySelectedKeys(); } GetSequencer().GetSelection().AddToSelection( Key ); } }
FReply SFlipbookTimeline::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { if (MouseEvent.IsControlDown()) { const float DirectionScale = 0.08f; const float MinFrameSize = 16.0f; const float Direction = MouseEvent.GetWheelDelta(); const float NewUnitsPerFrame = FMath::Max(MinFrameSize, SlateUnitsPerFrame * (1.0f + Direction * DirectionScale)); SlateUnitsPerFrame = NewUnitsPerFrame; CheckForRebuild(/*bRebuildAll=*/ true); return FReply::Handled(); } else { return FReply::Unhandled(); } }
FReply FSequencerTimeSliderController::OnMouseWheel( SWidget& WidgetOwner, const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { TOptional<TRange<float>> NewTargetRange; float MouseFractionX = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()).X / MyGeometry.GetLocalSize().X; if ( TimeSliderArgs.AllowZoom && MouseEvent.IsControlDown() ) { const float ZoomDelta = -0.2f * MouseEvent.GetWheelDelta(); if (ZoomByDelta(ZoomDelta, MouseFractionX)) { return FReply::Handled(); } } else if (MouseEvent.IsShiftDown()) { PanByDelta(-MouseEvent.GetWheelDelta()); return FReply::Handled(); } return FReply::Unhandled(); }
virtual FReply OnMouseButtonUp(const FGeometry& InMyGeometry, const FPointerEvent& InMouseEvent) override { if (!InMouseEvent.IsControlDown()) { return SCheckBox::OnMouseButtonUp(InMyGeometry, InMouseEvent); } if (InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) { bIsPressed = false; if (IsHovered() && HasMouseCapture()) { if (OnLayerCtrlClicked.IsBound()) { return OnLayerCtrlClicked.Execute(); } } } return FReply::Handled().ReleaseMouseCapture(); }
FReply STableViewBase::OnMouseWheel( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if( !MouseEvent.IsControlDown() ) { // Make sure scroll velocity is cleared so it doesn't fight with the mouse wheel input this->InertialScrollManager.ClearScrollVelocity(); const float AmountScrolledInItems = this->ScrollBy( MyGeometry, -MouseEvent.GetWheelDelta()*WheelScrollAmount, EAllowOverscroll::No ); switch ( ConsumeMouseWheel ) { case EConsumeMouseWheel::Always: return FReply::Handled(); case EConsumeMouseWheel::WhenScrollingPossible: //default behavior default: if ( FMath::Abs( AmountScrolledInItems ) > 0.0f ) { return FReply::Handled(); } } } return FReply::Unhandled(); }
FReply SGraphPin::OnMouseMove( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { bIsMovingLinks = MouseEvent.IsControlDown() && (GraphPinObj->LinkedTo.Num() > 0); return FReply::Unhandled(); }
FReply SGraphPin::OnPinMouseDown( const FGeometry& SenderGeometry, const FPointerEvent& MouseEvent ) { bIsMovingLinks = false; if (MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton) { if (!GraphPinObj->bNotConnectable && IsEditable.Get()) { if (MouseEvent.IsAltDown()) { // Alt-Left clicking will break all existing connections to a pin const UEdGraphSchema* Schema = GraphPinObj->GetSchema(); Schema->BreakPinLinks(*GraphPinObj, true); return FReply::Handled(); } auto OwnerNodePinned = OwnerNodePtr.Pin(); if (MouseEvent.IsControlDown() && (GraphPinObj->LinkedTo.Num() > 0)) { // Get a reference to the owning panel widget check(OwnerNodePinned.IsValid()); TSharedPtr<SGraphPanel> OwnerPanelPtr = OwnerNodePinned->GetOwnerPanel(); check(OwnerPanelPtr.IsValid()); // Obtain the set of all pins within the panel TSet<TSharedRef<SWidget> > AllPins; OwnerPanelPtr->GetAllPins(AllPins); // Construct a UEdGraphPin->SGraphPin mapping for the full pin set TMap< UEdGraphPin*, TSharedRef<SGraphPin> > PinToPinWidgetMap; for( TSet< TSharedRef<SWidget> >::TIterator ConnectorIt(AllPins); ConnectorIt; ++ConnectorIt ) { const TSharedRef<SWidget>& SomePinWidget = *ConnectorIt; const SGraphPin& PinWidget = static_cast<const SGraphPin&>(SomePinWidget.Get()); PinToPinWidgetMap.Add(PinWidget.GetPinObj(), StaticCastSharedRef<SGraphPin>(SomePinWidget)); } // Define a local struct to temporarily store lookup information for pins that we are currently linked to struct LinkedToPinInfo { // Pin name string FString PinName; // A weak reference to the node object that owns the pin TWeakObjectPtr<UEdGraphNode> OwnerNodePtr; }; // Build a lookup table containing information about the set of pins that we're currently linked to TArray<LinkedToPinInfo> LinkedToPinInfoArray; for( TArray<UEdGraphPin*>::TIterator LinkArrayIter(GetPinObj()->LinkedTo); LinkArrayIter; ++LinkArrayIter ) { if (auto PinWidget = PinToPinWidgetMap.Find(*LinkArrayIter)) { check((*PinWidget)->OwnerNodePtr.IsValid()); LinkedToPinInfo PinInfo; PinInfo.PinName = (*PinWidget)->GetPinObj()->PinName; PinInfo.OwnerNodePtr = (*PinWidget)->OwnerNodePtr.Pin()->GetNodeObj(); LinkedToPinInfoArray.Add(PinInfo); } } // Control-Left clicking will break all existing connections to a pin // Note that for some nodes, this can cause reconstruction. In that case, pins we had previously linked to may now be destroyed. const UEdGraphSchema* Schema = GraphPinObj->GetSchema(); Schema->BreakPinLinks(*GraphPinObj, true); // Check to see if the panel has been invalidated by a graph change notification if (!OwnerPanelPtr->Contains(OwnerNodePinned->GetNodeObj())) { // Force the panel to update. This will cause node & pin widgets to be reinstanced to match any reconstructed node/pin object references. OwnerPanelPtr->Update(); // Obtain the full set of pins again after the update AllPins.Empty(AllPins.Num()); OwnerPanelPtr->GetAllPins(AllPins); // Rebuild the UEdGraphPin->SGraphPin mapping for the full pin set PinToPinWidgetMap.Empty(PinToPinWidgetMap.Num()); for( TSet< TSharedRef<SWidget> >::TIterator ConnectorIt(AllPins); ConnectorIt; ++ConnectorIt ) { const TSharedRef<SWidget>& SomePinWidget = *ConnectorIt; const SGraphPin& PinWidget = static_cast<const SGraphPin&>(SomePinWidget.Get()); PinToPinWidgetMap.Add(PinWidget.GetPinObj(), StaticCastSharedRef<SGraphPin>(SomePinWidget)); } } // Now iterate over our lookup table to find the instances of pin widgets that we had previously linked to TArray<TSharedRef<SGraphPin>> PinArray; for(auto LinkedToPinInfoIter = LinkedToPinInfoArray.CreateConstIterator(); LinkedToPinInfoIter; ++LinkedToPinInfoIter) { LinkedToPinInfo PinInfo = *LinkedToPinInfoIter; UEdGraphNode* OwnerNodeObj = PinInfo.OwnerNodePtr.Get(); if(OwnerNodeObj != NULL) { for(auto PinIter = PinInfo.OwnerNodePtr.Get()->Pins.CreateConstIterator(); PinIter; ++PinIter) { UEdGraphPin* Pin = *PinIter; if(Pin->PinName == PinInfo.PinName) { if (auto pWidget = PinToPinWidgetMap.Find(Pin)) { PinArray.Add(*pWidget); } } } } } if(PinArray.Num() > 0) { bIsMovingLinks = true; return FReply::Handled().BeginDragDrop(SpawnPinDragEvent(OwnerPanelPtr.ToSharedRef(), PinArray, /*bIsShiftOperation=*/ false)); } else { // Shouldn't get here, but just in case we lose our previous links somehow after breaking them, we'll just skip the drag. return FReply::Handled(); } } // Start a drag-drop on the pin if (ensure(OwnerNodePinned.IsValid())) { TArray<TSharedRef<SGraphPin>> PinArray; PinArray.Add(SharedThis(this)); return FReply::Handled().BeginDragDrop(SpawnPinDragEvent(OwnerNodePinned->GetOwnerPanel().ToSharedRef(), PinArray, MouseEvent.IsShiftDown())); } else { return FReply::Unhandled(); } } else { // It's not connectable, but we don't want anything above us to process this left click. return FReply::Handled(); } } else { return FReply::Unhandled(); } }
FReply SAnimationOutlinerTreeNode::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if( MouseEvent.GetEffectingButton() == EKeys::LeftMouseButton && DisplayNode->IsSelectable() ) { FSequencer& Sequencer = DisplayNode->GetSequencer(); bool bSelected = Sequencer.GetSelection().IsSelected(DisplayNode.ToSharedRef()); TArray<TSharedPtr<FSequencerDisplayNode> > AffectedNodes; AffectedNodes.Add(DisplayNode.ToSharedRef()); if (MouseEvent.IsShiftDown()) { FSequencerNodeTree& ParentTree = DisplayNode->GetParentTree(); const TArray< TSharedRef<FSequencerDisplayNode> >RootNodes = ParentTree.GetRootNodes(); // Get all nodes in order TArray<TSharedRef<FSequencerDisplayNode> > AllNodes; for (int32 i = 0; i < RootNodes.Num(); ++i) { GetAllDescendantNodes(RootNodes[i], AllNodes); } int32 FirstIndexToSelect = INT32_MAX; int32 LastIndexToSelect = INT32_MIN; for (int32 ChildIndex = 0; ChildIndex < AllNodes.Num(); ++ChildIndex) { TSharedRef<FSequencerDisplayNode> ChildNode = AllNodes[ChildIndex]; if (ChildNode == DisplayNode.ToSharedRef() || Sequencer.GetSelection().IsSelected(ChildNode)) { if (ChildIndex < FirstIndexToSelect) { FirstIndexToSelect = ChildIndex; } if (ChildIndex > LastIndexToSelect) { LastIndexToSelect = ChildIndex; } } } if (FirstIndexToSelect != INT32_MAX && LastIndexToSelect != INT32_MIN) { for (int32 ChildIndex = FirstIndexToSelect; ChildIndex <= LastIndexToSelect; ++ChildIndex) { TSharedRef<FSequencerDisplayNode> ChildNode = AllNodes[ChildIndex]; if (!Sequencer.GetSelection().IsSelected(ChildNode)) { Sequencer.GetSelection().AddToSelection(ChildNode); AffectedNodes.Add(ChildNode); } } } } else if( MouseEvent.IsControlDown() ) { // Toggle selection when control is down if (bSelected) { Sequencer.GetSelection().RemoveFromSelection(DisplayNode.ToSharedRef()); } else { Sequencer.GetSelection().AddToSelection(DisplayNode.ToSharedRef()); } } else { // Deselect the other nodes and select this node. Sequencer.GetSelection().EmptySelectedOutlinerNodes(); Sequencer.GetSelection().AddToSelection(DisplayNode.ToSharedRef()); } OnSelectionChanged.ExecuteIfBound( AffectedNodes ); return FReply::Handled(); } return FReply::Unhandled(); }
void FResizeSection::OnDrag( const FPointerEvent& MouseEvent, const FVector2D& LocalMousePos, const FTimeToPixel& TimeToPixelConverter, TSharedPtr<FTrackNode> SequencerNode ) { bool bIsDilating = MouseEvent.IsControlDown(); if( Section.IsValid() ) { // Convert the current mouse position to a time float NewTime = TimeToPixelConverter.PixelToTime( LocalMousePos.X ); // Find the borders of where you can drag to TRange<float> SectionBoundaries = GetSectionBoundaries(Section.Get(), SequencerNode); // Snapping if ( Settings->GetIsSnapEnabled() ) { bool bSnappedToSection = false; if ( Settings->GetSnapSectionTimesToSections() ) { TArray<float> TimesToSnapTo; GetSectionSnapTimes(TimesToSnapTo, Section.Get(), SequencerNode, bIsDilating); TOptional<float> NewSnappedTime = SnapToTimes(NewTime, TimesToSnapTo, TimeToPixelConverter); if (NewSnappedTime.IsSet()) { NewTime = NewSnappedTime.GetValue(); bSnappedToSection = true; } } if ( bSnappedToSection == false && Settings->GetSnapSectionTimesToInterval() ) { NewTime = Settings->SnapTimeToInterval(NewTime); } } if( bDraggingByEnd ) { // Dragging the end of a section // Ensure we aren't shrinking past the start time NewTime = FMath::Clamp( NewTime, Section->GetStartTime(), SectionBoundaries.GetUpperBoundValue() ); if (bIsDilating) { float NewSize = NewTime - Section->GetStartTime(); float DilationFactor = NewSize / Section->GetTimeSize(); Section->DilateSection(DilationFactor, Section->GetStartTime(), DraggedKeyHandles); } else { Section->SetEndTime( NewTime ); } } else if( !bDraggingByEnd ) { // Dragging the start of a section // Ensure we arent expanding past the end time NewTime = FMath::Clamp( NewTime, SectionBoundaries.GetLowerBoundValue(), Section->GetEndTime() ); if (bIsDilating) { float NewSize = Section->GetEndTime() - NewTime; float DilationFactor = NewSize / Section->GetTimeSize(); Section->DilateSection(DilationFactor, Section->GetEndTime(), DraggedKeyHandles); } else { Section->SetStartTime( NewTime ); } } } }