virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override { TArray<UWidgetComponent*, TInlineAllocator<1>> DeadComponents; for ( TWeakObjectPtr<UWidgetComponent> Component : Components ) { if ( UWidgetComponent* WidgetComponent = Component.Get() ) { if ( ULocalPlayer* LocalPlayer = WidgetComponent->GetOwnerPlayer() ) { if ( APlayerController* PlayerController = LocalPlayer->PlayerController ) { FVector WorldLocation = WidgetComponent->GetComponentLocation(); FVector ScreenPosition; const bool bProjected = UWidgetLayoutLibrary::ProjectWorldLocationToWidgetPositionWithDistance(PlayerController, WorldLocation, ScreenPosition); if ( bProjected ) { WidgetComponent->GetUserWidgetObject()->SetVisibility(ESlateVisibility::SelfHitTestInvisible); if ( SConstraintCanvas::FSlot* CanvasSlot = ComponentToSlot.FindRef(WidgetComponent) ) { FVector2D DrawSize = WidgetComponent->GetDrawSize(); FVector2D Pivot = WidgetComponent->GetPivot(); CanvasSlot->AutoSize(DrawSize.IsZero()); CanvasSlot->Offset(FMargin(ScreenPosition.X, ScreenPosition.Y, DrawSize.X, DrawSize.Y)); CanvasSlot->Anchors(FAnchors(0, 0, 0, 0)); CanvasSlot->Alignment(Pivot); CanvasSlot->ZOrder(-ScreenPosition.Z); } } else { WidgetComponent->GetUserWidgetObject()->SetVisibility(ESlateVisibility::Hidden); } } } } else { DeadComponents.Add(WidgetComponent); } } // Normally components should be removed by someone calling remove component, but just in case it was // deleted in a way where they didn't happen, this is our backup solution to enure we remove stale widgets. for ( int32 Index = 0; Index < DeadComponents.Num(); Index++ ) { RemoveComponent(DeadComponents[Index]); } }
FMargin UUserWidget::GetFullScreenOffset() const { // If the size is zero, and we're not stretched, then use the desired size. FVector2D FinalSize = FVector2D(ViewportOffsets.Right, ViewportOffsets.Bottom); if ( FinalSize.IsZero() && !ViewportAnchors.IsStretchedVertical() && !ViewportAnchors.IsStretchedHorizontal() ) { TSharedPtr<SWidget> CachedWidget = GetCachedWidget(); if ( CachedWidget.IsValid() ) { FinalSize = CachedWidget->GetDesiredSize(); } } return FMargin(ViewportOffsets.Left, ViewportOffsets.Top, FinalSize.X, FinalSize.Y); }
FReply SPaperEditorViewport::OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) { const bool bIsRightMouseButtonDown = MouseEvent.IsMouseButtonDown(EKeys::RightMouseButton); const bool bIsLeftMouseButtonDown = MouseEvent.IsMouseButtonDown(EKeys::LeftMouseButton); if (HasMouseCapture()) { // Track how much the mouse moved since the mouse down. const FVector2D CursorDelta = MouseEvent.GetCursorDelta(); TotalMouseDelta += CursorDelta.Size(); if (bIsRightMouseButtonDown) { FReply ReplyState = FReply::Handled(); if (!CursorDelta.IsZero()) { bShowSoftwareCursor = true; } bIsPanning = true; ViewOffset -= CursorDelta / GetZoomAmount(); return ReplyState; } else if (bIsLeftMouseButtonDown) { // TSharedPtr<SNode> NodeBeingDragged = NodeUnderMousePtr.Pin(); // Update the amount to pan panel UpdateViewOffset(MyGeometry, MouseEvent.GetScreenSpacePosition()); const bool bCursorInDeadZone = TotalMouseDelta <= FSlateApplication::Get().GetDragTriggerDistance(); { // We are marquee selecting const FVector2D GraphMousePos = PanelCoordToGraphCoord( MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ) ); Marquee.Rect.UpdateEndPoint(GraphMousePos); return FReply::Handled(); } } } return FReply::Unhandled(); }
/** SWidget interface */ virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override { const bool bIsRightMouseButtonDown = MouseEvent.IsMouseButtonDown( EKeys::RightMouseButton ); const bool bIsLeftMouseButtonDown = MouseEvent.IsMouseButtonDown( EKeys::LeftMouseButton ); PastePosition = PanelCoordToGraphCoord( MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ) ); if ( this->HasMouseCapture() ) { const FVector2D CursorDelta = MouseEvent.GetCursorDelta(); // Track how much the mouse moved since the mouse down. TotalMouseDelta += CursorDelta.Size(); if (bIsRightMouseButtonDown) { FReply ReplyState = FReply::Handled(); if( !CursorDelta.IsZero() ) { bShowSoftwareCursor = true; } // Panning and mouse is outside of panel? Pasting should just go to the screen center. PastePosition = PanelCoordToGraphCoord( 0.5 * MyGeometry.Size ); this->bIsPanning = true; ViewOffset -= CursorDelta / GetZoomAmount(); return ReplyState; } else if (bIsLeftMouseButtonDown) { TSharedPtr<SNode> NodeBeingDragged = NodeUnderMousePtr.Pin(); if ( IsEditable.Get() ) { // Update the amount to pan panel UpdateViewOffset(MyGeometry, MouseEvent.GetScreenSpacePosition()); const bool bCursorInDeadZone = TotalMouseDelta <= FSlateApplication::Get().GetDragTriggerDistance(); if ( NodeBeingDragged.IsValid() ) { if ( !bCursorInDeadZone ) { // Note, NodeGrabOffset() comes from the node itself, so it's already scaled correctly. FVector2D AnchorNodeNewPos = PanelCoordToGraphCoord( MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ) ) - NodeGrabOffset; // Dragging an unselected node automatically selects it. SelectionManager.StartDraggingNode(NodeBeingDragged->GetObjectBeingDisplayed(), MouseEvent); // Move all the selected nodes. { const FVector2D AnchorNodeOldPos = NodeBeingDragged->GetPosition(); const FVector2D DeltaPos = AnchorNodeNewPos - AnchorNodeOldPos; if (DeltaPos.Size() > KINDA_SMALL_NUMBER) { MoveSelectedNodes(NodeBeingDragged, AnchorNodeNewPos); } } } return FReply::Handled(); } } if ( !NodeBeingDragged.IsValid() ) { // We are marquee selecting const FVector2D GraphMousePos = PanelCoordToGraphCoord( MyGeometry.AbsoluteToLocal( MouseEvent.GetScreenSpacePosition() ) ); Marquee.Rect.UpdateEndPoint(GraphMousePos); FindNodesAffectedByMarquee( /*out*/ Marquee.AffectedNodes ); return FReply::Handled(); } } } return FReply::Unhandled(); }
void AHUD::PostRender() { // Theres nothing we can really do without a canvas or a world - so leave now in that case if ( (GetWorld() == nullptr) || (Canvas == nullptr)) { return; } // Set up delta time RenderDelta = GetWorld()->TimeSeconds - LastHUDRenderTime; if ( PlayerOwner != NULL ) { // draw any debug text in real-time DrawDebugTextList(); } if ( bShowDebugInfo ) { if (DebugCanvas) { DebugCanvas->DisplayDebugManager.Initialize(DebugCanvas, GEngine->GetTinyFont(), FVector2D(4.f, 50.f)); ShowDebugInfo(DebugCanvas->DisplayDebugManager.GetMaxCharHeightRef(), DebugCanvas->DisplayDebugManager.GetYPosRef()); } } else if ( bShowHUD && FApp::CanEverRender() ) { DrawHUD(); // No need to do work to determine hit box candidates if there will never be any if (HitBoxMap.Num() > 0) { ULocalPlayer* LocalPlayer = GetOwningPlayerController() ? Cast<ULocalPlayer>(GetOwningPlayerController()->Player) : NULL; if (LocalPlayer && LocalPlayer->ViewportClient) { TArray<FVector2D> ContactPoints; if (!FSlateApplication::Get().IsFakingTouchEvents()) { FVector2D MousePosition; if (LocalPlayer->ViewportClient->GetMousePosition(MousePosition)) { ContactPoints.Add(MousePosition); } } for (int32 FingerIndex = 0; FingerIndex < EKeys::NUM_TOUCH_KEYS; ++FingerIndex) { FVector2D TouchLocation; bool bPressed = false; GetOwningPlayerController()->GetInputTouchState((ETouchIndex::Type)FingerIndex, TouchLocation.X, TouchLocation.Y, bPressed); if (bPressed) { ContactPoints.Add(TouchLocation); } } const FVector2D ContactPointOffset = GetCoordinateOffset(); if (!ContactPointOffset.IsZero()) { for (FVector2D& ContactPoint : ContactPoints) { ContactPoint += ContactPointOffset; } } UpdateHitBoxCandidates( MoveTemp(ContactPoints) ); } } else if (HitBoxesOver.Num() > 0) { // We still need to dispatch any end cursor over messages even if we don't have any hitboxes anymore for (const FName HitBoxName : HitBoxesOver) { NotifyHitBoxEndCursorOver(HitBoxName); } HitBoxesOver.Reset(); } } if( bShowHitBoxDebugInfo ) { RenderHitBoxes( Canvas->Canvas ); } DrawSafeZoneOverlay(); LastHUDRenderTime = GetWorld()->TimeSeconds; }