// Copyright Epic Games, Inc. All Rights Reserved. #include "MeshPaintInteractions.h" #include "InteractiveTool.h" #include "InteractiveToolManager.h" #include "ToolContextInterfaces.h" #include "MeshPaintHelpers.h" #include "Components/MeshComponent.h" #include "IMeshPaintComponentAdapter.h" #include "MeshPaintAdapterFactory.h" #include "Elements/Framework/TypedElementRegistry.h" #include "Elements/Interfaces/TypedElementObjectInterface.h" #include "UnrealClient.h" #include UE_INLINE_GENERATED_CPP_BY_NAME(MeshPaintInteractions) #if WITH_EDITOR #endif #define LOCTEXT_NAMESPACE "MeshSelection" FInputRayHit UMeshPaintSelectionMechanic::IsHitByClick(const FInputDeviceRay& ClickPos, bool bIsFallbackClick) { IMeshPaintSelectionInterface* Interface = Cast(GetParentTool()); if (!bAddToSelectionSet || !Interface->AllowsMultiselect()) { CachedClickedComponents.Empty(); CachedClickedActors.Empty(); } // for fallback clicks, assume we must be adding to our selection set if (bIsFallbackClick) { if (Interface->AllowsMultiselect() && bAddToSelectionSet) { return FindClickedComponentsAndCacheAdapters(ClickPos) ? FInputRayHit(0.0f) : FInputRayHit(); } else { return FInputRayHit(); } } return FindClickedComponentsAndCacheAdapters(ClickPos) ? FInputRayHit(0.0f) : FInputRayHit(); } void UMeshPaintSelectionMechanic::OnClicked(const FInputDeviceRay& ClickPos) { if (UMeshPaintingSubsystem* MeshPaintingSubsystem = GEngine->GetEngineSubsystem()) { for (UMeshComponent* MeshComponent : CachedClickedComponents) { TSharedPtr MeshAdapter; if (MeshComponent) { MeshAdapter = MeshPaintingSubsystem->GetAdapterForComponent(MeshComponent); } IMeshPaintSelectionInterface* Interface = Cast(GetParentTool()); if (MeshComponent && MeshComponent->IsVisible() && MeshAdapter.IsValid() && MeshAdapter->IsValid() && Interface->IsMeshAdapterSupported(MeshAdapter)) { MeshPaintingSubsystem->AddPaintableMeshComponent(MeshComponent); MeshAdapter->OnAdded(); } GetParentTool()->GetToolManager()->BeginUndoTransaction(LOCTEXT("MeshSelection", "Select Mesh")); FSelectedObjectsChangeList NewSelection; // TODO add CTRL handling const bool bShouldAddToSelection = bAddToSelectionSet && Interface->AllowsMultiselect(); NewSelection.ModificationType = bShouldAddToSelection ? ESelectedObjectsModificationType::Add : ESelectedObjectsModificationType::Replace; NewSelection.Actors.Append(CachedClickedActors); GetParentTool()->GetToolManager()->RequestSelectionChange(NewSelection); GetParentTool()->GetToolManager()->EndUndoTransaction(); } } } bool UMeshPaintSelectionMechanic::FindClickedComponentsAndCacheAdapters(const FInputDeviceRay& ClickPos) { bool bFoundValidComponents = false; #if WITH_EDITOR UMeshPaintingSubsystem* MeshPaintingSubsystem = GEngine->GetEngineSubsystem(); if (!MeshPaintingSubsystem) { return bFoundValidComponents; } FViewport* FocusedViewport = GetParentTool()->GetToolManager()->GetContextQueriesAPI()->GetFocusedViewport(); if (FocusedViewport) { if (HHitProxy* HitProxy = FocusedViewport->GetHitProxy(ClickPos.ScreenPosition.X, ClickPos.ScreenPosition.Y)) { if (TTypedElement ObjectInterface = UTypedElementRegistry::GetInstance()->GetElement(HitProxy->GetElementHandle())) { if (AActor* Actor = ObjectInterface.GetObjectAs()->GetOwner()) { TArray CandidateComponents = Actor->K2_GetComponentsByClass(UMeshComponent::StaticClass()); for (UActorComponent* CandidateComponent : CandidateComponents) { UMeshComponent* MeshComponent = Cast(CandidateComponent); TSharedPtr MeshAdapter = MeshPaintingSubsystem->GetAdapterForComponent(MeshComponent); if (!MeshAdapter.IsValid()) { MeshAdapter = FMeshPaintComponentAdapterFactory::CreateAdapterForMesh(MeshComponent, 0); if (MeshAdapter) { MeshPaintingSubsystem->AddToComponentToAdapterMap(MeshComponent, MeshAdapter); } } IMeshPaintSelectionInterface* Interface = Cast(GetParentTool()); if (MeshAdapter.IsValid() && Interface->IsMeshAdapterSupported(MeshAdapter)) { CachedClickedComponents.AddUnique(MeshComponent); CachedClickedActors.AddUnique(Cast(MeshComponent->GetOuter())); bFoundValidComponents = true; } } } } } } #endif return bFoundValidComponents; } #undef LOCTEXT_NAMESPACE