<commit_before>// @(#)root/base:$Name:  $:$Id: TBits.cxx,v 1.11 2003/02/11 20:25:08 brun Exp $
// Author: Philippe Canal 05/02/2001
//    Feb  5 2001: Creation
//    Feb  6 2001: Changed all int to unsigned int.
//______________________________________________________________________________

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBits                                                                //
//                                                                      //
// Container of bits                                                    //
//                                                                      //
// This class provides a simple container of bits.                      //
// Each bit can be set and tested via the functions SetBitNumber and    //
// TestBitNumber.                                             .         //
// The default value of all bits is kFALSE.                             //
// The size of the container is automatically extended when a bit       //
// number is either set or tested.  To reduce the memory size of the    //
// container use the Compact function, this will discard the memory     //
// occupied by the upper bits that are 0.                               //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBits.h"
#include "string.h"

ClassImp(TBits)

//______________________________________________________________________________
TBits::TBits(UInt_t nbits) : fNbits(nbits)
{
   // TBits constructor.  All bits set to 0

   if (nbits <= 0) nbits = 8;
   fNbytes  = ((nbits-1)/8) + 1;
   fAllBits = new UChar_t[fNbytes];
   // this is redundant only with libNew
   memset(fAllBits,0,fNbytes);
}

//______________________________________________________________________________
TBits::TBits(const TBits &original) : TObject(original), fNbits(original.fNbits),
   fNbytes(original.fNbytes)
{
   // TBits copy constructor

   fAllBits = new UChar_t[fNbytes];
   memcpy(fAllBits,original.fAllBits,fNbytes);

}

//______________________________________________________________________________
TBits& TBits::operator=(const TBits& rhs)
{
   // TBits assignment operator

   if (this != &rhs) {
      TObject::operator=(rhs);
      fNbits   = rhs.fNbits;
      fNbytes  = rhs.fNbytes;
      delete [] fAllBits;
      fAllBits = new UChar_t[fNbytes];
      memcpy(fAllBits,rhs.fAllBits,fNbytes);
   }
   return *this;
}

//______________________________________________________________________________
TBits::~TBits()
{
   // TBits destructor

   delete [] fAllBits;
}

//______________________________________________________________________________
void TBits::Clear(Option_t * /*option*/)
{
   delete [] fAllBits;
   fAllBits = 0;
}

//______________________________________________________________________________
void TBits::Compact()
{
   // Reduce the storage used by the object to a minimun

   UInt_t needed;
   for(needed=fNbytes-1;
       needed > 0 && fAllBits[needed]==0; ) { needed--; };
   needed++;

   if (needed!=fNbytes) {
      UChar_t *old_location = fAllBits;
      fAllBits = new UChar_t[needed];

      memcpy(fAllBits,old_location,needed);
      delete [] old_location;

      fNbytes = needed;
      fNbits = 8*fNbytes;
   }
}

//______________________________________________________________________________
UInt_t TBits::CountBits(UInt_t startBit) const
{
   // Return number of bits set to 1 starting at bit startBit

   const Int_t nbits[256] = {
             0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
             1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
             1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
             1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
             3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
             4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};

   UInt_t i,count = 0;
   if (startBit == 0) {
      for(i=0; i<fNbytes; i++) {
         count += nbits[fAllBits[i]];
      }
      return count;
   }
   if (startBit >= fNbits) return count;
   UInt_t startByte = startBit/8;
   UInt_t ibit = startBit%8;
   if (ibit) {
      for (i=ibit;i<8;i++) {
         if (fAllBits[startByte] & (1<<ibit)) count++;
      }
      startByte++;
   }
   for(i=startByte; i<fNbytes; i++) {
      count += nbits[fAllBits[i]];
   }
   return count;
}

//______________________________________________________________________________
UInt_t TBits::FirstNullBit(UInt_t startBit) const
{
   // Return position of first null bit

   const Int_t fbits[256] = {
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8};

   UInt_t i;
   if (startBit == 0) {
      for(UInt_t i=0; i<fNbytes; i++) {
         if (fAllBits[i] != 255) return 8*i + fbits[fAllBits[i]];
      }
      return fNbits;
   }
   if (startBit >= fNbits) return fNbits;
   UInt_t startByte = startBit/8;
   UInt_t ibit = startBit%8;
   if (ibit) {
      for (i=ibit;i<8;i++) {
         if ((fAllBits[startByte] & (1<<i)) == 0) return 8*startByte+i;
      }
      startByte++;
   }
   for(i=startByte; i<fNbytes; i++) {
      if (fAllBits[i] != 255) return 8*i + fbits[fAllBits[i]];
   }
   return fNbits;
}

//______________________________________________________________________________
UInt_t TBits::FirstSetBit(UInt_t startBit) const
{
   // Return position of first non null bit

   const Int_t fbits[256] = {
             8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};

   UInt_t i;
   if (startBit == 0) {
      for(UInt_t i=0; i<fNbytes; i++) {
         if (fAllBits[i] != 0) return 8*i + fbits[fAllBits[i]];
      }
      return fNbits;
   }
   if (startBit >= fNbits) return fNbits;
   UInt_t startByte = startBit/8;
   UInt_t ibit = startBit%8;
   if (ibit) {
      for (i=ibit;i<8;i++) {
         if ((fAllBits[startByte] & (1<<i)) != 0) return 8*startByte+i;
      }
      startByte++;
   }
   for(i=startByte; i<fNbytes; i++) {
      if (fAllBits[i] != 0) return 8*i + fbits[fAllBits[i]];
   }
   return fNbits;
}

//______________________________________________________________________________
void TBits::Paint(Option_t *)
{
   // Once implemented, it will draw the bit field as an histogram.
   // use the TVirtualPainter as the usual trick

}

//______________________________________________________________________________
void TBits::Print(Option_t *) const
{
   // Print the list of active bits

   Int_t count = 0;
   for(UInt_t i=0; i<fNbytes; i++) {
      UChar_t val = fAllBits[i];
      for (UInt_t j=0; j<8; j++) {
         if (val & 1) printf(" bit:%4d = 1\n",count);
         count++;
         val = val >> 1;
      }
   }
}

//______________________________________________________________________________
void TBits::ResetAllBits(Bool_t)
{
   // Reset all bits to 0 (false).

   memset(fAllBits,0,fNbytes);
}

//______________________________________________________________________________
void TBits::SetBitNumber(UInt_t bitnumber, Bool_t value)
{
   // Set bit number 'bitnumber' to be value

   if (bitnumber >= fNbits) {
      UInt_t new_size = (bitnumber/8) + 1;
      if (new_size > fNbytes) {
         UChar_t *old_location = fAllBits;
         fAllBits = new UChar_t[new_size];
         memcpy(fAllBits,old_location,fNbytes);
         memset(fAllBits+fNbytes ,0, new_size-fNbytes);
         fNbytes = new_size;
         delete [] old_location;
      }
      fNbits = bitnumber+1;
   }
   UInt_t  loc = bitnumber/8;
   UChar_t bit = bitnumber%8;
   if (value)
      fAllBits[loc] |= (1<<bit);
   else
      fAllBits[loc] &= (0xFF ^ (1<<bit));
}

//______________________________________________________________________________
Bool_t TBits::TestBitNumber(UInt_t bitnumber) const
{
   // Return the current value of the bit

   if (bitnumber >= fNbits) return kFALSE;
   UInt_t  loc = bitnumber/8;
   UChar_t value = fAllBits[loc];
   UChar_t bit = bitnumber%8;
   Bool_t  result = (value & (1<<bit)) != 0;
   return result;
   // short: return 0 != (fAllBits[bitnumber/8] & (1<< (bitnumber%8)));
}

<commit_msg>Add a few protections such that the object can be reused after TBits::Clear. TBits::Clear sets fNbits and fNbytes to 0.<commit_after>// @(#)root/base:$Name:  $:$Id: TBits.cxx,v 1.12 2004/01/06 08:27:33 brun Exp $
// Author: Philippe Canal 05/02/2001
//    Feb  5 2001: Creation
//    Feb  6 2001: Changed all int to unsigned int.
//______________________________________________________________________________

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBits                                                                //
//                                                                      //
// Container of bits                                                    //
//                                                                      //
// This class provides a simple container of bits.                      //
// Each bit can be set and tested via the functions SetBitNumber and    //
// TestBitNumber.                                             .         //
// The default value of all bits is kFALSE.                             //
// The size of the container is automatically extended when a bit       //
// number is either set or tested.  To reduce the memory size of the    //
// container use the Compact function, this will discard the memory     //
// occupied by the upper bits that are 0.                               //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TBits.h"
#include "string.h"

ClassImp(TBits)

//______________________________________________________________________________
TBits::TBits(UInt_t nbits) : fNbits(nbits)
{
   // TBits constructor.  All bits set to 0

   if (nbits <= 0) nbits = 8;
   fNbytes  = ((nbits-1)/8) + 1;
   fAllBits = new UChar_t[fNbytes];
   // this is redundant only with libNew
   memset(fAllBits,0,fNbytes);
}

//______________________________________________________________________________
TBits::TBits(const TBits &original) : TObject(original), fNbits(original.fNbits),
   fNbytes(original.fNbytes)
{
   // TBits copy constructor

   fAllBits = new UChar_t[fNbytes];
   memcpy(fAllBits,original.fAllBits,fNbytes);

}

//______________________________________________________________________________
TBits& TBits::operator=(const TBits& rhs)
{
   // TBits assignment operator

   if (this != &rhs) {
      TObject::operator=(rhs);
      fNbits   = rhs.fNbits;
      fNbytes  = rhs.fNbytes;
      delete [] fAllBits;
      fAllBits = new UChar_t[fNbytes];
      memcpy(fAllBits,rhs.fAllBits,fNbytes);
   }
   return *this;
}

