void FUMGViewportClient::Draw(FViewport* InViewport, FCanvas* Canvas) { FViewport* ViewportBackup = Viewport; Viewport = InViewport ? InViewport : Viewport; // Determine whether we should use world time or real time based on the scene. float TimeSeconds; float RealTimeSeconds; float DeltaTimeSeconds; const bool bIsRealTime = true; UWorld* World = GWorld; if ( ( GetScene() != World->Scene ) || ( bIsRealTime == true ) ) { // Use time relative to start time to avoid issues with float vs double TimeSeconds = FApp::GetCurrentTime() - GStartTime; RealTimeSeconds = FApp::GetCurrentTime() - GStartTime; DeltaTimeSeconds = FApp::GetDeltaTime(); } else { TimeSeconds = World->GetTimeSeconds(); RealTimeSeconds = World->GetRealTimeSeconds(); DeltaTimeSeconds = World->GetDeltaSeconds(); } // Setup a FSceneViewFamily/FSceneView for the viewport. FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( Canvas->GetRenderTarget(), GetScene(), EngineShowFlags) .SetWorldTimes(TimeSeconds, DeltaTimeSeconds, RealTimeSeconds) .SetRealtimeUpdate(bIsRealTime)); ViewFamily.EngineShowFlags = EngineShowFlags; //UpdateLightingShowFlags(ViewFamily.EngineShowFlags); //ViewFamily.ExposureSettings = ExposureSettings; //ViewFamily.LandscapeLODOverride = LandscapeLODOverride; FSceneView* View = CalcSceneView(&ViewFamily); //SetupViewForRendering(ViewFamily, *View); FSlateRect SafeFrame; View->CameraConstrainedViewRect = View->UnscaledViewRect; //if ( CalculateEditorConstrainedViewRect(SafeFrame, Viewport) ) //{ // View->CameraConstrainedViewRect = FIntRect(SafeFrame.Left, SafeFrame.Top, SafeFrame.Right, SafeFrame.Bottom); //} if ( IsAspectRatioConstrained() ) { // Clear the background to black if the aspect ratio is constrained, as the scene view won't write to all pixels. Canvas->Clear(FLinearColor::Black); } Canvas->Clear(BackgroundColor); GetRendererModule().BeginRenderingViewFamily(Canvas, &ViewFamily); // Remove temporary debug lines. // Possibly a hack. Lines may get added without the scene being rendered etc. if ( World->LineBatcher != NULL && ( World->LineBatcher->BatchedLines.Num() || World->LineBatcher->BatchedPoints.Num() ) ) { World->LineBatcher->Flush(); } if ( World->ForegroundLineBatcher != NULL && ( World->ForegroundLineBatcher->BatchedLines.Num() || World->ForegroundLineBatcher->BatchedPoints.Num() ) ) { World->ForegroundLineBatcher->Flush(); } //FCanvas* DebugCanvas = Viewport->GetDebugCanvas(); //UDebugDrawService::Draw(ViewFamily.EngineShowFlags, Viewport, View, DebugCanvas); // //FlushRenderingCommands(); Viewport = ViewportBackup; }
void FJavascriptUMGViewportClient::Draw(FViewport* InViewport, FCanvas* Canvas) { FViewport* ViewportBackup = Viewport; Viewport = InViewport ? InViewport : Viewport; // Determine whether we should use world time or real time based on the scene. float TimeSeconds; float RealTimeSeconds; float DeltaTimeSeconds; const bool bIsRealTime = true; UWorld* World = GWorld; if ((GetScene() != World->Scene) || (bIsRealTime == true)) { // Use time relative to start time to avoid issues with float vs double TimeSeconds = FApp::GetCurrentTime() - GStartTime; RealTimeSeconds = FApp::GetCurrentTime() - GStartTime; DeltaTimeSeconds = FApp::GetDeltaTime(); } else { TimeSeconds = World->GetTimeSeconds(); RealTimeSeconds = World->GetRealTimeSeconds(); DeltaTimeSeconds = World->GetDeltaSeconds(); } // Setup a FSceneViewFamily/FSceneView for the viewport. FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( Canvas->GetRenderTarget(), GetScene(), EngineShowFlags) .SetWorldTimes(TimeSeconds, DeltaTimeSeconds, RealTimeSeconds) .SetRealtimeUpdate(bIsRealTime)); ViewFamily.EngineShowFlags = EngineShowFlags; //UpdateLightingShowFlags(ViewFamily.EngineShowFlags); //ViewFamily.ExposureSettings = ExposureSettings; //ViewFamily.LandscapeLODOverride = LandscapeLODOverride; FSceneView* View = CalcSceneView(&ViewFamily); //SetupViewForRendering(ViewFamily, *View); FSlateRect SafeFrame; View->CameraConstrainedViewRect = View->UnscaledViewRect; //if ( CalculateEditorConstrainedViewRect(SafeFrame, Viewport) ) //{ // View->CameraConstrainedViewRect = FIntRect(SafeFrame.Left, SafeFrame.Top, SafeFrame.Right, SafeFrame.Bottom); //} if (IsAspectRatioConstrained()) { // Clear the background to black if the aspect ratio is constrained, as the scene view won't write to all pixels. Canvas->Clear(FLinearColor::Black); } Canvas->Clear(BackgroundColor); // workaround for hacky renderer code that uses GFrameNumber to decide whether to resize render targets --GFrameNumber; GetRendererModule().BeginRenderingViewFamily(Canvas, &ViewFamily); Viewport = ViewportBackup; }
/* After release of left mouse button, check if this unit is within selection box. */ void ARTSUnit::CheckForSelection() { /* Find screen coordinates of the unit. */ FVector2D MyResult = FVector2D(0, 0); ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(PC->Player); if (LocalPlayer != NULL && LocalPlayer->ViewportClient != NULL && LocalPlayer->ViewportClient->Viewport != NULL) { FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( LocalPlayer->ViewportClient->Viewport, GetWorld()->Scene, LocalPlayer->ViewportClient->EngineShowFlags) .SetRealtimeUpdate(true)); FVector ViewLocation; FRotator ViewRotation; FSceneView* SceneView = LocalPlayer->CalcSceneView(&ViewFamily, /*out*/ ViewLocation, /*out*/ ViewRotation, LocalPlayer->ViewportClient->Viewport); if (SceneView) { auto MyWorldPosition = GetActorLocation(); MyResult; SceneView->WorldToPixel(MyWorldPosition, MyResult); } } /* If the selection box contains the screen postion: */ if (ARTSHUD::SelectionContainsPoint(MyResult)){ // Select this unit, and leave possibility to select others. Select(); } }
void UBlendSpaceThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* RenderTarget, FCanvas* Canvas) { UBlendSpaceBase* BlendSpace = Cast<UBlendSpaceBase>(Object); if (BlendSpace != nullptr) { if (ThumbnailScene == nullptr) { ThumbnailScene = new FBlendSpaceThumbnailScene(); } if (ThumbnailScene->SetBlendSpace(BlendSpace)) { FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(RenderTarget, ThumbnailScene->GetScene(), FEngineShowFlags(ESFIM_Game)) .SetWorldTimes(FApp::GetCurrentTime() - GStartTime, FApp::GetDeltaTime(), FApp::GetCurrentTime() - GStartTime)); ViewFamily.EngineShowFlags.DisableAdvancedFeatures(); ViewFamily.EngineShowFlags.MotionBlur = 0; ViewFamily.EngineShowFlags.LOD = 0; ThumbnailScene->GetView(&ViewFamily, X, Y, Width, Height); GetRendererModule().BeginRenderingViewFamily(Canvas, &ViewFamily); ThumbnailScene->SetBlendSpace(nullptr); } } }
void UStaticMeshThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* RenderTarget, FCanvas* Canvas) { UStaticMesh* StaticMesh = Cast<UStaticMesh>(Object); if (StaticMesh != nullptr && !StaticMesh->IsPendingKill()) { if ( ThumbnailScene == nullptr ) { ThumbnailScene = new FStaticMeshThumbnailScene(); } ThumbnailScene->SetStaticMesh(StaticMesh); ThumbnailScene->GetScene()->UpdateSpeedTreeWind(0.0); FSceneViewFamilyContext ViewFamily( FSceneViewFamily::ConstructionValues( RenderTarget, ThumbnailScene->GetScene(), FEngineShowFlags(ESFIM_Game) ) .SetWorldTimes(FApp::GetCurrentTime() - GStartTime, FApp::GetDeltaTime(), FApp::GetCurrentTime() - GStartTime)); ViewFamily.EngineShowFlags.DisableAdvancedFeatures(); ViewFamily.EngineShowFlags.MotionBlur = 0; ViewFamily.EngineShowFlags.LOD = 0; ThumbnailScene->GetView(&ViewFamily, X, Y, Width, Height); GetRendererModule().BeginRenderingViewFamily(Canvas,&ViewFamily); ThumbnailScene->SetStaticMesh(nullptr); } }
FVector2D AHUD::GetCoordinateOffset() const { FVector2D Offset(0.f, 0.f); ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(GetOwningPlayerController()->Player); if (LocalPlayer) { // Create a view family for the game viewport FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( LocalPlayer->ViewportClient->Viewport, GetWorld()->Scene, LocalPlayer->ViewportClient->EngineShowFlags) .SetRealtimeUpdate(true)); // Calculate a view where the player is to update the streaming from the players start location FVector ViewLocation; FRotator ViewRotation; FSceneView* SceneView = LocalPlayer->CalcSceneView(&ViewFamily, /*out*/ ViewLocation, /*out*/ ViewRotation, LocalPlayer->ViewportClient->Viewport); if (SceneView) { Offset.X = (SceneView->ViewRect.Min.X - SceneView->UnscaledViewRect.Min.X) // This accounts for the borders when the aspect ratio is locked - SceneView->UnscaledViewRect.Min.X; // And this will deal with the viewport offset if its a split screen Offset.Y = (SceneView->ViewRect.Min.Y - SceneView->UnscaledViewRect.Min.Y) - SceneView->UnscaledViewRect.Min.Y; } } return Offset; }
void UMaterialFunctionThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* RenderTarget, FCanvas* Canvas) { UMaterialFunction* MatFunc = Cast<UMaterialFunction>(Object); if (MatFunc != nullptr) { if ( ThumbnailScene == nullptr ) { ThumbnailScene = new FMaterialThumbnailScene(); } UMaterial* PreviewMaterial = MatFunc->GetPreviewMaterial(); if( PreviewMaterial ) { PreviewMaterial->ThumbnailInfo = MatFunc->ThumbnailInfo; ThumbnailScene->SetMaterialInterface( PreviewMaterial ); FSceneViewFamilyContext ViewFamily( FSceneViewFamily::ConstructionValues( RenderTarget, ThumbnailScene->GetScene(), FEngineShowFlags(ESFIM_Game) ) .SetWorldTimes(FApp::GetCurrentTime() - GStartTime, FApp::GetDeltaTime(), FApp::GetCurrentTime() - GStartTime)); ViewFamily.EngineShowFlags.DisableAdvancedFeatures(); ViewFamily.EngineShowFlags.MotionBlur = 0; ThumbnailScene->GetView(&ViewFamily, X, Y, Width, Height); if (ViewFamily.Views.Num() > 0) { GetRendererModule().BeginRenderingViewFamily(Canvas,&ViewFamily); } ThumbnailScene->SetMaterialInterface(nullptr); } } }
bool FCascadeEdPreviewViewportClient::InputKey(FViewport* Viewport, int32 ControllerId, FKey Key, EInputEvent Event, float AmountDepressed, bool Gamepad) { //Update cursor UpdateAndApplyCursorVisibility(); bool bHandled = false; const int32 HitX = Viewport->GetMouseX(); const int32 HitY = Viewport->GetMouseY(); if(Key == EKeys::LeftMouseButton) { if (Event == IE_Pressed) { Viewport->InvalidateHitProxy(); HHitProxy* HitResult = Viewport->GetHitProxy(HitX,HitY); if (HitResult && HitResult->IsA(HWidgetUtilProxy::StaticGetType())) { HWidgetUtilProxy* WidgetProxy = (HWidgetUtilProxy*)HitResult; if (WidgetProxy->Info1 == VectorFieldHitproxyInfo) { bManipulatingVectorField = true; } WidgetAxis = WidgetProxy->Axis; // Calculate the scree-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 (Event == IE_Released) { if (bManipulatingVectorField) { WidgetAxis = EAxisList::None; bManipulatingVectorField = false; bHandled = true; } } } else if (Key == EKeys::SpaceBar && Event == IE_Pressed) { if (CascadePtr.Pin()->GetSelectedModule() && CascadePtr.Pin()->GetSelectedModule()->IsA(UParticleModuleVectorFieldLocal::StaticClass())) { bHandled = true; WidgetMM = (EWidgetMovementMode)((WidgetMM+1) % WMM_MAX); } } if( !bHandled ) { bHandled = FEditorViewportClient::InputKey(Viewport,ControllerId,Key,Event,AmountDepressed,Gamepad); } return bHandled; }
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 FSpriteGeometryEditMode::InputKey(FEditorViewportClient* ViewportClient, FViewport* Viewport, FKey Key, EInputEvent Event) { bool bHandled = false; FInputEventState InputState(Viewport, Key, Event); // Handle marquee tracking in source region edit mode if (IsEditingGeometry()) { if (SpriteGeometryHelper.IsAddingPolygon()) { if (Key == EKeys::LeftMouseButton) { const int32 HitX = Viewport->GetMouseX(); const int32 HitY = Viewport->GetMouseY(); // Calculate the texture space position of the mouse click FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags)); FSceneView* View = ViewportClient->CalcSceneView(&ViewFamily); const FVector WorldPoint = View->PixelToWorld(HitX, HitY, 0); const FVector2D TexturePoint = SpriteGeometryHelper.GetEditorContext()->WorldSpaceToTextureSpace(WorldPoint); // Add or close the polygon (depending on where the click happened and how) const bool bMakeSubtractiveIfAllowed = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl); SpriteGeometryHelper.HandleAddPolygonClick(TexturePoint, bMakeSubtractiveIfAllowed, *View, Event); } else if ((Key == EKeys::BackSpace) && (Event == IE_Pressed)) { SpriteGeometryHelper.DeleteLastVertexFromAddPolygonMode(); } else if (Key == EKeys::Enter) { SpriteGeometryHelper.ResetAddPolygonMode(); } else if (Key == EKeys::Escape) { SpriteGeometryHelper.AbandonAddPolygonMode(); } } else { if (ProcessMarquee(Viewport, Key, Event, true)) { const bool bAddingToSelection = InputState.IsShiftButtonPressed(); //@TODO: control button moves widget? Hopefully make this more consistent when that is changed SelectVerticesInMarquee(ViewportClient, Viewport, bAddingToSelection); } } } //@TODO: Support select-and-drag in a single operation (may involve InputAxis and StartTracking) // Pass keys to standard controls, if we didn't consume input return bHandled ? true : FEdMode::InputKey(ViewportClient, Viewport, Key, Event); }
void AEyeXSimpleInteractorPawn::UpdateRegion() { FVector Origin; FVector Extents; GetActorBounds(false, Origin, Extents); auto playerController = Cast<APlayerController>(Controller); ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(playerController->Player); auto ViewFamilyArguments = FSceneViewFamily::ConstructionValues(LocalPlayer->ViewportClient->Viewport, GetWorld()->Scene, LocalPlayer->ViewportClient->EngineShowFlags); ViewFamilyArguments.SetRealtimeUpdate(true); FSceneViewFamilyContext ViewFamily(ViewFamilyArguments); // Calculate a view where the player is to update the streaming from the players start location FVector ViewLocation; FRotator ViewRotation; FSceneView* SceneView = LocalPlayer->CalcSceneView(&ViewFamily, /*out*/ ViewLocation, /*out*/ ViewRotation, LocalPlayer->ViewportClient->Viewport); FVector2D ExtentPoints[8]; SceneView->WorldToPixel(Origin + FVector(Extents.X, Extents.Y, Extents.Z), ExtentPoints[0]); //Right Top Front SceneView->WorldToPixel(Origin + FVector(Extents.X, Extents.Y, -Extents.Z), ExtentPoints[1]); //Right Top Back SceneView->WorldToPixel(Origin + FVector(Extents.X, -Extents.Y, Extents.Z), ExtentPoints[2]); //Right Bottom Front SceneView->WorldToPixel(Origin + FVector(Extents.X, -Extents.Y, -Extents.Z), ExtentPoints[3]); //Right Bottom Back SceneView->WorldToPixel(Origin + FVector(-Extents.X, Extents.Y, Extents.Z), ExtentPoints[4]); //Left Top Front SceneView->WorldToPixel(Origin + FVector(-Extents.X, Extents.Y, -Extents.Z), ExtentPoints[5]); //Left Top Back SceneView->WorldToPixel(Origin + FVector(-Extents.X, -Extents.Y, Extents.Z), ExtentPoints[6]); //Left Bottom Front SceneView->WorldToPixel(Origin + FVector(-Extents.X, -Extents.Y, -Extents.Z), ExtentPoints[7]); //Left Bottom Back FVector2D TopLeft = FVector2D(std::numeric_limits<float>::max(), std::numeric_limits<float>::max()); FVector2D BottomRight = FVector2D(std::numeric_limits<float>::min(), std::numeric_limits<float>::min()); for (auto Point : ExtentPoints) { if (Point.X < TopLeft.X) TopLeft.X = Point.X; else if (Point.X > BottomRight.X) BottomRight.X = Point.X; if (Point.Y < TopLeft.Y) TopLeft.Y = Point.Y; else if (Point.Y > BottomRight.Y) BottomRight.Y = Point.Y; } MyRegion->bounds.left = TopLeft.X; MyRegion->bounds.top = TopLeft.Y; MyRegion->bounds.right = BottomRight.X; MyRegion->bounds.bottom = BottomRight.Y; }
bool FVertexSnappingImpl::SnapDragLocationToNearestVertex( const FVector& BaseLocation, FVector& DragDelta, FLevelEditorViewportClient* ViewportClient ) { int32 MouseX = ViewportClient->Viewport->GetMouseX(); int32 MouseY = ViewportClient->Viewport->GetMouseY(); FVector2D MousePosition = FVector2D( MouseX, MouseY ) ; EAxisList::Type CurrentAxis = ViewportClient->GetCurrentWidgetAxis(); bool bSnapped = false; if( !DragDelta.IsNearlyZero() ) { FVector Direction = DragDelta.GetSafeNormal(); FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( ViewportClient->Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags ) .SetRealtimeUpdate( ViewportClient->IsRealtime() )); FSceneView* View = ViewportClient->CalcSceneView( &ViewFamily ); FVector DesiredUnsnappedLocation = BaseLocation+DragDelta; FBoxSphereBounds SnappingAreaBox( FBox( DesiredUnsnappedLocation-VertexSnappingConstants::MaxSnappingDistance, DesiredUnsnappedLocation+VertexSnappingConstants::MaxSnappingDistance ) ); FBox AllowedSnappingBox = SnappingAreaBox.GetBox(); AllowedSnappingBox += DragDelta; FPlane ActorPlane( DesiredUnsnappedLocation, Direction ); TSet< TWeakObjectPtr<AActor> > NoActorsToIgnore; FVertexSnappingArgs Args ( ActorPlane, DesiredUnsnappedLocation, ViewportClient, View, MousePosition, CurrentAxis, true ); SnapDragDelta( Args, BaseLocation, AllowedSnappingBox, NoActorsToIgnore, DragDelta ); } return bSnapped; }
bool FVertexSnappingImpl::SnapLocationToNearestVertex( FVector& Location, const FVector2D& MouseLocation, FLevelEditorViewportClient* ViewportClient, FVector& OutVertexNormal, bool bDrawVertexHelpers ) { bool bSnapped = false; // Make a box around the actor which is the area we are allowed to snap in FBox AllowedSnappingBox = FBox( Location-VertexSnappingConstants::MaxSnappingDistance, Location+VertexSnappingConstants::MaxSnappingDistance ); FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( ViewportClient->Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags ) .SetRealtimeUpdate( ViewportClient->IsRealtime() )); FSceneView* View = ViewportClient->CalcSceneView( &ViewFamily ); TArray<FSnapActor> ActorsInBox; TSet<TWeakObjectPtr<AActor> > ActorsToIgnore; // Ignore actors currently being moved ActorsToIgnore.Append( ViewportClient->GetDropPreviewActors() ); GetPossibleSnapActors( AllowedSnappingBox, MouseLocation.IntPoint(), ViewportClient, View, EAxisList::Screen, ActorsToIgnore, ActorsInBox ); FViewportCursorLocation Cursor(View, ViewportClient, MouseLocation.X, MouseLocation.Y ); FPlane ActorPlane( Location, Cursor.GetDirection() ); FVertexSnappingArgs Args ( ActorPlane, Location, ViewportClient, View, Cursor.GetCursorPos(), EAxisList::Screen, bDrawVertexHelpers ); // Snap to the nearest vertex FSnappingVertex ClosestVertex = GetClosestVertex( ActorsInBox, Args ); Location = ClosestVertex.Position; OutVertexNormal = ClosestVertex.Normal; bSnapped = true; return bSnapped; }
AEyeXActorBase* AEyeXPlayerController::FindFocusedActor(FHitResult& OutHit, const FVector2D& GazePoint) { // Get the scene view to deproject the gazepoint to world space ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(Player); if (!LocalPlayer) return nullptr; FSceneViewFamily ViewFamily(FSceneViewFamily::ConstructionValues( LocalPlayer->ViewportClient->Viewport, GetWorld()->Scene, LocalPlayer->ViewportClient->EngineShowFlags) .SetRealtimeUpdate(true)); FVector ViewLocation; FRotator ViewRotation; FSceneView* View = LocalPlayer->CalcSceneView(&ViewFamily, /*out*/ ViewLocation, /*out*/ ViewRotation, LocalPlayer->ViewportClient->Viewport); // Initiate sweep/trace variables const FCollisionObjectQueryParams ObjectParams(FEyeXUtils::ECCArrayToBitField(CollisionChannels)); const FCollisionQueryParams TraceParams(FName(TEXT("GazeTrace")), true, GetPawn()); FHitResult HitResult; AEyeXActorBase* EyeXActor = nullptr; switch (DetectionMode) { case EEyeXDetectionMode::LineTrace: EyeXActor = FindByLineTrace(HitResult, View, GazePoint, ObjectParams, TraceParams); break; case EEyeXDetectionMode::BoxedLineTrace: EyeXActor = FindByBoxedLineTrace(HitResult, View, GazePoint, ObjectParams, TraceParams); break; case EEyeXDetectionMode::Sweep: EyeXActor = FindBySweep(HitResult, View, GazePoint, ObjectParams, TraceParams); break; case EEyeXDetectionMode::FrustrumIntersection: EyeXActor = FindByFrustumIntersection(HitResult, View, GazePoint, ObjectParams, TraceParams); break; default: break; } OutHit = HitResult; return EyeXActor; // use out param for actor as well, alternatively use hit actor in hit result (with cast). make the method const too. }
void UWorldThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* RenderTarget, FCanvas* Canvas) { UWorld* World = Cast<UWorld>(Object); if (World != nullptr && World->Scene) { FSceneViewFamilyContext ViewFamily( FSceneViewFamily::ConstructionValues( RenderTarget, World->Scene, FEngineShowFlags(ESFIM_All0) ) .SetWorldTimes(FApp::GetCurrentTime() - GStartTime, FApp::GetDeltaTime(), FApp::GetCurrentTime() - GStartTime)); ViewFamily.EngineShowFlags.SetDiffuse(true); ViewFamily.EngineShowFlags.SetSkeletalMeshes(true); ViewFamily.EngineShowFlags.SetTranslucency(true); ViewFamily.EngineShowFlags.SetBillboardSprites(true); ViewFamily.EngineShowFlags.SetLOD(true); ViewFamily.EngineShowFlags.SetMaterials(true); ViewFamily.EngineShowFlags.SetStaticMeshes(true); ViewFamily.EngineShowFlags.SetLandscape(true); ViewFamily.EngineShowFlags.SetGame(true); ViewFamily.EngineShowFlags.SetBSP(true); ViewFamily.EngineShowFlags.SetRendering(true); ViewFamily.EngineShowFlags.SetPaper2DSprites(true); if ( !bUseUnlitScene ) { ViewFamily.EngineShowFlags.SetSpecular(true); ViewFamily.EngineShowFlags.SetLighting(true); ViewFamily.EngineShowFlags.SetDirectLighting(true); ViewFamily.EngineShowFlags.SetIndirectLightingCache(true); ViewFamily.EngineShowFlags.SetDeferredLighting(true); ViewFamily.EngineShowFlags.SetDirectionalLights(true); ViewFamily.EngineShowFlags.SetGlobalIllumination(true); ViewFamily.EngineShowFlags.SetPointLights(true); ViewFamily.EngineShowFlags.SetSpotLights(true); ViewFamily.EngineShowFlags.SetSkyLighting(true); ViewFamily.EngineShowFlags.SetReflectionEnvironment(true); } GetView(World, &ViewFamily, X, Y, Width, Height); if (ViewFamily.Views.Num() > 0) { GetRendererModule().BeginRenderingViewFamily(Canvas, &ViewFamily); } } }
void FPhATEdPreviewViewportClient::TrackingStarted( const struct FInputEventState& InInputState, bool bIsDraggingWidget, bool bNudge ) { // If releasing the mouse button, check we are done manipulating if ( bIsDraggingWidget ) { FSceneViewFamilyContext ViewFamily( FSceneViewFamily::ConstructionValues( Viewport, GetScene(), EngineShowFlags )); FSceneView* View = CalcSceneView(&ViewFamily); const int32 HitX = InInputState.GetViewport()->GetMouseX(); const int32 HitY = InInputState.GetViewport()->GetMouseY(); StartManipulating(Widget->GetCurrentAxis(), FViewportClick(View, this, InInputState.GetKey(), InInputState.GetInputEvent(), HitX, HitY), View->ViewMatrices.ViewMatrix); // If we are manipulating, don't move the camera as we drag now. if (SharedData->bManipulating) { bAllowedToMoveCamera = false; } } }
void ULevelThumbnailRenderer::Draw(UObject* Object, int32 X, int32 Y, uint32 Width, uint32 Height, FRenderTarget* RenderTarget, FCanvas* Canvas) { ULevel* Level = Cast<ULevel>(Object); if (Level != nullptr) { FSceneViewFamilyContext ViewFamily( FSceneViewFamily::ConstructionValues( RenderTarget, Level->OwningWorld->Scene, FEngineShowFlags(ESFIM_Game) ) .SetWorldTimes(GCurrentTime - GStartTime,GDeltaTime,GCurrentTime - GStartTime) ); ViewFamily.EngineShowFlags.DisableAdvancedFeatures(); ViewFamily.EngineShowFlags.MotionBlur = 0; ViewFamily.EngineShowFlags.Lighting = 1; ViewFamily.EngineShowFlags.PostProcessing = 0; GetView(Level, &ViewFamily, X, Y, Width, Height); if (ViewFamily.Views.Num() > 0) { GetRendererModule().BeginRenderingViewFamily(Canvas, &ViewFamily); } } }
void AMouseController::GetCameraRay(FVector& WorldOrigin, FVector& WorldDirection) { ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(Player); FVector2D MousePosition; if (LocalPlayer) { if (!LocalPlayer->ViewportClient->GetMousePosition(MousePosition)) { return; } } // Early out if we clicked on a HUD hitbox if (GetHUD() != NULL && GetHUD()->GetHitBoxAtCoordinates(MousePosition, true)) { return; } if (LocalPlayer != NULL && LocalPlayer->ViewportClient != NULL && LocalPlayer->ViewportClient->Viewport != NULL) { // Create a view family for the game viewport FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( LocalPlayer->ViewportClient->Viewport, GetWorld()->Scene, LocalPlayer->ViewportClient->EngineShowFlags) .SetRealtimeUpdate(true)); // Calculate a view where the player is to update the streaming from the players start location FVector ViewLocation; FRotator ViewRotation; FSceneView* SceneView = LocalPlayer->CalcSceneView(&ViewFamily, /*out*/ ViewLocation, /*out*/ ViewRotation, LocalPlayer->ViewportClient->Viewport); if (SceneView) { SceneView->DeprojectFVector2D(MousePosition, WorldOrigin, WorldDirection); } } }
/** Trace under the mouse cursor and update brush position */ void FEdModeHaste::HasteBrushTrace(FEditorViewportClient* ViewportClient, int32 MouseX, int32 MouseY) { bBrushTraceValid = false; if (!ViewportClient->IsMovingCamera()) { // Compute a world space ray from the screen space mouse coordinates FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( ViewportClient->Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags) .SetRealtimeUpdate(ViewportClient->IsRealtime())); FSceneView* View = ViewportClient->CalcSceneView(&ViewFamily); FViewportCursorLocation MouseViewportRay(View, ViewportClient, MouseX, MouseY); FVector Start = MouseViewportRay.GetOrigin(); BrushTraceDirection = MouseViewportRay.GetDirection(); FVector End = Start + WORLD_MAX * BrushTraceDirection; FHitResult Hit; UWorld* World = ViewportClient->GetWorld(); static FName NAME_HasteBrush = FName(TEXT("HasteBrush")); if (HasteTrace(World, Hit, Start, End, NAME_HasteBrush)) { // Adjust the sphere brush BrushLocation = PerformLocationSnap(Hit.Location); // Find the rotation based on the normal LastHitImpact = Hit.ImpactNormal; UpdateBrushRotation(); bBrushTraceValid = true; } } if (bBrushTraceValid) { BrushCursorTransform = FTransform(BrushRotation, BrushLocation, BrushScale); BrushCursorTransform = ApplyTransformers(BrushCursorTransform); } }
void FPhATEdPreviewViewportClient::SimMouseMove(float DeltaX, float DeltaY) { DragX = Viewport->GetMouseX() - SharedData->LastClickPos.X; DragY = Viewport->GetMouseY() - SharedData->LastClickPos.Y; if (!SharedData->MouseHandle->GrabbedComponent) { return; } //We need to convert Pixel Delta into Screen position (deal with different viewport sizes) FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( Viewport, GetScene(), EngineShowFlags )); FSceneView* View = CalcSceneView(&ViewFamily); FVector4 ScreenOldPos = View->PixelToScreen(SharedData->LastClickPos.X, SharedData->LastClickPos.Y, 1.f); FVector4 ScreenNewPos = View->PixelToScreen(DragX + SharedData->LastClickPos.X, DragY + SharedData->LastClickPos.Y, 1.f); FVector4 ScreenDelta = ScreenNewPos - ScreenOldPos; FVector4 ProjectedDelta = View->ScreenToWorld(ScreenDelta); FVector4 WorldDelta; //Now we project new ScreenPos to xy-plane of SimGrabLocation FVector LocalOffset = View->ViewMatrices.ViewMatrix.TransformPosition(SimGrabLocation + SimGrabZ * SimGrabPush); float ZDistance = GetViewportType() == ELevelViewportType::LVT_Perspective ? fabs(LocalOffset.Z) : 1.f; //in the ortho case we don't need to do any fixup because there is no perspective WorldDelta = ProjectedDelta * ZDistance; //Now we convert back into WorldPos FVector WorldPos = SimGrabLocation + WorldDelta + SimGrabZ * SimGrabPush; FVector NewLocation = WorldPos; float QuickRadius = 5 - SimGrabPush / SimHoldDistanceChangeDelta; QuickRadius = QuickRadius < 2 ? 2 : QuickRadius; DrawDebugPoint(GetWorld(), NewLocation, QuickRadius, FColorList::Red, false, 0.3); SharedData->MouseHandle->SetTargetLocation(NewLocation); SharedData->MouseHandle->GrabbedComponent->WakeRigidBody(SharedData->MouseHandle->GrabbedBoneName); }
FSceneRenderer* FScene::CreateSceneRenderer( USceneCaptureComponent* SceneCaptureComponent, UTextureRenderTarget* TextureTarget, const FMatrix& ViewMatrix, const FVector& ViewLocation, float FOV, float MaxViewDistance, bool bCaptureSceneColour, FPostProcessSettings* PostProcessSettings, float PostProcessBlendWeight ) { FIntPoint CaptureSize(TextureTarget->GetSurfaceWidth(), TextureTarget->GetSurfaceHeight()); FTextureRenderTargetResource* Resource = TextureTarget->GameThread_GetRenderTargetResource(); FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( Resource, this, FEngineShowFlags(ESFIM_Game)) .SetResolveScene(!bCaptureSceneColour)); // Disable features that are not desired when capturing the scene ViewFamily.EngineShowFlags.MotionBlur = 0; // motion blur doesn't work correctly with scene captures. ViewFamily.EngineShowFlags.SeparateTranslucency = 0; ViewFamily.EngineShowFlags.HMDDistortion = 0; FSceneViewInitOptions ViewInitOptions; ViewInitOptions.SetViewRectangle(FIntRect(0, 0, CaptureSize.X, CaptureSize.Y)); ViewInitOptions.ViewFamily = &ViewFamily; ViewInitOptions.ViewMatrix = ViewMatrix; ViewInitOptions.BackgroundColor = FLinearColor::Black; ViewInitOptions.OverrideFarClippingPlaneDistance = MaxViewDistance; if (bCaptureSceneColour) { ViewFamily.EngineShowFlags.PostProcessing = 0; ViewInitOptions.OverlayColor = FLinearColor::Black; } // Build projection matrix { float XAxisMultiplier; float YAxisMultiplier; if (CaptureSize.X > CaptureSize.Y) { // if the viewport is wider than it is tall XAxisMultiplier = 1.0f; YAxisMultiplier = CaptureSize.X / (float)CaptureSize.Y; } else { // if the viewport is taller than it is wide XAxisMultiplier = CaptureSize.Y / (float)CaptureSize.X; YAxisMultiplier = 1.0f; } ViewInitOptions.ProjectionMatrix = FReversedZPerspectiveMatrix ( FOV, FOV, XAxisMultiplier, YAxisMultiplier, GNearClippingPlane, GNearClippingPlane ); } FSceneView* View = new FSceneView(ViewInitOptions); View->bIsSceneCapture = true; check(SceneCaptureComponent); for (auto It = SceneCaptureComponent->HiddenComponents.CreateConstIterator(); It; ++It) { // If the primitive component was destroyed, the weak pointer will return NULL. UPrimitiveComponent* PrimitiveComponent = It->Get(); if (PrimitiveComponent) { View->HiddenPrimitives.Add(PrimitiveComponent->ComponentId); } } ViewFamily.Views.Add(View); View->StartFinalPostprocessSettings(ViewLocation); if (!bCaptureSceneColour) { View->OverridePostProcessSettings(*PostProcessSettings, PostProcessBlendWeight); } View->EndFinalPostprocessSettings(); return FSceneRenderer::CreateSceneRenderer(&ViewFamily, NULL); }
void RenderLandscapeMaterialForLightmass(const FLandscapeStaticLightingMesh* LandscapeMesh, FMaterialRenderProxy* MaterialProxy, const FRenderTarget* RenderTarget) { const ULandscapeComponent* LandscapeComponent = CastChecked<ULandscapeComponent>(LandscapeMesh->Component); const int32 SubsectionSizeQuads = LandscapeComponent->SubsectionSizeQuads; const int32 NumSubsections = LandscapeComponent->NumSubsections; const int32 ComponentSizeQuads = LandscapeComponent->ComponentSizeQuads; int32 PatchExpandCountX = 0; int32 PatchExpandCountY = 0; int32 DesiredSize = 1; const float LightMapOffset = 0.0f; const float LightMapRes = LandscapeComponent->StaticLightingResolution > 0.f ? LandscapeComponent->StaticLightingResolution : LandscapeComponent->GetLandscapeProxy()->StaticLightingResolution; const int32 LightingLOD = LandscapeComponent->GetLandscapeProxy()->StaticLightingLOD; const float LightMapRatio = ::GetTerrainExpandPatchCount(LightMapRes, PatchExpandCountX, PatchExpandCountY, ComponentSizeQuads, (NumSubsections * (SubsectionSizeQuads + 1)), DesiredSize, LightingLOD); const FVector2D PatchExpandOffset = FVector2D((float)PatchExpandCountX / (ComponentSizeQuads + 2 * PatchExpandCountX), (float)PatchExpandCountY / (ComponentSizeQuads + 2 * PatchExpandCountY)) * FVector2D(RenderTarget->GetSizeXY()); const FVector2D PatchExpandScale = FVector2D((float)ComponentSizeQuads / (ComponentSizeQuads + 2 * PatchExpandCountX), (float)ComponentSizeQuads / (ComponentSizeQuads + 2 * PatchExpandCountY)); TArray<FLightmassLandscapeVertex> Vertices; TArray<uint16> Indices; Vertices.Reserve(FMath::Square(NumSubsections) * 4); Indices.Reserve(FMath::Square(NumSubsections) * 6); const float fraction = 1.0f / NumSubsections; const FVector2D PositionScale = FVector2D(RenderTarget->GetSizeXY()) * fraction * PatchExpandScale; const float LayerScale = SubsectionSizeQuads; const float WeightmapSubsection = LandscapeComponent->WeightmapSubsectionOffset; const FVector2D WeightmapBias = FVector2D(LandscapeComponent->WeightmapScaleBias.Z, LandscapeComponent->WeightmapScaleBias.W); const FVector2D WeightmapScale = FVector2D(LandscapeComponent->WeightmapScaleBias.X, LandscapeComponent->WeightmapScaleBias.Y) * SubsectionSizeQuads; const int32 SubsectionX_Start = PatchExpandCountX > 0 ? -1 : 0; const int32 SubsectionX_End = NumSubsections + (PatchExpandCountX > 0 ? 1 : 0); const int32 SubsectionY_Start = PatchExpandCountY > 0 ? -1 : 0; const int32 SubsectionY_End = NumSubsections + (PatchExpandCountY > 0 ? 1 : 0); for (int32 SubsectionY = SubsectionY_Start; SubsectionY < SubsectionY_End; ++SubsectionY) { for (int32 SubsectionX = SubsectionX_Start; SubsectionX < SubsectionX_End; ++SubsectionX) { const FIntPoint UVSubsection = FIntPoint((SubsectionX >= 0 ? SubsectionX : 0), (SubsectionY >= 0 ? SubsectionY : 0)); const FVector2D UVScale = FVector2D((SubsectionX >= 0 && SubsectionX < NumSubsections ? 1 : 0), (SubsectionY >= 0 && SubsectionY < NumSubsections ? 1 : 0)); const FVector2D BasePosition = PatchExpandOffset + FVector2D(SubsectionX, SubsectionY) * PositionScale; const FVector2D BaseLayerCoords = FVector2D(UVSubsection) * LayerScale; const FVector2D BaseWeightmapCoords = WeightmapBias + FVector2D(UVSubsection) * WeightmapSubsection; int32 Index = Vertices.Add(FLightmassLandscapeVertex(FVector(BasePosition /*FVector2D(0, 0) * PositionScale*/, 0), FVector(BaseLayerCoords /*FVector2D(0, 0) * UVScale * LayerScale*/, 0), BaseWeightmapCoords /*FVector2D(0, 0) * UVScale * WeightmapScale*/)); verifySlow( Vertices.Add(FLightmassLandscapeVertex(FVector(BasePosition + FVector2D(1, 0) * PositionScale, 0), FVector(BaseLayerCoords + FVector2D(1, 0) * UVScale * LayerScale, 0), BaseWeightmapCoords + FVector2D(1, 0) * UVScale * WeightmapScale )) == Index + 1); verifySlow( Vertices.Add(FLightmassLandscapeVertex(FVector(BasePosition + FVector2D(0, 1) * PositionScale, 0), FVector(BaseLayerCoords + FVector2D(0, 1) * UVScale * LayerScale, 0), BaseWeightmapCoords + FVector2D(0, 1) * UVScale * WeightmapScale )) == Index + 2); verifySlow( Vertices.Add(FLightmassLandscapeVertex(FVector(BasePosition + FVector2D(1, 1) * PositionScale, 0), FVector(BaseLayerCoords + FVector2D(1, 1) * UVScale * LayerScale, 0), BaseWeightmapCoords + FVector2D(1, 1) * UVScale * WeightmapScale )) == Index + 3); checkSlow(Index + 3 <= MAX_uint16); Indices.Add(Index); Indices.Add(Index + 3); Indices.Add(Index + 1); Indices.Add(Index); Indices.Add(Index + 2); Indices.Add(Index + 3); } } FMeshBatch MeshElement; MeshElement.DynamicVertexStride = sizeof(FLightmassLandscapeVertex); MeshElement.UseDynamicData = true; MeshElement.bDisableBackfaceCulling = true; MeshElement.CastShadow = false; MeshElement.bWireframe = false; MeshElement.Type = PT_TriangleList; MeshElement.DepthPriorityGroup = SDPG_Foreground; MeshElement.bUseAsOccluder = false; MeshElement.bSelectable = false; MeshElement.DynamicVertexData = Vertices.GetData(); MeshElement.VertexFactory = &LightmassLandscapeVertexFactory; MeshElement.MaterialRenderProxy = MaterialProxy; FMeshBatchElement& BatchElement = MeshElement.Elements[0]; BatchElement.PrimitiveUniformBufferResource = &LightmassLandscapeUniformBuffer; BatchElement.DynamicIndexData = Indices.GetData(); BatchElement.FirstIndex = 0; BatchElement.NumPrimitives = Indices.Num() / 3; BatchElement.MinVertexIndex = 0; BatchElement.MaxVertexIndex = Vertices.Num() - 1; BatchElement.DynamicIndexStride = sizeof(uint16); FSceneViewFamily ViewFamily(FSceneViewFamily::ConstructionValues( RenderTarget, NULL, FEngineShowFlags(ESFIM_Game)) .SetWorldTimes(0, 0, 0) .SetGammaCorrection(RenderTarget->GetDisplayGamma())); const FIntRect ViewRect(FIntPoint(0, 0), RenderTarget->GetSizeXY()); // make a temporary view FSceneViewInitOptions ViewInitOptions; ViewInitOptions.ViewFamily = &ViewFamily; ViewInitOptions.SetViewRectangle(ViewRect); ViewInitOptions.ViewOrigin = FVector::ZeroVector; ViewInitOptions.ViewRotationMatrix = FMatrix::Identity; ViewInitOptions.ProjectionMatrix = FCanvas::CalcBaseTransform2D(RenderTarget->GetSizeXY().X, RenderTarget->GetSizeXY().Y); ViewInitOptions.BackgroundColor = FLinearColor::Black; ViewInitOptions.OverlayColor = FLinearColor::White; FSceneView View(ViewInitOptions); ENQUEUE_UNIQUE_RENDER_COMMAND_ONEPARAMETER( CanvasFlushSetupCommand, const FRenderTarget*, RenderTarget, RenderTarget, { //SCOPED_DRAW_EVENT(RHICmdList, CanvasFlush); // Set the RHI render target. ::SetRenderTarget(RHICmdList, RenderTarget->GetRenderTargetTexture(), FTextureRHIRef()); // disable depth test & writes RHICmdList.SetDepthStencilState(TStaticDepthStencilState<false,CF_Always>::GetRHI()); const FIntRect RTViewRect = FIntRect(0, 0, RenderTarget->GetRenderTargetTexture()->GetSizeX(), RenderTarget->GetRenderTargetTexture()->GetSizeY()); // set viewport to RT size RHICmdList.SetViewport(RTViewRect.Min.X, RTViewRect.Min.Y, 0.0f, RTViewRect.Max.X, RTViewRect.Max.Y, 1.0f); });
void FStaticMeshEditorViewportClient::ProcessClick(class FSceneView& InView, class HHitProxy* HitProxy, FKey Key, EInputEvent Event, uint32 HitX, uint32 HitY) { const bool bCtrlDown = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl); bool ClearSelectedSockets = true; bool ClearSelectedPrims = true; bool ClearSelectedEdges = true; if( HitProxy ) { if(HitProxy->IsA( HSMESocketProxy::StaticGetType() ) ) { HSMESocketProxy* SocketProxy = (HSMESocketProxy*)HitProxy; UStaticMeshSocket* Socket = NULL; if(SocketProxy->SocketIndex < StaticMesh->Sockets.Num()) { Socket = StaticMesh->Sockets[SocketProxy->SocketIndex]; } if(Socket) { StaticMeshEditorPtr.Pin()->SetSelectedSocket(Socket); } ClearSelectedSockets = false; } else if (HitProxy->IsA(HSMECollisionProxy::StaticGetType()) && StaticMesh->BodySetup) { HSMECollisionProxy* CollisionProxy = (HSMECollisionProxy*)HitProxy; if (StaticMeshEditorPtr.Pin()->IsSelectedPrim(CollisionProxy->PrimData)) { if (!bCtrlDown) { StaticMeshEditorPtr.Pin()->AddSelectedPrim(CollisionProxy->PrimData, true); } else { StaticMeshEditorPtr.Pin()->RemoveSelectedPrim(CollisionProxy->PrimData); } } else { StaticMeshEditorPtr.Pin()->AddSelectedPrim(CollisionProxy->PrimData, !bCtrlDown); } // Force the widget to translate, if not already set if (WidgetMode == FWidget::WM_None) { WidgetMode = FWidget::WM_Translate; } ClearSelectedPrims = false; } } else { const bool bShiftDown = Viewport->KeyState(EKeys::LeftShift) || Viewport->KeyState(EKeys::RightShift); if(!bCtrlDown && !bShiftDown) { SelectedEdgeIndices.Empty(); } // Check to see if we clicked on a mesh edge if( StaticMeshComponent != NULL && Viewport->GetSizeXY().X > 0 && Viewport->GetSizeXY().Y > 0 ) { FSceneViewFamilyContext ViewFamily( FSceneViewFamily::ConstructionValues( Viewport, GetScene(), EngineShowFlags )); FSceneView* View = CalcSceneView(&ViewFamily); FViewportClick ViewportClick(View, this, Key, Event, HitX, HitY); const FVector ClickLineStart( ViewportClick.GetOrigin() ); const FVector ClickLineEnd( ViewportClick.GetOrigin() + ViewportClick.GetDirection() * HALF_WORLD_MAX ); // Don't bother doing a line check as there is only one mesh in the SME and it makes fuzzy selection difficult // FHitResult CheckResult( 1.0f ); // if( StaticMeshComponent->LineCheck( // CheckResult, // In/Out: Result // ClickLineEnd, // Target // ClickLineStart, // Source // FVector::ZeroVector, // Extend // TRACE_ComplexCollision ) ) // Trace flags { // @todo: Should be in screen space ideally const float WorldSpaceMinClickDistance = 100.0f; float ClosestEdgeDistance = FLT_MAX; TArray< int32 > ClosestEdgeIndices; FVector ClosestEdgeVertices[ 2 ]; const uint32 LODLevel = FMath::Clamp( StaticMeshComponent->ForcedLodModel - 1, 0, StaticMeshComponent->StaticMesh->GetNumLODs() - 1 ); FRawMesh RawMesh; StaticMeshComponent->StaticMesh->SourceModels[LODLevel].RawMeshBulkData->LoadRawMesh(RawMesh); const int32 RawEdgeCount = RawMesh.WedgeIndices.Num() - 1; const int32 NumFaces = RawMesh.WedgeIndices.Num() / 3; int32 NumBackFacingTriangles = 0; for(int32 FaceIndex = 0; FaceIndex < NumFaces; ++FaceIndex) { // We disable edge selection where all adjoining triangles are back face culled and the // material is not two-sided. This prevents edges that are back-face culled from being selected. bool bIsBackFacing = false; bool bIsTwoSided = false; UMaterialInterface* Material = StaticMeshComponent->GetMaterial(RawMesh.FaceMaterialIndices[FaceIndex]); if (Material && Material->GetMaterial()) { bIsTwoSided = Material->IsTwoSided(); } if(!bIsTwoSided) { // Check whether triangle if back facing const FVector A = RawMesh.GetWedgePosition( FaceIndex * 3); const FVector B = RawMesh.GetWedgePosition( FaceIndex * 3 + 1); const FVector C = RawMesh.GetWedgePosition( FaceIndex * 3 + 2); // Compute the per-triangle normal const FVector BA = A - B; const FVector CA = A - C; const FVector TriangleNormal = (CA ^ BA).SafeNormal(); // Transform the view position from world to component space const FVector ComponentSpaceViewOrigin = StaticMeshComponent->ComponentToWorld.InverseTransformPosition( View->ViewMatrices.ViewOrigin); // Determine which side of the triangle's plane that the view position lies on. bIsBackFacing = (FVector::PointPlaneDist( ComponentSpaceViewOrigin, A, TriangleNormal) < 0.0f); } for( int32 VertIndex = 0; VertIndex < 3; ++VertIndex ) { const int32 EdgeIndex = FaceIndex * 3 + VertIndex; const int32 EdgeIndex2 = FaceIndex * 3 + ((VertIndex + 1) % 3); FVector EdgeVertices[ 2 ]; EdgeVertices[0] = RawMesh.GetWedgePosition(EdgeIndex); EdgeVertices[1] = RawMesh.GetWedgePosition(EdgeIndex2); // First check to see if this edge is already in our "closest to click" list. // Most edges are shared by two faces in our raw triangle data set, so we want // to select (or deselect) both of these edges that the user clicks on (what // appears to be) a single edge if( ClosestEdgeIndices.Num() > 0 && ( ( EdgeVertices[ 0 ].Equals( ClosestEdgeVertices[ 0 ] ) && EdgeVertices[ 1 ].Equals( ClosestEdgeVertices[ 1 ] ) ) || ( EdgeVertices[ 0 ].Equals( ClosestEdgeVertices[ 1 ] ) && EdgeVertices[ 1 ].Equals( ClosestEdgeVertices[ 0 ] ) ) ) ) { // Edge overlaps the closest edge we have so far, so just add it to the list ClosestEdgeIndices.Add( EdgeIndex ); // Increment the number of back facing triangles if the adjoining triangle // is back facing and isn't two-sided if(bIsBackFacing && !bIsTwoSided) { ++NumBackFacingTriangles; } } else { FVector WorldSpaceEdgeStart( StaticMeshComponent->ComponentToWorld.TransformPosition( EdgeVertices[ 0 ] ) ); FVector WorldSpaceEdgeEnd( StaticMeshComponent->ComponentToWorld.TransformPosition( EdgeVertices[ 1 ] ) ); // Determine the mesh edge that's closest to the ray cast through the eye towards the click location FVector ClosestPointToEdgeOnClickLine; FVector ClosestPointToClickLineOnEdge; FMath::SegmentDistToSegment( ClickLineStart, ClickLineEnd, WorldSpaceEdgeStart, WorldSpaceEdgeEnd, ClosestPointToEdgeOnClickLine, ClosestPointToClickLineOnEdge ); // Compute the minimum distance (squared) const float MinDistanceToEdgeSquared = ( ClosestPointToClickLineOnEdge - ClosestPointToEdgeOnClickLine ).SizeSquared(); if( MinDistanceToEdgeSquared <= WorldSpaceMinClickDistance ) { if( MinDistanceToEdgeSquared <= ClosestEdgeDistance ) { // This is the closest edge to the click line that we've found so far! ClosestEdgeDistance = MinDistanceToEdgeSquared; ClosestEdgeVertices[ 0 ] = EdgeVertices[ 0 ]; ClosestEdgeVertices[ 1 ] = EdgeVertices[ 1 ]; ClosestEdgeIndices.Reset(); ClosestEdgeIndices.Add( EdgeIndex ); // Reset the number of back facing triangles. NumBackFacingTriangles = (bIsBackFacing && !bIsTwoSided) ? 1 : 0; } } } } } // Did the user click on an edge? Edges must also have at least one adjoining triangle // which isn't back face culled (for one-sided materials) if( ClosestEdgeIndices.Num() > 0 && ClosestEdgeIndices.Num() > NumBackFacingTriangles) { for( int32 CurIndex = 0; CurIndex < ClosestEdgeIndices.Num(); ++CurIndex ) { const int32 CurEdgeIndex = ClosestEdgeIndices[ CurIndex ]; if( bCtrlDown ) { // Toggle selection if( SelectedEdgeIndices.Contains( CurEdgeIndex ) ) { SelectedEdgeIndices.Remove( CurEdgeIndex ); } else { SelectedEdgeIndices.Add( CurEdgeIndex ); } } else { // Append to selection SelectedEdgeIndices.Add( CurEdgeIndex ); } } // Reset cached vertices and uv coordinates. SelectedEdgeVertices.Reset(); for(int32 TexCoordIndex = 0; TexCoordIndex < MAX_STATIC_TEXCOORDS; ++TexCoordIndex) { SelectedEdgeTexCoords[TexCoordIndex].Reset(); } for(FSelectedEdgeSet::TIterator SelectionIt( SelectedEdgeIndices ); SelectionIt; ++SelectionIt) { const uint32 EdgeIndex = *SelectionIt; const uint32 FaceIndex = EdgeIndex / 3; const uint32 WedgeIndex = FaceIndex * 3 + (EdgeIndex % 3); const uint32 WedgeIndex2 = FaceIndex * 3 + ((EdgeIndex + 1) % 3); // Cache edge vertices in local space. FVector EdgeVertices[ 2 ]; EdgeVertices[ 0 ] = RawMesh.GetWedgePosition(WedgeIndex); EdgeVertices[ 1 ] = RawMesh.GetWedgePosition(WedgeIndex2); SelectedEdgeVertices.Add(EdgeVertices[0]); SelectedEdgeVertices.Add(EdgeVertices[1]); // Cache UV for(int32 TexCoordIndex = 0; TexCoordIndex < MAX_STATIC_TEXCOORDS; ++TexCoordIndex) { if( RawMesh.WedgeTexCoords[TexCoordIndex].Num() > 0) { FVector2D UVIndex1, UVIndex2; UVIndex1 = RawMesh.WedgeTexCoords[TexCoordIndex][WedgeIndex]; UVIndex2 = RawMesh.WedgeTexCoords[TexCoordIndex][WedgeIndex2]; SelectedEdgeTexCoords[TexCoordIndex].Add(UVIndex1); SelectedEdgeTexCoords[TexCoordIndex].Add(UVIndex2); } } } ClearSelectedEdges = false; } } } } if (ClearSelectedSockets && StaticMeshEditorPtr.Pin()->GetSelectedSocket()) { StaticMeshEditorPtr.Pin()->SetSelectedSocket(NULL); } if (ClearSelectedPrims) { StaticMeshEditorPtr.Pin()->ClearSelectedPrims(); } if (ClearSelectedEdges) { SelectedEdgeIndices.Empty(); } Invalidate(); }
bool FVertexSnappingImpl::SnapDraggedActorsToNearestVertex( FVector& DragDelta, FLevelEditorViewportClient* ViewportClient ) { int32 MouseX = ViewportClient->Viewport->GetMouseX(); int32 MouseY = ViewportClient->Viewport->GetMouseY(); FVector2D MousePosition = FVector2D( MouseX, MouseY ) ; EAxisList::Type CurrentAxis = ViewportClient->GetCurrentWidgetAxis(); bool bSnapped = false; if( !DragDelta.IsNearlyZero() ) { // Are there selected actors? USelection* Selection = GEditor->GetSelectedActors(); FVector Direction = DragDelta.GetSafeNormal(); FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( ViewportClient->Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags ) .SetRealtimeUpdate( ViewportClient->IsRealtime() )); FSceneView* View = ViewportClient->CalcSceneView( &ViewFamily ); FVector StartLocation = ViewportClient->GetModeTools()->PivotLocation; FVector DesiredUnsnappedLocation = StartLocation+DragDelta; // Plane facing in the direction of axis movement. This is for clipping actors which are behind the desired location (they should not be considered for snap) FPlane ActorPlane( DesiredUnsnappedLocation, Direction ); TSet< TWeakObjectPtr<AActor> > ActorsToIgnore; // Snap each selected actor for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It ) { // Build up a region that actors must be in for snapping FBoxSphereBounds SnappingAreaBox( FBox( DesiredUnsnappedLocation-VertexSnappingConstants::MaxSnappingDistance, DesiredUnsnappedLocation+VertexSnappingConstants::MaxSnappingDistance ) ); AActor* Actor = CastChecked<AActor>( *It ); if( Actor->GetRootComponent() != NULL ) { // Get a bounding box around the actor const bool bNonColliding = true; FBoxSphereBounds ActorBounds = Actor->GetComponentsBoundingBox(bNonColliding); // The allowed snapping box is a box around the selected actor plus a region around the actor that other actors must be in for snapping FBox AllowedSnappingBox = ActorBounds.GetBox(); // Extend the box to include the drag point AllowedSnappingBox += SnappingAreaBox.GetBox(); GetActorsToIgnore( Actor, ActorsToIgnore ); FVertexSnappingArgs Args ( ActorPlane, DesiredUnsnappedLocation, ViewportClient, View, MousePosition, CurrentAxis, true ); // Snap the drag delta SnapDragDelta( Args, StartLocation, AllowedSnappingBox, ActorsToIgnore, DragDelta ); } } } return bSnapped; }
void UOffAxisGameViewportClient::Draw(FViewport* InViewport, FCanvas* SceneCanvas) { //Valid SceneCanvas is required. Make this explicit. check(SceneCanvas); FCanvas* DebugCanvas = InViewport->GetDebugCanvas(); // Create a temporary canvas if there isn't already one. static FName CanvasObjectName(TEXT("CanvasObject")); UCanvas* CanvasObject = GetCanvasByName(CanvasObjectName); CanvasObject->Canvas = SceneCanvas; // Create temp debug canvas object static FName DebugCanvasObjectName(TEXT("DebugCanvasObject")); UCanvas* DebugCanvasObject = GetCanvasByName(DebugCanvasObjectName); DebugCanvasObject->Canvas = DebugCanvas; DebugCanvasObject->Init(InViewport->GetSizeXY().X, InViewport->GetSizeXY().Y, NULL); const bool bScaledToRenderTarget = GEngine->HMDDevice.IsValid() && GEngine->IsStereoscopic3D(InViewport); if (bScaledToRenderTarget) { // Allow HMD to modify screen settings GEngine->HMDDevice->UpdateScreenSettings(Viewport); } if (DebugCanvas) { DebugCanvas->SetScaledToRenderTarget(bScaledToRenderTarget); } if (SceneCanvas) { SceneCanvas->SetScaledToRenderTarget(bScaledToRenderTarget); } bool bUIDisableWorldRendering = false; FViewElementDrawer GameViewDrawer; // create the view family for rendering the world scene to the viewport's render target FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( InViewport, GetWorld()->Scene, EngineShowFlags) .SetRealtimeUpdate(true)); // Allow HMD to modify the view later, just before rendering if (GEngine->HMDDevice.IsValid() && GEngine->IsStereoscopic3D(InViewport)) { ISceneViewExtension* HmdViewExt = GEngine->HMDDevice->GetViewExtension(); if (HmdViewExt) { ViewFamily.ViewExtensions.Add(HmdViewExt); HmdViewExt->ModifyShowFlags(ViewFamily.EngineShowFlags); } } ESplitScreenType::Type SplitScreenConfig = GetCurrentSplitscreenConfiguration(); EngineShowFlagOverride(ESFIM_Game, (EViewModeIndex)ViewModeIndex, ViewFamily.EngineShowFlags, NAME_None, SplitScreenConfig != ESplitScreenType::None); TMap<ULocalPlayer*, FSceneView*> PlayerViewMap; FAudioDevice* AudioDevice = GEngine->GetAudioDevice(); bool bReverbSettingsFound = false; FReverbSettings ReverbSettings; class AAudioVolume* AudioVolume = nullptr; for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator) { APlayerController* PlayerController = *Iterator; if (PlayerController) { ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(PlayerController->Player); if (LocalPlayer) { const bool bEnableStereo = GEngine->IsStereoscopic3D(InViewport); int32 NumViews = bEnableStereo ? 2 : 1; for (int i = 0; i < NumViews; ++i) { // Calculate the player's view information. FVector ViewLocation; FRotator ViewRotation; EStereoscopicPass PassType = !bEnableStereo ? eSSP_FULL : ((i == 0) ? eSSP_LEFT_EYE : eSSP_RIGHT_EYE); FSceneView* View = LocalPlayer->CalcSceneView(&ViewFamily, ViewLocation, ViewRotation, InViewport, &GameViewDrawer, PassType); if (mOffAxisMatrixSetted) UpdateProjectionMatrix(View, mOffAxisMatrix); if (View) { if (View->Family->EngineShowFlags.Wireframe) { // Wireframe color is emissive-only, and mesh-modifying materials do not use material substitution, hence... View->DiffuseOverrideParameter = FVector4(0.f, 0.f, 0.f, 0.f); View->SpecularOverrideParameter = FVector4(0.f, 0.f, 0.f, 0.f); } else if (View->Family->EngineShowFlags.OverrideDiffuseAndSpecular) { View->DiffuseOverrideParameter = FVector4(GEngine->LightingOnlyBrightness.R, GEngine->LightingOnlyBrightness.G, GEngine->LightingOnlyBrightness.B, 0.0f); View->SpecularOverrideParameter = FVector4(.1f, .1f, .1f, 0.0f); } else if (View->Family->EngineShowFlags.ReflectionOverride) { View->DiffuseOverrideParameter = FVector4(0.f, 0.f, 0.f, 0.f); View->SpecularOverrideParameter = FVector4(1, 1, 1, 0.0f); View->NormalOverrideParameter = FVector4(0, 0, 1, 0.0f); View->RoughnessOverrideParameter = FVector2D(0.0f, 0.0f); } if (!View->Family->EngineShowFlags.Diffuse) { View->DiffuseOverrideParameter = FVector4(0.f, 0.f, 0.f, 0.f); } if (!View->Family->EngineShowFlags.Specular) { View->SpecularOverrideParameter = FVector4(0.f, 0.f, 0.f, 0.f); } View->CameraConstrainedViewRect = View->UnscaledViewRect; // If this is the primary drawing pass, update things that depend on the view location if (i == 0) { // Save the location of the view. LocalPlayer->LastViewLocation = ViewLocation; PlayerViewMap.Add(LocalPlayer, View); // Update the listener. if (AudioDevice != NULL) { FVector Location; FVector ProjFront; FVector ProjRight; PlayerController->GetAudioListenerPosition(/*out*/ Location, /*out*/ ProjFront, /*out*/ ProjRight); FTransform ListenerTransform(FRotationMatrix::MakeFromXY(ProjFront, ProjRight)); ListenerTransform.SetTranslation(Location); ListenerTransform.NormalizeRotation(); bReverbSettingsFound = true; FReverbSettings PlayerReverbSettings; FInteriorSettings PlayerInteriorSettings; class AAudioVolume* PlayerAudioVolume = GetWorld()->GetAudioSettings(Location, &PlayerReverbSettings, &PlayerInteriorSettings); if (AudioVolume == nullptr || (PlayerAudioVolume != nullptr && PlayerAudioVolume->Priority > AudioVolume->Priority)) { AudioVolume = PlayerAudioVolume; ReverbSettings = PlayerReverbSettings; } uint32 ViewportIndex = PlayerViewMap.Num() - 1; AudioDevice->SetListener(ViewportIndex, ListenerTransform, (View->bCameraCut ? 0.f : GetWorld()->GetDeltaSeconds()), PlayerAudioVolume, PlayerInteriorSettings); } } // Add view information for resource streaming. IStreamingManager::Get().AddViewInformation(View->ViewMatrices.ViewOrigin, View->ViewRect.Width(), View->ViewRect.Width() * View->ViewMatrices.ProjMatrix.M[0][0]); GetWorld()->ViewLocationsRenderedLastFrame.Add(View->ViewMatrices.ViewOrigin); } } } } } if (bReverbSettingsFound) { AudioDevice->SetReverbSettings(AudioVolume, ReverbSettings); } // Update level streaming. GetWorld()->UpdateLevelStreaming(); // Draw the player views. if (!bDisableWorldRendering && !bUIDisableWorldRendering && PlayerViewMap.Num() > 0) { GetRendererModule().BeginRenderingViewFamily(SceneCanvas, &ViewFamily); } // Clear areas of the rendertarget (backbuffer) that aren't drawn over by the views. { // Find largest rectangle bounded by all rendered views. uint32 MinX = InViewport->GetSizeXY().X, MinY = InViewport->GetSizeXY().Y, MaxX = 0, MaxY = 0; uint32 TotalArea = 0; for (int32 ViewIndex = 0; ViewIndex < ViewFamily.Views.Num(); ++ViewIndex) { const FSceneView* View = ViewFamily.Views[ViewIndex]; FIntRect UpscaledViewRect = View->UnscaledViewRect; MinX = FMath::Min<uint32>(UpscaledViewRect.Min.X, MinX); MinY = FMath::Min<uint32>(UpscaledViewRect.Min.Y, MinY); MaxX = FMath::Max<uint32>(UpscaledViewRect.Max.X, MaxX); MaxY = FMath::Max<uint32>(UpscaledViewRect.Max.Y, MaxY); TotalArea += FMath::TruncToInt(UpscaledViewRect.Width()) * FMath::TruncToInt(UpscaledViewRect.Height()); } // To draw black borders around the rendered image (prevents artifacts from post processing passes that read outside of the image e.g. PostProcessAA) { int32 BlackBorders = 0; // FMath::Clamp(CVarSetBlackBordersEnabled.GetValueOnGameThread(), 0, 10); if (ViewFamily.Views.Num() == 1 && BlackBorders) { MinX += BlackBorders; MinY += BlackBorders; MaxX -= BlackBorders; MaxY -= BlackBorders; TotalArea = (MaxX - MinX) * (MaxY - MinY); } } // If the views don't cover the entire bounding rectangle, clear the entire buffer. if (ViewFamily.Views.Num() == 0 || TotalArea != (MaxX - MinX)*(MaxY - MinY) || bDisableWorldRendering) { SceneCanvas->DrawTile(0, 0, InViewport->GetSizeXY().X, InViewport->GetSizeXY().Y, 0.0f, 0.0f, 1.0f, 1.f, FLinearColor::Black, NULL, false); } else { // clear left if (MinX > 0) { SceneCanvas->DrawTile(0, 0, MinX, InViewport->GetSizeXY().Y, 0.0f, 0.0f, 1.0f, 1.f, FLinearColor::Black, NULL, false); } // clear right if (MaxX < (uint32)InViewport->GetSizeXY().X) { SceneCanvas->DrawTile(MaxX, 0, InViewport->GetSizeXY().X, InViewport->GetSizeXY().Y, 0.0f, 0.0f, 1.0f, 1.f, FLinearColor::Black, NULL, false); } // clear top if (MinY > 0) { SceneCanvas->DrawTile(MinX, 0, MaxX, MinY, 0.0f, 0.0f, 1.0f, 1.f, FLinearColor::Black, NULL, false); } // clear bottom if (MaxY < (uint32)InViewport->GetSizeXY().Y) { SceneCanvas->DrawTile(MinX, MaxY, MaxX, InViewport->GetSizeXY().Y, 0.0f, 0.0f, 1.0f, 1.f, FLinearColor::Black, NULL, false); } } } // Remove temporary debug lines. if (GetWorld()->LineBatcher != NULL) { GetWorld()->LineBatcher->Flush(); } if (GetWorld()->ForegroundLineBatcher != NULL) { GetWorld()->ForegroundLineBatcher->Flush(); } // Draw FX debug information. if (GetWorld()->FXSystem) { GetWorld()->FXSystem->DrawDebug(SceneCanvas); } // Render the UI. { //SCOPE_CYCLE_COUNTER(STAT_UIDrawingTime); // render HUD bool bDisplayedSubtitles = false; for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator) { APlayerController* PlayerController = *Iterator; if (PlayerController) { ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(PlayerController->Player); if (LocalPlayer) { FSceneView* View = PlayerViewMap.FindRef(LocalPlayer); if (View != NULL) { // rendering to directly to viewport target FVector CanvasOrigin(FMath::TruncToFloat(View->UnscaledViewRect.Min.X), FMath::TruncToInt(View->UnscaledViewRect.Min.Y), 0.f); CanvasObject->Init(View->UnscaledViewRect.Width(), View->UnscaledViewRect.Height(), View); // Set the canvas transform for the player's view rectangle. SceneCanvas->PushAbsoluteTransform(FTranslationMatrix(CanvasOrigin)); CanvasObject->ApplySafeZoneTransform(); // Render the player's HUD. if (PlayerController->MyHUD) { //SCOPE_CYCLE_COUNTER(STAT_HudTime); DebugCanvasObject->SceneView = View; PlayerController->MyHUD->SetCanvas(CanvasObject, DebugCanvasObject); if (GEngine->IsStereoscopic3D(InViewport)) { check(GEngine->StereoRenderingDevice.IsValid()); GEngine->StereoRenderingDevice->PushViewportCanvas(eSSP_LEFT_EYE, SceneCanvas, CanvasObject, Viewport); PlayerController->MyHUD->PostRender(); SceneCanvas->PopTransform(); GEngine->StereoRenderingDevice->PushViewportCanvas(eSSP_RIGHT_EYE, SceneCanvas, CanvasObject, Viewport); PlayerController->MyHUD->PostRender(); SceneCanvas->PopTransform(); // Reset the canvas for rendering to the full viewport. CanvasObject->Reset(); CanvasObject->SizeX = View->UnscaledViewRect.Width(); CanvasObject->SizeY = View->UnscaledViewRect.Height(); CanvasObject->SetView(NULL); CanvasObject->Update(); } else { PlayerController->MyHUD->PostRender(); } // Put these pointers back as if a blueprint breakpoint hits during HUD PostRender they can // have been changed CanvasObject->Canvas = SceneCanvas; DebugCanvasObject->Canvas = DebugCanvas; // A side effect of PostRender is that the playercontroller could be destroyed if (!PlayerController->IsPendingKill()) { PlayerController->MyHUD->SetCanvas(NULL, NULL); } } if (DebugCanvas != NULL) { DebugCanvas->PushAbsoluteTransform(FTranslationMatrix(CanvasOrigin)); UDebugDrawService::Draw(ViewFamily.EngineShowFlags, InViewport, View, DebugCanvas); DebugCanvas->PopTransform(); } CanvasObject->PopSafeZoneTransform(); SceneCanvas->PopTransform(); // draw subtitles if (!bDisplayedSubtitles) { FVector2D MinPos(0.f, 0.f); FVector2D MaxPos(1.f, 1.f); GetSubtitleRegion(MinPos, MaxPos); uint32 SizeX = SceneCanvas->GetRenderTarget()->GetSizeXY().X; uint32 SizeY = SceneCanvas->GetRenderTarget()->GetSizeXY().Y; FIntRect SubtitleRegion(FMath::TruncToInt(SizeX * MinPos.X), FMath::TruncToInt(SizeY * MinPos.Y), FMath::TruncToInt(SizeX * MaxPos.X), FMath::TruncToInt(SizeY * MaxPos.Y)); // We need a world to do this FSubtitleManager::GetSubtitleManager()->DisplaySubtitles(SceneCanvas, SubtitleRegion, GetWorld()->GetAudioTimeSeconds()); } } } } } //ensure canvas has been flushed before rendering UI SceneCanvas->Flush_GameThread(); if (DebugCanvas != NULL) { DebugCanvas->Flush_GameThread(); } // Allow the viewport to render additional stuff PostRender(DebugCanvasObject); // Render the console. if (ViewportConsole) { if (GEngine->IsStereoscopic3D(InViewport)) { GEngine->StereoRenderingDevice->PushViewportCanvas(eSSP_LEFT_EYE, DebugCanvas, DebugCanvasObject, Viewport); ViewportConsole->PostRender_Console(DebugCanvasObject); #if !UE_BUILD_SHIPPING if (DebugCanvas != NULL && GEngine->HMDDevice.IsValid()) { GEngine->HMDDevice->DrawDebug(DebugCanvasObject, eSSP_LEFT_EYE); } #endif DebugCanvas->PopTransform(); GEngine->StereoRenderingDevice->PushViewportCanvas(eSSP_RIGHT_EYE, DebugCanvas, DebugCanvasObject, Viewport); ViewportConsole->PostRender_Console(DebugCanvasObject); #if !UE_BUILD_SHIPPING if (DebugCanvas != NULL && GEngine->HMDDevice.IsValid()) { GEngine->HMDDevice->DrawDebug(DebugCanvasObject, eSSP_RIGHT_EYE); } #endif DebugCanvas->PopTransform(); // Reset the canvas for rendering to the full viewport. DebugCanvasObject->Reset(); DebugCanvasObject->SizeX = Viewport->GetSizeXY().X; DebugCanvasObject->SizeY = Viewport->GetSizeXY().Y; DebugCanvasObject->SetView(NULL); DebugCanvasObject->Update(); } else { ViewportConsole->PostRender_Console(DebugCanvasObject); } } } // Grab the player camera location and orientation so we can pass that along to the stats drawing code. FVector PlayerCameraLocation = FVector::ZeroVector; FRotator PlayerCameraRotation = FRotator::ZeroRotator; { for (FConstPlayerControllerIterator Iterator = GetWorld()->GetPlayerControllerIterator(); Iterator; ++Iterator) { (*Iterator)->GetPlayerViewPoint(PlayerCameraLocation, PlayerCameraRotation); } } if (GEngine->IsStereoscopic3D(InViewport)) { GEngine->StereoRenderingDevice->PushViewportCanvas(eSSP_LEFT_EYE, DebugCanvas, DebugCanvasObject, InViewport); DrawStatsHUD(GetWorld(), InViewport, DebugCanvas, DebugCanvasObject, DebugProperties, PlayerCameraLocation, PlayerCameraRotation); DebugCanvas->PopTransform(); GEngine->StereoRenderingDevice->PushViewportCanvas(eSSP_RIGHT_EYE, DebugCanvas, DebugCanvasObject, InViewport); DrawStatsHUD(GetWorld(), InViewport, DebugCanvas, DebugCanvasObject, DebugProperties, PlayerCameraLocation, PlayerCameraRotation); DebugCanvas->PopTransform(); // Reset the canvas for rendering to the full viewport. DebugCanvasObject->Reset(); DebugCanvasObject->SizeX = Viewport->GetSizeXY().X; DebugCanvasObject->SizeY = Viewport->GetSizeXY().Y; DebugCanvasObject->SetView(NULL); DebugCanvasObject->Update(); #if !UE_BUILD_SHIPPING if (GEngine->HMDDevice.IsValid()) { GEngine->HMDDevice->DrawDebug(DebugCanvasObject, eSSP_FULL); } #endif } else { DrawStatsHUD(GetWorld(), InViewport, DebugCanvas, DebugCanvasObject, DebugProperties, PlayerCameraLocation, PlayerCameraRotation); } }
void FSpriteGeometryEditMode::SelectVerticesInMarquee(FEditorViewportClient* ViewportClient, FViewport* Viewport, bool bAddToSelection) { if (!bAddToSelection) { SpriteGeometryHelper.ClearSelectionSet(); } { // Calculate world space positions FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(Viewport, ViewportClient->GetScene(), ViewportClient->EngineShowFlags)); FSceneView* View = ViewportClient->CalcSceneView(&ViewFamily); const FVector StartPos = View->PixelToWorld(MarqueeStartPos.X, MarqueeStartPos.Y, 0); const FVector EndPos = View->PixelToWorld(MarqueeEndPos.X, MarqueeEndPos.Y, 0); // Convert to source texture space to work out the pixels dragged FVector2D TextureSpaceStartPos = SpriteGeometryHelper.GetEditorContext()->WorldSpaceToTextureSpace(StartPos); FVector2D TextureSpaceEndPos = SpriteGeometryHelper.GetEditorContext()->WorldSpaceToTextureSpace(EndPos); if (TextureSpaceStartPos.X > TextureSpaceEndPos.X) { Swap(TextureSpaceStartPos.X, TextureSpaceEndPos.X); } if (TextureSpaceStartPos.Y > TextureSpaceEndPos.Y) { Swap(TextureSpaceStartPos.Y, TextureSpaceEndPos.Y); } const FBox2D QueryBounds(TextureSpaceStartPos, TextureSpaceEndPos); // Check geometry if (FSpriteGeometryCollection* Geometry = SpriteGeometryHelper.GetGeometryBeingEdited()) { for (int32 ShapeIndex = 0; ShapeIndex < Geometry->Shapes.Num(); ++ShapeIndex) { const FSpriteGeometryShape& Shape = Geometry->Shapes[ShapeIndex]; bool bSelectWholeShape = false; if ((Shape.ShapeType == ESpriteShapeType::Circle) || (Shape.ShapeType == ESpriteShapeType::Box)) { // First see if we are fully contained const FBox2D ShapeBoxBounds(Shape.BoxPosition - Shape.BoxSize * 0.5f, Shape.BoxPosition + Shape.BoxSize * 0.5f); if (QueryBounds.IsInside(ShapeBoxBounds)) { bSelectWholeShape = true; } } //@TODO: Try intersecting with the circle if it wasn't entirely enclosed if (bSelectWholeShape) { SpriteGeometryHelper.AddShapeToSelection(ShapeIndex); } else { // Try to select some subset of the vertices for (int32 VertexIndex = 0; VertexIndex < Shape.Vertices.Num(); ++VertexIndex) { const FVector2D TextureSpaceVertex = Shape.ConvertShapeSpaceToTextureSpace(Shape.Vertices[VertexIndex]); if (QueryBounds.IsInside(TextureSpaceVertex)) { SpriteGeometryHelper.AddPolygonVertexToSelection(ShapeIndex, VertexIndex); } } } } } //@TODO: Check other items (sockets/etc...) } }
/** * Adds delta movement into the tracker. */ void FMouseDeltaTracker::AddDelta(FEditorViewportClient* InViewportClient, FKey InKey, const int32 InDelta, bool InNudge) { const bool LeftMouseButtonDown = InViewportClient->Viewport->KeyState(EKeys::LeftMouseButton); const bool RightMouseButtonDown = InViewportClient->Viewport->KeyState(EKeys::RightMouseButton); const bool MiddleMouseButtonDown = InViewportClient->Viewport->KeyState(EKeys::MiddleMouseButton); const bool bAltDown = InViewportClient->IsAltPressed(); const bool bShiftDown = InViewportClient->IsShiftPressed(); const bool bControlDown = InViewportClient->IsCtrlPressed(); if( !LeftMouseButtonDown && !MiddleMouseButtonDown && !RightMouseButtonDown && !InNudge ) { return; } // Accumulate raw delta RawDelta += FVector(InKey == EKeys::MouseX ? InDelta : 0, InKey == EKeys::MouseY ? InDelta : 0, 0); // Note that AddDelta has been called since StartTracking bHasReceivedAddDelta = true; // If we are using a drag tool, the widget isn't involved so set it to having no active axis. This // means we will get unmodified mouse movement returned to us by other functions. const EAxisList::Type SaveAxis = InViewportClient->GetCurrentWidgetAxis(); // If the user isn't dragging with the left mouse button, clear out the axis // as the widget only responds to the left mouse button. // // We allow an exception for dragging with the left and/or right mouse button while holding control // as that simulates moving objects with the gizmo // // We also allow the exception of the middle mouse button when Alt is pressed as it // allows movement of only the pivot. const bool bIsOrthoObjectRotation = bControlDown && InViewportClient->IsOrtho(); const bool bUsingDragTool = UsingDragTool(); const bool bUsingAxis = !bUsingDragTool && (LeftMouseButtonDown || (bAltDown && MiddleMouseButtonDown) || ((bIsOrthoObjectRotation || bControlDown) && RightMouseButtonDown)); ConditionalBeginUsingDragTool( InViewportClient ); if( bUsingDragTool || !InViewportClient->IsTracking() || !bUsingAxis ) { InViewportClient->SetCurrentWidgetAxis( EAxisList::None ); } FVector Wk = InViewportClient->TranslateDelta( InKey, InDelta, InNudge ); EndScreen += Wk; if( InViewportClient->GetCurrentWidgetAxis() != EAxisList::None ) { // Affect input delta by the camera speed FWidget::EWidgetMode WidgetMode = InViewportClient->GetWidgetMode(); bool bIsRotation = (WidgetMode == FWidget::WM_Rotate) || ( ( WidgetMode == FWidget::WM_TranslateRotateZ ) && ( InViewportClient->GetCurrentWidgetAxis() == EAxisList::ZRotation ) ) || ( ( WidgetMode == FWidget::WM_2D) && (InViewportClient->GetCurrentWidgetAxis() == EAxisList::Rotate2D ) ); if (bIsRotation) { Wk *= GetDefault<ULevelEditorViewportSettings>()->MouseSensitivty; } else if( WidgetMode == FWidget::WM_Scale && !GEditor->UsePercentageBasedScaling() ) { const float ScaleSpeedMultipler = 0.01f; Wk *= ScaleSpeedMultipler; } // Make rotations occur at the same speed, regardless of ortho zoom if( InViewportClient->IsOrtho() ) { if (bIsRotation) { float Scale = 1.0f; if( InViewportClient->IsOrtho() ) { Scale = DEFAULT_ORTHOZOOM / (float)InViewportClient->GetOrthoZoom(); } Wk *= Scale; } } //if Absolute Translation, and not just moving the camera around else if (InViewportClient->IsUsingAbsoluteTranslation()) { // Compute a view. FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( InViewportClient->Viewport, InViewportClient->GetScene(), InViewportClient->EngineShowFlags ) .SetRealtimeUpdate( InViewportClient->IsRealtime() )); FSceneView* View = InViewportClient->CalcSceneView( &ViewFamily ); //calculate mouse position check(InViewportClient->Viewport); FVector2D MousePosition(InViewportClient->Viewport->GetMouseX(), InViewportClient->Viewport->GetMouseY()); FVector WidgetPosition = InViewportClient->GetWidgetLocation(); FRotator TempRot; FVector TempScale; InViewportClient->Widget->AbsoluteTranslationConvertMouseMovementToAxisMovement(View, InViewportClient, WidgetPosition, MousePosition, Wk, TempRot, TempScale ); } } End += Wk; EndSnapped = End; if( UsingDragTool() ) { FVector Drag = Wk; if( DragTool->bConvertDelta ) { FRotator Rot; InViewportClient->ConvertMovementToDragRot( Wk, Drag, Rot ); } if ( InViewportClient->IsPerspective() ) { DragTool->AddDelta(Wk); } else { DragTool->AddDelta( Drag ); } InViewportClient->SetCurrentWidgetAxis( SaveAxis ); } else { switch( InViewportClient->GetWidgetMode() ) { case FWidget::WM_Translate: FSnappingUtils::SnapPointToGrid( EndSnapped, FVector(GEditor->GetGridSize(),GEditor->GetGridSize(),GEditor->GetGridSize()) ); break; case FWidget::WM_Scale: FSnappingUtils::SnapScale( EndSnapped, FVector(GEditor->GetGridSize(),GEditor->GetGridSize(),GEditor->GetGridSize()) ); break; case FWidget::WM_Rotate: { FRotator Rotation( EndSnapped.X, EndSnapped.Y, EndSnapped.Z ); FSnappingUtils::SnapRotatorToGrid( Rotation ); EndSnapped = FVector( Rotation.Pitch, Rotation.Yaw, Rotation.Roll ); } break; case FWidget::WM_TranslateRotateZ: case FWidget::WM_2D: { if (InViewportClient->GetCurrentWidgetAxis() == EAxisList::Rotate2D) { FRotator Rotation( EndSnapped.X, EndSnapped.Y, EndSnapped.Z ); FSnappingUtils::SnapRotatorToGrid( Rotation ); EndSnapped = FVector( Rotation.Pitch, Rotation.Yaw, Rotation.Roll ); } else { //translation (either xy plane or z) FSnappingUtils::SnapPointToGrid( EndSnapped, FVector(GEditor->GetGridSize(),GEditor->GetGridSize(),GEditor->GetGridSize()) ); } } default: break; } } }
bool FSpriteEditorViewportClient::ConvertMarqueeToSourceTextureSpace(/*out*/ FIntPoint& OutStartPos, /*out*/ FIntPoint& OutDimension) { FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry); check(GeometryEditMode); const FVector2D MarqueeStartPos = GeometryEditMode->GetMarqueeStartPos(); const FVector2D MarqueeEndPos = GeometryEditMode->GetMarqueeEndPos(); bool bSuccessful = false; UPaperSprite* Sprite = SourceTextureViewComponent->GetSprite(); UTexture2D* SpriteSourceTexture = Sprite->GetSourceTexture(); if (SpriteSourceTexture != nullptr) { // Calculate world space positions FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(Viewport, GetScene(), EngineShowFlags)); FSceneView* View = CalcSceneView(&ViewFamily); const FVector StartPos = View->PixelToWorld(MarqueeStartPos.X, MarqueeStartPos.Y, 0); const FVector EndPos = View->PixelToWorld(MarqueeEndPos.X, MarqueeEndPos.Y, 0); // Convert to source texture space to work out the pixels dragged FVector2D TextureSpaceStartPos = Sprite->ConvertWorldSpaceToTextureSpace(StartPos); FVector2D TextureSpaceEndPos = Sprite->ConvertWorldSpaceToTextureSpace(EndPos); if (TextureSpaceStartPos.X > TextureSpaceEndPos.X) { Swap(TextureSpaceStartPos.X, TextureSpaceEndPos.X); } if (TextureSpaceStartPos.Y > TextureSpaceEndPos.Y) { Swap(TextureSpaceStartPos.Y, TextureSpaceEndPos.Y); } const FIntPoint SourceTextureSize(SpriteSourceTexture->GetImportedSize()); const int32 SourceTextureWidth = SourceTextureSize.X; const int32 SourceTextureHeight = SourceTextureSize.Y; FIntPoint TSStartPos; TSStartPos.X = FMath::Clamp<int32>((int32)TextureSpaceStartPos.X, 0, SourceTextureWidth - 1); TSStartPos.Y = FMath::Clamp<int32>((int32)TextureSpaceStartPos.Y, 0, SourceTextureHeight - 1); FIntPoint TSEndPos; TSEndPos.X = FMath::Clamp<int32>((int32)TextureSpaceEndPos.X, 0, SourceTextureWidth - 1); TSEndPos.Y = FMath::Clamp<int32>((int32)TextureSpaceEndPos.Y, 0, SourceTextureHeight - 1); const FIntPoint TextureSpaceDimensions = TSEndPos - TSStartPos; if ((TextureSpaceDimensions.X > 0) || (TextureSpaceDimensions.Y > 0)) { OutStartPos = TSStartPos; OutDimension = TextureSpaceDimensions; bSuccessful = true; } } return bSuccessful; }