binds... * z, backspace (DeleteSelection): also delete selected components (vertices/edges/faces) of brush in a component mode
This commit is contained in:
parent
0f7af6aaa4
commit
2836989099
120
radiant/csg.cpp
120
radiant/csg.cpp
|
|
@ -983,10 +983,14 @@ class MergeVertices
|
||||||
public:
|
public:
|
||||||
typedef Vertices::const_iterator const_iterator;
|
typedef Vertices::const_iterator const_iterator;
|
||||||
void insert( const Vector3& vertex ){
|
void insert( const Vector3& vertex ){
|
||||||
|
if( !contains( vertex ) )
|
||||||
|
m_vertices.push_back( vertex );
|
||||||
|
}
|
||||||
|
bool contains( const Vector3& vertex ) const {
|
||||||
for( const_iterator i = begin(); i != end(); ++i )
|
for( const_iterator i = begin(); i != end(); ++i )
|
||||||
if( Edge_isDegenerate( vertex, *i ) )
|
if( Edge_isDegenerate( vertex, *i ) )
|
||||||
return;
|
return true;
|
||||||
m_vertices.push_back( vertex );
|
return false;
|
||||||
}
|
}
|
||||||
const_iterator begin() const {
|
const_iterator begin() const {
|
||||||
return m_vertices.begin();
|
return m_vertices.begin();
|
||||||
|
|
@ -1001,7 +1005,7 @@ public:
|
||||||
brushsplit_t split;
|
brushsplit_t split;
|
||||||
for( const_iterator i = begin(); i != end(); ++i ){
|
for( const_iterator i = begin(); i != end(); ++i ){
|
||||||
WindingVertex_ClassifyPlane( ( *i ), plane, split );
|
WindingVertex_ClassifyPlane( ( *i ), plane, split );
|
||||||
if( ( split.counts[ePlaneFront] != 0 ) && ( split.counts[ePlaneBack] != 0 ) )
|
if( ( split.counts[ePlaneFront] != 0 ) && ( split.counts[ePlaneBack] != 0 ) ) // optimized to break, if plane is inside
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return split;
|
return split;
|
||||||
|
|
@ -1156,8 +1160,6 @@ void CSG_WrapMerge(){
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ASSERT_MESSAGE( !brush->empty(), "brush left with no faces after merge" );
|
|
||||||
|
|
||||||
scene::Path path = ultimate_group_path();
|
scene::Path path = ultimate_group_path();
|
||||||
|
|
||||||
// free the original brushes
|
// free the original brushes
|
||||||
|
|
@ -1173,6 +1175,114 @@ void CSG_WrapMerge(){
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class find_instance_to_DeleteComponents : public SelectionSystem::Visitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mutable scene::Instance* m_instance;
|
||||||
|
find_instance_to_DeleteComponents()
|
||||||
|
: m_instance( 0 ) {
|
||||||
|
}
|
||||||
|
void visit( scene::Instance& instance ) const {
|
||||||
|
if( Instance_getBrush( instance ) ){
|
||||||
|
//Instance_isSelectedComponents()
|
||||||
|
ComponentSelectionTestable* componentSelectionTestable = Instance_getComponentSelectionTestable( instance );
|
||||||
|
if( componentSelectionTestable != 0 && componentSelectionTestable->isSelectedComponents() )
|
||||||
|
m_instance = &instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* deletes one brush components */
|
||||||
|
void CSG_DeleteComponents(){
|
||||||
|
find_instance_to_DeleteComponents find_instance;
|
||||||
|
GlobalSelectionSystem().foreachSelected( find_instance );
|
||||||
|
scene::Instance* instance = find_instance.m_instance;
|
||||||
|
if( instance ){
|
||||||
|
MergeVertices deleteVertices;
|
||||||
|
{
|
||||||
|
Scene_gatherSelectedComponents get_deleteVertices( deleteVertices );
|
||||||
|
get_deleteVertices.pre( instance->path(), *instance );
|
||||||
|
}
|
||||||
|
Brush* brush = Node_getBrush( instance->path().top() );
|
||||||
|
/* gather vertices to keep */
|
||||||
|
MergeVertices mergeVertices;
|
||||||
|
for ( Brush::const_iterator f = brush->begin(); f != brush->end(); ++f )
|
||||||
|
if ( ( *f )->contributes() ){
|
||||||
|
const Winding& winding = ( *f )->getWinding();
|
||||||
|
for ( std::size_t w = 0; w != winding.numpoints; ++w )
|
||||||
|
if( !deleteVertices.contains( winding[w].vertex ) )
|
||||||
|
mergeVertices.insert( winding[w].vertex );
|
||||||
|
}
|
||||||
|
if( mergeVertices.size() < 4 ){
|
||||||
|
globalWarningStream() << "CSG_DeleteComponents: Too few vertices left: " << mergeVertices.size() << ".\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* gather original planes */
|
||||||
|
MergePlanes mergePlanes;
|
||||||
|
for ( Brush::const_iterator f = brush->begin(); f != brush->end(); ++f ){
|
||||||
|
const Face& face = *( *f );
|
||||||
|
if ( face.contributes() ){
|
||||||
|
mergePlanes.insert( MergePlane( face.getPlane().plane3(), &face ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bruteforce new planes */
|
||||||
|
for( MergeVertices::const_iterator i = mergeVertices.begin() + 0; i != mergeVertices.end() - 2; ++i )
|
||||||
|
for( MergeVertices::const_iterator j = i + 1; j != mergeVertices.end() - 1; ++j )
|
||||||
|
for( MergeVertices::const_iterator k = j + 1; k != mergeVertices.end() - 0; ++k ){
|
||||||
|
const Plane3 plane = plane3_for_points( *i, *j, *k );
|
||||||
|
if( plane3_valid( plane ) ){
|
||||||
|
const brushsplit_t split = mergeVertices.classify_plane( plane );
|
||||||
|
if( ( split.counts[ePlaneFront] == 0 ) != ( split.counts[ePlaneBack] == 0 ) ){
|
||||||
|
if( split.counts[ePlaneFront] != 0 )
|
||||||
|
mergePlanes.insert( MergePlane( plane3_flipped( plane ), *i, *j, *k ) );
|
||||||
|
else
|
||||||
|
mergePlanes.insert( MergePlane( plane, *i, *k, *j ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( mergePlanes.size() < 4 ){
|
||||||
|
globalWarningStream() << "CSG_DeleteComponents: Too few planes left: " << mergePlanes.size() << ".\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeSmartReference node( ( new BrushNode() )->node() );
|
||||||
|
brush = Node_getBrush( node );
|
||||||
|
|
||||||
|
{
|
||||||
|
const char* shader = TextureBrowser_GetSelectedShader();
|
||||||
|
TextureProjection projection;
|
||||||
|
TexDef_Construct_Default( projection );
|
||||||
|
for( MergePlanes::const_iterator i = mergePlanes.begin(); i != mergePlanes.end(); ++i ){
|
||||||
|
if( i->m_face )
|
||||||
|
brush->addFace( *( i->m_face ) );
|
||||||
|
else
|
||||||
|
brush->addPlane( i->m_v1, i->m_v2, i->m_v3, shader, projection );
|
||||||
|
}
|
||||||
|
brush->removeEmptyFaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the new brush would not be convex
|
||||||
|
if ( !brush->hasContributingFaces() ) {
|
||||||
|
globalWarningStream() << "CSG_DeleteComponents: Failed - result would not be convex.\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scene::Path path = instance->path();
|
||||||
|
path.pop();
|
||||||
|
|
||||||
|
Node_getTraversable( path.top() )->insert( node );
|
||||||
|
path.push( makeReference( node.get() ) );
|
||||||
|
|
||||||
|
selectPath( path, true ); //b4 original deletion, so component mode will stay enabled
|
||||||
|
|
||||||
|
// free the original brush
|
||||||
|
Path_deleteTop( instance->path() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ void CSG_MakeRoom();
|
||||||
void CSG_Subtract();
|
void CSG_Subtract();
|
||||||
void CSG_Merge();
|
void CSG_Merge();
|
||||||
void CSG_WrapMerge();
|
void CSG_WrapMerge();
|
||||||
|
void CSG_DeleteComponents();
|
||||||
void CSG_Tool();
|
void CSG_Tool();
|
||||||
|
|
||||||
namespace scene
|
namespace scene
|
||||||
|
|
|
||||||
|
|
@ -677,8 +677,14 @@ void Redo(){
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteSelection(){
|
void deleteSelection(){
|
||||||
|
if( GlobalSelectionSystem().Mode() == SelectionSystem::eComponent && GlobalSelectionSystem().countSelectedComponents() != 0 ){
|
||||||
|
UndoableCommand undo( "deleteSelectedComponents" );
|
||||||
|
CSG_DeleteComponents();
|
||||||
|
}
|
||||||
|
else{
|
||||||
UndoableCommand undo( "deleteSelected" );
|
UndoableCommand undo( "deleteSelected" );
|
||||||
Select_Delete();
|
Select_Delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map_ExportSelected( TextOutputStream& ostream ){
|
void Map_ExportSelected( TextOutputStream& ostream ){
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user