You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb none #rnx #jira none #preflight 60c52c5db9446100014da02d [CL 16653115 by Ryan Schmidt in ue5-main branch]
290 lines
7.6 KiB
C++
290 lines
7.6 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "EditMeshMaterialsTool.h"
|
|
#include "InteractiveToolManager.h"
|
|
#include "ToolBuilderUtil.h"
|
|
#include "Drawing/MeshDebugDrawing.h"
|
|
#include "DynamicMeshEditor.h"
|
|
#include "DynamicMesh/DynamicMeshChangeTracker.h"
|
|
#include "Changes/ToolCommandChangeSequence.h"
|
|
#include "Changes/MeshChange.h"
|
|
#include "Util/ColorConstants.h"
|
|
#include "Selections/MeshConnectedComponents.h"
|
|
#include "MeshRegionBoundaryLoops.h"
|
|
#include "DynamicMesh/MeshIndexUtil.h"
|
|
#include "ToolSetupUtil.h"
|
|
|
|
#include "TargetInterfaces/MaterialProvider.h"
|
|
#include "TargetInterfaces/MeshDescriptionCommitter.h"
|
|
#include "TargetInterfaces/PrimitiveComponentBackedTarget.h"
|
|
|
|
#include "ExplicitUseGeometryMathTypes.h" // using UE::Geometry::(math types)
|
|
using namespace UE::Geometry;
|
|
|
|
#define LOCTEXT_NAMESPACE "UEditMeshMaterialsTool"
|
|
|
|
void UEditMeshMaterialsEditActions::PostMaterialAction(EEditMeshMaterialsToolActions Action)
|
|
{
|
|
if (ParentTool.IsValid() && Cast<UEditMeshMaterialsTool>(ParentTool))
|
|
{
|
|
Cast<UEditMeshMaterialsTool>(ParentTool)->RequestMaterialAction(Action);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ToolBuilder
|
|
*/
|
|
|
|
UMeshSurfacePointTool* UEditMeshMaterialsToolBuilder::CreateNewTool(const FToolBuilderState& SceneState) const
|
|
{
|
|
UEditMeshMaterialsTool* SelectionTool = NewObject<UEditMeshMaterialsTool>(SceneState.ToolManager);
|
|
SelectionTool->SetWorld(SceneState.World);
|
|
return SelectionTool;
|
|
}
|
|
|
|
|
|
|
|
|
|
void UEditMeshMaterialsTool::Setup()
|
|
{
|
|
UMeshSelectionTool::Setup();
|
|
|
|
SetToolDisplayName(LOCTEXT("ToolName", "Edit Materials"));
|
|
|
|
PreviewMesh->ClearOverrideRenderMaterial();
|
|
|
|
IMaterialProvider* TargetMaterial = Cast<IMaterialProvider>(Target);
|
|
FComponentMaterialSet AssetMaterials;
|
|
TargetMaterial->GetMaterialSet(AssetMaterials, true);
|
|
MaterialProps->Materials = AssetMaterials.Materials;
|
|
CurrentMaterials = MaterialProps->Materials;
|
|
InitialMaterialKey = GetMaterialKey();
|
|
|
|
MaterialProps->WatchProperty<FMaterialSetKey>(
|
|
[this](){ return GetMaterialKey(); },
|
|
[this](FMaterialSetKey NewKey) { OnMaterialSetChanged(); });
|
|
|
|
FComponentMaterialSet ComponentMaterials;
|
|
TargetMaterial->GetMaterialSet(ComponentMaterials, false);
|
|
if (ComponentMaterials != AssetMaterials)
|
|
{
|
|
GetToolManager()->DisplayMessage(
|
|
LOCTEXT("MaterialWarning", "The selected Component has a different Material set than the underlying Asset. Asset materials are shown."),
|
|
EToolMessageLevel::UserWarning);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
UMeshSelectionToolActionPropertySet* UEditMeshMaterialsTool::CreateEditActions()
|
|
{
|
|
UEditMeshMaterialsEditActions* Actions = NewObject<UEditMeshMaterialsEditActions>(this);
|
|
Actions->Initialize(this);
|
|
return Actions;
|
|
}
|
|
|
|
void UEditMeshMaterialsTool::AddSubclassPropertySets()
|
|
{
|
|
MaterialProps = NewObject<UEditMeshMaterialsToolProperties>(this);
|
|
MaterialProps->RestoreProperties(this);
|
|
AddToolPropertySource(MaterialProps);
|
|
}
|
|
|
|
|
|
void UEditMeshMaterialsTool::RequestMaterialAction(EEditMeshMaterialsToolActions ActionType)
|
|
{
|
|
if (bHavePendingAction)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PendingSubAction = ActionType;
|
|
bHavePendingSubAction = true;
|
|
}
|
|
|
|
|
|
|
|
|
|
void UEditMeshMaterialsTool::OnTick(float DeltaTime)
|
|
{
|
|
UMeshSelectionTool::OnTick(DeltaTime);
|
|
|
|
if (bHavePendingSubAction)
|
|
{
|
|
ApplyMaterialAction(PendingSubAction);
|
|
bHavePendingSubAction = false;
|
|
PendingSubAction = EEditMeshMaterialsToolActions::NoAction;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
void UEditMeshMaterialsTool::ApplyMaterialAction(EEditMeshMaterialsToolActions ActionType)
|
|
{
|
|
switch (ActionType)
|
|
{
|
|
case EEditMeshMaterialsToolActions::AssignMaterial:
|
|
AssignMaterialToSelectedTriangles();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void UEditMeshMaterialsTool::AssignMaterialToSelectedTriangles()
|
|
{
|
|
check(SelectionType == EMeshSelectionElementType::Face);
|
|
TArray<int32> SelectedFaces = Selection->GetElements(EMeshSelectionElementType::Face);
|
|
if (SelectedFaces.Num() == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TUniquePtr<FToolCommandChangeSequence> ChangeSeq = MakeUnique<FToolCommandChangeSequence>();
|
|
|
|
// clear current selection
|
|
BeginChange(false);
|
|
for (int tid : SelectedFaces)
|
|
{
|
|
ActiveSelectionChange->Add(tid);
|
|
}
|
|
Selection->RemoveIndices(EMeshSelectionElementType::Face, SelectedFaces);
|
|
TUniquePtr<FToolCommandChange> SelectionChange = EndChange();
|
|
ChangeSeq->AppendChange(Selection, MoveTemp(SelectionChange));
|
|
|
|
int32 SetMaterialID = MaterialProps->SelectedMaterial;
|
|
|
|
// assign new groups to triangles
|
|
// note: using an FMeshChange is kind of overkill here
|
|
TUniquePtr<FMeshChange> MeshChange = PreviewMesh->TrackedEditMesh(
|
|
[&SelectedFaces, SetMaterialID](FDynamicMesh3& Mesh, FDynamicMeshChangeTracker& ChangeTracker)
|
|
{
|
|
if (Mesh.Attributes() && Mesh.Attributes()->HasMaterialID())
|
|
{
|
|
FDynamicMeshMaterialAttribute* MaterialIDAttrib = Mesh.Attributes()->GetMaterialID();
|
|
for (int tid : SelectedFaces)
|
|
{
|
|
ChangeTracker.SaveTriangle(tid, true);
|
|
MaterialIDAttrib->SetNewValue(tid, SetMaterialID);
|
|
}
|
|
}
|
|
});
|
|
ChangeSeq->AppendChange(PreviewMesh, MoveTemp(MeshChange));
|
|
|
|
// emit combined change sequence
|
|
GetToolManager()->EmitObjectChange(this, MoveTemp(ChangeSeq), LOCTEXT("MeshSelectionToolAssignMaterial", "Assign Material"));
|
|
|
|
OnExternalSelectionChange();
|
|
bHaveModifiedMesh = true;
|
|
}
|
|
|
|
|
|
|
|
|
|
void UEditMeshMaterialsTool::OnMaterialSetChanged()
|
|
{
|
|
TUniquePtr<FEditMeshMaterials_MaterialSetChange> MaterialChange = MakeUnique<FEditMeshMaterials_MaterialSetChange>();
|
|
MaterialChange->MaterialsBefore = CurrentMaterials;
|
|
MaterialChange->MaterialsAfter = MaterialProps->Materials;
|
|
|
|
PreviewMesh->SetMaterials(MaterialProps->Materials);
|
|
|
|
CurrentMaterials = MaterialProps->Materials;
|
|
|
|
GetToolManager()->EmitObjectChange(this, MoveTemp(MaterialChange), LOCTEXT("MaterialSetChange", "Material Change"));
|
|
|
|
bHaveModifiedMaterials = true;
|
|
}
|
|
|
|
|
|
|
|
void UEditMeshMaterialsTool::ExternalUpdateMaterialSet(const TArray<UMaterialInterface*>& NewMaterialSet)
|
|
{
|
|
// Disable props so they don't update
|
|
SetToolPropertySourceEnabled(MaterialProps, false);
|
|
MaterialProps->Materials = NewMaterialSet;
|
|
SetToolPropertySourceEnabled(MaterialProps, true);
|
|
PreviewMesh->SetMaterials(MaterialProps->Materials);
|
|
CurrentMaterials = MaterialProps->Materials;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UEditMeshMaterialsTool::OnShutdown(EToolShutdownType ShutdownType)
|
|
{
|
|
// this is a bit of a hack, UMeshSelectionTool::OnShutdown will also do this...
|
|
SelectionProps->SaveProperties(this);
|
|
|
|
if (ShutdownType == EToolShutdownType::Accept)
|
|
{
|
|
GetToolManager()->BeginUndoTransaction(LOCTEXT("EditMeshMaterialsTransactionName", "Edit Materials"));
|
|
|
|
if (GetMaterialKey() != InitialMaterialKey)
|
|
{
|
|
FComponentMaterialSet NewMaterialSet;
|
|
NewMaterialSet.Materials = CurrentMaterials;
|
|
Cast<IMaterialProvider>(Target)->CommitMaterialSetUpdate(NewMaterialSet, true);
|
|
}
|
|
|
|
UMeshSelectionTool::OnShutdown(ShutdownType);
|
|
|
|
GetToolManager()->EndUndoTransaction();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UEditMeshMaterialsTool::FMaterialSetKey::operator!=(const FMaterialSetKey& Key2) const
|
|
{
|
|
int Num = Values.Num();
|
|
if (Key2.Values.Num() != Num)
|
|
{
|
|
return true;
|
|
}
|
|
for (int j = 0; j < Num; ++j)
|
|
{
|
|
if (Key2.Values[j] != Values[j])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
UEditMeshMaterialsTool::FMaterialSetKey UEditMeshMaterialsTool::GetMaterialKey()
|
|
{
|
|
FMaterialSetKey Key;
|
|
for (UMaterialInterface* Material : MaterialProps->Materials)
|
|
{
|
|
Key.Values.Add(Material);
|
|
}
|
|
return Key;
|
|
}
|
|
|
|
|
|
|
|
|
|
void FEditMeshMaterials_MaterialSetChange::Apply(UObject* Object)
|
|
{
|
|
UEditMeshMaterialsTool* Tool = CastChecked<UEditMeshMaterialsTool>(Object);
|
|
Tool->ExternalUpdateMaterialSet(MaterialsAfter);
|
|
}
|
|
|
|
void FEditMeshMaterials_MaterialSetChange::Revert(UObject* Object)
|
|
{
|
|
UEditMeshMaterialsTool* Tool = CastChecked<UEditMeshMaterialsTool>(Object);
|
|
Tool->ExternalUpdateMaterialSet(MaterialsBefore);
|
|
}
|
|
|
|
FString FEditMeshMaterials_MaterialSetChange::ToString() const
|
|
{
|
|
return FString(TEXT("MaterialSet Change"));
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|