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); } } } } }
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 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 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 ); } } } }
void FStaticMeshEditorViewportClient::DrawCanvas( FViewport& InViewport, FSceneView& View, FCanvas& Canvas ) { #if TODO_STATICMESH if ( StaticMesh->bHasBeenSimplified && SimplygonLogo && SimplygonLogo->Resource ) { const float LogoSizeX = 64.0f; const float LogoSizeY = 40.65f; const float Padding = 6.0f; const float LogoX = Viewport->GetSizeXY().X - Padding - LogoSizeX; const float LogoY = Viewport->GetSizeXY().Y - Padding - LogoSizeY; Canvas->DrawTile( LogoX, LogoY, LogoSizeX, LogoSizeY, 0.0f, 0.0f, 1.0f, 1.0f, FLinearColor::White, SimplygonLogo->Resource, SE_BLEND_Opaque ); } #endif // #if TODO_STATICMESH auto StaticMeshEditor = StaticMeshEditorPtr.Pin(); auto StaticMeshEditorViewport = StaticMeshEditorViewportPtr.Pin(); if (!StaticMeshEditor.IsValid() || !StaticMeshEditorViewport.IsValid()) { return; } const int32 HalfX = Viewport->GetSizeXY().X/2; const int32 HalfY = Viewport->GetSizeXY().Y/2; // Draw socket names if desired. if( bShowSockets ) { for(int32 i=0; i<StaticMesh->Sockets.Num(); i++) { UStaticMeshSocket* Socket = StaticMesh->Sockets[i]; if(Socket!=NULL) { FMatrix SocketTM; Socket->GetSocketMatrix(SocketTM, StaticMeshComponent); const FVector SocketPos = SocketTM.GetOrigin(); const FPlane proj = View.Project( SocketPos ); if(proj.W > 0.f) { const int32 XPos = HalfX + ( HalfX * proj.X ); const int32 YPos = HalfY + ( HalfY * (proj.Y * -1) ); FCanvasTextItem TextItem( FVector2D( XPos, YPos ), FText::FromString( Socket->SocketName.ToString() ), GEngine->GetSmallFont(), FLinearColor(FColor(255,196,196)) ); Canvas.DrawItem( TextItem ); const UStaticMeshSocket* SelectedSocket = StaticMeshEditor->GetSelectedSocket(); if (bManipulating && SelectedSocket == 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); } } } } } TArray<SStaticMeshEditorViewport::FOverlayTextItem> TextItems; int32 CurrentLODLevel = StaticMeshEditor->GetCurrentLODLevel(); if (CurrentLODLevel == 0) { CurrentLODLevel = ComputeStaticMeshLOD(StaticMesh->RenderData, StaticMeshComponent->Bounds.Origin, StaticMeshComponent->Bounds.SphereRadius, View); } else { CurrentLODLevel -= 1; } TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( FText::Format(NSLOCTEXT("UnrealEd", "LOD_F", "LOD: {0}"), FText::AsNumber(CurrentLODLevel)))); float CurrentScreenSize = ComputeBoundsScreenSize(StaticMeshComponent->Bounds.Origin, StaticMeshComponent->Bounds.SphereRadius, View); FNumberFormattingOptions FormatOptions; FormatOptions.MinimumFractionalDigits = 3; FormatOptions.MaximumFractionalDigits = 6; FormatOptions.MaximumIntegralDigits = 6; TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( FText::Format(NSLOCTEXT("UnrealEd", "ScreenSize_F", "Current Screen Size: {0}"), FText::AsNumber(CurrentScreenSize, &FormatOptions)))); TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( FText::Format(NSLOCTEXT("UnrealEd", "Triangles_F", "Triangles: {0}"), FText::AsNumber(StaticMeshEditorPtr.Pin()->GetNumTriangles(CurrentLODLevel))))); TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( FText::Format(NSLOCTEXT("UnrealEd", "Vertices_F", "Vertices: {0}"), FText::AsNumber(StaticMeshEditorPtr.Pin()->GetNumVertices(CurrentLODLevel))))); TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( FText::Format(NSLOCTEXT("UnrealEd", "UVChannels_F", "UV Channels: {0}"), FText::AsNumber(StaticMeshEditorPtr.Pin()->GetNumUVChannels(CurrentLODLevel))))); if( StaticMesh->RenderData->LODResources.Num() > 0 ) { if (StaticMesh->RenderData->LODResources[0].DistanceFieldData != nullptr ) { const FDistanceFieldVolumeData& VolumeData = *(StaticMesh->RenderData->LODResources[0].DistanceFieldData); if (VolumeData.Size.GetMax() > 0) { float MemoryMb = (VolumeData.Size.X * VolumeData.Size.Y * VolumeData.Size.Z * VolumeData.DistanceFieldVolume.GetTypeSize()) / (1024.0f * 1024.0f); FNumberFormattingOptions NumberOptions; NumberOptions.MinimumFractionalDigits = 2; NumberOptions.MaximumFractionalDigits = 2; if (VolumeData.bMeshWasClosed) { TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( FText::Format(NSLOCTEXT("UnrealEd", "DistanceFieldRes_F", "Distance Field: {0}x{1}x{2} = {3}Mb"), FText::AsNumber(VolumeData.Size.X), FText::AsNumber(VolumeData.Size.Y), FText::AsNumber(VolumeData.Size.Z), FText::AsNumber(MemoryMb, &NumberOptions)))); } else { TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( NSLOCTEXT("UnrealEd", "DistanceFieldClosed_F", "Distance Field: Mesh was not closed and material was one-sided"))); } } } } TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( FText::Format(NSLOCTEXT("UnrealEd", "ApproxSize_F", "Approx Size: {0}x{1}x{2}"), FText::AsNumber(int32(StaticMesh->GetBounds().BoxExtent.X * 2.0f)), // x2 as artists wanted length not radius FText::AsNumber(int32(StaticMesh->GetBounds().BoxExtent.Y * 2.0f)), FText::AsNumber(int32(StaticMesh->GetBounds().BoxExtent.Z * 2.0f))))); // Show the number of collision primitives if we are drawing collision. if(bShowCollision && StaticMesh->BodySetup) { TextItems.Add(SStaticMeshEditorViewport::FOverlayTextItem( FText::Format(NSLOCTEXT("UnrealEd", "NumPrimitives_F", "Num Primitives: {0}"), FText::AsNumber(StaticMesh->BodySetup->AggGeom.GetElementCount())))); } StaticMeshEditorViewport->PopulateOverlayText(TextItems); if(bDrawUVs) { const int32 YPos = 160; DrawUVsForMesh(Viewport, &Canvas, YPos); } }