//______________________________________________________________________________
TBits::~TBits()
{
   // TBits destructor

   delete [] fAllBits;
}

//______________________________________________________________________________
void TBits::Clear(Option_t * /*option*/)
{
   delete [] fAllBits;
   fAllBits = 0;
   fNbits   = 0;
   fNbytes  = 0;
}

//______________________________________________________________________________
void TBits::Compact()
{
   // Reduce the storage used by the object to a minimun

   if (!fNbits || !fAllBits) return;
   UInt_t needed;
   for(needed=fNbytes-1;
       needed > 0 && fAllBits[needed]==0; ) { needed--; };
   needed++;

   if (needed!=fNbytes) {
      UChar_t *old_location = fAllBits;
      fAllBits = new UChar_t[needed];

      memcpy(fAllBits,old_location,needed);
      delete [] old_location;

      fNbytes = needed;
      fNbits = 8*fNbytes;
   }
}

//______________________________________________________________________________
UInt_t TBits::CountBits(UInt_t startBit) const
{
   // Return number of bits set to 1 starting at bit startBit

   const Int_t nbits[256] = {
             0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
             1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
             1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
             1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
             2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
             3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
             3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
             4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};

   UInt_t i,count = 0;
   if (startBit == 0) {
      for(i=0; i<fNbytes; i++) {
         count += nbits[fAllBits[i]];
      }
      return count;
   }
   if (startBit >= fNbits) return count;
   UInt_t startByte = startBit/8;
   UInt_t ibit = startBit%8;
   if (ibit) {
      for (i=ibit;i<8;i++) {
         if (fAllBits[startByte] & (1<<ibit)) count++;
      }
      startByte++;
   }
   for(i=startByte; i<fNbytes; i++) {
      count += nbits[fAllBits[i]];
   }
   return count;
}

//______________________________________________________________________________
UInt_t TBits::FirstNullBit(UInt_t startBit) const
{
   // Return position of first null bit

   const Int_t fbits[256] = {
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,
             0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8};

   UInt_t i;
   if (startBit == 0) {
      for(UInt_t i=0; i<fNbytes; i++) {
         if (fAllBits[i] != 255) return 8*i + fbits[fAllBits[i]];
      }
      return fNbits;
   }
   if (startBit >= fNbits) return fNbits;
   UInt_t startByte = startBit/8;
   UInt_t ibit = startBit%8;
   if (ibit) {
      for (i=ibit;i<8;i++) {
         if ((fAllBits[startByte] & (1<<i)) == 0) return 8*startByte+i;
      }
      startByte++;
   }
   for(i=startByte; i<fNbytes; i++) {
      if (fAllBits[i] != 255) return 8*i + fbits[fAllBits[i]];
   }
   return fNbits;
}

//______________________________________________________________________________
UInt_t TBits::FirstSetBit(UInt_t startBit) const
{
   // Return position of first non null bit

   const Int_t fbits[256] = {
             8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
             4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};

   UInt_t i;
   if (startBit == 0) {
      for(UInt_t i=0; i<fNbytes; i++) {
         if (fAllBits[i] != 0) return 8*i + fbits[fAllBits[i]];
      }
      return fNbits;
   }
   if (startBit >= fNbits) return fNbits;
   UInt_t startByte = startBit/8;
   UInt_t ibit = startBit%8;
   if (ibit) {
      for (i=ibit;i<8;i++) {
         if ((fAllBits[startByte] & (1<<i)) != 0) return 8*startByte+i;
      }
      startByte++;
   }
   for(i=startByte; i<fNbytes; i++) {
      if (fAllBits[i] != 0) return 8*i + fbits[fAllBits[i]];
   }
   return fNbits;
}

//______________________________________________________________________________
void TBits::Paint(Option_t *)
{
   // Once implemented, it will draw the bit field as an histogram.
   // use the TVirtualPainter as the usual trick

}

//______________________________________________________________________________
void TBits::Print(Option_t *) const
{
   // Print the list of active bits

   Int_t count = 0;
   for(UInt_t i=0; i<fNbytes; i++) {
      UChar_t val = fAllBits[i];
      for (UInt_t j=0; j<8; j++) {
         if (val & 1) printf(" bit:%4d = 1\n",count);
         count++;
         val = val >> 1;
      }
   }
}

//______________________________________________________________________________
void TBits::ResetAllBits(Bool_t)
{
   // Reset all bits to 0 (false).

   if (fAllBits) memset(fAllBits,0,fNbytes);
}

//______________________________________________________________________________
void TBits::SetBitNumber(UInt_t bitnumber, Bool_t value)
{
   // Set bit number 'bitnumber' to be value

   if (bitnumber >= fNbits) {
      UInt_t new_size = (bitnumber/8) + 1;
      if (new_size > fNbytes) {
         UChar_t *old_location = fAllBits;
         fAllBits = new UChar_t[new_size];
         if (old_location) {
            memcpy(fAllBits,old_location,fNbytes);
            delete [] old_location;
         }
         memset(fAllBits+fNbytes ,0, new_size-fNbytes);
         fNbytes = new_size;
      }
      fNbits = bitnumber+1;
   }
   UInt_t  loc = bitnumber/8;
   UChar_t bit = bitnumber%8;
   if (value)
      fAllBits[loc] |= (1<<bit);
   else
      fAllBits[loc] &= (0xFF ^ (1<<bit));
}

//______________________________________________________________________________
Bool_t TBits::TestBitNumber(UInt_t bitnumber) const
{
   // Return the current value of the bit

   if (bitnumber >= fNbits) return kFALSE;
   UInt_t  loc = bitnumber/8;
   UChar_t value = fAllBits[loc];
   UChar_t bit = bitnumber%8;
   Bool_t  result = (value & (1<<bit)) != 0;
   return result;
   // short: return 0 != (fAllBits[bitnumber/8] & (1<< (bitnumber%8)));
}

<|endoftext|>


<commit_before>#include "ResourceView.hpp"

#include <Engine/Geometry/Model.hpp>
#include <Engine/Texture/TextureAsset.hpp>
#include <Engine/Audio/SoundBuffer.hpp>
#include <Engine/Script/ScriptFile.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <Editor/Util/EditorSettings.hpp>
#include <Engine/Hymn.hpp>
#include <DefaultAlbedo.png.hpp>
#include <Engine/MainWindow.hpp>
#include <imgui.h>
#include <limits>
#include "../ImGui/Splitter.hpp"
#include "../Resources.hpp"
#include <Engine/Manager/Managers.hpp>
#include <Engine/Manager/ResourceManager.hpp>
#include <cstdio>
#include <Utility/Log.hpp>

using namespace GUI;
using namespace std;

ResourceView::ResourceView() {
    savePromptWindow.SetTitle("Save before you switch scene?");
    savePromptWindow.ResetDecision();
}

