Files
ryan schmidt 70ac55822d ModelingMode: improve interop with new Selection System and existing Tools
Add support for Tools to provide an "output" selection. Add UGeometrySelectionManager::SetSelectionForComponent() which can set an explicit externally-provided selection. FBaseDynamicMeshSelector::UpdateSelectionFromSelection() now supports selection conversion when available and requested (is used to implement SetSelectionForComponent). New GeometrySelectionUtil functions InitializeSelectionFromTriangles() and ConvertSelection() are used to implement this (note: only Triangles->other conversion is currently supported). Add HaveAvailableGeometrySelection() and SetToolOutputGeometrySelectionForTarget() in StoredMeshSelectionUtil.h, this is the top-level function that Tools can use to set an Output selection.

ExtrudeMeshSelectionTool now emits output selection.

Update EditMeshPolygonsTool to use new Selection system and allow individual operations to be utilized as standalone Tools. Convert EditMeshPolygonsTool to be a USingleTargetWithSelectionTool, use FGeometrySelection to initialize selection. Add bTerminateOnPendingActionComplete flag, which is set when Tool is directly initialized to a specific operation, and forces tool to shut down when operation completes. This allows it to be used to more cleanly implement multiple action buttons in Modeling UI. When in this mode, selection panels are not shown. On Shutdown, now emits an "output" selection which GeometrySelectionManager can use to provide new selection to user. Update UPolygonSelectionMechanic Set/Get selection APIs to use FGeometrySelection instead of UPersistentMeshSelection.

port UVProjectionTool to derive from USingleTargetWithSelectionTool, use FGeometrySelection to initialize target ROI

deprecate UPersistentMeshSelection and related functions in StoredMeshSelectionUtil.h. Deprecate Tool Input Selection APIs in USingleSelectionMeshEditingTool and Builder.

Repurpose old ModelingMode-level PolyModel tab operations for new Selection Tools UI, now support Inset, Outset, Cut Faces, Insert Edge Loop, PushPull, and Bevel.

#rb none
#preflight 63c84fa2b065224750b9831f

[CL 23766643 by ryan schmidt in ue5-main branch]
2023-01-18 17:59:31 -05:00

141 lines
4.6 KiB
C++

// 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"
#include UE_INLINE_GENERATED_CPP_BY_NAME(PersistentMeshSelection)
using namespace UE::Geometry;
void UDEPRECATED_PersistentMeshSelection::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 UDEPRECATED_PersistentMeshSelection::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);
}
}