Files
UnrealEngine/Engine/Plugins/MeshPainting/Source/MeshPaintingToolset/Private/MeshPaintInteractions.cpp
2025-05-18 13:04:45 +08:00

129 lines
4.6 KiB
C++

// 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<IMeshPaintSelectionInterface>(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<UMeshPaintingSubsystem>())
{
for (UMeshComponent* MeshComponent : CachedClickedComponents)
{
TSharedPtr<IMeshPaintComponentAdapter> MeshAdapter;
if (MeshComponent)
{
MeshAdapter = MeshPaintingSubsystem->GetAdapterForComponent(MeshComponent);
}
IMeshPaintSelectionInterface* Interface = Cast<IMeshPaintSelectionInterface>(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<UMeshPaintingSubsystem>();
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<ITypedElementObjectInterface> ObjectInterface = UTypedElementRegistry::GetInstance()->GetElement<ITypedElementObjectInterface>(HitProxy->GetElementHandle()))
{
if (AActor* Actor = ObjectInterface.GetObjectAs<UActorComponent>()->GetOwner())
{
TArray<UActorComponent*> CandidateComponents = Actor->K2_GetComponentsByClass(UMeshComponent::StaticClass());
for (UActorComponent* CandidateComponent : CandidateComponents)
{
UMeshComponent* MeshComponent = Cast<UMeshComponent>(CandidateComponent);
TSharedPtr<IMeshPaintComponentAdapter> MeshAdapter = MeshPaintingSubsystem->GetAdapterForComponent(MeshComponent);
if (!MeshAdapter.IsValid())
{
MeshAdapter = FMeshPaintComponentAdapterFactory::CreateAdapterForMesh(MeshComponent, 0);
if (MeshAdapter)
{
MeshPaintingSubsystem->AddToComponentToAdapterMap(MeshComponent, MeshAdapter);
}
}
IMeshPaintSelectionInterface* Interface = Cast<IMeshPaintSelectionInterface>(GetParentTool());
if (MeshAdapter.IsValid() && Interface->IsMeshAdapterSupported(MeshAdapter))
{
CachedClickedComponents.AddUnique(MeshComponent);
CachedClickedActors.AddUnique(Cast<AActor>(MeshComponent->GetOuter()));
bFoundValidComponents = true;
}
}
}
}
}
}
#endif
return bFoundValidComponents;
}
#undef LOCTEXT_NAMESPACE