EM_Task/UnrealEd/Private/PhysicsManipulationMode.cpp
Boshuang Zhao 5144a49c9b add
2026-02-13 16:18:33 +08:00

147 lines
4.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "PhysicsManipulationMode.h"
#include "Components/PrimitiveComponent.h"
#include "EditorViewportClient.h"
#include "PhysicsEngine/PhysicsHandleComponent.h"
#include "Engine/Selection.h"
#include "EditorModeManager.h"
#include "EditorModes.h"
DEFINE_LOG_CATEGORY_STATIC(LogEditorPhysMode, Log, All);
void FPhysicsManipulationEdModeFactory::OnSelectionChanged(FEditorModeTools& Tools, UObject* ItemUndergoingChange) const
{
USelection* Selection = GEditor->GetSelectedActors();
if (ItemUndergoingChange != NULL && ItemUndergoingChange->IsSelected())
{
AActor* SelectedActor = Cast<AActor>(ItemUndergoingChange);
if (SelectedActor != NULL)
{
UPrimitiveComponent* PC = Cast<UPrimitiveComponent>(SelectedActor->GetRootComponent());
if (PC != NULL && PC->BodyInstance.bSimulatePhysics)
{
Tools.ActivateMode(FBuiltinEditorModes::EM_Physics);
return;
}
}
}
else if (ItemUndergoingChange != NULL && !ItemUndergoingChange->IsA(USelection::StaticClass()))
{
Tools.DeactivateMode(FBuiltinEditorModes::EM_Physics);
}
}
FEditorModeInfo FPhysicsManipulationEdModeFactory::GetModeInfo() const
{
return FEditorModeInfo(FBuiltinEditorModes::EM_Physics, NSLOCTEXT("EditorModes", "PhysicsMode", "Physics Mode"));
}
TSharedRef<FEdMode> FPhysicsManipulationEdModeFactory::CreateMode() const
{
return MakeShareable(new FPhysicsManipulationEdMode);
}
FPhysicsManipulationEdMode::FPhysicsManipulationEdMode()
{
HandleComp = NewObject<UPhysicsHandleComponent>();
}
FPhysicsManipulationEdMode::~FPhysicsManipulationEdMode()
{
HandleComp = NULL;
}
void FPhysicsManipulationEdMode::Enter()
{
FWorldContext* PIEWorldContext = GEditor->GetPIEWorldContext();
check(PIEWorldContext && PIEWorldContext->World());
HandleComp->RegisterComponentWithWorld(PIEWorldContext->World());
}
void FPhysicsManipulationEdMode::Exit()
{
HandleComp->UnregisterComponent();
}
bool FPhysicsManipulationEdMode::InputDelta(FEditorViewportClient* InViewportClient, FViewport* InViewport, FVector& InDrag, FRotator& InRot, FVector& InScale)
{
// UE_LOG(LogEditorPhysMode, Warning, TEXT("Mouse: %s InDrag: %s InRot: %s"), *GEditor->MouseMovement.ToString(), *InDrag.ToString(), *InRot.ToString());
const float GrabMoveSpeed = 1.0f;
const float GrabRotateSpeed = 1.0f;
if (InViewportClient->GetCurrentWidgetAxis() != EAxisList::None && HandleComp->GrabbedComponent)
{
HandleTargetLocation += InDrag * GrabMoveSpeed;
HandleTargetRotation += InRot;
HandleComp->SetTargetLocation(HandleTargetLocation);
HandleComp->SetTargetRotation(HandleTargetRotation);
return true;
}
else
{
return FEdMode::InputDelta(InViewportClient, InViewport, InDrag, InRot, InScale);
}
}
bool FPhysicsManipulationEdMode::StartTracking(FEditorViewportClient* InViewportClient, FViewport* InViewport)
{
// UE_LOG(LogEditorPhysMode, Warning, TEXT("Start Tracking"));
if (InViewportClient->GetCurrentWidgetAxis() != EAxisList::None)
{
FVector GrabLocation(0, 0, 0);
UPrimitiveComponent* ComponentToGrab = NULL;
USelection* Selection = GEditor->GetSelectedActors();
for (int32 i = 0; i < Selection->Num(); ++i)
{
AActor* SelectedActor = Cast<AActor>(Selection->GetSelectedObject(i));
if (SelectedActor != NULL)
{
UPrimitiveComponent* PC = Cast<UPrimitiveComponent>(SelectedActor->GetRootComponent());
if (PC != NULL && PC->BodyInstance.bSimulatePhysics)
{
ComponentToGrab = PC;
HandleTargetLocation = SelectedActor->GetActorLocation();
HandleTargetRotation = SelectedActor->GetActorRotation();
break;
}
if (ComponentToGrab != NULL)
{
break;
}
}
}
if (ComponentToGrab != NULL)
{
HandleComp->GrabComponentAtLocationWithRotation(ComponentToGrab, NAME_None, ComponentToGrab->GetOwner()->GetActorLocation(), ComponentToGrab->GetOwner()->GetActorRotation());
}
}
return FEdMode::StartTracking(InViewportClient, InViewport);
}
bool FPhysicsManipulationEdMode::EndTracking(FEditorViewportClient* InViewportClient, FViewport* InViewport)
{
// UE_LOG(LogEditorPhysMode, Warning, TEXT("End Tracking"));
HandleComp->ReleaseComponent();
return FEdMode::EndTracking(InViewportClient, InViewport);
}
void FPhysicsManipulationEdMode::AddReferencedObjects(FReferenceCollector& Collector)
{
Collector.AddReferencedObject(HandleComp);
}