void ResourceView::Show() {
    ImVec2 size(MainWindow::GetInstance()->GetSize().x, MainWindow::GetInstance()->GetSize().y);

    // Splitter.
    ImGui::VerticalSplitter(ImVec2(sceneWidth, size.y - resourceHeight), size.x - sceneWidth - editorWidth, splitterSize, resourceHeight, resourceResize, 20, size.y - 20);
    if (resourceResize)
        resourceHeight = size.y - resourceHeight;

    ImGui::SetNextWindowPos(ImVec2(sceneWidth, size.y - resourceHeight));
    ImGui::SetNextWindowSize(ImVec2(size.x - sceneWidth - editorWidth, resourceHeight));

    ImGui::Begin("Resources", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_ShowBorders);

    // Scenes.
    if (ImGui::TreeNode("Scenes")) {
        if (ImGui::Button("Add scene"))
            Resources().scenes.push_back("Scene #" + std::to_string(Resources().scenes.size()));

        for (std::size_t i = 0; i < Resources().scenes.size(); ++i) {
            if (ImGui::Selectable(Resources().scenes[i].c_str())) {
                // Sets to dont save when opening first scene.
                if (sceneIndex == -1) {
                    changeScene = true;
                    sceneIndex = i;
                    savePromptWindow.SetVisible(false);
                    savePromptWindow.SetDecision(1);
                } else {
                    // Does so that the prompt window wont show if you select active scene.
                    if (Resources().scenes[i] != Resources().scenes[Resources().activeScene]) {
                        changeScene = true;
                        sceneIndex = i;
                    }
                }
            }

            if (ImGui::BeginPopupContextItem(Resources().scenes[i].c_str())) {
                if (ImGui::Selectable("Delete")) {
                    Resources().scenes.erase(Resources().scenes.begin() + i);
                    ImGui::EndPopup();

                    if (Resources().activeScene >= i) {
                        if (Resources().activeScene > 0)
                            Resources().activeScene = Resources().activeScene - 1;

                        sceneEditor.SetScene(Resources().activeScene);
                    }
                    break;
                }
                ImGui::EndPopup();
            }
        }
        ImGui::TreePop();
        if (changeScene) {

            if (Hymn().GetPath() != "") {

                if (!HasMadeChanges()) {

                    SwitchScene(sceneIndex);

                }
                else {

                    savePromptWindow.SetVisible(true);
                    savePromptWindow.ResetDecision();
                    savePromptWindow.Show();

                    switch (savePromptWindow.GetDecision())
                    {
                    case 0:
                        sceneEditor.Save();
                        SwitchScene(sceneIndex);
                        break;

                    case 1:
                        SwitchScene(sceneIndex);
                        break;

                    case 2:
                        changeScene = false;
                        savePromptWindow.ResetDecision();
                        savePromptWindow.SetVisible(false);
                        break;

                    default:
                        break;

                    }
                }
            }
        }
    }

    // Models.
    bool modelPressed = false;
    if (ImGui::TreeNode("Models")) {
        if (ImGui::Button("Add model")) {
            Geometry::Model* model = new Geometry::Model();
            model->name = "Model #" + std::to_string(Resources().modelNumber++);
            Resources().models.push_back(model);
        }

        for (auto it = Resources().models.begin(); it != Resources().models.end(); ++it) {
            Geometry::Model* model = *it;
            if (ImGui::Selectable(model->name.c_str())) {
                modelPressed = true;
                modelEditor.SetModel(model);
            }

            if (ImGui::BeginPopupContextItem(model->name.c_str())) {
                if (ImGui::Selectable("Delete")) {
                    if (modelEditor.GetModel() == model)
                        modelEditor.SetVisible(false);

                    delete model;
                    Resources().models.erase(it);
                    ImGui::EndPopup();
                    break;
                }
                ImGui::EndPopup();
            }
        }
        ImGui::TreePop();
    }

    // Textures.
    bool texturePressed = false;
    if (ImGui::TreeNode("Textures")) {
        if (ImGui::Button("Add texture")) {
            TextureAsset* texture = new TextureAsset();
            texture->name = "Texture #" + std::to_string(Resources().textureNumber++);
            Resources().textures.push_back(texture);
        }

        for (auto it = Resources().textures.begin(); it != Resources().textures.end(); ++it) {
            TextureAsset* texture = *it;
            if (ImGui::Selectable(texture->name.c_str())) {
                texturePressed = true;
                textureEditor.SetTexture(texture);
            }

            if (ImGui::BeginPopupContextItem(texture->name.c_str())) {
                if (ImGui::Selectable("Delete")) {
                    if (Managers().resourceManager->GetTextureAssetInstanceCount(texture) > 1) {
                        Log() << "This texture is in use. Remove all references to the texture first.\n";
                    } else {
                        if (textureEditor.GetTexture() == texture)
                            textureEditor.SetVisible(false);

                        // Remove files.
                        remove((Hymn().GetPath() + FileSystem::DELIMITER + "Textures" + FileSystem::DELIMITER + texture->name + ".png").c_str());
                        remove((Hymn().GetPath() + FileSystem::DELIMITER + "Textures" + FileSystem::DELIMITER + texture->name + ".json").c_str());

                        Managers().resourceManager->FreeTextureAsset(texture);
                        Resources().textures.erase(it);
                    }
                    ImGui::EndPopup();
                    break;
                }
                ImGui::EndPopup();
            }
        }

        ImGui::TreePop();
    }

    // Scripts.
    bool scriptPressed = false;
    if (ImGui::TreeNode("Scripts")) {
        if (ImGui::Button("Add script")) {
            ScriptFile* scriptFile = new ScriptFile();
            scriptFile->name = "Script #" + std::to_string(Hymn().scriptNumber++);
            Hymn().scripts.push_back(scriptFile);
        }

        for (auto it = Hymn().scripts.begin(); it != Hymn().scripts.end(); ++it) {
            ScriptFile* script = *it;
            std::string name = script->name;

            if (ImGui::Selectable(name.c_str())) {
                scriptPressed = true;
                scriptEditor.SetScript(script);
            }

            if (ImGui::BeginPopupContextItem(name.c_str())) {
                if (ImGui::Selectable("Delete")) {
                    if (scriptEditor.GetScript() == script)
                        scriptEditor.SetVisible(false);

                    delete script;
                    Hymn().scripts.erase(it);
                    ImGui::EndPopup();
                    break;
                }
                ImGui::EndPopup();
            }
        }

        ImGui::TreePop();
    }

    // Sounds.
    bool soundPressed = false;
    if (ImGui::TreeNode("Sounds")) {
        if (ImGui::Button("Add sound")) {
            Audio::SoundBuffer* sound = new Audio::SoundBuffer();
            sound->name = "Sound #" + std::to_string(Resources().soundNumber++);
            Resources().sounds.push_back(sound);
        }

        for (auto it = Resources().sounds.begin(); it != Resources().sounds.end(); ++it) {
            Audio::SoundBuffer* sound = *it;
            if (ImGui::Selectable(sound->name.c_str())) {
                soundPressed = true;
                soundEditor.SetSound(sound);
            }

            if (ImGui::BeginPopupContextItem(sound->name.c_str())) {
                if (ImGui::Selectable("Delete")) {
                    if (soundEditor.GetSound() == sound)
                        soundEditor.SetVisible(false);

                    delete sound;
                    Resources().sounds.erase(it);
                    ImGui::EndPopup();
                    break;
                }
                ImGui::EndPopup();
            }
        }

        ImGui::TreePop();
    }

    if (sceneEditor.entityPressed || scriptPressed || texturePressed || modelPressed || soundPressed) {
        sceneEditor.entityEditor.SetVisible(sceneEditor.entityPressed);
        scriptEditor.SetVisible(scriptPressed);
        textureEditor.SetVisible(texturePressed);
        modelEditor.SetVisible(modelPressed);
        soundEditor.SetVisible(soundPressed);
    }

    if (sceneEditor.IsVisible()) {
        ImGui::HorizontalSplitter(ImVec2(sceneWidth, 20), size.y - 20, splitterSize, sceneWidth, sceneResize, 20, size.x - editorWidth - 20);
        ImGui::SetNextWindowPos(ImVec2(0, 20));
        ImGui::SetNextWindowSize(ImVec2(sceneWidth, size.y - 20));
        sceneEditor.Show();
    }

    if (sceneEditor.entityEditor.IsVisible() || scriptEditor.IsVisible() || textureEditor.IsVisible() || modelEditor.IsVisible() || soundEditor.IsVisible()) {
        editorWidth = size.x - editorWidth;
        ImGui::HorizontalSplitter(ImVec2(editorWidth, 20), size.y - 20, splitterSize, editorWidth, editorResize, sceneWidth + 20, size.x - 20);
        editorWidth = size.x - editorWidth;

        ImGui::SetNextWindowPos(ImVec2(size.x - editorWidth, 20));
        ImGui::SetNextWindowSize(ImVec2(editorWidth, size.y - 20));
    }

    if (sceneEditor.entityEditor.IsVisible())
        sceneEditor.entityEditor.Show();
    if (scriptEditor.IsVisible())
        scriptEditor.Show();
    if (textureEditor.IsVisible())
        textureEditor.Show();
    if (modelEditor.IsVisible())
        modelEditor.Show();
    if (soundEditor.IsVisible())
        soundEditor.Show();

    ImGui::End();
}

bool ResourceView::HasMadeChanges() const{

    std::string* sceneFilename = new std::string();
    Json::Value sceneJson = sceneEditor.GetSaveFileJson(sceneFilename);

    // Load Json document from file.
    Json::Value reference;
    std::ifstream file(*sceneFilename);

    if (!file.good())
        return true;

    file >> reference;
    file.close();

    std::string hymnJsonString = sceneJson.toStyledString();
    std::string referenceString = reference.toStyledString();

    int response = referenceString.compare(hymnJsonString);
    if (response != 0)
        return true;

    return false;

}

bool ResourceView::IsVisible() const {
    return visible;
}

void ResourceView::SetVisible(bool visible) {
    this->visible = visible;
}

void ResourceView::HideEditors() {
    sceneEditor.SetVisible(false);
    sceneEditor.entityEditor.SetVisible(false);
    scriptEditor.SetVisible(false);
    modelEditor.SetVisible(false);
    textureEditor.SetVisible(false);
    soundEditor.SetVisible(false);
}

void ResourceView::SaveScene() const {
    sceneEditor.Save();
}

Json::Value ResourceView::GetSceneJson(std::string* filename) const {
    return sceneEditor.GetSaveFileJson(filename);
}

void ResourceView::SwitchScene(int index) {

    sceneEditor.SetVisible(true);
    sceneEditor.SetScene(index);
    Resources().activeScene = index;
    sceneEditor.entityEditor.SetVisible(false);
    Hymn().world.Clear();
    Hymn().world.Load(Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + Resources().scenes[index] + ".json");
    changeScene = false;
    savePromptWindow.SetVisible(false);
    savePromptWindow.ResetDecision();

}

#undef max
void ResourceView::ResetScene() {
    sceneEditor.SetScene(std::numeric_limits<std::size_t>::max());
    sceneEditor.SetVisible(false);
}

SceneEditor& ResourceView::GetScene() {
    return sceneEditor;
}
<commit_msg>Added comment.<commit_after>#include "ResourceView.hpp"

#include <Engine/Geometry/Model.hpp>
#include <Engine/Texture/TextureAsset.hpp>
#include <Engine/Audio/SoundBuffer.hpp>
#include <Engine/Script/ScriptFile.hpp>
#include <Engine/Util/FileSystem.hpp>
#include <Editor/Util/EditorSettings.hpp>
#include <Engine/Hymn.hpp>
#include <DefaultAlbedo.png.hpp>
#include <Engine/MainWindow.hpp>
#include <imgui.h>
#include <limits>
#include "../ImGui/Splitter.hpp"
#include "../Resources.hpp"
#include <Engine/Manager/Managers.hpp>
#include <Engine/Manager/ResourceManager.hpp>
#include <cstdio>
#include <Utility/Log.hpp>

using namespace GUI;
using namespace std;

ResourceView::ResourceView() {
    savePromptWindow.SetTitle("Save before you switch scene?");
    savePromptWindow.ResetDecision();
}

