Files
UnrealEngineUWP/Engine/Plugins/Runtime/MeshModelingToolset/Source/ModelingComponents/Private/Selection/PersistentMeshSelection.cpp

138 lines
4.5 KiB
C++
Raw Normal View History

ModelingTools: replace StorableSelection mechanism with new UPersistentMeshSelection and UPersistentMeshSelectionManager context object. - UPersistentMeshSelection is largely a port of UGroupTopologyStorableSelection, with the actual selection data moved to FGenericMeshSelection - UPersistentMeshSelectionManager is meant to be used as a ContextObject in a ToolsContext, also contains utility functions to register/unregister/find context object - Selection is no longer passed as part of FToolBuilderState. Instead Tools access the selection via ContextObject - UPersistentMeshSelectionManager currently supports a single active selection. Selection changes are transacted via an FChange. - When not inside a Tool, Selection is visualized with a pink border outline. Currently vertex selection is not visualized. - Usage model is that on Tool Accept/Complete, prior to Tool Shutdown, any existing selection is cleared, and Tool may set a new Output selection which becomes the active selection - StoredMeshSelectionUtil.h has utility functions to get current selection, set output selection, and clear it - SingleSelectionMeshEditingTool already made input selection available to subclasses, port that capability to new architecture - convert EditMeshPolygonsTool to be a SingleSelectionMeshEditingTool, use provided Input selection and set Output selection as appropriate - ModelingToolsEditorMode clears active selection where appropriate, eg if selected object changes. However the behavior here will need further improvement, currently relies on questionable event handling from the TypedElement system #rb semion.piskarev #rnx #jira none #preflight 6136cbbfd9c85a0001fc3b56 #ROBOMERGE-AUTHOR: ryan.schmidt #ROBOMERGE-SOURCE: CL 17441056 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17441061 by ryan schmidt in ue5-release-engine-test branch]
2021-09-06 23:05:07 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "Selection/PersistentMeshSelection.h"
#include "DynamicMesh/DynamicMesh3.h"
#include "Util/CompactMaps.h"
#include "GroupTopology.h"
#include "Selection/StoredMeshSelectionUtil.h"
#include "MeshRegionBoundaryLoops.h"
using namespace UE::Geometry;
void UPersistentMeshSelection::SetSelection(const FGroupTopology& TopologyIn, const FGroupTopologySelection& SelectionIn,
const FCompactMaps* CompactMaps)
{
FGenericMeshSelection& Data = this->Selection;
Data.FaceIDs = SelectionIn.SelectedGroupIDs.Array();
Data.VertexIDs.Reset();
Data.EdgeIDs.Reset();
const FDynamicMesh3* GroupMesh = TopologyIn.GetMesh();
for (int32 CornerID : SelectionIn.SelectedCornerIDs)
{
int32 CornerVID = TopologyIn.GetCornerVertexID(CornerID);
if (CompactMaps != nullptr)
{
CornerVID = CompactMaps->GetVertexMapping(CornerVID);
}
Data.VertexIDs.Add(CornerVID);
Data.RenderVertices.Add(GroupMesh->GetVertex(CornerVID));
}
for (int32 GroupEdgeID : SelectionIn.SelectedEdgeIDs)
{
FIndex2i EdgeVerts = (CompactMaps != nullptr) ?
GetGroupEdgeRepresentativeVerts(TopologyIn, GroupEdgeID, *CompactMaps) : GetGroupEdgeRepresentativeVerts(TopologyIn, GroupEdgeID);
Data.EdgeIDs.Add(EdgeVerts);
const FGroupTopology::FGroupEdge& GroupEdge = TopologyIn.Edges[GroupEdgeID];
const TArray<int32>& GroupEdgeVertices = GroupEdge.Span.Vertices;
int32 N = GroupEdgeVertices.Num();
int32 EdgeVertA = (CompactMaps) ? CompactMaps->GetVertexMapping(GroupEdgeVertices[0]) : GroupEdgeVertices[0];
for (int32 k = 1; k < N; ++k)
{
int32 EdgeVertB = (CompactMaps) ? CompactMaps->GetVertexMapping(GroupEdgeVertices[k]) : GroupEdgeVertices[k];
Data.RenderEdges.Add( FSegment3d(GroupMesh->GetVertex(EdgeVertA), GroupMesh->GetVertex(EdgeVertB)) );
EdgeVertA = EdgeVertB;
}
}
if (Data.FaceIDs.Num() > 0)
{
TArray<int32> TriangleIDs;
TopologyIn.GetSelectedTriangles(SelectionIn, TriangleIDs);
if (CompactMaps)
{
for (int32& tid : TriangleIDs)
{
tid = CompactMaps->GetTriangleMapping(tid);
}
}
FMeshRegionBoundaryLoops RegionLoops(GroupMesh, TriangleIDs, true);
for (const FEdgeLoop& Loop : RegionLoops.Loops)
{
int32 N = Loop.GetVertexCount();
for (int32 k = 0; k < N; ++k )
{
Data.RenderEdges.Add( FSegment3d(GroupMesh->GetVertex(Loop.Vertices[k]), GroupMesh->GetVertex(Loop.Vertices[(k+1)%N])) );
}
}
}
}
void UPersistentMeshSelection::ExtractIntoSelectionObject(const FGroupTopology& TopologyIn, FGroupTopologySelection& SelectionOut) const
{
const FGenericMeshSelection& Data = this->Selection;
SelectionOut.Clear();
const FDynamicMesh3* Mesh = TopologyIn.GetMesh();
if (!Mesh)
{
ensureMsgf(false, TEXT("FStoredGroupTopologySelection::ExtractIntoSelectionObject: target topology must have valid underlying mesh. "));
return;
}
SelectionOut.SelectedGroupIDs = TSet<int32>(Data.FaceIDs);
for (int32 Vid : Data.VertexIDs)
{
if (!Mesh->IsVertex(Vid))
{
ensureMsgf(false, TEXT("FStoredGroupTopologySelection::ExtractIntoSelectionObject: target topology's mesh was missing a vertex ID. "
"Perhaps the mesh was compacted without updating the stored selection?"));
continue;
}
int32 CornerID = TopologyIn.GetCornerIDFromVertexID(Vid);
if (CornerID == IndexConstants::InvalidID)
{
ensureMsgf(false, TEXT("FStoredGroupTopologySelection::ExtractIntoSelectionObject: target topology did not have an expected vert as a corner. "
"Is the topology initialized, and based on the same mesh?"));
continue;
}
SelectionOut.SelectedCornerIDs.Add(CornerID);
}
for (const FIndex2i& EdgeVerts : Data.EdgeIDs)
{
if (!Mesh->IsVertex(EdgeVerts.A) || !Mesh->IsVertex(EdgeVerts.B))
{
ensureMsgf(false, TEXT("FStoredGroupTopologySelection::ExtractIntoSelectionObject: target topology's mesh was missing a vertex ID. "
"Perhaps the mesh was compacted without updating the stored selection?"));
continue;
}
int32 Eid = Mesh->FindEdge(EdgeVerts.A, EdgeVerts.B);
if (Eid == IndexConstants::InvalidID)
{
ensureMsgf(false, TEXT("FStoredGroupTopologySelection::ExtractIntoSelectionObject: target topology's mesh was missing an expected edge."));
continue;
}
int32 GroupEdgeID = TopologyIn.FindGroupEdgeID(Eid);
if (Eid == IndexConstants::InvalidID)
{
ensureMsgf(false, TEXT("FStoredGroupTopologySelection::ExtractIntoSelectionObject: target topology did not have an expected group edge."
"Is the topology initialized, and based on the same mesh?"));
continue;
}
SelectionOut.SelectedEdgeIDs.Add(GroupEdgeID);
}
}