/* 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(); } }
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); }
FSceneView* FJavascriptUMGViewportClient::CalcSceneView(FSceneViewFamily* ViewFamily) { FSceneViewInitOptions ViewInitOptions; const FVector& ViewLocation = GetViewLocation(); const FRotator& ViewRotation = GetViewRotation(); const FIntPoint ViewportSizeXY = Viewport->GetSizeXY(); FIntRect ViewRect = FIntRect(0, 0, ViewportSizeXY.X, ViewportSizeXY.Y); ViewInitOptions.SetViewRectangle(ViewRect); ViewInitOptions.ViewOrigin = ViewLocation; ViewInitOptions.ViewRotationMatrix = FInverseRotationMatrix(ViewRotation); ViewInitOptions.ViewRotationMatrix = ViewInitOptions.ViewRotationMatrix * FMatrix( FPlane(0, 0, 1, 0), FPlane(1, 0, 0, 0), FPlane(0, 1, 0, 0), FPlane(0, 0, 0, 1)); //@TODO: Should probably be locally configurable (or just made into a FMinimalViewInfo property) const EAspectRatioAxisConstraint AspectRatioAxisConstraint = GetDefault<ULocalPlayer>()->AspectRatioAxisConstraint; FMinimalViewInfo::CalculateProjectionMatrixGivenView(ViewInfo, AspectRatioAxisConstraint, Viewport, /*inout*/ ViewInitOptions); ViewInitOptions.ViewFamily = ViewFamily; ViewInitOptions.SceneViewStateInterface = ViewState.GetReference(); ViewInitOptions.ViewElementDrawer = this; ViewInitOptions.BackgroundColor = GetBackgroundColor(); //ViewInitOptions.EditorViewBitflag = 0, // send the bit for this view - each actor will check it's visibility bits against this // for ortho views to steal perspective view origin //ViewInitOptions.OverrideLODViewOrigin = FVector::ZeroVector; //ViewInitOptions.bUseFauxOrthoViewPos = true; //ViewInitOptions.CursorPos = CurrentMousePos; FSceneView* View = new FSceneView(ViewInitOptions); ViewFamily->Views.Add(View); View->StartFinalPostprocessSettings(ViewLocation); //OverridePostProcessSettings(*View); View->EndFinalPostprocessSettings(ViewInitOptions); return View; }
virtual void SetMesh(FRHICommandList& RHICmdList, FShader* Shader,const FVertexFactory* VertexFactory,const FSceneView& View,const FMeshBatchElement& BatchElement,uint32 DataFlags) const override { const bool bInstanced = View.GetFeatureLevel() >= ERHIFeatureLevel::SM4; FMeshParticleVertexFactory* MeshParticleVF = (FMeshParticleVertexFactory*)VertexFactory; FVertexShaderRHIParamRef VertexShaderRHI = Shader->GetVertexShader(); SetUniformBufferParameter(RHICmdList, VertexShaderRHI, Shader->GetUniformBufferParameter<FMeshParticleUniformParameters>(), MeshParticleVF->GetUniformBuffer() ); if (!bInstanced) { const FMeshParticleVertexFactory::FBatchParametersCPU* BatchParameters = (const FMeshParticleVertexFactory::FBatchParametersCPU*)BatchElement.UserData; const FMeshParticleInstanceVertex* Vertex = BatchParameters->InstanceBuffer + BatchElement.UserIndex; const FMeshParticleInstanceVertexDynamicParameter* DynamicVertex = BatchParameters->DynamicParameterBuffer + BatchElement.UserIndex; SetShaderValue(RHICmdList, VertexShaderRHI, Transform1, Vertex->Transform[0]); SetShaderValue(RHICmdList, VertexShaderRHI, Transform2, Vertex->Transform[1]); SetShaderValue(RHICmdList, VertexShaderRHI, Transform3, Vertex->Transform[2]); SetShaderValue(RHICmdList, VertexShaderRHI, SubUVParams, FVector4((float)Vertex->SubUVParams[0], (float)Vertex->SubUVParams[1], (float)Vertex->SubUVParams[2], (float)Vertex->SubUVParams[3])); SetShaderValue(RHICmdList, VertexShaderRHI, SubUVLerp, Vertex->SubUVLerp); SetShaderValue(RHICmdList, VertexShaderRHI, ParticleDirection, Vertex->Velocity); SetShaderValue(RHICmdList, VertexShaderRHI, RelativeTime, Vertex->RelativeTime); if (BatchParameters->DynamicParameterBuffer) { SetShaderValue(RHICmdList, VertexShaderRHI, DynamicParameter, FVector4(DynamicVertex->DynamicValue[0], DynamicVertex->DynamicValue[1], DynamicVertex->DynamicValue[2], DynamicVertex->DynamicValue[3])); } SetShaderValue(RHICmdList, VertexShaderRHI, ParticleColor, FVector4(Vertex->Color.Component(0), Vertex->Color.Component(1), Vertex->Color.Component(2), Vertex->Color.Component(3))); } }
void FSCSEditorViewportClient::DrawCanvas( FViewport& InViewport, FSceneView& View, FCanvas& Canvas ) { AActor* PreviewActor = GetPreviewActor(); if(PreviewActor) { TGuardValue<bool> AutoRestore(GAllowActorScriptExecutionInEditor, true); const int32 HalfX = 0.5f * Viewport->GetSizeXY().X; const int32 HalfY = 0.5f * Viewport->GetSizeXY().Y; auto SelectedNodes = BlueprintEditorPtr.Pin()->GetSelectedSCSEditorTreeNodes(); if(bIsManipulating && SelectedNodes.Num() > 0) { USceneComponent* SceneComp = Cast<USceneComponent>(SelectedNodes[0]->FindComponentInstanceInActor(PreviewActor, true)); if(SceneComp) { const FVector WidgetLocation = GetWidgetLocation(); const FPlane Proj = View.Project(WidgetLocation); if(Proj.W > 0.0f) { const int32 XPos = HalfX + (HalfX * Proj.X); const int32 YPos = HalfY + (HalfY * (Proj.Y * -1)); DrawAngles(&Canvas, XPos, YPos, GetCurrentWidgetAxis(), GetWidgetMode(), GetWidgetCoordSystem().Rotator(), WidgetLocation); } } } } }
FVector2D FSpriteEditorViewportClient::SourceTextureSpaceToScreenSpace(const FSceneView& View, const FVector2D& SourcePoint) const { const FVector WorldSpacePoint = SourceTextureSpaceToWorldSpace(SourcePoint); FVector2D PixelLocation; View.WorldToPixel(WorldSpacePoint, /*out*/ PixelLocation); return PixelLocation; }
FVector2D FSpriteGeometryEditingHelper::TextureSpaceToScreenSpace(const FSceneView& View, const FVector2D& SourcePoint) const { const FVector WorldSpacePoint = EditorContext->TextureSpaceToWorldSpace(SourcePoint); FVector2D PixelLocation; View.WorldToPixel(WorldSpacePoint, /*out*/ PixelLocation); return PixelLocation; }
void FSteamVRHMD::PreRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& View) { check(IsInRenderingThread()); // The last view location used to set the view will be in BaseHmdOrientation. We need to calculate the delta from that, so that // cameras that rely on game objects (e.g. other components) for their positions don't need to be updated on the render thread. const FQuat DeltaOrient = View.BaseHmdOrientation.Inverse() * TrackingFrame.DeviceOrientation[vr::k_unTrackedDeviceIndex_Hmd]; View.ViewRotation = FRotator(View.ViewRotation.Quaternion() * DeltaOrient); View.UpdateViewMatrix(); }
void FSimpleElementCollector::DrawBatchedElements(FRHICommandList& RHICmdList, const FSceneView& View, FTexture2DRHIRef DepthTexture, EBlendModeFilter::Type Filter) const { // Mobile HDR does not execute post process, so does not need to render flipped const bool bNeedToSwitchVerticalAxis = RHINeedsToSwitchVerticalAxis(View.GetShaderPlatform()) && !bIsMobileHDR; // Draw the batched elements. BatchedElements.Draw( RHICmdList, View.GetFeatureLevel(), bNeedToSwitchVerticalAxis, View.ViewProjectionMatrix, View.ViewRect.Width(), View.ViewRect.Height(), View.Family->EngineShowFlags.HitProxies, 1.0f, &View, DepthTexture, Filter ); }
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); } } }
bool TDistortionMeshDrawingPolicyFactory<DistortMeshPolicy>::DrawDynamicMesh( FRHICommandList& RHICmdList, const FSceneView& View, ContextType bInitializeOffsets, const FMeshBatch& Mesh, bool bBackFace, bool bPreFog, const FPrimitiveSceneProxy* PrimitiveSceneProxy, FHitProxyId HitProxyId ) { const auto FeatureLevel = View.GetFeatureLevel(); bool bDistorted = Mesh.MaterialRenderProxy && Mesh.MaterialRenderProxy->GetMaterial(FeatureLevel)->IsDistorted(); if(bDistorted && !bBackFace) { // draw dynamic mesh element using distortion mesh policy TDistortionMeshDrawingPolicy<DistortMeshPolicy> DrawingPolicy( Mesh.VertexFactory, Mesh.MaterialRenderProxy, *Mesh.MaterialRenderProxy->GetMaterial(FeatureLevel), bInitializeOffsets, View.Family->EngineShowFlags.ShaderComplexity, FeatureLevel ); RHICmdList.BuildAndSetLocalBoundShaderState(DrawingPolicy.GetBoundShaderStateInput(View.GetFeatureLevel())); DrawingPolicy.SetSharedState(RHICmdList, &View, typename TDistortionMeshDrawingPolicy<DistortMeshPolicy>::ContextDataType()); for (int32 BatchElementIndex = 0; BatchElementIndex < Mesh.Elements.Num(); BatchElementIndex++) { DrawingPolicy.SetMeshRenderState(RHICmdList, View,PrimitiveSceneProxy,Mesh,BatchElementIndex,bBackFace,typename TDistortionMeshDrawingPolicy<DistortMeshPolicy>::ElementDataType(), typename TDistortionMeshDrawingPolicy<DistortMeshPolicy>::ContextDataType()); DrawingPolicy.DrawMesh(RHICmdList, Mesh,BatchElementIndex); } return true; } else { return false; } }
void RunBenchmarkShader(FRHICommandList& RHICmdList, const FSceneView& View, TRefCountPtr<IPooledRenderTarget>& Src, float WorkScale) { auto ShaderMap = GetGlobalShaderMap(View.GetFeatureLevel()); TShaderMapRef<FPostProcessBenchmarkVS> VertexShader(ShaderMap); TShaderMapRef<FPostProcessBenchmarkPS<Method> > PixelShader(ShaderMap); static FGlobalBoundShaderState BoundShaderState; SetGlobalBoundShaderState(RHICmdList, View.GetFeatureLevel(), BoundShaderState, GFilterVertexDeclaration.VertexDeclarationRHI, *VertexShader, *PixelShader); PixelShader->SetParameters(RHICmdList, View, Src); VertexShader->SetParameters(RHICmdList, View); // single pass was not fine grained enough so we reduce the pass size based on the fractional part of WorkScale float TotalHeight = GBenchmarkResolution * WorkScale; // rounds up uint32 PassCount = (uint32)FMath::CeilToFloat(TotalHeight / GBenchmarkResolution); for(uint32 i = 0; i < PassCount; ++i) { float Top = i * GBenchmarkResolution; float Bottom = FMath::Min(Top + GBenchmarkResolution, TotalHeight); float LocalHeight = Bottom - Top; DrawRectangle( RHICmdList, 0, 0, GBenchmarkResolution, LocalHeight, 0, 0, GBenchmarkResolution, LocalHeight, FIntPoint(GBenchmarkResolution, GBenchmarkResolution), FIntPoint(GBenchmarkResolution, GBenchmarkResolution), *VertexShader, EDRF_Default); } }
float ComputeTemporalLODBoundsScreenSize( const FVector& Origin, const float SphereRadius, const FSceneView& View, int32 SampleIndex ) { // This is radial LOD, not the view parallel computation used in ComputeBoundsScreenSize const float Divisor = (Origin - View.GetTemporalLODOrigin(SampleIndex)).Size(); // Get projection multiple accounting for view scaling. const float ScreenMultiple = FMath::Max(View.ViewRect.Width() / 2.0f * View.ViewMatrices.ProjMatrix.M[0][0], View.ViewRect.Height() / 2.0f * View.ViewMatrices.ProjMatrix.M[1][1]); const float ScreenRadius = ScreenMultiple * SphereRadius / FMath::Max(Divisor, 1.0f); const float ScreenArea = PI * ScreenRadius * ScreenRadius; return FMath::Clamp(ScreenArea / View.ViewRect.Area(), 0.0f, 1.0f); }
void FMeshElementCollector::AddMesh(int32 ViewIndex, FMeshBatch& MeshBatch) { checkSlow(MeshBatch.GetNumPrimitives() > 0); checkSlow(MeshBatch.VertexFactory && MeshBatch.MaterialRenderProxy); checkSlow(PrimitiveSceneProxy); if (MeshBatch.bCanApplyViewModeOverrides) { FSceneView* View = Views[ViewIndex]; ApplyViewModeOverrides( ViewIndex, View->Family->EngineShowFlags, View->GetFeatureLevel(), PrimitiveSceneProxy, MeshBatch.bUseWireframeSelectionColoring, MeshBatch, *this); } TArray<FMeshBatchAndRelevance,SceneRenderingAllocator>& ViewMeshBatches = *MeshBatches[ViewIndex]; new (ViewMeshBatches) FMeshBatchAndRelevance(MeshBatch, PrimitiveSceneProxy, FeatureLevel); }
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); }
void FSocketEditingHelper::DrawSocketNames(FSpriteGeometryEditMode* GeometryEditMode, UPrimitiveComponent* PreviewComponent, FViewport& Viewport, FSceneView& View, FCanvas& Canvas) { if (PreviewComponent != nullptr) { const int32 HalfX = Viewport.GetSizeXY().X / 2; const int32 HalfY = Viewport.GetSizeXY().Y / 2; const FColor UnselectedSocketNameColor(255, 196, 196); const FColor SelectedSocketNameColor(FColor::White); TArray<FComponentSocketDescription> SocketList; PreviewComponent->QuerySupportedSockets(/*out*/ SocketList); for (const FComponentSocketDescription& Socket : SocketList) { const FVector SocketWorldPos = PreviewComponent->GetSocketLocation(Socket.Name); const FPlane Proj = View.Project(SocketWorldPos); if (Proj.W > 0.f) { const int32 XPos = HalfX + (HalfX * Proj.X); const int32 YPos = HalfY + (HalfY * (-Proj.Y)); const bool bIsSelected = (GeometryEditMode != nullptr) && GeometryEditMode->IsSocketSelected(Socket.Name); const FColor& SocketColor = bIsSelected ? SelectedSocketNameColor : UnselectedSocketNameColor; FCanvasTextItem Msg(FVector2D(XPos, YPos), FText::FromString(Socket.Name.ToString()), GEngine->GetMediumFont(), SocketColor); Msg.EnableShadow(FLinearColor::Black); Canvas.DrawItem(Msg); // //@TODO: Draws the current value of the rotation (probably want to keep this!) // if (bManipulating && StaticMeshEditorPtr.Pin()->GetSelectedSocket() == Socket) // { // // Figure out the text height // FTextSizingParameters Parameters(GEngine->GetSmallFont(), 1.0f, 1.0f); // UCanvas::CanvasStringSize(Parameters, *Socket->SocketName.ToString()); // int32 YL = FMath::TruncToInt(Parameters.DrawYL); // // DrawAngles(&Canvas, XPos, YPos + YL, // Widget->GetCurrentAxis(), // GetWidgetMode(), // Socket->RelativeRotation, // Socket->RelativeLocation); // } } } } }
void FSCSEditorViewportClient::DrawCanvas( FViewport& InViewport, FSceneView& View, FCanvas& Canvas ) { AActor* PreviewActor = GetPreviewActor(); if(PreviewActor) { if (GUnrealEd != NULL) { TArray<FSCSEditorTreeNodePtrType> SelectedNodes = BlueprintEditorPtr.Pin()->GetSelectedSCSEditorTreeNodes(); for (int32 SelectionIndex = 0; SelectionIndex < SelectedNodes.Num(); ++SelectionIndex) { FSCSEditorTreeNodePtrType SelectedNode = SelectedNodes[SelectionIndex]; UActorComponent* Comp = Cast<USceneComponent>(SelectedNode->FindComponentInstanceInActor(PreviewActor)); if (Comp != NULL && Comp->IsRegistered()) { // Try and find a visualizer TSharedPtr<FComponentVisualizer> Visualizer = GUnrealEd->FindComponentVisualizer(Comp->GetClass()); if (Visualizer.IsValid()) { Visualizer->DrawVisualizationHUD(Comp, &InViewport, &View, &Canvas); } } } } TGuardValue<bool> AutoRestore(GAllowActorScriptExecutionInEditor, true); const int32 HalfX = 0.5f * Viewport->GetSizeXY().X; const int32 HalfY = 0.5f * Viewport->GetSizeXY().Y; auto SelectedNodes = BlueprintEditorPtr.Pin()->GetSelectedSCSEditorTreeNodes(); if(bIsManipulating && SelectedNodes.Num() > 0) { USceneComponent* SceneComp = Cast<USceneComponent>(SelectedNodes[0]->FindComponentInstanceInActor(PreviewActor)); if(SceneComp) { const FVector WidgetLocation = GetWidgetLocation(); const FPlane Proj = View.Project(WidgetLocation); if(Proj.W > 0.0f) { const int32 XPos = HalfX + (HalfX * Proj.X); const int32 YPos = HalfY + (HalfY * (Proj.Y * -1)); DrawAngles(&Canvas, XPos, YPos, GetCurrentWidgetAxis(), GetWidgetMode(), GetWidgetCoordSystem().Rotator(), WidgetLocation); } } } } }
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; }
void SetParameters(FRHICommandList& RHICmdList, const ShaderRHIParamRef Shader, const FLightSceneInfo* LightSceneInfo, const FSceneView& View, TRefCountPtr<IPooledRenderTarget>& PassSource) { FSceneRenderTargets& SceneContext = FSceneRenderTargets::Get(RHICmdList); const uint32 DownsampleFactor = GetLightShaftDownsampleFactor(); FIntPoint DownSampledViewSize(FMath::FloorToInt(View.ViewRect.Width() / DownsampleFactor), FMath::FloorToInt(View.ViewRect.Height() / DownsampleFactor)); const FIntPoint FilterBufferSize = SceneContext.GetBufferSizeXY() / DownsampleFactor; const FVector2D ViewRatioOfBuffer((float)DownSampledViewSize.X / FilterBufferSize.X, (float)DownSampledViewSize.Y / FilterBufferSize.Y); const FVector4 AspectRatioAndInvAspectRatio( ViewRatioOfBuffer.X, (float)FilterBufferSize.X * ViewRatioOfBuffer.Y / FilterBufferSize.Y, 1.0f / ViewRatioOfBuffer.X, (float)FilterBufferSize.Y / (FilterBufferSize.X * ViewRatioOfBuffer.Y)); SetShaderValue(RHICmdList, Shader, AspectRatioAndInvAspectRatioParameter, AspectRatioAndInvAspectRatio); const FVector WorldSpaceBlurOrigin = LightSceneInfo->Proxy->GetLightPositionForLightShafts(View.ViewMatrices.ViewOrigin); // Transform into texture coordinates FVector4 ProjectedBlurOrigin = View.WorldToScreen(WorldSpaceBlurOrigin); const FIntPoint BufferSize = SceneContext.GetBufferSizeXY(); const float InvBufferSizeX = 1.0f / BufferSize.X; const float InvBufferSizeY = 1.0f / BufferSize.Y; FVector2D ScreenSpaceBlurOrigin; { verify(ProjectedBlurOrigin.W > 0.0f); float InvW = 1.0f / ProjectedBlurOrigin.W; float Y = (GProjectionSignY > 0.0f) ? ProjectedBlurOrigin.Y : 1.0f - ProjectedBlurOrigin.Y; ScreenSpaceBlurOrigin = FVector2D( View.ViewRect.Min.X + (0.5f + ProjectedBlurOrigin.X * 0.5f * InvW) * View.ViewRect.Width(), View.ViewRect.Min.Y + (0.5f - Y * 0.5f * InvW) * View.ViewRect.Height() ); } ScreenSpaceBlurOrigin.X *= InvBufferSizeX; ScreenSpaceBlurOrigin.Y *= InvBufferSizeY; FVector2D TextureSpaceBlurOrigin(ScreenSpaceBlurOrigin * FVector2D(AspectRatioAndInvAspectRatio.Z, AspectRatioAndInvAspectRatio.W)); SetShaderValue(RHICmdList, Shader, TextureSpaceBlurOriginParameter, TextureSpaceBlurOrigin); SetShaderValue(RHICmdList, Shader, WorldSpaceBlurOriginAndRadiusParameter, FVector4(WorldSpaceBlurOrigin, LightSceneInfo->Proxy->GetRadius())); SetShaderValue(RHICmdList, Shader, LightSourceRadius, LightSceneInfo->Proxy->GetSourceRadius()); const bool bIsSpotLight = LightSceneInfo->Proxy->GetLightType() == LightType_Spot; if (bIsSpotLight) { SetShaderValue(RHICmdList, Shader, WorldSpaceSpotDirectionParameter, LightSceneInfo->Proxy->GetDirection()); SetShaderValue(RHICmdList, Shader, SpotAnglesParameter, LightSceneInfo->Proxy->GetLightShaftConeParams()); } const float DistanceFromLight = (View.ViewMatrices.ViewOrigin - WorldSpaceBlurOrigin).Size() + PointLightFadeDistanceIncrease; SetShaderValue(RHICmdList, Shader, WorldSpaceCameraPositionParameter, FVector4(View.ViewMatrices.ViewOrigin, DistanceFromLight)); const FIntPoint DownSampledXY = View.ViewRect.Min / DownsampleFactor; const uint32 DownsampledSizeX = View.ViewRect.Width() / DownsampleFactor; const uint32 DownsampledSizeY = View.ViewRect.Height() / DownsampleFactor; // Limits for where the pixel shader is allowed to sample // Prevents reading from outside the valid region of a render target // Clamp to 1 less than the actual max, // Since the bottom-right row/column of texels will contain some unwanted values if the size of scene color is not a factor of the downsample factor float MinU, MinV, MaxU, MaxV; { MinU = DownSampledXY.X / (float)FilterBufferSize.X; MinV = DownSampledXY.Y / (float)FilterBufferSize.Y; MaxU = (float(DownSampledXY.X) + DownsampledSizeX - 1) / (float)FilterBufferSize.X; MaxV = (float(DownSampledXY.Y) + DownsampledSizeY - 1) / (float)FilterBufferSize.Y; } FVector4 UVMinMax( MinU, MinV, MaxU, MaxV ); SetShaderValue(RHICmdList, Shader, UVMinMaxParameter, UVMinMax); const FLinearColor BloomTint = LightSceneInfo->BloomTint; SetShaderValue(RHICmdList, Shader, BloomTintAndThresholdParameter, FVector4(BloomTint.R, BloomTint.G, BloomTint.B, LightSceneInfo->BloomThreshold)); float OcclusionMaskDarkness; float OcclusionDepthRange; LightSceneInfo->Proxy->GetLightShaftOcclusionParameters(OcclusionMaskDarkness, OcclusionDepthRange); const FVector4 LightShaftParameterValues(1.0f / OcclusionDepthRange, LightSceneInfo->BloomScale, 1, OcclusionMaskDarkness); SetShaderValue(RHICmdList, Shader, LightShaftParameters, LightShaftParameterValues); float DistanceFade = 0.0f; if (LightSceneInfo->Proxy->GetLightType() != LightType_Directional) { DistanceFade = FMath::Clamp(DistanceFromLight / (LightSceneInfo->Proxy->GetRadius() * PointLightRadiusFadeFactor), 0.0f, 1.0f); } SetShaderValue(RHICmdList, Shader, DistanceFadeParameter, DistanceFade); if (IsValidRef(PassSource)) { SetTextureParameter( RHICmdList, Shader, SourceTextureParameter, SourceTextureSamplerParameter, TStaticSamplerState<SF_Bilinear,AM_Clamp,AM_Clamp,AM_Clamp>::GetRHI(), PassSource->GetRenderTargetItem().ShaderResourceTexture ); } }
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy, const float FadeAlphaValue=1.0f) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, View.ViewUniformBuffer, true, ESceneRenderTargetsMode::SetTextures); FTransform ComponentTrans = DecalProxy.ComponentTrans; FMatrix WorldToComponent = ComponentTrans.ToInverseMatrixWithScale(); // Set the transform from screen space to light space. if(SvPositionToDecal.IsBound()) { FVector2D InvViewSize = FVector2D(1.0f / View.ViewRect.Width(), 1.0f / View.ViewRect.Height()); // setup a matrix to transform float4(SvPosition.xyz,1) directly to Decal (quality, performance as we don't need to convert or use interpolator) // new_xy = (xy - ViewRectMin.xy) * ViewSizeAndInvSize.zw * float2(2,-2) + float2(-1, 1); // transformed into one MAD: new_xy = xy * ViewSizeAndInvSize.zw * float2(2,-2) + (-ViewRectMin.xy) * ViewSizeAndInvSize.zw * float2(2,-2) + float2(-1, 1); float Mx = 2.0f * InvViewSize.X; float My = -2.0f * InvViewSize.Y; float Ax = -1.0f - 2.0f * View.ViewRect.Min.X * InvViewSize.X; float Ay = 1.0f + 2.0f * View.ViewRect.Min.Y * InvViewSize.Y; // todo: we could use InvTranslatedViewProjectionMatrix and TranslatedWorldToComponent for better quality const FMatrix SvPositionToDecalValue = FMatrix( FPlane(Mx, 0, 0, 0), FPlane( 0, My, 0, 0), FPlane( 0, 0, 1, 0), FPlane(Ax, Ay, 0, 1) ) * View.InvViewProjectionMatrix * WorldToComponent; SetShaderValue(RHICmdList, ShaderRHI, SvPositionToDecal, SvPositionToDecalValue); } // Set the transform from light space to world space if(DecalToWorld.IsBound()) { const FMatrix DecalToWorldValue = ComponentTrans.ToMatrixWithScale(); SetShaderValue(RHICmdList, ShaderRHI, DecalToWorld, DecalToWorldValue); } SetShaderValue(RHICmdList, ShaderRHI, WorldToDecal, WorldToComponent); float LifetimeAlpha = FMath::Clamp(View.Family->CurrentWorldTime * -DecalProxy.InvFadeDuration + DecalProxy.FadeStartDelayNormalized, 0.0f, 1.0f); SetShaderValue(RHICmdList, ShaderRHI, DecalParams, FVector2D(FadeAlphaValue, LifetimeAlpha)); }
virtual void OverridePostProcessSettings(FSceneView& View) override { View.OverridePostProcessSettings(PostProcessSettings, PostProcessSettingsWeight); }
void SetParameters(FRHICommandList& RHICmdList, const FSceneView& View, const FMaterialRenderProxy* MaterialProxy, const FDeferredDecalProxy& DecalProxy, const float FadeAlphaValue=1.0f) { const FPixelShaderRHIParamRef ShaderRHI = GetPixelShader(); FMaterialShader::SetParameters(RHICmdList, ShaderRHI, MaterialProxy, *MaterialProxy->GetMaterial(View.GetFeatureLevel()), View, true, ESceneRenderTargetsMode::SetTextures); FTransform ComponentTrans = DecalProxy.ComponentTrans; FMatrix WorldToComponent = ComponentTrans.ToInverseMatrixWithScale(); // Set the transform from screen space to light space. if(ScreenToDecal.IsBound()) { const FMatrix ScreenToDecalValue = FMatrix( FPlane(1,0,0,0), FPlane(0,1,0,0), FPlane(0,0,View.ViewMatrices.ProjMatrix.M[2][2],1), FPlane(0,0,View.ViewMatrices.ProjMatrix.M[3][2],0) ) * View.InvViewProjectionMatrix * WorldToComponent; SetShaderValue(RHICmdList, ShaderRHI, ScreenToDecal, ScreenToDecalValue); } // Set the transform from light space to world space if(DecalToWorld.IsBound()) { const FMatrix DecalToWorldValue = ComponentTrans.ToMatrixWithScale(); SetShaderValue(RHICmdList, ShaderRHI, DecalToWorld, DecalToWorldValue); } SetShaderValue(RHICmdList, ShaderRHI, FadeAlpha, FadeAlphaValue); SetShaderValue(RHICmdList, ShaderRHI, WorldToDecal, WorldToComponent); }
void FViewExtension::PreRenderView_RenderThread(FRHICommandListImmediate& RHICmdList, FSceneView& View) { check(IsInRenderingThread()); FViewExtension& RenderContext = *this; FGameFrame* CurrentFrame = static_cast<FGameFrame*>(RenderContext.RenderFrame.Get()); if (!RenderContext.ShowFlags.Rendering || !CurrentFrame || !CurrentFrame->Settings->IsStereoEnabled()) { return; } const ovrEyeType eyeIdx = (View.StereoPass == eSSP_LEFT_EYE) ? ovrEye_Left : ovrEye_Right; if (RenderContext.ShowFlags.Rendering && CurrentFrame->Settings->Flags.bUpdateOnRT) { FQuat CurrentEyeOrientation; FVector CurrentEyePosition; CurrentFrame->PoseToOrientationAndPosition(RenderContext.CurEyeRenderPose[eyeIdx], CurrentEyeOrientation, CurrentEyePosition); FQuat ViewOrientation = View.ViewRotation.Quaternion(); // recalculate delta control orientation; it should match the one we used in CalculateStereoViewOffset on a game thread. FVector GameEyePosition; FQuat GameEyeOrient; CurrentFrame->PoseToOrientationAndPosition(CurrentFrame->EyeRenderPose[eyeIdx], GameEyeOrient, GameEyePosition); const FQuat DeltaControlOrientation = ViewOrientation * GameEyeOrient.Inverse(); // make sure we use the same viewrotation as we had on a game thread check(View.ViewRotation == CurrentFrame->CachedViewRotation[eyeIdx]); if (CurrentFrame->Flags.bOrientationChanged) { // Apply updated orientation to corresponding View at recalc matrices. // The updated position will be applied from inside of the UpdateViewMatrix() call. const FQuat DeltaOrient = View.BaseHmdOrientation.Inverse() * CurrentEyeOrientation; View.ViewRotation = FRotator(ViewOrientation * DeltaOrient); //UE_LOG(LogHMD, Log, TEXT("VIEWDLT: Yaw %.3f Pitch %.3f Roll %.3f"), DeltaOrient.Rotator().Yaw, DeltaOrient.Rotator().Pitch, DeltaOrient.Rotator().Roll); } if (!CurrentFrame->Flags.bPositionChanged) { // if no positional change applied then we still need to calculate proper stereo disparity. // use the current head pose for this calculation instead of the one that was saved on a game thread. FQuat HeadOrientation; CurrentFrame->PoseToOrientationAndPosition(RenderContext.CurHeadPose, HeadOrientation, View.BaseHmdLocation); } // The HMDPosition already has HMD orientation applied. // Apply rotational difference between HMD orientation and ViewRotation // to HMDPosition vector. const FVector DeltaPosition = CurrentEyePosition - View.BaseHmdLocation; const FVector vEyePosition = DeltaControlOrientation.RotateVector(DeltaPosition) + CurrentFrame->Settings->PositionOffset; View.ViewLocation += vEyePosition; //UE_LOG(LogHMD, Log, TEXT("VDLTPOS: %.3f %.3f %.3f"), vEyePosition.X, vEyePosition.Y, vEyePosition.Z); if (CurrentFrame->Flags.bOrientationChanged || CurrentFrame->Flags.bPositionChanged) { View.UpdateViewMatrix(); } } FSettings* FrameSettings = CurrentFrame->GetSettings(); check(FrameSettings); FrameSettings->EyeLayer.EyeFov.RenderPose[eyeIdx] = RenderContext.CurEyeRenderPose[eyeIdx]; }
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...) } }
void FSpriteGeometryEditingHelper::DrawGeometry_CanvasPass(FViewport& InViewport, const FSceneView& View, FCanvas& Canvas, /*inout*/ int32& YPos, const FLinearColor& GeometryVertexColor, const FLinearColor& NegativeGeometryVertexColor) { if (GeometryBeingEdited == nullptr) { return; } // Calculate the texture-space position of the mouse const FVector MousePositionWorldSpace = View.PixelToWorld(InViewport.GetMouseX(), InViewport.GetMouseY(), 0); const FVector2D MousePositionTextureSpace = EditorContext->WorldSpaceToTextureSpace(MousePositionWorldSpace); //@TODO: Move all of the line drawing to the PDI pass FSpriteGeometryCollection& Geometry = GetGeometryChecked(); // Display tool help { static const FText GeomHelpStr = LOCTEXT("GeomEditHelp", "Shift + click to insert a vertex.\nSelect one or more vertices and press Delete to remove them.\nDouble click a vertex to select a polygon\n"); static const FText GeomClickAddPolygon_NoSubtractive = LOCTEXT("GeomClickAddPolygon_NoSubtractive", "Click to start creating a polygon\n"); static const FText GeomClickAddPolygon_AllowSubtractive = LOCTEXT("GeomClickAddPolygon_AllowSubtractive", "Click to start creating a polygon\nCtrl + Click to start creating a subtractive polygon\n"); static const FText GeomAddVerticesHelpStr = LOCTEXT("GeomClickAddVertices", "Click to add points to the polygon\nDouble-click to add a point and close the shape\nClick again on the first point or press Enter to close the shape\nPress Backspace to remove the last added point or Escape to remove the shape\n"); FLinearColor ToolTextColor = FLinearColor::White; const FText* HelpStr; if (IsAddingPolygon()) { if (AddingPolygonIndex == INDEX_NONE) { HelpStr = bAllowSubtractivePolygons ? &GeomClickAddPolygon_AllowSubtractive : &GeomClickAddPolygon_NoSubtractive; } else { HelpStr = &GeomAddVerticesHelpStr; } ToolTextColor = FLinearColor::Yellow; } else { HelpStr = &GeomHelpStr; } FCanvasTextItem TextItem(FVector2D(6, YPos), *HelpStr, GEngine->GetSmallFont(), ToolTextColor); TextItem.EnableShadow(FLinearColor::Black); TextItem.Draw(&Canvas); YPos += 54; } const bool bIsHitTesting = Canvas.IsHitTesting(); // Run thru the geometry shapes and draw hit proxies for them for (int32 ShapeIndex = 0; ShapeIndex < Geometry.Shapes.Num(); ++ShapeIndex) { const FSpriteGeometryShape& Shape = Geometry.Shapes[ShapeIndex]; const bool bIsShapeSelected = IsGeometrySelected(FShapeVertexPair(ShapeIndex, INDEX_NONE)); const FLinearColor LineColorRaw = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor; const FLinearColor VertexColor = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor; const FLinearColor LineColor = Shape.IsShapeValid() ? LineColorRaw : FMath::Lerp(LineColorRaw, FLinearColor::Red, 0.8f); // Draw the circle shape if necessary if (Shape.ShapeType == ESpriteShapeType::Circle) { if (bIsHitTesting) { TSharedPtr<FSpriteSelectedShape> Data = MakeShareable(new FSpriteSelectedShape(EditorContext, Geometry, ShapeIndex, /*bIsBackground=*/ false)); Canvas.SetHitProxy(new HSpriteSelectableObjectHitProxy(Data)); } // Draw the circle const float RadiusX = Shape.BoxSize.X * 0.5f; const float RadiusY = Shape.BoxSize.Y * 0.5f; const float AngleDelta = 2.0f * PI / SpriteEditingConstantsEX::CircleShapeNumSides; const float LastX = Shape.BoxPosition.X + RadiusX; const float LastY = Shape.BoxPosition.Y; FVector2D LastVertexPos = TextureSpaceToScreenSpace(View, FVector2D(LastX, LastY)); for (int32 SideIndex = 0; SideIndex < SpriteEditingConstantsEX::CircleShapeNumSides; SideIndex++) { const float X = Shape.BoxPosition.X + RadiusX * FMath::Cos(AngleDelta * (SideIndex + 1)); const float Y = Shape.BoxPosition.Y + RadiusY * FMath::Sin(AngleDelta * (SideIndex + 1)); const FVector2D ScreenPos = TextureSpaceToScreenSpace(View, FVector2D(X, Y)); FCanvasLineItem LineItem(LastVertexPos, ScreenPos); LineItem.SetColor(bIsShapeSelected ? SpriteEditingConstantsEX::GeometrySelectedColor : LineColor); LineItem.LineThickness = SpriteEditingConstantsEX::GeometryBorderLineThickness; Canvas.DrawItem(LineItem); LastVertexPos = ScreenPos; } if (bIsHitTesting) { Canvas.SetHitProxy(nullptr); } } // Draw lines connecting the vertices of the shape for (int32 VertexIndex = 0; VertexIndex < Shape.Vertices.Num(); ++VertexIndex) { const int32 NextVertexIndex = (VertexIndex + 1) % Shape.Vertices.Num(); const FVector2D ScreenPos = TextureSpaceToScreenSpace(View, Shape.ConvertShapeSpaceToTextureSpace(Shape.Vertices[VertexIndex])); const FVector2D NextScreenPos = TextureSpaceToScreenSpace(View, Shape.ConvertShapeSpaceToTextureSpace(Shape.Vertices[NextVertexIndex])); const bool bIsThisVertexSelected = IsGeometrySelected(FShapeVertexPair(ShapeIndex, VertexIndex)); const bool bIsNextVertexSelected = IsGeometrySelected(FShapeVertexPair(ShapeIndex, NextVertexIndex)); const bool bIsEdgeSelected = bIsShapeSelected || (bIsThisVertexSelected && bIsNextVertexSelected); // Draw the normal tick if (bShowNormals) { const FVector2D Direction = (NextScreenPos - ScreenPos).GetSafeNormal(); const FVector2D Normal = FVector2D(-Direction.Y, Direction.X); const FVector2D Midpoint = (ScreenPos + NextScreenPos) * 0.5f; const FVector2D NormalPoint = Midpoint - Normal * SpriteEditingConstantsEX::GeometryNormalLength; FCanvasLineItem LineItem(Midpoint, NormalPoint); LineItem.SetColor(SpriteEditingConstantsEX::GeometryNormalColor); Canvas.DrawItem(LineItem); } // Draw the edge { if (bIsHitTesting) { TSharedPtr<FSpriteSelectedEdge> Data = MakeShareable(new FSpriteSelectedEdge(EditorContext, Geometry, ShapeIndex, VertexIndex)); Canvas.SetHitProxy(new HSpriteSelectableObjectHitProxy(Data)); } FCanvasLineItem LineItem(ScreenPos, NextScreenPos); LineItem.SetColor(bIsEdgeSelected ? SpriteEditingConstantsEX::GeometrySelectedColor : LineColor); LineItem.LineThickness = SpriteEditingConstantsEX::GeometryBorderLineThickness; Canvas.DrawItem(LineItem); if (bIsHitTesting) { Canvas.SetHitProxy(nullptr); } } } // Draw the vertices for (int32 VertexIndex = 0; VertexIndex < Shape.Vertices.Num(); ++VertexIndex) { const FVector2D ScreenPos = TextureSpaceToScreenSpace(View, Shape.ConvertShapeSpaceToTextureSpace(Shape.Vertices[VertexIndex])); const float X = ScreenPos.X; const float Y = ScreenPos.Y; const bool bIsVertexSelected = IsGeometrySelected(FShapeVertexPair(ShapeIndex, VertexIndex)); const bool bIsVertexLastAdded = IsAddingPolygon() && (AddingPolygonIndex == ShapeIndex) && (VertexIndex == Shape.Vertices.Num() - 1); const bool bNeedHighlightVertex = bIsShapeSelected || bIsVertexSelected || bIsVertexLastAdded; if (bIsHitTesting) { TSharedPtr<FSpriteSelectedVertex> Data = MakeShareable(new FSpriteSelectedVertex(EditorContext, Geometry, ShapeIndex, VertexIndex)); Canvas.SetHitProxy(new HSpriteSelectableObjectHitProxy(Data)); } const float VertSize = SpriteEditingConstantsEX::GeometryVertexSize; Canvas.DrawTile(ScreenPos.X - VertSize*0.5f, ScreenPos.Y - VertSize*0.5f, VertSize, VertSize, 0.f, 0.f, 1.f, 1.f, bNeedHighlightVertex ? SpriteEditingConstantsEX::GeometrySelectedColor : VertexColor, GWhiteTexture); if (bIsHitTesting) { Canvas.SetHitProxy(nullptr); } } } // Draw a preview cursor for the add polygon tool if (IsAddingPolygon()) { // Figure out where the mouse is back in screen space const FVector2D PotentialVertexScreenPos = TextureSpaceToScreenSpace(View, MousePositionTextureSpace); bool bWillCloseByClicking = false; if (Geometry.Shapes.IsValidIndex(AddingPolygonIndex)) { const FSpriteGeometryShape& Shape = Geometry.Shapes[AddingPolygonIndex]; const FLinearColor LineColorRaw = Shape.bNegativeWinding ? NegativeGeometryVertexColor : GeometryVertexColor; const FLinearColor LineColorValidity = Shape.IsShapeValid() ? LineColorRaw : FMath::Lerp(LineColorRaw, FLinearColor::Red, 0.8f); const FLinearColor LineColor = FMath::Lerp(LineColorValidity, SpriteEditingConstantsEX::GeometrySelectedColor, 0.2f); if (Shape.Vertices.Num() > 0) { // Draw a line from the last vertex to the potential insertion point for the new one { const FVector2D LastScreenPos = TextureSpaceToScreenSpace(View, Shape.ConvertShapeSpaceToTextureSpace(Shape.Vertices[Shape.Vertices.Num() - 1])); FCanvasLineItem LineItem(LastScreenPos, PotentialVertexScreenPos); LineItem.SetColor(LineColor); LineItem.LineThickness = SpriteEditingConstantsEX::GeometryBorderLineThickness; Canvas.DrawItem(LineItem); } // And to the first vertex if there were at least 2 if (Shape.Vertices.Num() >= 2) { const FVector2D FirstScreenPos = TextureSpaceToScreenSpace(View, Shape.ConvertShapeSpaceToTextureSpace(Shape.Vertices[0])); FCanvasLineItem LineItem(PotentialVertexScreenPos, FirstScreenPos); LineItem.SetColor(LineColor); LineItem.LineThickness = SpriteEditingConstantsEX::GeometryBorderLineThickness; Canvas.DrawItem(LineItem); // Determine how close we are to the first vertex (will we close the shape by clicking)? bWillCloseByClicking = (Shape.Vertices.Num() >= 3) && (FVector2D::Distance(FirstScreenPos, PotentialVertexScreenPos) < SpriteEditingConstantsEX::AddPolygonVertexWeldScreenSpaceDistance); } } } // Draw the prospective vert const float VertSize = SpriteEditingConstantsEX::GeometryVertexSize; Canvas.DrawTile(PotentialVertexScreenPos.X - VertSize*0.5f, PotentialVertexScreenPos.Y - VertSize*0.5f, VertSize, VertSize, 0.f, 0.f, 1.f, 1.f, SpriteEditingConstantsEX::GeometrySelectedColor, GWhiteTexture); // Draw a prompt above and to the right of the cursor static const FText CloseButton(LOCTEXT("ClosePolygonPrompt", "Close")); static const FText AddButton(LOCTEXT("AddVertexToPolygonPrompt", "+")); const FText PromptText(bWillCloseByClicking ? CloseButton : AddButton); FCanvasTextItem PromptTextItem(FVector2D(PotentialVertexScreenPos.X + VertSize, PotentialVertexScreenPos.Y - VertSize), PromptText, GEngine->GetSmallFont(), FLinearColor::White); PromptTextItem.EnableShadow(FLinearColor::Black); PromptTextItem.Draw(&Canvas); } }
void SetParameters( FRHICommandList& RHICmdList, const FMaterialRenderProxy* MaterialRenderProxy, const FSceneView& View ) { FMeshMaterialShader::SetParameters(RHICmdList, GetPixelShader(), MaterialRenderProxy, *MaterialRenderProxy->GetMaterial(View.GetFeatureLevel()), View, ESceneRenderTargetsMode::SetTextures); float Ratio = View.UnscaledViewRect.Width() / (float)View.UnscaledViewRect.Height(); float Params[4]; Params[0] = View.ViewMatrices.ProjMatrix.M[0][0]; Params[1] = Ratio; Params[2] = (float)View.UnscaledViewRect.Width(); Params[3] = (float)View.UnscaledViewRect.Height(); SetShaderValue(RHICmdList, GetPixelShader(), DistortionParams, Params); }
void FPhATEdPreviewViewportClient::DrawCanvas( FViewport& InViewport, FSceneView& View, FCanvas& Canvas ) { if (!PhATPtr.IsValid()) { return; } // Turn on/off the ground box SharedData->EditorFloorComp->SetVisibility(SharedData->bDrawGround); float W, H; PhATFont->GetCharSize(TEXT('L'), W, H); const float XOffset = 5.0f; const float YOffset = 32.0f; FCanvasTextItem TextItem( FVector2D::ZeroVector, FText::GetEmpty(), PhATFont, FLinearColor::White ); // Write body/constraint count at top. FString StatusString = FText::Format( NSLOCTEXT("UnrealEd", "BodiesConstraints_F", "{0} Bodies {1} Considered for bounds {2} Ratio {3} Constraints"), FText::AsNumber(SharedData->PhysicsAsset->SkeletalBodySetups.Num()), FText::AsNumber(SharedData->PhysicsAsset->BoundsBodies.Num()), FText::AsNumber(static_cast<float>(SharedData->PhysicsAsset->BoundsBodies.Num())/static_cast<float>(SharedData->PhysicsAsset->SkeletalBodySetups.Num())), FText::AsNumber(SharedData->PhysicsAsset->ConstraintSetup.Num()) ).ToString(); TextItem.Text = FText::FromString( StatusString ); Canvas.DrawItem( TextItem, XOffset, YOffset); TextItem.Text = FText::GetEmpty(); if (SharedData->bRunningSimulation) { #if PLATFORM_MAC TextItem.Text = NSLOCTEXT("UnrealEd", "Sim_Mac", "SIM: Command+RightMouse to interact with bodies"); #else TextItem.Text = NSLOCTEXT("UnrealEd", "Sim", "SIM: Ctrl+RightMouse to interact with bodies"); #endif } else if (SharedData->bSelectionLock) { TextItem.Text = NSLOCTEXT("UnrealEd", "Lock", "LOCK"); }else if(SharedData->EditingMode == FPhATSharedData::PEM_ConstraintEdit) { if(GetWidgetMode() == FWidget::WM_Translate) { TextItem.Text = NSLOCTEXT("UnrealEd", "SingleMove", "hold ALT to move a single reference frame"); }else if(GetWidgetMode() == FWidget::WM_Rotate) { TextItem.Text = NSLOCTEXT("UnrealEd", "DoubleRotate", "hold ALT to rotate both reference frames"); } } Canvas.DrawItem( TextItem, XOffset, Viewport->GetSizeXY().Y - (3 + H) ); // Draw current physics weight if (SharedData->bRunningSimulation) { FString PhysWeightString = FString::Printf(TEXT("Phys Blend: %3.0f pct"), SharedData->EditorSimOptions->PhysicsBlend * 100.f); int32 PWLW, PWLH; StringSize(PhATFont, PWLW, PWLH, *PhysWeightString); TextItem.Text = FText::FromString(PhysWeightString); Canvas.DrawItem( TextItem, Viewport->GetSizeXY().X - (3 + PWLW + 2*W), Viewport->GetSizeXY().Y - (3 + H) ); } int32 HalfX = (Viewport->GetSizeXY().X-XOffset)/2; int32 HalfY = Viewport->GetSizeXY().Y/2; if ((SharedData->bShowHierarchy && SharedData->EditorSimOptions->bShowNamesInHierarchy)) { // Iterate over each graphics bone. for (int32 i = 0; i < SharedData->EditorSkelComp->GetNumComponentSpaceTransforms(); ++i) { FVector BonePos = SharedData->EditorSkelComp->ComponentToWorld.TransformPosition(SharedData->EditorSkelComp->GetComponentSpaceTransforms()[i].GetLocation()); FPlane proj = View.Project(BonePos); if (proj.W > 0.f) // This avoids drawing bone names that are behind us. { int32 XPos = HalfX + (HalfX * proj.X); int32 YPos = HalfY + (HalfY * (proj.Y * -1)); FName BoneName = SharedData->EditorSkelMesh->RefSkeleton.GetBoneName(i); FColor BoneNameColor = FColor::White; //iterate through selected bones and see if any match for(int32 j=0; j< SharedData->SelectedBodies.Num(); ++j) { int32 SelectedBodyIndex = SharedData->SelectedBodies[j].Index; FName SelectedBoneName = SharedData->PhysicsAsset->SkeletalBodySetups[SelectedBodyIndex]->BoneName; if(SelectedBoneName == BoneName) { BoneNameColor = FColor::Green; break; } } if (Canvas.IsHitTesting()) { Canvas.SetHitProxy(new HPhATEdBoneNameProxy(i)); } TextItem.Text = FText::FromString(BoneName.ToString()); TextItem.SetColor(BoneNameColor); Canvas.DrawItem( TextItem, XPos, YPos ); if (Canvas.IsHitTesting()) { Canvas.SetHitProxy(NULL); } } } } // If showing center-of-mass, and physics is started up.. if (SharedData->bShowCOM) { // iterate over each bone for (int32 i = 0; i <SharedData->EditorSkelComp->Bodies.Num(); ++i) { FBodyInstance* BodyInst = SharedData->EditorSkelComp->Bodies[i]; check(BodyInst); FVector BodyCOMPos = BodyInst->GetCOMPosition(); float BodyMass = BodyInst->GetBodyMass(); FPlane Projection = View.Project(BodyCOMPos); if (Projection.W > 0.f) // This avoids drawing bone names that are behind us. { int32 XPos = HalfX + (HalfX * Projection.X); int32 YPos = HalfY + (HalfY * (Projection.Y * -1)); FString COMString = FString::Printf(TEXT("%3.3f"), BodyMass); TextItem.Text = FText::FromString(COMString); TextItem.SetColor(SharedData->COMRenderColor); Canvas.DrawItem( TextItem, XPos, YPos ); } } } }
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 FSpriteEditorViewportClient::ProcessClick(FSceneView& View, HHitProxy* HitProxy, FKey Key, EInputEvent Event, uint32 HitX, uint32 HitY) { const FViewportClick Click(&View, this, Key, Event, HitX, HitY); 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; HSpriteSelectableObjectHitProxy* SelectedItemProxy = HitProxyCast<HSpriteSelectableObjectHitProxy>(HitProxy); if (IsInSourceRegionEditMode()) { if ((Event == EInputEvent::IE_DoubleClick) && (Key == EKeys::LeftMouseButton)) { FVector4 WorldPoint = View.PixelToWorld(HitX, HitY, 0); UPaperSprite* Sprite = GetSpriteBeingEdited(); FVector2D TexturePoint = SourceTextureViewComponent->GetSprite()->ConvertWorldSpaceToTextureSpace(WorldPoint); if (bIsCtrlKeyDown) { const FVector2D StartingUV = Sprite->GetSourceUV(); const FVector2D StartingSize = Sprite->GetSourceSize(); if (UPaperSprite* NewSprite = CreateNewSprite(FIntPoint((int32)StartingUV.X, (int32)StartingUV.Y), FIntPoint((int32)StartingSize.X, (int32)StartingSize.Y))) { NewSprite->ExtractSourceRegionFromTexturePoint(TexturePoint); bHandled = true; } } else { Sprite->ExtractSourceRegionFromTexturePoint(TexturePoint); bHandled = true; } } else if ((Event == EInputEvent::IE_Released) && (Key == EKeys::LeftMouseButton)) { FVector4 WorldPoint = View.PixelToWorld(HitX, HitY, 0); FVector2D TexturePoint = SourceTextureViewComponent->GetSprite()->ConvertWorldSpaceToTextureSpace(WorldPoint); for (int32 RelatedSpriteIndex = 0; RelatedSpriteIndex < RelatedSprites.Num(); ++RelatedSpriteIndex) { FRelatedSprite& RelatedSprite = RelatedSprites[RelatedSpriteIndex]; if ((TexturePoint.X >= RelatedSprite.SourceUV.X) && (TexturePoint.Y >= RelatedSprite.SourceUV.Y) && (TexturePoint.X < (RelatedSprite.SourceUV.X + RelatedSprite.SourceDimension.X)) && (TexturePoint.Y < (RelatedSprite.SourceUV.Y + RelatedSprite.SourceDimension.Y))) { bHandled = true; // Select this sprite if (UPaperSprite* LoadedSprite = Cast<UPaperSprite>(RelatedSprite.AssetData.GetAsset())) { if (SpriteEditorPtr.IsValid()) { SpriteEditorPtr.Pin()->SetSpriteBeingEdited(LoadedSprite); break; } } } } } } if (!bHandled) { FPaperEditorViewportClient::ProcessClick(View, HitProxy, Key, Event, HitX, HitY); } }
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; }