void ResourceView::Show() {
    ImVec2 size(MainWindow::GetInstance()->GetSize().x, MainWindow::GetInstance()->GetSize().y);

    // Splitter.
    ImGui::VerticalSplitter(ImVec2(sceneWidth, size.y - resourceHeight), size.x - sceneWidth - editorWidth, splitterSize, resourceHeight, resourceResize, 20, size.y - 20);
    if (resourceResize)
        resourceHeight = size.y - resourceHeight;

    ImGui::SetNextWindowPos(ImVec2(sceneWidth, size.y - resourceHeight));
    ImGui::SetNextWindowSize(ImVec2(size.x - sceneWidth - editorWidth, resourceHeight));

    ImGui::Begin("Resources", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_ShowBorders);

    // Scenes.
    if (ImGui::TreeNode("Scenes")) {
        if (ImGui::Button("Add scene"))
            Resources().scenes.push_back("Scene #" + std::to_string(Resources().scenes.size()));

        for (std::size_t i = 0; i < Resources().scenes.size(); ++i) {
            if (ImGui::Selectable(Resources().scenes[i].c_str())) {
                // Sets to dont save when opening first scene.
                if (sceneIndex == -1) {
                    changeScene = true;
                    sceneIndex = i;
                    savePromptWindow.SetVisible(false);
                    savePromptWindow.SetDecision(1);
                } else {
                    // Does so that the prompt window wont show if you select active scene.
                    if (Resources().scenes[i] != Resources().scenes[Resources().activeScene]) {
                        changeScene = true;
                        sceneIndex = i;
                    }
                }
            }

            if (ImGui::BeginPopupContextItem(Resources().scenes[i].c_str())) {
                if (ImGui::Selectable("Delete")) {
                    Resources().scenes.erase(Resources().scenes.begin() + i);
                    ImGui::EndPopup();

                    if (Resources().activeScene >= i) {
                        if (Resources().activeScene > 0)
                            Resources().activeScene = Resources().activeScene - 1;

                        sceneEditor.SetScene(Resources().activeScene);
                    }
                    break;
                }
                ImGui::EndPopup();
            }
        }
        ImGui::TreePop();
        if (changeScene) {

            if (Hymn().GetPath() != "") {

                if (!HasMadeChanges()) {

                    SwitchScene(sceneIndex);

                }
                else {

                    savePromptWindow.SetVisible(true);
                    savePromptWindow.ResetDecision();
                    savePromptWindow.Show();

                    switch (savePromptWindow.GetDecision())
                    {
                    case 0:
                        sceneEditor.Save();
                        SwitchScene(sceneIndex);
                        break;

                    case 1:
                        SwitchScene(sceneIndex);
                        break;

                    case 2:
                        changeScene = false;
                        savePromptWindow.ResetDecision();
                        savePromptWindow.SetVisible(false);
                        break;

                    default:
                        break;

                    }
                }
            }
        }
    }

    // Models.
    bool modelPressed = false;
    if (ImGui::TreeNode("Models")) {
        if (ImGui::Button("Add model")) {
            Geometry::Model* model = new Geometry::Model();
            model->name = "Model #" + std::to_string(Resources().modelNumber++);
            Resources().models.push_back(model);
        }

        for (auto it = Resources().models.begin(); it != Resources().models.end(); ++it) {
            Geometry::Model* model = *it;
            if (ImGui::Selectable(model->name.c_str())) {
                modelPressed = true;
                modelEditor.SetModel(model);
            }

            if (ImGui::BeginPopupContextItem(model->name.c_str())) {
                if (ImGui::Selectable("Delete")) {
                    if (modelEditor.GetModel() == model)
                        modelEditor.SetVisible(false);

                    delete model;
                    Resources().models.erase(it);
                    ImGui::EndPopup();
                    break;
                }
                ImGui::EndPopup();
            }
        }
        ImGui::TreePop();
    }

    // Textures.
    bool texturePressed = false;
    if (ImGui::TreeNode("Textures")) {
        if (ImGui::Button("Add texture")) {
            TextureAsset* texture = new TextureAsset();
            texture->name = "Texture #" + std::to_string(Resources().textureNumber++);
            Resources().textures.push_back(texture);
        }

        for (auto it = Resources().textures.begin(); it != Resources().textures.end(); ++it) {
            TextureAsset* texture = *it;
            if (ImGui::Selectable(texture->name.c_str())) {
                texturePressed = true;
                textureEditor.SetTexture(texture);
            }

            if (ImGui::BeginPopupContextItem(texture->name.c_str())) {
                if (ImGui::Selectable("Delete")) {
                    if (Managers().resourceManager->GetTextureAssetInstanceCount(texture) > 1) {
                        Log() << "This texture is in use. Remove all references to the texture first.\n";
                    } else {
                        if (textureEditor.GetTexture() == texture)
                            textureEditor.SetVisible(false);

                        // Remove files.
                        remove((Hymn().GetPath() + FileSystem::DELIMITER + "Textures" + FileSystem::DELIMITER + texture->name + ".png").c_str());

                        // Remove meta file
                        remove((Hymn().GetPath() + FileSystem::DELIMITER + "Textures" + FileSystem::DELIMITER + texture->name + ".json").c_str());

                        Managers().resourceManager->FreeTextureAsset(texture);
                        Resources().textures.erase(it);
                    }
                    ImGui::EndPopup();
                    break;
                }
                ImGui::EndPopup();
            }
        }

        ImGui::TreePop();
    }

    // Scripts.
    bool scriptPressed = false;
    if (ImGui::TreeNode("Scripts")) {
        if (ImGui::Button("Add script")) {
            ScriptFile* scriptFile = new ScriptFile();
            scriptFile->name = "Script #" + std::to_string(Hymn().scriptNumber++);
            Hymn().scripts.push_back(scriptFile);
        }

        for (auto it = Hymn().scripts.begin(); it != Hymn().scripts.end(); ++it) {
            ScriptFile* script = *it;
            std::string name = script->name;

            if (ImGui::Selectable(name.c_str())) {
                scriptPressed = true;
                scriptEditor.SetScript(script);
            }

            if (ImGui::BeginPopupContextItem(name.c_str())) {
                if (ImGui::Selectable("Delete")) {
                    if (scriptEditor.GetScript() == script)
                        scriptEditor.SetVisible(false);

                    delete script;
                    Hymn().scripts.erase(it);
                    ImGui::EndPopup();
                    break;
                }
                ImGui::EndPopup();
            }
        }

        ImGui::TreePop();
    }

    // Sounds.
    bool soundPressed = false;
    if (ImGui::TreeNode("Sounds")) {
        if (ImGui::Button("Add sound")) {
            Audio::SoundBuffer* sound = new Audio::SoundBuffer();
            sound->name = "Sound #" + std::to_string(Resources().soundNumber++);
            Resources().sounds.push_back(sound);
        }

        for (auto it = Resources().sounds.begin(); it != Resources().sounds.end(); ++it) {
            Audio::SoundBuffer* sound = *it;
            if (ImGui::Selectable(sound->name.c_str())) {
                soundPressed = true;
                soundEditor.SetSound(sound);
            }

            if (ImGui::BeginPopupContextItem(sound->name.c_str())) {
                if (ImGui::Selectable("Delete")) {
                    if (soundEditor.GetSound() == sound)
                        soundEditor.SetVisible(false);

                    delete sound;
                    Resources().sounds.erase(it);
                    ImGui::EndPopup();
                    break;
                }
                ImGui::EndPopup();
            }
        }

        ImGui::TreePop();
    }

    if (sceneEditor.entityPressed || scriptPressed || texturePressed || modelPressed || soundPressed) {
        sceneEditor.entityEditor.SetVisible(sceneEditor.entityPressed);
        scriptEditor.SetVisible(scriptPressed);
        textureEditor.SetVisible(texturePressed);
        modelEditor.SetVisible(modelPressed);
        soundEditor.SetVisible(soundPressed);
    }

    if (sceneEditor.IsVisible()) {
        ImGui::HorizontalSplitter(ImVec2(sceneWidth, 20), size.y - 20, splitterSize, sceneWidth, sceneResize, 20, size.x - editorWidth - 20);
        ImGui::SetNextWindowPos(ImVec2(0, 20));
        ImGui::SetNextWindowSize(ImVec2(sceneWidth, size.y - 20));
        sceneEditor.Show();
    }

    if (sceneEditor.entityEditor.IsVisible() || scriptEditor.IsVisible() || textureEditor.IsVisible() || modelEditor.IsVisible() || soundEditor.IsVisible()) {
        editorWidth = size.x - editorWidth;
        ImGui::HorizontalSplitter(ImVec2(editorWidth, 20), size.y - 20, splitterSize, editorWidth, editorResize, sceneWidth + 20, size.x - 20);
        editorWidth = size.x - editorWidth;

        ImGui::SetNextWindowPos(ImVec2(size.x - editorWidth, 20));
        ImGui::SetNextWindowSize(ImVec2(editorWidth, size.y - 20));
    }

    if (sceneEditor.entityEditor.IsVisible())
        sceneEditor.entityEditor.Show();
    if (scriptEditor.IsVisible())
        scriptEditor.Show();
    if (textureEditor.IsVisible())
        textureEditor.Show();
    if (modelEditor.IsVisible())
        modelEditor.Show();
    if (soundEditor.IsVisible())
        soundEditor.Show();

    ImGui::End();
}

bool ResourceView::HasMadeChanges() const{

    std::string* sceneFilename = new std::string();
    Json::Value sceneJson = sceneEditor.GetSaveFileJson(sceneFilename);

    // Load Json document from file.
    Json::Value reference;
    std::ifstream file(*sceneFilename);

    if (!file.good())
        return true;

    file >> reference;
    file.close();

    std::string hymnJsonString = sceneJson.toStyledString();
    std::string referenceString = reference.toStyledString();

    int response = referenceString.compare(hymnJsonString);
    if (response != 0)
        return true;

    return false;

}

bool ResourceView::IsVisible() const {
    return visible;
}

void ResourceView::SetVisible(bool visible) {
    this->visible = visible;
}

