FVector FEdMode::GetWidgetLocation() const { if(UsesPropertyWidgets()) { AActor* SelectedActor = GetFirstSelectedActorInstance(); if(SelectedActor != NULL) { if(EditedPropertyName != TEXT("")) { FVector LocalPos = FVector::ZeroVector; if(bEditedPropertyIsTransform) { FTransform LocalTM = GetPropertyValueByName<FTransform>(SelectedActor, EditedPropertyName, EditedPropertyIndex); LocalPos = LocalTM.GetLocation(); } else { LocalPos = GetPropertyValueByName<FVector>(SelectedActor, EditedPropertyName, EditedPropertyIndex); } FTransform ActorToWorld = SelectedActor->ActorToWorld(); FVector WorldPos = ActorToWorld.TransformPosition(LocalPos); return WorldPos; } } } //UE_LOG(LogEditorModes, Log, TEXT("In FEdMode::GetWidgetLocation")); return Owner->PivotLocation; }
FBoxSphereBounds UNavLinkRenderingComponent::CalcBounds(const FTransform& InLocalToWorld) const { AActor* LinkOwnerActor = Cast<AActor>(GetOwner()); INavLinkHostInterface* LinkOwnerHost = Cast<INavLinkHostInterface>(GetOwner()); if (LinkOwnerActor != NULL && LinkOwnerHost != NULL) { FBox BoundingBox(0); const FTransform LocalToWorld = LinkOwnerActor->ActorToWorld(); TArray<TSubclassOf<UNavLinkDefinition> > NavLinkClasses; TArray<FNavigationLink> SimpleLinks; TArray<FNavigationSegmentLink> DummySegmentLinks; if (LinkOwnerHost->GetNavigationLinksClasses(NavLinkClasses)) { for (int32 NavLinkClassIdx = 0; NavLinkClassIdx < NavLinkClasses.Num(); ++NavLinkClassIdx) { if (NavLinkClasses[NavLinkClassIdx] != NULL) { const TArray<FNavigationLink>& Links = UNavLinkDefinition::GetLinksDefinition(NavLinkClasses[NavLinkClassIdx]); for (const auto& Link : Links) { BoundingBox += Link.Left; BoundingBox += Link.Right; } } } } if (LinkOwnerHost->GetNavigationLinksArray(SimpleLinks, DummySegmentLinks)) { for (const auto& Link : SimpleLinks) { BoundingBox += Link.Left; BoundingBox += Link.Right; } } return FBoxSphereBounds(BoundingBox).TransformBy(LocalToWorld); } return FBoxSphereBounds(EForceInit::ForceInitToZero); }
void UUnrealEdEngine::SetPivot( FVector NewPivot, bool bSnapPivotToGrid, bool bIgnoreAxis, bool bAssignPivot/*=false*/ ) { FEditorModeTools& EditorModeTools = GLevelEditorModeTools(); if( !bIgnoreAxis ) { // Don't stomp on orthonormal axis. if( NewPivot.X==0 ) NewPivot.X=EditorModeTools.PivotLocation.X; if( NewPivot.Y==0 ) NewPivot.Y=EditorModeTools.PivotLocation.Y; if( NewPivot.Z==0 ) NewPivot.Z=EditorModeTools.PivotLocation.Z; } // Set the pivot. //EditorModeTools.CachedLocation = NewPivot; // Don't set the cached location, this is our pre-move point EditorModeTools.PivotLocation = NewPivot; EditorModeTools.SnappedLocation = NewPivot; EditorModeTools.GridBase = FVector::ZeroVector; if( bSnapPivotToGrid ) { FRotator DummyRotator(0,0,0); FSnappingUtils::SnapToBSPVertex( EditorModeTools.SnappedLocation, EditorModeTools.GridBase, DummyRotator ); EditorModeTools.PivotLocation = EditorModeTools.SnappedLocation; } // Check all actors. int32 Count=0, SnapCount=0; //default to using the x axis for the translate rotate widget EditorModeTools.TranslateRotateXAxisAngle = 0.0f; EditorModeTools.TranslateRotate2DAngle = 0.0f; FVector TranslateRotateWidgetWorldXAxis; FVector Widget2DWorldXAxis; AActor* LastSelectedActor = NULL; for ( FSelectionIterator It( GetSelectedActorIterator() ) ; It ; ++It ) { AActor* Actor = static_cast<AActor*>( *It ); checkSlow( Actor->IsA(AActor::StaticClass()) ); if (Count==0) { TranslateRotateWidgetWorldXAxis = Actor->ActorToWorld().TransformVector(FVector(1.0f, 0.0f, 0.0f)); //get the xy plane project of this vector TranslateRotateWidgetWorldXAxis.Z = 0.0f; if (!TranslateRotateWidgetWorldXAxis.Normalize()) { TranslateRotateWidgetWorldXAxis = FVector(1.0f, 0.0f, 0.0f); } Widget2DWorldXAxis = Actor->ActorToWorld().TransformVector(FVector(1, 0, 0)); Widget2DWorldXAxis.Y = 0; if (!Widget2DWorldXAxis.Normalize()) { Widget2DWorldXAxis = FVector(1, 0, 0); } } LastSelectedActor = Actor; ++Count; ++SnapCount; } if( bAssignPivot && LastSelectedActor && GEditor->bGroupingActive ) { // set group pivot for the root-most group AGroupActor* ActorGroupRoot = AGroupActor::GetRootForActor(LastSelectedActor, true, true); if(ActorGroupRoot) { ActorGroupRoot->SetActorLocation( EditorModeTools.PivotLocation, false ); } } //if there are multiple actors selected, just use the x-axis for the "translate/rotate" or 2D widgets if (Count == 1) { EditorModeTools.TranslateRotateXAxisAngle = TranslateRotateWidgetWorldXAxis.Rotation().Yaw; EditorModeTools.TranslateRotate2DAngle = FMath::RadiansToDegrees(FMath::Atan2(Widget2DWorldXAxis.Z, Widget2DWorldXAxis.X)); } // Update showing. EditorModeTools.PivotShown = SnapCount>0 || Count>1; }
void FEdMode::DrawHUD(FEditorViewportClient* ViewportClient,FViewport* Viewport,const FSceneView* View,FCanvas* Canvas) { // Render the drag tool. ViewportClient->RenderDragTool( View, Canvas ); // Let the current mode tool draw a HUD if it wants to FModeTool* tool = GetCurrentTool(); if( tool ) { tool->DrawHUD( ViewportClient, Viewport, View, Canvas ); } if (ViewportClient->IsPerspective() && GetDefault<ULevelEditorViewportSettings>()->bHighlightWithBrackets) { DrawBrackets( ViewportClient, Viewport, View, Canvas ); } // If this viewport doesn't show mode widgets or the mode itself doesn't want them, leave. if( !(ViewportClient->EngineShowFlags.ModeWidgets) || !ShowModeWidgets() ) { return; } // Clear Hit proxies const bool bIsHitTesting = Canvas->IsHitTesting(); if ( !bIsHitTesting ) { Canvas->SetHitProxy(NULL); } // Draw vertices for selected BSP brushes and static meshes if the large vertices show flag is set. if ( !ViewportClient->bDrawVertices ) { return; } const bool bLargeVertices = View->Family->EngineShowFlags.LargeVertices; const bool bShowBrushes = View->Family->EngineShowFlags.Brushes; const bool bShowBSP = View->Family->EngineShowFlags.BSP; const bool bShowBuilderBrush = View->Family->EngineShowFlags.BuilderBrush != 0; UTexture2D* VertexTexture = GetVertexTexture(); const float TextureSizeX = VertexTexture->GetSizeX() * ( bLargeVertices ? 1.0f : 0.5f ); const float TextureSizeY = VertexTexture->GetSizeY() * ( bLargeVertices ? 1.0f : 0.5f ); // Temporaries. TArray<FVector> Vertices; for ( FSelectionIterator It( *Owner->GetSelectedActors() ) ; It ; ++It ) { AActor* SelectedActor = static_cast<AActor*>( *It ); checkSlow( SelectedActor->IsA(AActor::StaticClass()) ); if( bLargeVertices ) { FCanvasItemTestbed::bTestState = !FCanvasItemTestbed::bTestState; // Static mesh vertices AStaticMeshActor* Actor = Cast<AStaticMeshActor>( SelectedActor ); if( Actor && Actor->GetStaticMeshComponent() && Actor->GetStaticMeshComponent()->StaticMesh && Actor->GetStaticMeshComponent()->StaticMesh->RenderData ) { FTransform ActorToWorld = Actor->ActorToWorld(); Vertices.Empty(); const FPositionVertexBuffer& VertexBuffer = Actor->GetStaticMeshComponent()->StaticMesh->RenderData->LODResources[0].PositionVertexBuffer; for( uint32 i = 0 ; i < VertexBuffer.GetNumVertices() ; i++ ) { Vertices.AddUnique( ActorToWorld.TransformPosition( VertexBuffer.VertexPosition(i) ) ); } FCanvasTileItem TileItem( FVector2D( 0.0f, 0.0f ), FVector2D( 0.0f, 0.0f ), FLinearColor::White ); TileItem.BlendMode = SE_BLEND_Translucent; for( int32 VertexIndex = 0 ; VertexIndex < Vertices.Num() ; ++VertexIndex ) { const FVector& Vertex = Vertices[VertexIndex]; FVector2D PixelLocation; if(View->ScreenToPixel(View->WorldToScreen(Vertex),PixelLocation)) { const bool bOutside = PixelLocation.X < 0.0f || PixelLocation.X > View->ViewRect.Width() || PixelLocation.Y < 0.0f || PixelLocation.Y > View->ViewRect.Height(); if( !bOutside ) { const float X = PixelLocation.X - (TextureSizeX/2); const float Y = PixelLocation.Y - (TextureSizeY/2); if( bIsHitTesting ) { Canvas->SetHitProxy( new HStaticMeshVert(Actor,Vertex) ); } TileItem.Texture = VertexTexture->Resource; TileItem.Size = FVector2D( TextureSizeX, TextureSizeY ); Canvas->DrawItem( TileItem, FVector2D( X, Y ) ); if( bIsHitTesting ) { Canvas->SetHitProxy( NULL ); } } } } } } } if(UsesPropertyWidgets()) { AActor* SelectedActor = GetFirstSelectedActorInstance(); if (SelectedActor != NULL) { FEditorScriptExecutionGuard ScriptGuard; const int32 HalfX = 0.5f * Viewport->GetSizeXY().X; const int32 HalfY = 0.5f * Viewport->GetSizeXY().Y; UClass* Class = SelectedActor->GetClass(); TArray<FPropertyWidgetInfo> WidgetInfos; GetPropertyWidgetInfos(Class, SelectedActor, WidgetInfos); for(int32 i=0; i<WidgetInfos.Num(); i++) { FString WidgetName = WidgetInfos[i].PropertyName; FName WidgetValidator = WidgetInfos[i].PropertyValidationName; int32 WidgetIndex = WidgetInfos[i].PropertyIndex; bool bIsTransform = WidgetInfos[i].bIsTransform; FVector LocalPos = FVector::ZeroVector; if(bIsTransform) { FTransform LocalTM = GetPropertyValueByName<FTransform>(SelectedActor, WidgetName, WidgetIndex); LocalPos = LocalTM.GetLocation(); } else { LocalPos = GetPropertyValueByName<FVector>(SelectedActor, WidgetName, WidgetIndex); } FTransform ActorToWorld = SelectedActor->ActorToWorld(); FVector WorldPos = ActorToWorld.TransformPosition(LocalPos); UFunction* ValidateFunc = NULL; FString FinalString; if(WidgetValidator != NAME_None && (ValidateFunc = SelectedActor->FindFunction(WidgetValidator)) != NULL) { SelectedActor->ProcessEvent(ValidateFunc, &FinalString); } const FPlane Proj = View->Project( WorldPos ); //do some string fixing const uint32 VectorIndex = WidgetInfos[i].PropertyIndex; const FString WidgetDisplayName = WidgetInfos[i].DisplayName + ((VectorIndex != INDEX_NONE) ? FString::Printf(TEXT("[%d]"), VectorIndex) : TEXT("")); FinalString = FinalString.IsEmpty() ? WidgetDisplayName : FinalString; if(Proj.W > 0.f) { const int32 XPos = HalfX + ( HalfX * Proj.X ); const int32 YPos = HalfY + ( HalfY * (Proj.Y * -1.f) ); FCanvasTextItem TextItem( FVector2D( XPos + 5, YPos), FText::FromString( FinalString ), GEngine->GetSmallFont(), FLinearColor::White ); Canvas->DrawItem( TextItem ); } } } } }
void FEdMode::Render(const FSceneView* View,FViewport* Viewport,FPrimitiveDrawInterface* PDI) { // Let the current mode tool render if it wants to FModeTool* tool = GetCurrentTool(); if( tool ) { tool->Render( View, Viewport, PDI ); } if(UsesPropertyWidgets()) { bool bHitTesting = PDI->IsHitTesting(); AActor* SelectedActor = GetFirstSelectedActorInstance(); if (SelectedActor != NULL) { UClass* Class = SelectedActor->GetClass(); TArray<FPropertyWidgetInfo> WidgetInfos; GetPropertyWidgetInfos(Class, SelectedActor, WidgetInfos); FEditorScriptExecutionGuard ScriptGuard; for(int32 i=0; i<WidgetInfos.Num(); i++) { FString WidgetName = WidgetInfos[i].PropertyName; FName WidgetValidator = WidgetInfos[i].PropertyValidationName; int32 WidgetIndex = WidgetInfos[i].PropertyIndex; bool bIsTransform = WidgetInfos[i].bIsTransform; bool bSelected = (WidgetName == EditedPropertyName) && (WidgetIndex == EditedPropertyIndex); FColor WidgetColor = bSelected ? FColor::White : FColor(128, 128, 255); FVector LocalPos = FVector::ZeroVector; if(bIsTransform) { FTransform LocalTM = GetPropertyValueByName<FTransform>(SelectedActor, WidgetName, WidgetIndex); LocalPos = LocalTM.GetLocation(); } else { LocalPos = GetPropertyValueByName<FVector>(SelectedActor, WidgetName, WidgetIndex); } FTransform ActorToWorld = SelectedActor->ActorToWorld(); FVector WorldPos = ActorToWorld.TransformPosition(LocalPos); UFunction* ValidateFunc= NULL; if(WidgetValidator != NAME_None && (ValidateFunc = SelectedActor->FindFunction(WidgetValidator)) != NULL) { FString ReturnText; SelectedActor->ProcessEvent(ValidateFunc, &ReturnText); //if we have a negative result, the widget color is red. WidgetColor = ReturnText.IsEmpty() ? WidgetColor : FColor::Red; } FTranslationMatrix WidgetTM(WorldPos); const float WidgetSize = 0.035f; const float ZoomFactor = FMath::Min<float>(View->ViewMatrices.ProjMatrix.M[0][0], View->ViewMatrices.ProjMatrix.M[1][1]); const float WidgetRadius = View->Project(WorldPos).W * (WidgetSize / ZoomFactor); if(bHitTesting) PDI->SetHitProxy( new HPropertyWidgetProxy(WidgetName, WidgetIndex, bIsTransform) ); DrawWireDiamond(PDI, WidgetTM, WidgetRadius, WidgetColor, SDPG_Foreground ); if(bHitTesting) PDI->SetHitProxy( NULL ); } } } }
bool FEdMode::InputDelta(FEditorViewportClient* InViewportClient, FViewport* InViewport, FVector& InDrag, FRotator& InRot, FVector& InScale) { if(UsesPropertyWidgets()) { AActor* SelectedActor = GetFirstSelectedActorInstance(); if(SelectedActor != NULL && InViewportClient->GetCurrentWidgetAxis() != EAxisList::None) { GEditor->NoteActorMovement(); if (EditedPropertyName != TEXT("")) { FTransform LocalTM = FTransform::Identity; if(bEditedPropertyIsTransform) { LocalTM = GetPropertyValueByName<FTransform>(SelectedActor, EditedPropertyName, EditedPropertyIndex); } else { FVector LocalPos = GetPropertyValueByName<FVector>(SelectedActor, EditedPropertyName, EditedPropertyIndex); LocalTM = FTransform(LocalPos); } // Get actor transform (actor to world) FTransform ActorTM = SelectedActor->ActorToWorld(); // Calculate world transform FTransform WorldTM = LocalTM * ActorTM; // Calc delta specified by drag //FTransform DeltaTM(InRot.Quaternion(), InDrag); // Apply delta in world space WorldTM.SetTranslation(WorldTM.GetTranslation() + InDrag); WorldTM.SetRotation(InRot.Quaternion() * WorldTM.GetRotation()); // Convert new world transform back into local space LocalTM = WorldTM.GetRelativeTransform(ActorTM); // Apply delta scale LocalTM.SetScale3D(LocalTM.GetScale3D() + InScale); SelectedActor->PreEditChange(NULL); if(bEditedPropertyIsTransform) { SetPropertyValueByName<FTransform>(SelectedActor, EditedPropertyName, EditedPropertyIndex, LocalTM); } else { SetPropertyValueByName<FVector>(SelectedActor, EditedPropertyName, EditedPropertyIndex, LocalTM.GetLocation()); } SelectedActor->PostEditChange(); return true; } } } if( GetCurrentTool() ) { return GetCurrentTool()->InputDelta(InViewportClient,InViewport,InDrag,InRot,InScale); } return 0; }