2020-08-11 01:36:57 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "BaseTools/BaseCreateFromSelectedTool.h"
|
|
|
|
|
#include "InteractiveToolManager.h"
|
|
|
|
|
#include "ToolBuilderUtil.h"
|
|
|
|
|
#include "ToolSetupUtil.h"
|
2021-06-12 14:28:52 -04:00
|
|
|
#include "Components/DynamicMeshComponent.h"
|
2021-05-20 16:39:39 -04:00
|
|
|
#include "BaseGizmos/TransformGizmoUtil.h"
|
2020-08-11 01:36:57 -04:00
|
|
|
#include "Async/Async.h"
|
|
|
|
|
|
2021-06-13 00:35:22 -04:00
|
|
|
#include "DynamicMesh/MeshNormals.h"
|
|
|
|
|
#include "DynamicMesh/MeshTransforms.h"
|
2020-08-11 01:36:57 -04:00
|
|
|
#include "DynamicMeshToMeshDescription.h"
|
|
|
|
|
#include "MeshDescriptionToDynamicMesh.h"
|
|
|
|
|
|
2021-06-02 15:58:00 -04:00
|
|
|
#include "ModelingObjectsCreationAPI.h"
|
2020-08-11 01:36:57 -04:00
|
|
|
#include "Selection/ToolSelectionUtil.h"
|
|
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
#include "TargetInterfaces/MeshDescriptionCommitter.h"
|
|
|
|
|
#include "TargetInterfaces/MeshDescriptionProvider.h"
|
|
|
|
|
#include "TargetInterfaces/PrimitiveComponentBackedTarget.h"
|
|
|
|
|
#include "TargetInterfaces/MaterialProvider.h"
|
2021-03-23 14:51:49 -04:00
|
|
|
#include "TargetInterfaces/AssetBackedTarget.h"
|
2021-03-11 11:40:03 -04:00
|
|
|
#include "ToolTargetManager.h"
|
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs.
- Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module
- move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module
- Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options
- Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs
- Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget
- Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation
- Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate().
- Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets
- Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high).
- DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop
#rb none
#rnx
#jira none
#preflight 60ba50632c42ea0001cb54c5
[CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
|
|
|
#include "ModelingToolTargetUtil.h"
|
2020-08-11 01:36:57 -04:00
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "UBaseCreateFromSelectedTool"
|
|
|
|
|
|
2021-03-09 19:33:56 -04:00
|
|
|
using namespace UE::Geometry;
|
2020-08-11 01:36:57 -04:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* ToolBuilder
|
|
|
|
|
*/
|
|
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
const FToolTargetTypeRequirements& UBaseCreateFromSelectedToolBuilder::GetTargetRequirements() const
|
|
|
|
|
{
|
|
|
|
|
static FToolTargetTypeRequirements TypeRequirements({
|
|
|
|
|
UMeshDescriptionCommitter::StaticClass(),
|
|
|
|
|
UMeshDescriptionProvider::StaticClass(),
|
|
|
|
|
UPrimitiveComponentBackedTarget::StaticClass(),
|
ModelingTools: add support for creating Volumes directly from DrawPolygon, DrawRevolve, DrawPolyPath, and AddPrimitive, CombineMeshes, CutMeshWithMesh, PlaneCut, BaseCreateFromSelected Tools. Improve support for Editing volumes, eg handling mesh/volume interactions, and add configurable auto-simplification for volumes to avoid painful Editor hangs.
- Move ToolTarget implementations, DynamicMeshToVolume to ModelingComponentsEditorOnly module
- move VolumeToDynamicMesh, DynamicMeshProvider/Commiter interfaces to ModelingComponents module
- Add UCreateMeshObjectTypeProperties property set to expose mesh/volume options
- Add FCreateMeshObjectParams::TypeHintClass to allow AVolume type (or other UClass hints) to be passed to creation APIs
- Add UE::ToolTarget::ConfigureCreateMeshObjectParams() util function in ModelingToolTargetUtil, tries to determine output type in a FCreateMeshObjectParams based on input ToolTarget
- Add UEditorModelingObjectsCreationAPI::CreateVolume() implementation
- Add UEditorModelingObjectsCreationAPI::FilterMaterials() that strips out any internal materials and replaces with WorldGridMaterial. This occurs when (eg) subtracting a Volume from a StaticMesh, because the temporary volume mesh gets assigned internal materials, but the Tools don't know this. Use in EditorModelingObjectsCreationAPI when creating new objects. UStaticMeshComponentToolTarget also does this filtering in ::CommitMaterialSetUpdate().
- Add ::ComponentTypeSupportsCollision() function to ComponentCollisionUtil, use to avoid checks/ensures for Volume targets
- Add support for automatic mesh simplification in DynamicMeshToVolume. Add CVar to VolumeDynamicMeshToolTarget.h to control max triangle count (default 500). Apply auto-simplify when creating or updating an AVolume. This prevents the Editor from blocking for long periods on meshes that are too high-res for volumes (even 500 is quite high).
- DynamicMeshToVolume now emits polygroup-faces that contain holes (ie multiple boundary loops) as a set of triangles, rather than emitting separate overlapping faces for each boundary loop
#rb none
#rnx
#jira none
#preflight 60ba50632c42ea0001cb54c5
[CL 16561742 by Ryan Schmidt in ue5-main branch]
2021-06-04 16:04:03 -04:00
|
|
|
UMaterialProvider::StaticClass()
|
2021-03-11 11:40:03 -04:00
|
|
|
});
|
|
|
|
|
return TypeRequirements;
|
|
|
|
|
}
|
2020-08-11 01:36:57 -04:00
|
|
|
|
|
|
|
|
bool UBaseCreateFromSelectedToolBuilder::CanBuildTool(const FToolBuilderState& SceneState) const
|
|
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
int32 ComponentCount = SceneState.TargetManager->CountSelectedAndTargetable(SceneState, GetTargetRequirements());
|
2021-06-02 15:58:00 -04:00
|
|
|
return ComponentCount >= MinComponentsSupported() && (!MaxComponentsSupported().IsSet() || ComponentCount <= MaxComponentsSupported().GetValue());
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
UInteractiveTool* UBaseCreateFromSelectedToolBuilder::BuildTool(const FToolBuilderState& SceneState) const
|
|
|
|
|
{
|
|
|
|
|
UBaseCreateFromSelectedTool* NewTool = MakeNewToolInstance(SceneState.ToolManager);
|
|
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
TArray<TObjectPtr<UToolTarget>> Targets = SceneState.TargetManager->BuildAllSelectedTargetable(SceneState, GetTargetRequirements());
|
|
|
|
|
NewTool->SetTargets(MoveTemp(Targets));
|
2020-08-11 01:36:57 -04:00
|
|
|
NewTool->SetWorld(SceneState.World);
|
|
|
|
|
|
|
|
|
|
return NewTool;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Tool
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
void UBaseCreateFromSelectedTool::Setup()
|
|
|
|
|
{
|
|
|
|
|
UInteractiveTool::Setup();
|
|
|
|
|
|
|
|
|
|
// hide input StaticMeshComponents
|
2021-03-11 11:40:03 -04:00
|
|
|
for (int32 ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
TargetComponentInterface(ComponentIdx)->SetOwnerVisibility(false);
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initialize our properties
|
|
|
|
|
|
|
|
|
|
SetupProperties();
|
|
|
|
|
TransformProperties = NewObject<UTransformInputsToolProperties>(this);
|
|
|
|
|
TransformProperties->RestoreProperties(this);
|
|
|
|
|
AddToolPropertySource(TransformProperties);
|
2020-10-22 19:19:16 -04:00
|
|
|
|
2021-06-23 22:13:32 -04:00
|
|
|
OutputTypeProperties = NewObject<UCreateMeshObjectTypeProperties>(this);
|
|
|
|
|
OutputTypeProperties->InitializeDefaultWithAuto();
|
|
|
|
|
OutputTypeProperties->OutputType = UCreateMeshObjectTypeProperties::AutoIdentifier;
|
|
|
|
|
OutputTypeProperties->RestoreProperties(this, TEXT("OutputTypeFromInputTool"));
|
|
|
|
|
OutputTypeProperties->WatchProperty(OutputTypeProperties->OutputType, [this](FString) { OutputTypeProperties->UpdatePropertyVisibility(); });
|
|
|
|
|
AddToolPropertySource(OutputTypeProperties);
|
|
|
|
|
|
2020-10-22 19:19:16 -04:00
|
|
|
HandleSourcesProperties = NewObject<UBaseCreateFromSelectedHandleSourceProperties>(this);
|
2020-08-11 01:36:57 -04:00
|
|
|
HandleSourcesProperties->RestoreProperties(this);
|
|
|
|
|
AddToolPropertySource(HandleSourcesProperties);
|
|
|
|
|
|
2021-06-23 22:13:32 -04:00
|
|
|
Preview = NewObject<UMeshOpPreviewWithBackgroundCompute>(this);
|
2020-08-11 01:36:57 -04:00
|
|
|
Preview->Setup(this->TargetWorld, this);
|
|
|
|
|
|
|
|
|
|
SetPreviewCallbacks();
|
2021-02-05 16:33:02 -04:00
|
|
|
Preview->OnMeshUpdated.AddLambda(
|
|
|
|
|
[this](const UMeshOpPreviewWithBackgroundCompute* UpdatedPreview)
|
|
|
|
|
{
|
|
|
|
|
UpdateAcceptWarnings(UpdatedPreview->HaveEmptyResult() ? EAcceptWarning::EmptyForbidden : EAcceptWarning::NoWarning);
|
|
|
|
|
}
|
|
|
|
|
);
|
2020-08-11 01:36:57 -04:00
|
|
|
|
|
|
|
|
SetTransformGizmos();
|
|
|
|
|
|
|
|
|
|
ConvertInputsAndSetPreviewMaterials(true);
|
|
|
|
|
|
2020-10-22 19:19:16 -04:00
|
|
|
// output name fields
|
|
|
|
|
HandleSourcesProperties->OutputName = PrefixWithSourceNameIfSingleSelection(GetCreatedAssetName());
|
|
|
|
|
HandleSourcesProperties->WatchProperty(HandleSourcesProperties->WriteOutputTo, [&](EBaseCreateFromSelectedTargetType NewType)
|
|
|
|
|
{
|
2021-06-23 22:13:32 -04:00
|
|
|
SetToolPropertySourceEnabled(OutputTypeProperties, (NewType == EBaseCreateFromSelectedTargetType::NewAsset));
|
2020-10-22 19:19:16 -04:00
|
|
|
if (NewType == EBaseCreateFromSelectedTargetType::NewAsset)
|
|
|
|
|
{
|
|
|
|
|
HandleSourcesProperties->OutputAsset = TEXT("");
|
2021-02-03 19:00:42 -04:00
|
|
|
UpdateGizmoVisibility();
|
2020-10-22 19:19:16 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
int32 Index = (HandleSourcesProperties->WriteOutputTo == EBaseCreateFromSelectedTargetType::FirstInputAsset) ? 0 : Targets.Num() - 1;
|
2021-06-02 15:58:00 -04:00
|
|
|
HandleSourcesProperties->OutputAsset = UE::Modeling::GetComponentAssetBaseName(TargetComponentInterface(Index)->GetOwnerComponent(), false);
|
2021-03-09 21:27:22 -04:00
|
|
|
|
2021-02-03 19:00:42 -04:00
|
|
|
// Reset the hidden gizmo to its initial position
|
2021-03-11 11:40:03 -04:00
|
|
|
FTransform ComponentTransform = TargetComponentInterface(Index)->GetWorldTransform();
|
2021-02-03 19:00:42 -04:00
|
|
|
TransformGizmos[Index]->SetNewGizmoTransform(ComponentTransform, true);
|
|
|
|
|
UpdateGizmoVisibility();
|
2020-10-22 19:19:16 -04:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2020-08-11 01:36:57 -04:00
|
|
|
Preview->InvalidateResult();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-03-09 21:27:22 -04:00
|
|
|
int32 UBaseCreateFromSelectedTool::GetHiddenGizmoIndex() const
|
|
|
|
|
{
|
|
|
|
|
if (HandleSourcesProperties->WriteOutputTo == EBaseCreateFromSelectedTargetType::NewAsset)
|
|
|
|
|
{
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
return (HandleSourcesProperties->WriteOutputTo == EBaseCreateFromSelectedTargetType::FirstInputAsset) ? 0 : Targets.Num() - 1;
|
2021-03-09 21:27:22 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-08-11 01:36:57 -04:00
|
|
|
void UBaseCreateFromSelectedTool::SetWorld(UWorld* World)
|
|
|
|
|
{
|
|
|
|
|
this->TargetWorld = World;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBaseCreateFromSelectedTool::OnTick(float DeltaTime)
|
|
|
|
|
{
|
|
|
|
|
for (UTransformGizmo* Gizmo : TransformGizmos)
|
|
|
|
|
{
|
|
|
|
|
Gizmo->bSnapToWorldGrid = TransformProperties->bSnapToWorldGrid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Preview->Tick(DeltaTime);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBaseCreateFromSelectedTool::UpdateGizmoVisibility()
|
|
|
|
|
{
|
2021-02-03 19:00:42 -04:00
|
|
|
for (int32 GizmoIndex = 0; GizmoIndex < TransformGizmos.Num(); GizmoIndex++)
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
2021-02-03 19:00:42 -04:00
|
|
|
UTransformGizmo* Gizmo = TransformGizmos[GizmoIndex];
|
2021-03-09 21:27:22 -04:00
|
|
|
Gizmo->SetVisibility(TransformProperties->bShowTransformUI && GizmoIndex != GetHiddenGizmoIndex());
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-02-03 19:00:42 -04:00
|
|
|
|
2020-08-11 01:36:57 -04:00
|
|
|
void UBaseCreateFromSelectedTool::SetTransformGizmos()
|
|
|
|
|
{
|
|
|
|
|
UInteractiveGizmoManager* GizmoManager = GetToolManager()->GetPairedGizmoManager();
|
|
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
for (int ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
|
|
|
|
UTransformProxy* Proxy = TransformProxies.Add_GetRef(NewObject<UTransformProxy>(this));
|
2021-05-20 16:39:39 -04:00
|
|
|
UTransformGizmo* Gizmo = TransformGizmos.Add_GetRef(UE::TransformGizmoUtil::Create3AxisTransformGizmo(GizmoManager, this));
|
2021-03-11 11:40:03 -04:00
|
|
|
Proxy->SetTransform(TargetComponentInterface(ComponentIdx)->GetWorldTransform());
|
2020-09-24 00:43:27 -04:00
|
|
|
Gizmo->SetActiveTarget(Proxy, GetToolManager());
|
2020-08-11 01:36:57 -04:00
|
|
|
Proxy->OnTransformChanged.AddUObject(this, &UBaseCreateFromSelectedTool::TransformChanged);
|
|
|
|
|
}
|
|
|
|
|
UpdateGizmoVisibility();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBaseCreateFromSelectedTool::TransformChanged(UTransformProxy* Proxy, FTransform Transform)
|
|
|
|
|
{
|
|
|
|
|
Preview->InvalidateResult();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FText UBaseCreateFromSelectedTool::GetActionName() const
|
|
|
|
|
{
|
|
|
|
|
return LOCTEXT("BaseCreateFromSelectedTool", "Generated Mesh");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TArray<UMaterialInterface*> UBaseCreateFromSelectedTool::GetOutputMaterials() const
|
|
|
|
|
{
|
|
|
|
|
return Preview->StandardMaterials;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-06-02 15:58:00 -04:00
|
|
|
void UBaseCreateFromSelectedTool::GenerateAsset(const FDynamicMeshOpResult& OpResult)
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
2021-06-02 15:58:00 -04:00
|
|
|
if (OpResult.Mesh.Get() == nullptr) return;
|
2020-08-11 01:36:57 -04:00
|
|
|
|
|
|
|
|
FTransform3d NewTransform;
|
2021-03-11 11:40:03 -04:00
|
|
|
if (Targets.Num() == 1) // in the single-selection case, shove the result back into the original component space
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
FTransform3d ToSourceComponentSpace = (FTransform3d)TargetComponentInterface(0)->GetWorldTransform().Inverse();
|
2021-06-02 15:58:00 -04:00
|
|
|
MeshTransforms::ApplyTransform(*OpResult.Mesh, ToSourceComponentSpace);
|
2021-03-11 11:40:03 -04:00
|
|
|
NewTransform = (FTransform3d)TargetComponentInterface(0)->GetWorldTransform();
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
|
|
|
|
else // in the multi-selection case, center the pivot for the combined result
|
|
|
|
|
{
|
2021-06-02 15:58:00 -04:00
|
|
|
FVector3d Center = OpResult.Mesh->GetCachedBounds().Center();
|
|
|
|
|
double Rescale = OpResult.Transform.GetScale().X;
|
2020-08-11 01:36:57 -04:00
|
|
|
FTransform3d LocalTransform(-Center * Rescale);
|
|
|
|
|
LocalTransform.SetScale(FVector3d(Rescale, Rescale, Rescale));
|
2021-06-02 15:58:00 -04:00
|
|
|
MeshTransforms::ApplyTransform(*OpResult.Mesh, LocalTransform);
|
|
|
|
|
NewTransform = OpResult.Transform;
|
2020-08-11 01:36:57 -04:00
|
|
|
NewTransform.SetScale(FVector3d::One());
|
|
|
|
|
NewTransform.SetTranslation(NewTransform.GetTranslation() + NewTransform.TransformVector(Center * Rescale));
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 13:38:15 -04:00
|
|
|
// max len explicitly enforced here, would ideally notify user
|
|
|
|
|
FString UseBaseName = HandleSourcesProperties->OutputName.Left(250);
|
|
|
|
|
if (UseBaseName.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
UseBaseName = PrefixWithSourceNameIfSingleSelection(GetCreatedAssetName());
|
|
|
|
|
}
|
2020-08-11 01:36:57 -04:00
|
|
|
|
2021-06-02 15:58:00 -04:00
|
|
|
FCreateMeshObjectParams NewMeshObjectParams;
|
|
|
|
|
NewMeshObjectParams.TargetWorld = TargetWorld;
|
|
|
|
|
NewMeshObjectParams.Transform = (FTransform)NewTransform;
|
|
|
|
|
NewMeshObjectParams.BaseName = UseBaseName;
|
|
|
|
|
NewMeshObjectParams.Materials = GetOutputMaterials();
|
|
|
|
|
NewMeshObjectParams.SetMesh(OpResult.Mesh.Get());
|
2021-06-23 22:13:32 -04:00
|
|
|
if (OutputTypeProperties->OutputType == UCreateMeshObjectTypeProperties::AutoIdentifier)
|
|
|
|
|
{
|
|
|
|
|
UE::ToolTarget::ConfigureCreateMeshObjectParams(Targets[0], NewMeshObjectParams);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
OutputTypeProperties->ConfigureCreateMeshObjectParams(NewMeshObjectParams);
|
|
|
|
|
}
|
2021-06-02 15:58:00 -04:00
|
|
|
FCreateMeshObjectResult Result = UE::Modeling::CreateMeshObject(GetToolManager(), MoveTemp(NewMeshObjectParams));
|
|
|
|
|
if (Result.IsOK() && Result.NewActor != nullptr)
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
2021-06-02 15:58:00 -04:00
|
|
|
ToolSelectionUtil::SetNewActorSelection(GetToolManager(), Result.NewActor);
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-10-22 19:19:16 -04:00
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
void UBaseCreateFromSelectedTool::UpdateAsset(const FDynamicMeshOpResult& Result, UToolTarget* UpdateTarget)
|
2020-10-22 19:19:16 -04:00
|
|
|
{
|
|
|
|
|
check(Result.Mesh.Get() != nullptr);
|
|
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
IPrimitiveComponentBackedTarget* TargetComponent = Cast<IPrimitiveComponentBackedTarget>(UpdateTarget);
|
|
|
|
|
IMeshDescriptionCommitter* TargetMeshCommitter = Cast<IMeshDescriptionCommitter>(UpdateTarget);
|
|
|
|
|
IMaterialProvider* TargetMaterial = Cast<IMaterialProvider>(UpdateTarget);
|
|
|
|
|
|
|
|
|
|
FTransform3d TargetToWorld = (FTransform3d)TargetComponent->GetWorldTransform();
|
2020-10-22 19:19:16 -04:00
|
|
|
|
2021-02-03 19:00:42 -04:00
|
|
|
FTransform3d ResultTransform = Result.Transform;
|
|
|
|
|
MeshTransforms::ApplyTransform(*Result.Mesh, ResultTransform);
|
|
|
|
|
MeshTransforms::ApplyTransformInverse(*Result.Mesh, TargetToWorld);
|
2020-10-22 19:19:16 -04:00
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
TargetMeshCommitter->CommitMeshDescription([&](const IMeshDescriptionCommitter::FCommitterParams& CommitParams)
|
2021-02-03 19:00:42 -04:00
|
|
|
{
|
|
|
|
|
FDynamicMeshToMeshDescription Converter;
|
2021-03-11 11:40:03 -04:00
|
|
|
Converter.Convert(Result.Mesh.Get(), *CommitParams.MeshDescriptionOut);
|
2021-02-03 19:00:42 -04:00
|
|
|
});
|
2020-10-22 19:19:16 -04:00
|
|
|
|
|
|
|
|
FComponentMaterialSet MaterialSet;
|
|
|
|
|
MaterialSet.Materials = GetOutputMaterials();
|
2021-03-11 11:40:03 -04:00
|
|
|
TargetMaterial->CommitMaterialSetUpdate(MaterialSet, true);
|
2020-10-22 19:19:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-08-11 01:36:57 -04:00
|
|
|
FString UBaseCreateFromSelectedTool::PrefixWithSourceNameIfSingleSelection(const FString& AssetName) const
|
|
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
if (Targets.Num() == 1)
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
2021-06-02 15:58:00 -04:00
|
|
|
FString CurName = UE::Modeling::GetComponentAssetBaseName(TargetComponentInterface(0)->GetOwnerComponent());
|
2020-10-22 19:19:16 -04:00
|
|
|
return FString::Printf(TEXT("%s_%s"), *CurName, *AssetName);
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return AssetName;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBaseCreateFromSelectedTool::OnPropertyModified(UObject* PropertySet, FProperty* Property)
|
|
|
|
|
{
|
|
|
|
|
if (Property && (Property->GetFName() == GET_MEMBER_NAME_CHECKED(UTransformInputsToolProperties, bShowTransformUI)))
|
|
|
|
|
{
|
|
|
|
|
UpdateGizmoVisibility();
|
|
|
|
|
}
|
|
|
|
|
else if (Property &&
|
|
|
|
|
( PropertySet == HandleSourcesProperties
|
|
|
|
|
|| Property->GetFName() == GET_MEMBER_NAME_CHECKED(UTransformInputsToolProperties, bSnapToWorldGrid)
|
|
|
|
|
))
|
|
|
|
|
{
|
|
|
|
|
// nothing
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Preview->InvalidateResult();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void UBaseCreateFromSelectedTool::Shutdown(EToolShutdownType ShutdownType)
|
|
|
|
|
{
|
|
|
|
|
SaveProperties();
|
|
|
|
|
HandleSourcesProperties->SaveProperties(this);
|
2021-06-23 22:13:32 -04:00
|
|
|
OutputTypeProperties->SaveProperties(this, TEXT("OutputTypeFromInputTool"));
|
2020-08-11 01:36:57 -04:00
|
|
|
TransformProperties->SaveProperties(this);
|
|
|
|
|
|
|
|
|
|
FDynamicMeshOpResult Result = Preview->Shutdown();
|
|
|
|
|
// Restore (unhide) the source meshes
|
2021-03-11 11:40:03 -04:00
|
|
|
for (int32 ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
TargetComponentInterface(ComponentIdx)->SetOwnerVisibility(true);
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
2020-11-24 18:42:39 -04:00
|
|
|
|
2020-08-11 01:36:57 -04:00
|
|
|
if (ShutdownType == EToolShutdownType::Accept)
|
|
|
|
|
{
|
|
|
|
|
GetToolManager()->BeginUndoTransaction(GetActionName());
|
|
|
|
|
|
|
|
|
|
// Generate the result
|
2020-10-22 19:19:16 -04:00
|
|
|
AActor* KeepActor = nullptr;
|
|
|
|
|
if (HandleSourcesProperties->WriteOutputTo == EBaseCreateFromSelectedTargetType::NewAsset)
|
|
|
|
|
{
|
|
|
|
|
GenerateAsset(Result);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
int32 TargetIndex = (HandleSourcesProperties->WriteOutputTo == EBaseCreateFromSelectedTargetType::FirstInputAsset) ? 0 : (Targets.Num() - 1);
|
|
|
|
|
KeepActor = TargetComponentInterface(TargetIndex)->GetOwnerActor();
|
2020-10-22 19:19:16 -04:00
|
|
|
|
2021-03-11 11:40:03 -04:00
|
|
|
UpdateAsset(Result, Targets[TargetIndex]);
|
2020-10-22 19:19:16 -04:00
|
|
|
}
|
2020-08-11 01:36:57 -04:00
|
|
|
|
|
|
|
|
TArray<AActor*> Actors;
|
2021-03-11 11:40:03 -04:00
|
|
|
for (int32 ComponentIdx = 0; ComponentIdx < Targets.Num(); ComponentIdx++)
|
2020-08-11 01:36:57 -04:00
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
AActor* Actor = TargetComponentInterface(ComponentIdx)->GetOwnerActor();
|
2020-10-22 19:19:16 -04:00
|
|
|
if (Actor != KeepActor)
|
|
|
|
|
{
|
2021-03-11 11:40:03 -04:00
|
|
|
Actors.Add(Actor);
|
2020-10-22 19:19:16 -04:00
|
|
|
}
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
|
|
|
|
HandleSourcesProperties->ApplyMethod(Actors, GetToolManager());
|
|
|
|
|
|
2020-10-22 19:19:16 -04:00
|
|
|
if (KeepActor != nullptr)
|
|
|
|
|
{
|
|
|
|
|
// select the actor we kept
|
|
|
|
|
ToolSelectionUtil::SetNewActorSelection(GetToolManager(), KeepActor);
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-11 01:36:57 -04:00
|
|
|
GetToolManager()->EndUndoTransaction();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UInteractiveGizmoManager* GizmoManager = GetToolManager()->GetPairedGizmoManager();
|
|
|
|
|
GizmoManager->DestroyAllGizmosByOwner(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool UBaseCreateFromSelectedTool::CanAccept() const
|
|
|
|
|
{
|
2021-02-05 16:33:02 -04:00
|
|
|
return Super::CanAccept() && Preview->HaveValidNonEmptyResult();
|
2020-08-11 01:36:57 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef LOCTEXT_NAMESPACE
|