void ResourceView::HideEditors() {
    sceneEditor.SetVisible(false);
    sceneEditor.entityEditor.SetVisible(false);
    scriptEditor.SetVisible(false);
    modelEditor.SetVisible(false);
    textureEditor.SetVisible(false);
    soundEditor.SetVisible(false);
}

void ResourceView::SaveScene() const {
    sceneEditor.Save();
}

Json::Value ResourceView::GetSceneJson(std::string* filename) const {
    return sceneEditor.GetSaveFileJson(filename);
}

void ResourceView::SwitchScene(int index) {

    sceneEditor.SetVisible(true);
    sceneEditor.SetScene(index);
    Resources().activeScene = index;
    sceneEditor.entityEditor.SetVisible(false);
    Hymn().world.Clear();
    Hymn().world.Load(Hymn().GetPath() + FileSystem::DELIMITER + "Scenes" + FileSystem::DELIMITER + Resources().scenes[index] + ".json");
    changeScene = false;
    savePromptWindow.SetVisible(false);
    savePromptWindow.ResetDecision();

}

#undef max
void ResourceView::ResetScene() {
    sceneEditor.SetScene(std::numeric_limits<std::size_t>::max());
    sceneEditor.SetVisible(false);
}

SceneEditor& ResourceView::GetScene() {
    return sceneEditor;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include <gtest/gtest.h>
#include "watchman/thirdparty/jansson/jansson_private.h"

using namespace ::testing;

namespace {

std::string json_dtostr(double value) {
  char buf[30];
  int length = jsonp_dtostr(buf, std::size(buf), value);
  if (length >= 0) {
    return std::string{buf, buf + length};
  } else {
    throw std::domain_error(
        fmt::format("error converting value to buffer, length = {}", length));
  }
}

TEST(JsonTest, dtostr) {
  EXPECT_EQ("0.0", json_dtostr(0));
  EXPECT_EQ(
      "0.33333333333333331", json_dtostr(0.3333333333333333333333333333333333));
  EXPECT_EQ(
      "0.66666666666666663", json_dtostr(0.6666666666666666666666666666666666));
  EXPECT_EQ(
      "3.3333333333333333e+33",
      json_dtostr(3333333333333333333333333333333333.0));
  EXPECT_EQ(
      "6.6666666666666667e+33",
      json_dtostr(6666666666666666666666666666666666.0));
  EXPECT_EQ("1.0", json_dtostr(1.0));
  EXPECT_EQ("1e+20", json_dtostr(100000000000000000000.0));
}

TEST(JsonTest, double_round_trip) {
  double values[] = {
      0.3333333333333333333333333333333333,
      3333333333333333333333333333333333.0,
      1.0,
      100000000000000000000.0,
  };
  for (auto d : values) {
    SCOPED_TRACE(fmt::format("value = {}", d));
    auto encoded = json_dumps(json_real(d), JSON_ENCODE_ANY | JSON_COMPACT);
    json_error_t err{};
    auto value = json_loads(encoded.c_str(), JSON_DECODE_ANY, &err);

    EXPECT_EQ(JSON_REAL, value.value().type());
    EXPECT_EQ(d, json_real_value(value.value())) << " encoded = " << encoded;
  }
}

} // namespace
<commit_msg>Remove dead includes in watchman/test<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include <gtest/gtest.h>
#include "watchman/thirdparty/jansson/jansson_private.h"

namespace {

std::string json_dtostr(double value) {
  char buf[30];
  int length = jsonp_dtostr(buf, std::size(buf), value);
  if (length >= 0) {
    return std::string{buf, buf + length};
  } else {
    throw std::domain_error(
        fmt::format("error converting value to buffer, length = {}", length));
  }
}

TEST(JsonTest, dtostr) {
  EXPECT_EQ("0.0", json_dtostr(0));
  EXPECT_EQ(
      "0.33333333333333331", json_dtostr(0.3333333333333333333333333333333333));
  EXPECT_EQ(
      "0.66666666666666663", json_dtostr(0.6666666666666666666666666666666666));
  EXPECT_EQ(
      "3.3333333333333333e+33",
      json_dtostr(3333333333333333333333333333333333.0));
  EXPECT_EQ(
      "6.6666666666666667e+33",
      json_dtostr(6666666666666666666666666666666666.0));
  EXPECT_EQ("1.0", json_dtostr(1.0));
  EXPECT_EQ("1e+20", json_dtostr(100000000000000000000.0));
}

TEST(JsonTest, double_round_trip) {
  double values[] = {
      0.3333333333333333333333333333333333,
      3333333333333333333333333333333333.0,
      1.0,
      100000000000000000000.0,
  };
  for (auto d : values) {
    SCOPED_TRACE(fmt::format("value = {}", d));
    auto encoded = json_dumps(json_real(d), JSON_ENCODE_ANY | JSON_COMPACT);
    json_error_t err{};
    auto value = json_loads(encoded.c_str(), JSON_DECODE_ANY, &err);

    EXPECT_EQ(JSON_REAL, value.value().type());
    EXPECT_EQ(d, json_real_value(value.value())) << " encoded = " << encoded;
  }
}

} // namespace
<|endoftext|>


<commit_before>/*
 *  GreyscaleLuminanceSource.cpp
 *  zxing
 *
 *  Copyright 2010 ZXing authors All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <zxing/common/GreyscaleLuminanceSource.h>
#include <zxing/common/GreyscaleRotatedLuminanceSource.h>
#include <zxing/common/IllegalArgumentException.h>

namespace zxing {

GreyscaleLuminanceSource::GreyscaleLuminanceSource(unsigned char* greyData, int dataWidth,
    int dataHeight, int left, int top, int width, int height) : greyData_(greyData),
    dataWidth_(dataWidth), dataHeight_(dataHeight), left_(left), top_(top), width_(width),
    height_(height) {

  if (left + width > dataWidth || top + height > dataHeight || top < 0 || left < 0) {
    throw IllegalArgumentException("Crop rectangle does not fit within image data.");
  }
}

unsigned char* GreyscaleLuminanceSource::getRow(int y, unsigned char* row) {
  if (y < 0 || y >= this->getHeight()) {
    throw IllegalArgumentException("Requested row is outside the image: " + y);
  }
  int width = getWidth();
  // TODO(flyashi): determine if row has enough size.
  if (row == NULL) {
    row = new unsigned char[width_];
  }
  int offset = (y + top_) * dataWidth_ + left_;
  memcpy(row, &greyData_[offset], width);
  return row;
}

unsigned char* GreyscaleLuminanceSource::getMatrix() {
  if (left_ != 0 || top_ != 0 || dataWidth_ != width_ || dataHeight_ != height_) {
    unsigned char* cropped = new unsigned char[width_ * height_];
    for (int row = 0; row < height_; row++) {
      memcpy(cropped + row * width_, greyData_ + (top_ + row) * dataWidth_ + left_, width_);
    }
    return cropped;
  }
  return greyData_;
}

Ref<LuminanceSource> GreyscaleLuminanceSource::rotateCounterClockwise() {
  // Intentionally flip the left, top, width, and height arguments as needed. dataWidth and
  // dataHeight are always kept unrotated.
  return Ref<LuminanceSource> (new GreyscaleRotatedLuminanceSource(greyData_, dataWidth_,
      dataHeight_, top_, left_, height_, width_));
}

} /* namespace */
<commit_msg>Fixed the double delete problem remaining in issue 503.<commit_after>/*
 *  GreyscaleLuminanceSource.cpp
 *  zxing
 *
 *  Copyright 2010 ZXing authors All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <zxing/common/GreyscaleLuminanceSource.h>
#include <zxing/common/GreyscaleRotatedLuminanceSource.h>
#include <zxing/common/IllegalArgumentException.h>

namespace zxing {

GreyscaleLuminanceSource::GreyscaleLuminanceSource(unsigned char* greyData, int dataWidth,
    int dataHeight, int left, int top, int width, int height) : greyData_(greyData),
    dataWidth_(dataWidth), dataHeight_(dataHeight), left_(left), top_(top), width_(width),
    height_(height) {

  if (left + width > dataWidth || top + height > dataHeight || top < 0 || left < 0) {
    throw IllegalArgumentException("Crop rectangle does not fit within image data.");
  }
}

unsigned char* GreyscaleLuminanceSource::getRow(int y, unsigned char* row) {
  if (y < 0 || y >= this->getHeight()) {
    throw IllegalArgumentException("Requested row is outside the image: " + y);
  }
  int width = getWidth();
  // TODO(flyashi): determine if row has enough size.
  if (row == NULL) {
    row = new unsigned char[width_];
  }
  int offset = (y + top_) * dataWidth_ + left_;
  memcpy(row, &greyData_[offset], width);
  return row;
}

unsigned char* GreyscaleLuminanceSource::getMatrix() {
  int size = width_ * height_;
  unsigned char* result = new unsigned char[size];
  if (left_ == 0 && top_ == 0 && dataWidth_ == width_ && dataHeight_ == height_) {
    memcpy(result, greyData_, size);
  } else {
    for (int row = 0; row < height_; row++) {
      memcpy(result + row * width_, greyData_ + (top_ + row) * dataWidth_ + left_, width_);
    }
  }
  return result;
}

Ref<LuminanceSource> GreyscaleLuminanceSource::rotateCounterClockwise() {
  // Intentionally flip the left, top, width, and height arguments as needed. dataWidth and
  // dataHeight are always kept unrotated.
  return Ref<LuminanceSource> (new GreyscaleRotatedLuminanceSource(greyData_, dataWidth_,
      dataHeight_, top_, left_, height_, width_));
}

} /* namespace */
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2014-2016 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#define BOOST_TEST_NO_MAIN
#define BOOST_TEST_MODULE "Graphics/OpenGL Window"

#include <boost/test/unit_test.hpp>

#include <QtTest>

#include <DO/Sara/Graphics/DerivedQObjects/OpenGLWindow.hpp>

#include "event_scheduler.hpp"

Q_DECLARE_METATYPE(DO::Sara::Event)
Q_DECLARE_METATYPE(Qt::Key)
Q_DECLARE_METATYPE(Qt::MouseButtons)

using namespace DO::Sara;

BOOST_AUTO_TEST_SUITE(TestOpenGLWindow)

BOOST_AUTO_TEST_CASE(test_construction)
{
  int width = 300;
  int height = 300;
  QString windowName = "OpenGL Window";
  int x = 200;
  int y = 300;

  OpenGLWindow *window = new OpenGLWindow(width, height, windowName, x, y);

  BOOST_CHECK_EQUAL(window->width(), width);
  BOOST_CHECK_EQUAL(window->height(), height);
  BOOST_CHECK(window->windowTitle() == windowName);
  BOOST_CHECK(window->isVisible());

  delete window;
}

BOOST_AUTO_TEST_SUITE_END()

class TestFixtureForOpenGLWindowEvents
{
protected:  // data members.
  OpenGLWindow *_test_window;
  EventScheduler _event_scheduler;
  QPoint _mouse_pos;
  Qt::Key _key;
  int _mouse_buttons_type_id;
  int _event_type_id;

  int _wait_ms;
  int _event_time_ms;

public:
  TestFixtureForOpenGLWindowEvents()
  {
    _mouse_buttons_type_id =
        qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons");
    _event_type_id = qRegisterMetaType<Event>("Event");
    _test_window = new OpenGLWindow(300, 300);
    _event_scheduler.set_receiver(_test_window);
    _mouse_pos = QPoint(10, 10);
    _key = Qt::Key_F;

#ifdef _WIN32
    _wait_ms = 100;
    _event_time_ms = 10;
#else
    _wait_ms = 10;
    _event_time_ms = 1;
#endif
  }

  virtual ~TestFixtureForOpenGLWindowEvents()
  {
    _test_window->deleteLater();
  }

  void compare_key_event(QSignalSpy& spy) const
  {
    spy.wait(2 * _wait_ms);
    BOOST_CHECK_EQUAL(spy.count(), 1);

    auto arguments = spy.takeFirst();
    BOOST_CHECK_EQUAL(arguments.at(0).toInt(), static_cast<int>(_key));
  }
};

BOOST_FIXTURE_TEST_SUITE(TestOpenGLWindowEvents,
                         TestFixtureForOpenGLWindowEvents)

BOOST_AUTO_TEST_CASE(test_key_press_event)
{
  QSignalSpy spy(_test_window, SIGNAL(pressedKey(int)));
  BOOST_CHECK(spy.isValid());

  auto event = QKeyEvent{QEvent::KeyPress, _key, Qt::NoModifier};
  _event_scheduler.schedule_event(&event, _event_time_ms);

  compare_key_event(spy);
}

BOOST_AUTO_TEST_CASE(test_key_release_event)
{
  QSignalSpy spy{_test_window, SIGNAL(releasedKey(int))};
  BOOST_CHECK(spy.isValid());

  auto event = QKeyEvent{QEvent::KeyRelease, _key, Qt::NoModifier};
  _event_scheduler.schedule_event(&event, _event_time_ms);

  compare_key_event(spy);
}

BOOST_AUTO_TEST_CASE(test_send_no_event)
{
  QSignalSpy spy{_test_window, SIGNAL(sendEvent(Event))};
  BOOST_CHECK(spy.isValid());

  QMetaObject::invokeMethod(_test_window, "waitForEvent", Qt::AutoConnection,
                            Q_ARG(int, 1));

  // Nothing happens.
  BOOST_CHECK(spy.wait(10));
  BOOST_CHECK_EQUAL(spy.count(), 1);
  auto arguments = spy.takeFirst();
  auto arg = arguments.at(0);
  arg.convert(_event_type_id);
  auto event = arguments.at(0).value<Event>();
  BOOST_CHECK_EQUAL(event.type, DO::Sara::NO_EVENT);
}

BOOST_AUTO_TEST_CASE(test_send_pressed_key_event)
{
  // Spy the sendEvent signal.
  QSignalSpy spy{_test_window, SIGNAL(sendEvent(Event))};
  BOOST_CHECK(spy.isValid());

  // Ask the testing window to wait.
  QMetaObject::invokeMethod(_test_window, "waitForEvent", Qt::AutoConnection,
                            Q_ARG(int, _wait_ms));

  // Schedule a key press event.
  auto qt_event = QKeyEvent{QEvent::KeyPress, _key, Qt::NoModifier};
  _event_scheduler.schedule_event(&qt_event, _event_time_ms);

  // The spy waits for the events.
  BOOST_CHECK(spy.wait(2 * _wait_ms));

  // Check that the spy received one key press event.
  BOOST_CHECK_EQUAL(spy.count(), 1);

  // Check the details of the key press event.
  auto arguments = spy.takeFirst();
  auto arg = arguments.at(0);
  arg.convert(_event_type_id);
  auto event = arguments.at(0).value<Event>();
  BOOST_CHECK_EQUAL(event.type, DO::Sara::KEY_PRESSED);
  BOOST_CHECK_EQUAL(event.key, _key);
}

BOOST_AUTO_TEST_CASE(test_send_released_key_event)
{
  // Spy the sendEvent signal.
  QSignalSpy spy{_test_window, SIGNAL(sendEvent(Event))};
  BOOST_CHECK(spy.isValid());

  // Ask the testing window to wait for an event.
  QMetaObject::invokeMethod(_test_window, "waitForEvent", Qt::AutoConnection,
                            Q_ARG(int, _wait_ms));

  // Schedule a key press event.
  auto qt_event = QKeyEvent{QEvent::KeyRelease, _key, Qt::NoModifier};
  _event_scheduler.schedule_event(&qt_event, _event_time_ms);

  // Check that the spy received one key press event.
  BOOST_CHECK(spy.wait(2 * _wait_ms));
  BOOST_CHECK_EQUAL(spy.count(), 1);

  // Check the details of the key release event.
  auto arguments = spy.takeFirst();
  auto arg = arguments.at(0);
  arg.convert(_event_type_id);
  auto event = arguments.at(0).value<Event>();
  BOOST_CHECK_EQUAL(event.type, DO::Sara::KEY_RELEASED);
  BOOST_CHECK_EQUAL(event.key, _key);
}

BOOST_AUTO_TEST_SUITE_END()

int main(int argc, char* argv[])
{
  QApplication app{argc, argv};
  app.setAttribute(Qt::AA_Use96Dpi, true);
  return boost::unit_test::unit_test_main([]() { return true; }, argc, argv);
}
<commit_msg>MAINT: fix test and memory leak.<commit_after>// ========================================================================== //
// This file is part of Sara, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2014-2016 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#define BOOST_TEST_NO_MAIN
#define BOOST_TEST_MODULE "Graphics/OpenGL Window"

#include <boost/test/unit_test.hpp>

#include <QtTest>

#include <DO/Sara/Graphics/DerivedQObjects/OpenGLWindow.hpp>

#include "event_scheduler.hpp"

Q_DECLARE_METATYPE(DO::Sara::Event)
Q_DECLARE_METATYPE(Qt::Key)
Q_DECLARE_METATYPE(Qt::MouseButtons)

using namespace DO::Sara;

BOOST_AUTO_TEST_SUITE(TestOpenGLWindow)

BOOST_AUTO_TEST_CASE(test_construction)
{
  int width = 300;
  int height = 300;
  QString windowName = "OpenGL Window";
  int x = 200;
  int y = 300;

  OpenGLWindow *window = new OpenGLWindow(width, height, windowName, x, y);

  BOOST_CHECK_EQUAL(window->width(), width);
  BOOST_CHECK_EQUAL(window->height(), height);
  BOOST_CHECK(window->windowTitle() == windowName);
  BOOST_CHECK(window->isVisible());

  delete window;
}

BOOST_AUTO_TEST_SUITE_END()

class TestFixtureForOpenGLWindowEvents
{
protected:  // data members.
  OpenGLWindow *_test_window;
  EventScheduler _event_scheduler;
  QPoint _mouse_pos;
  Qt::Key _key;
  int _mouse_buttons_type_id;
  int _event_type_id;

  int _wait_ms;
  int _event_time_ms;

public:
  TestFixtureForOpenGLWindowEvents()
  {
    _mouse_buttons_type_id =
        qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons");
    _event_type_id = qRegisterMetaType<Event>("Event");
    _test_window = new OpenGLWindow(300, 300);
    _event_scheduler.set_receiver(_test_window);
    _mouse_pos = QPoint(10, 10);
    _key = Qt::Key_F;

#ifdef _WIN32
    _wait_ms = 100;
    _event_time_ms = 20;
#else
    _wait_ms = 10;
    _event_time_ms = 1;
#endif
  }

  virtual ~TestFixtureForOpenGLWindowEvents()
  {
    delete _test_window;
  }

  void compare_key_event(QSignalSpy& spy) const
  {
    spy.wait(2 * _wait_ms);
    BOOST_CHECK_EQUAL(spy.count(), 1);

    auto arguments = spy.takeFirst();
    BOOST_CHECK_EQUAL(arguments.at(0).toInt(), static_cast<int>(_key));
  }
};

BOOST_FIXTURE_TEST_SUITE(TestOpenGLWindowEvents,
                         TestFixtureForOpenGLWindowEvents)

BOOST_AUTO_TEST_CASE(test_key_press_event)
{
  QSignalSpy spy(_test_window, SIGNAL(pressedKey(int)));
  BOOST_CHECK(spy.isValid());

  auto event = QKeyEvent{QEvent::KeyPress, _key, Qt::NoModifier};
  _event_scheduler.schedule_event(&event, _event_time_ms);

  compare_key_event(spy);
}

BOOST_AUTO_TEST_CASE(test_key_release_event)
{
  QSignalSpy spy{_test_window, SIGNAL(releasedKey(int))};
  BOOST_CHECK(spy.isValid());

  auto event = QKeyEvent{QEvent::KeyRelease, _key, Qt::NoModifier};
  _event_scheduler.schedule_event(&event, _event_time_ms);

  compare_key_event(spy);
}

BOOST_AUTO_TEST_CASE(test_send_no_event)
{
  QSignalSpy spy{_test_window, SIGNAL(sendEvent(Event))};
  BOOST_CHECK(spy.isValid());

  QMetaObject::invokeMethod(_test_window, "waitForEvent", Qt::AutoConnection,
                            Q_ARG(int, 1));

  // Nothing happens.
  BOOST_CHECK(spy.wait(10));
  BOOST_CHECK_EQUAL(spy.count(), 1);
  auto arguments = spy.takeFirst();
  auto arg = arguments.at(0);
  arg.convert(_event_type_id);
  auto event = arguments.at(0).value<Event>();
  BOOST_CHECK_EQUAL(event.type, DO::Sara::NO_EVENT);
}

BOOST_AUTO_TEST_CASE(test_send_pressed_key_event)
{
  // Spy the sendEvent signal.
  QSignalSpy spy{_test_window, SIGNAL(sendEvent(Event))};
  BOOST_CHECK(spy.isValid());

  // Ask the testing window to wait.
  QMetaObject::invokeMethod(_test_window, "waitForEvent", Qt::AutoConnection,
                            Q_ARG(int, _wait_ms));

  // Schedule a key press event.
  auto qt_event = QKeyEvent{QEvent::KeyPress, _key, Qt::NoModifier};
  _event_scheduler.schedule_event(&qt_event, _event_time_ms);

  // The spy waits for the events.
  BOOST_CHECK(spy.wait(2 * _wait_ms));

  // Check that the spy received one key press event.
  BOOST_CHECK_EQUAL(spy.count(), 1);

  // Check the details of the key press event.
  auto arguments = spy.takeFirst();
  auto arg = arguments.at(0);
  arg.convert(_event_type_id);
  auto event = arguments.at(0).value<Event>();
  BOOST_CHECK_EQUAL(event.type, DO::Sara::KEY_PRESSED);
  BOOST_CHECK_EQUAL(event.key, _key);
}

BOOST_AUTO_TEST_CASE(test_send_released_key_event)
{
  // Spy the sendEvent signal.
  QSignalSpy spy{_test_window, SIGNAL(sendEvent(Event))};
  BOOST_CHECK(spy.isValid());

  // Ask the testing window to wait for an event.
  QMetaObject::invokeMethod(_test_window, "waitForEvent", Qt::AutoConnection,
                            Q_ARG(int, _wait_ms));

  // Schedule a key press event.
  auto qt_event = QKeyEvent{QEvent::KeyRelease, _key, Qt::NoModifier};
  _event_scheduler.schedule_event(&qt_event, _event_time_ms);

  // Check that the spy received one key press event.
  BOOST_CHECK(spy.wait(2 * _wait_ms));
  BOOST_CHECK_EQUAL(spy.count(), 1);

  // Check the details of the key release event.
  auto arguments = spy.takeFirst();
  auto arg = arguments.at(0);
  arg.convert(_event_type_id);
  auto event = arguments.at(0).value<Event>();
  BOOST_CHECK_EQUAL(event.type, DO::Sara::KEY_RELEASED);
  BOOST_CHECK_EQUAL(event.key, _key);
}

BOOST_AUTO_TEST_SUITE_END()

int main(int argc, char* argv[])
{
  QApplication app{argc, argv};
  app.setAttribute(Qt::AA_Use96Dpi, true);
  return boost::unit_test::unit_test_main([]() { return true; }, argc, argv);
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2010, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_SURFACE_IMPL_POISSON_H_
#define PCL_SURFACE_IMPL_POISSON_H_

#include "pcl/surface/poisson.h"
#include <pcl/common/common.h>
#include <pcl/common/vector_average.h>
#include <pcl/Vertices.h>

#include "pcl/surface/poisson/octree.h"
#include "pcl/surface/poisson/sparse_matrix.h"
#include "pcl/surface/poisson/function_data.h"
#include "pcl/surface/poisson/ppolynomial.h"
#include "pcl/surface/poisson/multi_grid_octree_data.h"

#define MEMORY_ALLOCATOR_BLOCK_SIZE 1<<12

#include <stdarg.h>
#include <string>

using namespace pcl::surface::poisson;

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
pcl::Poisson<PointNT>::Poisson ()
  : no_reset_samples_ (false),
    no_clip_tree_ (false),
    confidence_ (false),
    manifold_ (false),
    depth_ (10),
    solver_divide_ (8),
    iso_divide_ (8),
    refine_ (3),
    kernel_depth_ (8),
    degree_ (2),
    samples_per_node_ (1.0),
    scale_ (1.25)
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
pcl::Poisson<PointNT>::~Poisson ()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> template <int Degree> void
pcl::Poisson<PointNT>::execute (CoredMeshData &mesh,
                                         Point3D<float> &center)
{
  float scale = 1;
  //////////////////////////////////
  // Fix courtesy of David Gallup //
  // TreeNodeData::UseIndex = 1;  //
  //////////////////////////////////
  Octree<Degree> tree;
  PPolynomial<Degree> ReconstructionFunction = PPolynomial<Degree>::GaussianApproximation ();

  center.coords[0] = center.coords[1] = center.coords[2] = 0;

  TreeOctNode::SetAllocator(MEMORY_ALLOCATOR_BLOCK_SIZE);

  int kernel_depth=depth_-2;
  tree.setFunctionData (ReconstructionFunction,depth_, 0, float (1.0) / (1<<depth_));

  tree.setTree (input_, depth_, kernel_depth, float(samples_per_node_), scale_, center, scale, !no_reset_samples_, confidence_);

  if(!no_clip_tree_)
    tree.ClipTree ();

  tree.finalize1 (refine_);
  tree.SetLaplacianWeights ();
  tree.finalize2 (refine_);

  tree.LaplacianMatrixIteration (solver_divide_);

  float isoValue=tree.GetIsoValue ();

  if (iso_divide_)
    tree.GetMCIsoTriangles (isoValue, iso_divide_, &mesh, 0, 1, manifold_);
  else
    tree.GetMCIsoTriangles (isoValue, &mesh, 0, 1, manifold_);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::Poisson<PointNT>::performReconstruction (PolygonMesh &output)
{
  CoredVectorMeshData mesh;
  Point3D<float> center;

  switch (degree_)
  {
    case 1:
      execute<1> (mesh, center);
      break;
    case 2:
      execute<2> (mesh, center);
      break;
    case 3:
      execute<3> (mesh, center);
      break;
    case 4:
      execute<4> (mesh, center);
      break;
    case 5:
      execute<5> (mesh, center);
      break;
    default:
      PCL_ERROR (stderr,"Degree %d not supported\n", degree_);
  }

  /// Write output PolygonMesh
  float scale = 1;
   // write vertices
   pcl::PointCloud < pcl::PointXYZ > cloud;
   cloud.points.resize (int (mesh.outOfCorePointCount()+mesh.inCorePoints.size ()));
   Point3D<float> p;
   for (int i = 0; i < int (mesh.inCorePoints.size()); i++)
   {
     p = mesh.inCorePoints[i];
     cloud.points[i].x = p.coords[0]*scale+center.coords[0];
     cloud.points[i].y = p.coords[1]*scale+center.coords[1];
     cloud.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   for (int i = int (mesh.inCorePoints.size ()); i < int (mesh.outOfCorePointCount () + mesh.inCorePoints.size ()); i++)
   {
     mesh.nextOutOfCorePoint (p);
     cloud.points[i].x = p.coords[0]*scale+center.coords[0];
     cloud.points[i].y = p.coords[1]*scale+center.coords[1];
     cloud.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   pcl::toROSMsg (cloud, output.cloud);
   output.polygons.resize (mesh.triangleCount ());

   // Write faces
   TriangleIndex tIndex;
   int inCoreFlag;
   for (int i = 0; i < mesh.triangleCount(); i++)
   {
     // Create and fill a struct that the ply code can handle
     pcl::Vertices v;
     v.vertices.resize (3);

     mesh.nextTriangle(tIndex,inCoreFlag);
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0]))
       tIndex.idx[0] += int(mesh.inCorePoints.size());
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1]))
       tIndex.idx[1] += int(mesh.inCorePoints.size());
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2]))
       tIndex.idx[2] += int(mesh.inCorePoints.size());

     for (int j = 0; j < 3; j++)
       v.vertices[j] = tIndex.idx[j];
     output.polygons[i] = v;
   }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::Poisson<PointNT>::performReconstruction (pcl::PointCloud<PointNT> &points,
                                                       std::vector<pcl::Vertices> &polygons)
{
  CoredVectorMeshData mesh;
  Point3D<float> center;

  switch(degree_)
  {
    case 1:
      execute<1> (mesh, center);
      break;
    case 2:
      execute<2> (mesh, center);
      break;
    case 3:
      execute<3> (mesh, center);
      break;
    case 4:
      execute<4> (mesh, center);
      break;
    case 5:
      execute<5> (mesh, center);
      break;
    default:
      PCL_ERROR (stderr,"Degree %d not supported\n", degree_);
  }

  /// Write output PolygonMesh
  float scale = 1;
   // write vertices
   points.points.resize (int (mesh.outOfCorePointCount ()+mesh.inCorePoints.size ()));
   Point3D<float> p;
   for (int i = 0; i < int(mesh.inCorePoints.size()); i++)
   {
     p = mesh.inCorePoints[i];
     points.points[i].x = p.coords[0]*scale+center.coords[0];
     points.points[i].y = p.coords[1]*scale+center.coords[1];
     points.points[i].z = p.coords[2]*scale+center.coords[2];
   }
   for (int i = int(mesh.inCorePoints.size()); i < int (mesh.outOfCorePointCount() + mesh.inCorePoints.size ()); i++)
   {
     mesh.nextOutOfCorePoint(p);
     points.points[i].x = p.coords[0]*scale+center.coords[0];
     points.points[i].y = p.coords[1]*scale+center.coords[1];
     points.points[i].z = p.coords[2]*scale+center.coords[2];
   }

   polygons.resize (mesh.triangleCount ());

   // write faces
   TriangleIndex tIndex;
   int inCoreFlag;
   for (int i = 0; i < mesh.triangleCount (); i++)
   {
     // create and fill a struct that the ply code can handle
     pcl::Vertices v;
     v.vertices.resize (3);

     mesh.nextTriangle(tIndex,inCoreFlag);
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0]))
       tIndex.idx[0] += int(mesh.inCorePoints.size());
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1]))
       tIndex.idx[1] += int(mesh.inCorePoints.size());
     if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2]))
       tIndex.idx[2] += int(mesh.inCorePoints.size());
     for (int j = 0; j < 3; j++)
       v.vertices[j] = tIndex.idx[j];
     polygons[i] = v;
   }
}

