diff --git a/contrib/bobtoolz/DPatch.cpp b/contrib/bobtoolz/DPatch.cpp index 817fbaa8..26a6e541 100644 --- a/contrib/bobtoolz/DPatch.cpp +++ b/contrib/bobtoolz/DPatch.cpp @@ -188,7 +188,7 @@ bool DPatch::ResetTextures( const char *oldTextureName, const char *newTextureNa return false; } -void Build1dArray( vec3_t* array, drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT], +void Build1dArray( vec3_t* array, const drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT], int startX, int startY, int number, bool horizontal, bool inverse ){ int x = startX, y = startY, i, step; @@ -232,7 +232,7 @@ bool Compare1dArrays( vec3_t* a1, vec3_t* a2, int size ){ return equal; } -patch_merge_t DPatch::IsMergable( DPatch *other ){ +patch_merge_t DPatch::IsMergable( const DPatch& other ){ int i, j; vec3_t p1Array[4][MAX_PATCH_HEIGHT]; vec3_t p2Array[4][MAX_PATCH_HEIGHT]; @@ -242,25 +242,25 @@ patch_merge_t DPatch::IsMergable( DPatch *other ){ patch_merge_t merge_info; - Build1dArray( p1Array[0], this->points, 0, 0, this->width, true, false ); - Build1dArray( p1Array[1], this->points, this->width - 1, 0, this->height, false, false ); - Build1dArray( p1Array[2], this->points, this->width - 1, this->height - 1, this->width, true, true ); + Build1dArray( p1Array[0], this->points, 0, 0, this->width, true, false ); + Build1dArray( p1Array[1], this->points, this->width - 1, 0, this->height, false, false ); + Build1dArray( p1Array[2], this->points, this->width - 1, this->height - 1, this->width, true, true ); Build1dArray( p1Array[3], this->points, 0, this->height - 1, this->height, false, true ); - Build1dArray( p2Array[0], other->points, 0, 0, other->width, true, false ); - Build1dArray( p2Array[1], other->points, other->width - 1, 0, other->height, false, false ); - Build1dArray( p2Array[2], other->points, other->width - 1, other->height - 1, other->width, true, true ); - Build1dArray( p2Array[3], other->points, 0, other->height - 1, other->height, false, true ); + Build1dArray( p2Array[0], other.points, 0, 0, other.width, true, false ); + Build1dArray( p2Array[1], other.points, other.width - 1, 0, other.height, false, false ); + Build1dArray( p2Array[2], other.points, other.width - 1, other.height - 1, other.width, true, true ); + Build1dArray( p2Array[3], other.points, 0, other.height - 1, other.height, false, true ); p1ArraySizes[0] = this->width; p1ArraySizes[1] = this->height; p1ArraySizes[2] = this->width; p1ArraySizes[3] = this->height; - p2ArraySizes[0] = other->width; - p2ArraySizes[1] = other->height; - p2ArraySizes[2] = other->width; - p2ArraySizes[3] = other->height; + p2ArraySizes[0] = other.width; + p2ArraySizes[1] = other.height; + p2ArraySizes[2] = other.width; + p2ArraySizes[3] = other.height; for ( i = 0; i < 4; i++ ) { @@ -281,10 +281,10 @@ patch_merge_t DPatch::IsMergable( DPatch *other ){ return merge_info; } -DPatch* DPatch::MergePatches( patch_merge_t merge_info, DPatch *p1, DPatch *p2 ){ +DPatch* DPatch::MergePatches( patch_merge_t merge_info, DPatch& p1, DPatch& p2 ){ while ( merge_info.pos1 != 2 ) { - p1->Transpose(); + p1.Transpose(); merge_info.pos1--; if ( merge_info.pos1 < 0 ) { merge_info.pos1 += 4; @@ -293,14 +293,14 @@ DPatch* DPatch::MergePatches( patch_merge_t merge_info, DPatch *p1, DPatch *p2 ) while ( merge_info.pos2 != 0 ) { - p2->Transpose(); + p2.Transpose(); merge_info.pos2--; if ( merge_info.pos2 < 0 ) { merge_info.pos2 += 3; } } - int newHeight = p1->height + p2->height - 1; + const int newHeight = p1.height + p2.height - 1; if ( newHeight > MAX_PATCH_HEIGHT ) { return 0; } @@ -308,16 +308,16 @@ DPatch* DPatch::MergePatches( patch_merge_t merge_info, DPatch *p1, DPatch *p2 ) DPatch* newPatch = new DPatch(); newPatch->height = newHeight; - newPatch->width = p1->width; - newPatch->SetTexture( p1->texture ); + newPatch->width = p1.width; + newPatch->SetTexture( p1.texture ); - for ( int y = 0; y < p1->height; y++ ) - for ( int x = 0; x < p1->width; x++ ) - newPatch->points[x][y] = p1->points[x][y]; + for ( int y = 0; y < p1.height; y++ ) + for ( int x = 0; x < p1.width; x++ ) + newPatch->points[x][y] = p1.points[x][y]; - for ( int y = 1; y < p2->height; y++ ) - for ( int x = 0; x < p2->width; x++ ) - newPatch->points[x][( y + p1->height - 1 )] = p2->points[x][y]; + for ( int y = 1; y < p2.height; y++ ) + for ( int x = 0; x < p2.width; x++ ) + newPatch->points[x][( y + p1.height - 1 )] = p2.points[x][y]; // newPatch->Invert(); return newPatch; @@ -375,7 +375,7 @@ void DPatch::Invert(){ */ void DPatch::Transpose(){ - int i, j, w; + int i, j; if ( width > height ) { for ( i = 0 ; i < height ; i++ ) @@ -413,9 +413,7 @@ void DPatch::Transpose(){ } } - w = width; - width = height; - height = w; + std::swap( width, height ); Invert(); } diff --git a/contrib/bobtoolz/DPatch.h b/contrib/bobtoolz/DPatch.h index 2319515d..d26e53f9 100644 --- a/contrib/bobtoolz/DPatch.h +++ b/contrib/bobtoolz/DPatch.h @@ -62,8 +62,8 @@ public: //DPatch* TransposePatch(DPatch* p1); //void DebugPrint(); void Invert(); - DPatch* MergePatches( patch_merge_t merge_info, DPatch* p1, DPatch* p2 ); - patch_merge_t IsMergable( DPatch* other ); + DPatch* MergePatches( patch_merge_t merge_info, DPatch& p1, DPatch& p2 ); + patch_merge_t IsMergable( const DPatch& other ); bool ResetTextures( const char *oldTextureName, const char *newTextureName ); scene::Node* QER_entity; scene::Node* QER_brush; diff --git a/contrib/bobtoolz/funchandlers-GTK.cpp b/contrib/bobtoolz/funchandlers-GTK.cpp index e5ec0d8e..9066315b 100644 --- a/contrib/bobtoolz/funchandlers-GTK.cpp +++ b/contrib/bobtoolz/funchandlers-GTK.cpp @@ -425,76 +425,78 @@ void DoPitBuilder(){ void DoMergePatches(){ UndoableCommand undo( "bobToolz.mergePatches" ); - patch_merge_t merge_info; - DPatch mrgPatches[2]; - int i; - // ensure we have something selected - if ( GlobalSelectionSystem().countSelected() != 2 ) { - globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose 2 only.\n"; - //DoMessageBox("Invalid number of patches selected, choose 2 only", "Error", eMB_OK); + class : public SelectionSystem::Visitor + { + public: + void visit( scene::Instance& instance ) const override { + if( Node_isPatch( instance.path().top() ) ){ + mrg.emplace_back().patch.LoadFromPatch( instance ); + mrg.back().instance = &instance; + } + } + struct data{ + DPatch patch; + scene::Instance* instance; + bool merged; + }; + mutable std::list mrg; + mutable std::vector instances_erase; + } patches; + + GlobalSelectionSystem().foreachSelected( patches ); + + if( patches.mrg.size() < 2 ){ + globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose 2 or more.\n"; return; } - scene::Instance* patches[2]; - patches[0] = &GlobalSelectionSystem().ultimateSelected(); - patches[1] = &GlobalSelectionSystem().penultimateSelected(); - - for ( i = 0; i < 2; i++ ) - { - if ( !Node_isPatch( patches[i]->path().top() ) ) { - //DoMessageBox("No patches selected, select ONLY patches", "Error", eMB_OK); - globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose ONLY 2 patches.\n"; - return; - } - - mrgPatches[i].LoadFromPatch( *patches[i] ); - } - - /* mrgPatches[0].Transpose(); - mrgPatches[0].RemoveFromRadiant(); - mrgPatches[0].BuildInRadiant();*/ - - merge_info = mrgPatches[0].IsMergable( &mrgPatches[1] ); - - if ( merge_info.mergable ) { -// globalOutputStream() << merge_info.pos1 << " " << merge_info.pos2; - //Message removed, No tools give feedback on success. - //globalOutputStream() << "bobToolz MergePatches: Patches Mergable.\n"; - DPatch* newPatch = mrgPatches[0].MergePatches( merge_info, &mrgPatches[0], &mrgPatches[1] ); - - /* mrgPatches[0].RemoveFromRadiant(); - mrgPatches[0].BuildInRadiant(); - - mrgPatches[1].RemoveFromRadiant(); - mrgPatches[1].BuildInRadiant(); - - - delete newPatch;*/ - - if ( !newPatch ) { - globalErrorStream() << "bobToolz.mergePatch: Merge result would exceed max patch rows.\n"; - } - else + const auto try_merge_one = [&patches](){ + for( auto one = patches.mrg.begin(); one != patches.mrg.end(); ++one ) { - newPatch->BuildInRadiant( patches[0]->path().parent().get_pointer() ); - - scene::Instance& parent = *( patches[1]->parent() ); - Path_deleteTop( patches[0]->path() ); - Path_deleteTop( patches[1]->path() ); - Entity* entity = Node_getEntity( parent.path().top() ); - if ( entity != 0 - && Node_getTraversable( parent.path().top() )->empty() ) { - Path_deleteTop( parent.path() ); + for( auto two = std::next( one ); two != patches.mrg.end(); ++two ) + { + patch_merge_t merge_info = one->patch.IsMergable( two->patch ); + if( merge_info.mergable ){ + DPatch* newPatch = one->patch.MergePatches( merge_info, one->patch, two->patch ); + if( newPatch != nullptr ){ + one->merged = true; + one->patch = *newPatch; + delete newPatch; + patches.instances_erase.push_back( two->instance ); + patches.mrg.erase( two ); + return true; + } + } } + } + return false; + }; - delete newPatch; + while( try_merge_one() ){}; /* merge one by one for the sake of holy laziness */ + + if( patches.instances_erase.empty() ){ + globalErrorStream() << "bobToolz.mergePatch: The selected patches are not mergable.\n"; + return; + } + + for( auto&& mrg : patches.mrg ) + { + if( mrg.merged ){ + mrg.patch.BuildInRadiant( mrg.instance->path().parent().get_pointer() ); + Path_deleteTop( mrg.instance->path() ); } } - else - { - globalErrorStream() << "bobToolz.mergePatch: The selected patches are not mergable.\n"; + for( auto instance : patches.instances_erase ) + { + scene::Instance* parent = instance->parent(); + Path_deleteTop( instance->path() ); + /* don't leave empty entities */ + if( Node_isEntity( parent->path().top() ) + && Node_getTraversable( parent->path().top() )->empty() ){ + Path_deleteTop( parent->path() ); + } } }