* bobToolz.mergePatch: bruteforce merge all selected patches; keep unaffected patches selected

This commit is contained in:
Garux 2021-10-21 22:39:35 +03:00
parent 03d3dfccad
commit 3362f29500
3 changed files with 91 additions and 91 deletions

View File

@ -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();
}

View File

@ -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;

View File

@ -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<data> mrg;
mutable std::vector<scene::Instance*> 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() );
}
}
}