#define PCL_INSTANTIATE_Poisson(T) template class PCL_EXPORTS pcl::Poisson<T>;

#endif    // PCL_SURFACE_IMPL_POISSON_H_

<commit_msg>minor<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2010-2012, Willow Garage, Inc.
 *
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 *
 */

#ifndef PCL_SURFACE_IMPL_POISSON_H_
#define PCL_SURFACE_IMPL_POISSON_H_

#include "pcl/surface/poisson.h"
#include <pcl/common/common.h>
#include <pcl/common/vector_average.h>
#include <pcl/Vertices.h>

#include "pcl/surface/poisson/octree.h"
#include "pcl/surface/poisson/sparse_matrix.h"
#include "pcl/surface/poisson/function_data.h"
#include "pcl/surface/poisson/ppolynomial.h"
#include "pcl/surface/poisson/multi_grid_octree_data.h"

#define MEMORY_ALLOCATOR_BLOCK_SIZE 1<<12

#include <stdarg.h>
#include <string>

using namespace pcl::surface::poisson;

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
pcl::Poisson<PointNT>::Poisson ()
  : no_reset_samples_ (false),
    no_clip_tree_ (false),
    confidence_ (false),
    manifold_ (false),
    depth_ (10),
    solver_divide_ (8),
    iso_divide_ (8),
    refine_ (3),
    kernel_depth_ (8),
    degree_ (2),
    samples_per_node_ (1.0),
    scale_ (1.25)
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT>
pcl::Poisson<PointNT>::~Poisson ()
{
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> template <int Degree> void
pcl::Poisson<PointNT>::execute (CoredMeshData &mesh,
                                Point3D<float> &center)
{
  float scale = 1;
  //////////////////////////////////
  // Fix courtesy of David Gallup //
  // TreeNodeData::UseIndex = 1;  //
  //////////////////////////////////
  Octree<Degree> tree;
  PPolynomial<Degree> ReconstructionFunction = PPolynomial<Degree>::GaussianApproximation ();

  center.coords[0] = center.coords[1] = center.coords[2] = 0;

  TreeOctNode::SetAllocator (MEMORY_ALLOCATOR_BLOCK_SIZE);

  int kernel_depth=depth_-2;
  tree.setFunctionData (ReconstructionFunction, depth_, 0, float (1.0) / (1<<depth_));

  tree.setTree (input_, depth_, kernel_depth, float(samples_per_node_), scale_, center, scale, !no_reset_samples_, confidence_);

  if (!no_clip_tree_)
    tree.ClipTree ();

  tree.finalize1 (refine_);
  tree.SetLaplacianWeights ();
  tree.finalize2 (refine_);

  tree.LaplacianMatrixIteration (solver_divide_);

  float isoValue=tree.GetIsoValue ();

  if (iso_divide_)
    tree.GetMCIsoTriangles (isoValue, iso_divide_, &mesh, 0, 1, manifold_);
  else
    tree.GetMCIsoTriangles (isoValue, &mesh, 0, 1, manifold_);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::Poisson<PointNT>::performReconstruction (PolygonMesh &output)
{
  CoredVectorMeshData mesh;
  Point3D<float> center;

  switch (degree_)
  {
    case 1:
    {
      execute<1> (mesh, center);
      break;
    }
    case 2:
    {
      execute<2> (mesh, center);
      break;
    }
    case 3:
    {
      execute<3> (mesh, center);
      break;
    }
    case 4:
    {
      execute<4> (mesh, center);
      break;
    }
    case 5:
    {
      execute<5> (mesh, center);
      break;
    }
    default:
    {
      PCL_ERROR (stderr, "Degree %d not supported\n", degree_);
    }
  }

  /// Write output PolygonMesh
  float scale = 1;

  // write vertices
  pcl::PointCloud < pcl::PointXYZ > cloud;
  cloud.points.resize (int (mesh.outOfCorePointCount () + mesh.inCorePoints.size ()));
  Point3D<float> p;
  for (int i = 0; i < int (mesh.inCorePoints.size ()); i++)
  {
    p = mesh.inCorePoints[i];
    cloud.points[i].x = p.coords[0]*scale+center.coords[0];
    cloud.points[i].y = p.coords[1]*scale+center.coords[1];
    cloud.points[i].z = p.coords[2]*scale+center.coords[2];
  }
  for (int i = int (mesh.inCorePoints.size ()); i < int (mesh.outOfCorePointCount () + mesh.inCorePoints.size ()); i++)
  {
    mesh.nextOutOfCorePoint (p);
    cloud.points[i].x = p.coords[0]*scale+center.coords[0];
    cloud.points[i].y = p.coords[1]*scale+center.coords[1];
    cloud.points[i].z = p.coords[2]*scale+center.coords[2];
  }
  pcl::toROSMsg (cloud, output.cloud);
  output.polygons.resize (mesh.triangleCount ());

  // Write faces
  TriangleIndex tIndex;
  int inCoreFlag;
  for (int i = 0; i < mesh.triangleCount (); i++)
  {
    // Create and fill a struct that the ply code can handle
    pcl::Vertices v;
    v.vertices.resize (3);

    mesh.nextTriangle (tIndex,inCoreFlag);
    if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0]))
      tIndex.idx[0] += int(mesh.inCorePoints.size ());
    if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1]))
      tIndex.idx[1] += int(mesh.inCorePoints.size ());
    if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2]))
      tIndex.idx[2] += int(mesh.inCorePoints.size ());

    for (int j = 0; j < 3; j++)
      v.vertices[j] = tIndex.idx[j];
    output.polygons[i] = v;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointNT> void
