/** Utility for calculating drag direction when you click on this widget. */ void HWidgetUtilProxy::CalcVectors(FSceneView* SceneView, const FViewportClick& Click, FVector& LocalManDir, FVector& WorldManDir, float& DragDirX, float& DragDirY) { if(Axis == EAxisList::X) { WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::X ); LocalManDir = FVector(1,0,0); } else if(Axis == EAxisList::Y) { WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::Y ); LocalManDir = FVector(0,1,0); } else { WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::Z ); LocalManDir = FVector(0,0,1); } FVector WorldDragDir = WorldManDir; if(Mode == WMM_Rotate) { if( FMath::Abs(Click.GetDirection() | WorldManDir) > KINDA_SMALL_NUMBER ) // If click direction and circle plane are parallel.. can't resolve. { // First, find actual position we clicking on the circle in world space. const FVector ClickPosition = FMath::LinePlaneIntersection( Click.GetOrigin(), Click.GetOrigin() + Click.GetDirection(), WidgetMatrix.GetOrigin(), WorldManDir ); // Then find Radial direction vector (from center to widget to clicked position). FVector RadialDir = ( ClickPosition - WidgetMatrix.GetOrigin() ); RadialDir.Normalize(); // Then tangent in plane is just the cross product. Should always be unit length again because RadialDir and WorlManDir should be orthogonal. WorldDragDir = RadialDir ^ WorldManDir; } } // Transform world-space drag dir to screen space. FVector ScreenDir = SceneView->ViewMatrices.ViewMatrix.TransformVector(WorldDragDir); ScreenDir.Z = 0.0f; if( ScreenDir.IsZero() ) { DragDirX = 0.0f; DragDirY = 0.0f; } else { ScreenDir.Normalize(); DragDirX = ScreenDir.X; DragDirY = ScreenDir.Y; } }
/** Handle a click on the specified editor viewport client */ bool FComponentVisualizerManager::HandleClick(FEditorViewportClient* InViewportClient, HHitProxy* HitProxy, const FViewportClick& Click) { bool bHandled = HandleProxyForComponentVis(InViewportClient, HitProxy, Click); if (bHandled && Click.GetKey() == EKeys::RightMouseButton) { TSharedPtr<SWidget> MenuWidget = GenerateContextMenuForComponentVis(); if (MenuWidget.IsValid()) { TSharedPtr<SEditorViewport> ViewportWidget = InViewportClient->GetEditorViewportWidget(); if (ViewportWidget.IsValid()) { FSlateApplication::Get().PushMenu( ViewportWidget.ToSharedRef(), FWidgetPath(), MenuWidget.ToSharedRef(), FSlateApplication::Get().GetCursorPos(), FPopupTransitionEffect(FPopupTransitionEffect::ContextMenu)); return true; } } } return false; }
void FPhATEdPreviewViewportClient::SimMousePress(FViewport* InViewport, bool bConstrainRotation, FKey Key) { bool bCtrlDown = InViewport->KeyState(EKeys::LeftControl) || InViewport->KeyState(EKeys::RightControl); bool bShiftDown = InViewport->KeyState(EKeys::LeftShift) || InViewport->KeyState(EKeys::RightShift); FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( InViewport, GetScene(), EngineShowFlags )); FSceneView* View = CalcSceneView(&ViewFamily); const FViewportClick Click(View, this, EKeys::Invalid, IE_Released, InViewport->GetMouseX(), InViewport->GetMouseY()); #if DEBUG_CLICK_VIEWPORT SharedData->LastClickOrigin = Click.GetOrigin(); SharedData->LastClickDirection = Click.GetDirection(); #endif SharedData->LastClickPos = Click.GetClickPos(); FHitResult Result(1.f); bool bHit = SharedData->EditorSkelComp->LineTraceComponent(Result, Click.GetOrigin() - Click.GetDirection() * SimGrabCheckDistance, Click.GetOrigin() + Click.GetDirection() * SimGrabCheckDistance, FCollisionQueryParams(NAME_None,true)); if (bHit) { check(Result.Item != INDEX_NONE); FName BoneName = SharedData->PhysicsAsset->SkeletalBodySetups[Result.Item]->BoneName; //UE_LOG(LogPhysics, Warning, TEXT("Hit Bone Name (%s)"), *BoneName.ToString()); // Right mouse is for dragging things around if (Key == EKeys::RightMouseButton) { SharedData->bManipulating = true; DragX = 0.0f; DragY = 0.0f; SimGrabPush = 0.0f; // Update mouse force properties from sim options. SharedData->MouseHandle->LinearDamping = SharedData->EditorSimOptions->HandleLinearDamping; SharedData->MouseHandle->LinearStiffness = SharedData->EditorSimOptions->HandleLinearStiffness; SharedData->MouseHandle->AngularDamping = SharedData->EditorSimOptions->HandleAngularDamping; SharedData->MouseHandle->AngularStiffness = SharedData->EditorSimOptions->HandleAngularStiffness; SharedData->MouseHandle->InterpolationSpeed = SharedData->EditorSimOptions->InterpolationSpeed; // Create handle to object. SharedData->MouseHandle->GrabComponentAtLocationWithRotation(SharedData->EditorSkelComp, BoneName, Result.Location, FRotator::ZeroRotator); FMatrix InvViewMatrix = View->ViewMatrices.ViewMatrix.InverseFast(); SimGrabMinPush = SimMinHoldDistance - (Result.Time * SimGrabCheckDistance); SimGrabLocation = Result.Location; SimGrabX = InvViewMatrix.GetUnitAxis( EAxis::X ); SimGrabY = InvViewMatrix.GetUnitAxis( EAxis::Y ); SimGrabZ = InvViewMatrix.GetUnitAxis( EAxis::Z ); } // Left mouse is for poking things else if (Key == EKeys::LeftMouseButton) { SharedData->EditorSkelComp->AddImpulseAtLocation(Click.GetDirection() * SharedData->EditorSimOptions->PokeStrength, Result.Location, BoneName); } } }
bool FSplineComponentVisualizer::VisProxyHandleClick(FLevelEditorViewportClient* InViewportClient, HComponentVisProxy* VisProxy, const FViewportClick& Click) { if(VisProxy && VisProxy->Component.IsValid()) { const USplineComponent* SplineComp = CastChecked<const USplineComponent>(VisProxy->Component.Get()); SplineCompPropName = GetComponentPropertyName(SplineComp); if(SplineCompPropName.IsValid()) { AActor* OldSplineOwningActor = SplineOwningActor.Get(); SplineOwningActor = SplineComp->GetOwner(); if (OldSplineOwningActor != SplineOwningActor) { // Reset selection state if we are selecting a different actor to the one previously selected ChangeSelectionState(INDEX_NONE, false); SelectedSegmentIndex = INDEX_NONE; SelectedTangentHandle = INDEX_NONE; SelectedTangentHandleType = ESelectedTangentHandle::None; } if (VisProxy->IsA(HSplineKeyProxy::StaticGetType())) { // Control point clicked HSplineKeyProxy* KeyProxy = (HSplineKeyProxy*)VisProxy; // Modify the selection state, unless right-clicking on an already selected key if (Click.GetKey() != EKeys::RightMouseButton || !SelectedKeys.Contains(KeyProxy->KeyIndex)) { ChangeSelectionState(KeyProxy->KeyIndex, InViewportClient->IsCtrlPressed()); } SelectedSegmentIndex = INDEX_NONE; SelectedTangentHandle = INDEX_NONE; SelectedTangentHandleType = ESelectedTangentHandle::None; if (LastKeyIndexSelected == INDEX_NONE) { SplineOwningActor = nullptr; return false; } CachedRotation = SplineComp->GetQuaternionAtSplinePoint(LastKeyIndexSelected, ESplineCoordinateSpace::World); return true; } else if (VisProxy->IsA(HSplineSegmentProxy::StaticGetType())) { // Spline segment clicked // Divide segment into subsegments and test each subsegment against ray representing click position and camera direction. // Closest encounter with the spline determines the spline position. const int32 NumSubdivisions = 16; HSplineSegmentProxy* SegmentProxy = (HSplineSegmentProxy*)VisProxy; ChangeSelectionState(SegmentProxy->SegmentIndex, InViewportClient->IsCtrlPressed()); SelectedSegmentIndex = SegmentProxy->SegmentIndex; SelectedTangentHandle = INDEX_NONE; SelectedTangentHandleType = ESelectedTangentHandle::None; if (LastKeyIndexSelected == INDEX_NONE) { SplineOwningActor = nullptr; return false; } CachedRotation = SplineComp->GetQuaternionAtSplinePoint(LastKeyIndexSelected, ESplineCoordinateSpace::World); float SubsegmentStartKey = static_cast<float>(SelectedSegmentIndex); FVector SubsegmentStart = SplineComp->GetLocationAtSplineInputKey(SubsegmentStartKey, ESplineCoordinateSpace::World); float ClosestDistance = TNumericLimits<float>::Max(); FVector BestLocation = SubsegmentStart; for (int32 Step = 1; Step < NumSubdivisions; Step++) { const float SubsegmentEndKey = SelectedSegmentIndex + Step / static_cast<float>(NumSubdivisions); const FVector SubsegmentEnd = SplineComp->GetLocationAtSplineInputKey(SubsegmentEndKey, ESplineCoordinateSpace::World); FVector SplineClosest; FVector RayClosest; FMath::SegmentDistToSegmentSafe(SubsegmentStart, SubsegmentEnd, Click.GetOrigin(), Click.GetOrigin() + Click.GetDirection() * 50000.0f, SplineClosest, RayClosest); const float Distance = FVector::DistSquared(SplineClosest, RayClosest); if (Distance < ClosestDistance) { ClosestDistance = Distance; BestLocation = SplineClosest; } SubsegmentStartKey = SubsegmentEndKey; SubsegmentStart = SubsegmentEnd; } SelectedSplinePosition = BestLocation; return true; } else if (VisProxy->IsA(HSplineTangentHandleProxy::StaticGetType())) { // Tangent handle clicked HSplineTangentHandleProxy* KeyProxy = (HSplineTangentHandleProxy*)VisProxy; // Note: don't change key selection when a tangent handle is clicked SelectedSegmentIndex = INDEX_NONE; SelectedTangentHandle = KeyProxy->KeyIndex; SelectedTangentHandleType = KeyProxy->bArriveTangent ? ESelectedTangentHandle::Arrive : ESelectedTangentHandle::Leave; CachedRotation = SplineComp->GetQuaternionAtSplinePoint(SelectedTangentHandle, ESplineCoordinateSpace::World); return true; } } else { SplineOwningActor = nullptr; } } return false; }
bool FPlacementMode::HandleClick(FEditorViewportClient* InViewportClient, HHitProxy *HitProxy, const FViewportClick &Click ) { bool Handled = false; if ( IsCurrentlyPlacing() ) { if ( Click.GetKey() == EKeys::LeftMouseButton ) { TArray< UObject* > Assets; for (int Index = 0; Index < AssetsToPlace.Num(); Index++) { if ( AssetsToPlace[Index].IsValid() ) { Assets.Add( AssetsToPlace[Index].Get() ); } } TArray<AActor*> OutNewActors; const bool bCreateDropPreview = false; const bool SelectActor = false; const FViewport* const Viewport = Click.GetViewportClient()->Viewport; bool AllAssetsCanBeDropped = true; // Determine if we can drop the assets for ( auto AssetIt = Assets.CreateConstIterator(); AssetIt; ++AssetIt ) { UObject* Asset = *AssetIt; FDropQuery DropResult = InViewportClient->CanDropObjectsAtCoordinates( Viewport->GetMouseX(), Viewport->GetMouseY(), FAssetData( Asset ) ); if ( !DropResult.bCanDrop ) { // At least one of the assets can't be dropped. InViewportClient->DestroyDropPreviewActors(); AllAssetsCanBeDropped = false; CreatedPreviewActors = false; } } if ( AllAssetsCanBeDropped ) { if ( !Click.IsControlDown() ) { ClearAssetsToPlace(); IPlacementModeModule::Get().BroadcastStoppedPlacing( true ); InViewportClient->SetRequiredCursorOverride( true, EMouseCursor::GrabHand ); } InViewportClient->DropObjectsAtCoordinates( Viewport->GetMouseX(), Viewport->GetMouseY(), Assets, OutNewActors, false, bCreateDropPreview, SelectActor, PlacementFactory.Get() ); for (int Index = 0; Index < OutNewActors.Num(); Index++) { if ( OutNewActors[Index] != NULL ) { PlacedActorsThisTrackingSession = true; PlacedActors.Add( OutNewActors[Index] ); } } if ( !Click.IsControlDown() ) { SelectPlacedActors(); ClearAssetsToPlace(); } Handled = true; } } else { InViewportClient->DestroyDropPreviewActors(); CreatedPreviewActors = false; StopPlacing(); } } if ( !Handled ) { Handled = FEdMode::HandleClick(InViewportClient, HitProxy, Click); } return Handled; }
bool FSpriteGeometryEditMode::HandleClick(FEditorViewportClient* InViewportClient, HHitProxy* HitProxy, const FViewportClick& Click) { FViewport* Viewport = InViewportClient->Viewport; const bool bIsCtrlKeyDown = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl); const bool bIsShiftKeyDown = Viewport->KeyState(EKeys::LeftShift) || Viewport->KeyState(EKeys::RightShift); const bool bIsAltKeyDown = Viewport->KeyState(EKeys::LeftAlt) || Viewport->KeyState(EKeys::RightAlt); bool bHandled = false; const bool bAllowSelectVertex = !(IsEditingGeometry() && SpriteGeometryHelper.IsAddingPolygon()) && !bIsShiftKeyDown; const bool bClearSelectionModifier = bIsCtrlKeyDown; const bool bDeleteClickedVertex = bIsAltKeyDown; const bool bInsertVertexModifier = bIsShiftKeyDown; HSpriteSelectableObjectHitProxy* SelectedItemProxy = HitProxyCast<HSpriteSelectableObjectHitProxy>(HitProxy); if (bAllowSelectVertex && (SelectedItemProxy != nullptr)) { if (!bClearSelectionModifier) { SpriteGeometryHelper.ClearSelectionSet(); } if (bDeleteClickedVertex) { // Delete selection if (const FSpriteSelectedVertex* SelectedVertex = SelectedItemProxy->Data->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex)) { SpriteGeometryHelper.ClearSelectionSet(); SpriteGeometryHelper.AddPolygonVertexToSelection(SelectedVertex->ShapeIndex, SelectedVertex->VertexIndex); SpriteGeometryHelper.DeleteSelectedItems(); } else if (const FSpriteSelectedShape* SelectedShape = SelectedItemProxy->Data->CastTo<const FSpriteSelectedShape>(FSelectionTypes::GeometryShape)) { SpriteGeometryHelper.ClearSelectionSet(); SpriteGeometryHelper.AddShapeToSelection(SelectedShape->ShapeIndex); SpriteGeometryHelper.DeleteSelectedItems(); } } else if (Click.GetEvent() == EInputEvent::IE_DoubleClick) { // Double click to select a polygon if (const FSpriteSelectedVertex* SelectedVertex = SelectedItemProxy->Data->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex)) { SpriteGeometryHelper.ClearSelectionSet(); SpriteGeometryHelper.AddShapeToSelection(SelectedVertex->ShapeIndex); } } else { //@TODO: This needs to be generalized! if (const FSpriteSelectedEdge* SelectedEdge = SelectedItemProxy->Data->CastTo<const FSpriteSelectedEdge>(FSelectionTypes::Edge)) { // Add the next vertex defined by this edge SpriteGeometryHelper.AddPolygonEdgeToSelection(SelectedEdge->ShapeIndex, SelectedEdge->VertexIndex); } else if (const FSpriteSelectedVertex* SelectedVertex = SelectedItemProxy->Data->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex)) { SpriteGeometryHelper.AddPolygonVertexToSelection(SelectedVertex->ShapeIndex, SelectedVertex->VertexIndex); } else if (const FSpriteSelectedShape* SelectedShape = SelectedItemProxy->Data->CastTo<const FSpriteSelectedShape>(FSelectionTypes::GeometryShape)) { SpriteGeometryHelper.AddShapeToSelection(SelectedShape->ShapeIndex); } else { SpriteGeometryHelper.SelectItem(SelectedItemProxy->Data); } } bHandled = true; } // else if (HWidgetUtilProxy* PivotProxy = HitProxyCast<HWidgetUtilProxy>(HitProxy)) // { // //const bool bUserWantsPaint = bIsLeftButtonDown && ( !GetDefault<ULevelEditorViewportSettings>()->bLeftMouseDragMovesCamera || bIsCtrlDown ); // //findme // WidgetAxis = WidgetProxy->Axis; // // // Calculate the screen-space directions for this drag. // FSceneViewFamilyContext ViewFamily( FSceneViewFamily::ConstructionValues( Viewport, GetScene(), EngineShowFlags )); // FSceneView* View = CalcSceneView(&ViewFamily); // WidgetProxy->CalcVectors(View, FViewportClick(View, this, Key, Event, HitX, HitY), LocalManipulateDir, WorldManipulateDir, DragX, DragY); // bHandled = true; // } else { if (IsEditingGeometry() && !SpriteGeometryHelper.IsAddingPolygon()) { FSpriteGeometryCollection* Geometry = SpriteGeometryHelper.GetGeometryBeingEdited(); if (bInsertVertexModifier) { const FPlane SpritePlane(PaperAxisX, FVector::ZeroVector, PaperAxisY); const FVector WorldPoint = FMath::LinePlaneIntersection(Click.GetOrigin(), Click.GetOrigin() + Click.GetDirection(), SpritePlane); const FVector2D SpriteSpaceClickPoint = SpriteGeometryHelper.GetEditorContext()->WorldSpaceToTextureSpace(WorldPoint); // find a polygon to add vert to bool bFoundShapeToAddTo = false; for (TSharedPtr<FSelectedItem> SelectedItemPtr : SpriteGeometryHelper.GetSelectionSet()) { if (const FSpriteSelectedVertex* SelectedVertex = SelectedItemPtr->CastTo<const FSpriteSelectedVertex>(FSelectionTypes::Vertex)) //@TODO: Inflexible? { SpriteGeometryHelper.AddPointToGeometry(SpriteSpaceClickPoint, SelectedVertex->ShapeIndex); bFoundShapeToAddTo = true; break; } } if (!bFoundShapeToAddTo) { SpriteGeometryHelper.AddPointToGeometry(SpriteSpaceClickPoint); } bHandled = true; } } else if (!IsEditingGeometry()) { // Clicked on the background (missed any proxies), deselect the socket or whatever was selected SpriteGeometryHelper.ClearSelectionSet(); } } return bHandled ? true : FEdMode::HandleClick(InViewportClient, HitProxy, Click); }