FReply FCEFWebBrowserWindow::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent, bool bIsPopup) { FReply Reply = FReply::Unhandled(); if(IsValid()) { // The original delta is reduced so this should bring it back to what CEF expects const float SpinFactor = 50.0f; const float TrueDelta = MouseEvent.GetWheelDelta() * SpinFactor; CefMouseEvent Event = GetCefMouseEvent(MyGeometry, MouseEvent, bIsPopup); InternalCefBrowser->GetHost()->SendMouseWheelEvent(Event, MouseEvent.IsShiftDown() ? TrueDelta : 0, !MouseEvent.IsShiftDown() ? TrueDelta : 0); Reply = FReply::Handled(); } return Reply; }
/** * The system calls this method to notify the widget that a mouse button was release within it. This event is bubbled. * * @param MyGeometry The Geometry of the widget receiving the event * @param MouseEvent Information about the input event * * @return Whether the event was handled along with possible requests for the system to take action. */ FReply SGraphPin::OnMouseButtonUp( const FGeometry& MyGeometry, const FPointerEvent& MouseEvent ) { if (MouseEvent.IsShiftDown()) { // Either store the shift-clicked pin or attempt to connect it if already stored TSharedPtr<SGraphPanel> OwnerPanelPtr = OwnerNodePtr.Pin()->GetOwnerPanel(); check(OwnerPanelPtr.IsValid()); if (OwnerPanelPtr->MarkedPin.IsValid()) { // avoid creating transaction if toggling the marked pin if (!OwnerPanelPtr->MarkedPin.HasSameObject(this)) { const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "GraphEd_CreateConnection", "Create Pin Link") ); TryHandlePinConnection(*OwnerPanelPtr->MarkedPin.Pin()); } OwnerPanelPtr->MarkedPin.Reset(); } else { OwnerPanelPtr->MarkedPin = SharedThis(this); } return FReply::Handled(); } return FReply::Unhandled(); }
void FWebBrowserWindow::OnMouseWheel(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { if(IsValid()) { // The original delta is reduced so this should bring it back to what CEF expects const float SpinFactor = 120.0f; const float TrueDelta = MouseEvent.GetWheelDelta() * SpinFactor; CefMouseEvent Event; FVector2D LocalPos = MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()); Event.x = LocalPos.X; Event.y = LocalPos.Y; Event.modifiers = GetCefMouseModifiers(MouseEvent); InternalCefBrowser->GetHost()->SendMouseWheelEvent(Event, MouseEvent.IsShiftDown() ? TrueDelta : 0, !MouseEvent.IsShiftDown() ? TrueDelta : 0); } }
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(); }
TSharedPtr<SWidget> SGraphPanel::OnSummonContextMenu(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { //Editability is up to the user to consider for menu options { // If we didn't drag very far, summon a context menu. // Figure out what's under the mouse: Node, Pin or just the Panel, and summon the context menu for that. UEdGraphNode* NodeUnderCursor = NULL; UEdGraphPin* PinUnderCursor = NULL; { FArrangedChildren ArrangedNodes(EVisibility::Visible); this->ArrangeChildrenForContextMenuSummon(MyGeometry, ArrangedNodes); const int32 HoveredNodeIndex = SWidget::FindChildUnderMouse( ArrangedNodes, MouseEvent ); if (HoveredNodeIndex != INDEX_NONE) { const FArrangedWidget& HoveredNode = ArrangedNodes[HoveredNodeIndex]; TSharedRef<SGraphNode> GraphNode = StaticCastSharedRef<SGraphNode>(HoveredNode.Widget); TSharedPtr<SGraphNode> GraphSubNode = GraphNode->GetNodeUnderMouse(HoveredNode.Geometry, MouseEvent); GraphNode = GraphSubNode.IsValid() ? GraphSubNode.ToSharedRef() : GraphNode; NodeUnderCursor = GraphNode->GetNodeObj(); // Selection should switch to this code if it isn't already selected. // When multiple nodes are selected, we do nothing, provided that the // node for which the context menu is being created is in the selection set. if (!SelectionManager.IsNodeSelected(GraphNode->GetObjectBeingDisplayed())) { SelectionManager.SelectSingleNode(GraphNode->GetObjectBeingDisplayed()); } const TSharedPtr<SGraphPin> HoveredPin = GraphNode->GetHoveredPin( HoveredNode.Geometry, MouseEvent ); if (HoveredPin.IsValid()) { PinUnderCursor = HoveredPin->GetPinObj(); } } } const FVector2D NodeAddPosition = PanelCoordToGraphCoord( MyGeometry.AbsoluteToLocal(MouseEvent.GetScreenSpacePosition()) ); TArray<UEdGraphPin*> NoSourcePins; return SummonContextMenu(MouseEvent.GetScreenSpacePosition(), NodeAddPosition, NodeUnderCursor, PinUnderCursor, NoSourcePins, MouseEvent.IsShiftDown()); } return TSharedPtr<SWidget>(); }
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(); }
FReply FTextEditHelper::OnMouseButtonDown( const FGeometry& MyGeometry, const FPointerEvent& InMouseEvent, const TSharedRef< ITextEditorWidget >& TextEditor ) { FReply Reply = FReply::Unhandled(); // If the mouse is already captured, then don't allow a new action to be taken if( !TextEditor->GetWidget()->HasMouseCapture() ) { if( InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton || InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) { // Am I getting focus right now? const bool bIsGettingFocus = !TextEditor->GetWidget()->HasKeyboardFocus(); if( bIsGettingFocus ) { // We might be receiving keyboard focus due to this event. Because the keyboard focus received callback // won't fire until after this function exits, we need to make sure our widget's state is in order early // Assume we'll be given keyboard focus, so load text for editing TextEditor->LoadText(); // Reset 'mouse has moved' state. We'll use this in OnMouseMove to determine whether we // should reset the selection range to the caret's position. TextEditor->SetWasFocusedByLastMouseDown( true ); } if( InMouseEvent.GetEffectingButton() == EKeys::LeftMouseButton ) { if( InMouseEvent.IsShiftDown() ) { TextEditor->MoveCursor( FMoveCursor::ViaScreenPointer( MyGeometry.AbsoluteToLocal( InMouseEvent.GetScreenSpacePosition( ) ), MyGeometry.Scale, ECursorAction::SelectText ) ); } else { // Deselect any text that was selected TextEditor->ClearSelection(); TextEditor->MoveCursor( FMoveCursor::ViaScreenPointer( MyGeometry.AbsoluteToLocal( InMouseEvent.GetScreenSpacePosition( ) ), MyGeometry.Scale, ECursorAction::MoveCursor ) ); } // Start drag selection TextEditor->BeginDragSelection(); } else if( InMouseEvent.GetEffectingButton() == EKeys::RightMouseButton ) { // If the user right clicked on a character that wasn't already selected, we'll clear // the selection if ( TextEditor->AnyTextSelected( ) && !TextEditor->IsTextSelectedAt( MyGeometry, InMouseEvent.GetScreenSpacePosition() ) ) { // Deselect any text that was selected TextEditor->ClearSelection(); } } // Right clicking to summon context menu, but we'll do that on mouse-up. Reply = FReply::Handled(); Reply.CaptureMouse( TextEditor->GetWidget() ); Reply.SetUserFocus(TextEditor->GetWidget(), EFocusCause::Mouse); } } return Reply; }
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(); }