pcl::Poisson<PointNT>::performReconstruction (pcl::PointCloud<PointNT> &points,
                                              std::vector<pcl::Vertices> &polygons)
{
  CoredVectorMeshData mesh;
  Point3D<float> center;

  switch (degree_)
  {
    case 1:
    {
      execute<1> (mesh, center);
      break;
    }
    case 2:
    {
      execute<2> (mesh, center);
      break;
    }
    case 3:
    {
      execute<3> (mesh, center);
      break;
    }
    case 4:
    {
      execute<4> (mesh, center);
      break;
    }
    case 5:
    {
      execute<5> (mesh, center);
      break;
    }
    default:
    {
      PCL_ERROR (stderr, "Degree %d not supported\n", degree_);
    }
  }

  /// Write output PolygonMesh
  float scale = 1;
  // write vertices
  points.points.resize (int (mesh.outOfCorePointCount () + mesh.inCorePoints.size ()));
  Point3D<float> p;
  for (int i = 0; i < int(mesh.inCorePoints.size ()); i++)
  {
    p = mesh.inCorePoints[i];
    points.points[i].x = p.coords[0]*scale+center.coords[0];
    points.points[i].y = p.coords[1]*scale+center.coords[1];
    points.points[i].z = p.coords[2]*scale+center.coords[2];
  }
  for (int i = int(mesh.inCorePoints.size()); i < int (mesh.outOfCorePointCount() + mesh.inCorePoints.size ()); i++)
  {
    mesh.nextOutOfCorePoint (p);
    points.points[i].x = p.coords[0]*scale+center.coords[0];
    points.points[i].y = p.coords[1]*scale+center.coords[1];
    points.points[i].z = p.coords[2]*scale+center.coords[2];
  }

  polygons.resize (mesh.triangleCount ());

  // write faces
  TriangleIndex tIndex;
  int inCoreFlag;
  for (int i = 0; i < mesh.triangleCount (); i++)
  {
    // create and fill a struct that the ply code can handle
    pcl::Vertices v;
    v.vertices.resize (3);

    mesh.nextTriangle (tIndex,inCoreFlag);
    if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0]))
      tIndex.idx[0] += int(mesh.inCorePoints.size ());
    if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1]))
      tIndex.idx[1] += int(mesh.inCorePoints.size ());
    if (!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2]))
      tIndex.idx[2] += int(mesh.inCorePoints.size ());
    for (int j = 0; j < 3; j++)
      v.vertices[j] = tIndex.idx[j];
    polygons[i] = v;
  }
}

#define PCL_INSTANTIATE_Poisson(T) template class PCL_EXPORTS pcl::Poisson<T>;

#endif    // PCL_SURFACE_IMPL_POISSON_H_

<|endoftext|>