/***************************************************************************
 *                          Zanoza Modeler v2.x                            *
 *      This is unpublished propietary source code of Zanoza Software.     *
 *      The copyright notice does not evidence any actual or intended      *
 *                    publication of such source code.                     *
 *                                                                         *
 *                   Copyright (c) 2002 Zanoza Software.                   *
 *                                                                         *
 *                        All rights reserved.                             *
 ***************************************************************************
 *--------------------------------------------------------------------------
 * @author:   Oleg M.
 *--------------------------------------------------------------------------
 * @purpose:  ZModeler's polygon buffer class.
 *--------------------------------------------------------------------------
 * @histroy: 23.04.2003. Created
 */
#ifndef zpolygonbuffer_h_included
#define zpolygonbuffer_h_included
#include <core/coreTypes.h>

//------------------------------------------------------
//  ZPolyBuf - polygon buffer for editable meshes
//------------------------------------------------------
class DLL_LINKAGE ZPolyBuf
{
  //
  // constructors/destructors
  //
private:
  ZPolyBuf();
public:
  ZPolyBuf(const ZPoly::ePolyType  type, const long dwAlloc = 16);
  ZPolyBuf(const ZPolyBuf& pBuf);
  ~ZPolyBuf();

public:
  //
  // operators
  //
  ZPoly&        operator [] (const long n);
  const ZPoly   operator [] (const long n) const;
  ZPolyBuf&     operator = (const ZPolyBuf& pBuf);
  
public:
  //
  // operations
  //
  inline ZPoly::ePolyType type()const { return m_polyType;            }
  // [creates new] polyon at specified position
  ZPoly&  at(const long n, ZPoly::ePolyType type);
  // tries to perform convertion of buffer from current type to supplied
  bool type(const ZPoly::ePolyType t);
  inline DWORD stride() const         { return m_dwStride;            }
  inline ZPoly& at(const long n)      { return (*this)[n];            }
  // provides size of allocated buffer (polygons)
  inline long maximum() const         { return m_dwBufSize/m_dwStride;}
  // amount of polygons in the buffer (amount of triangles might be much more)
  inline long length() const          { return m_nLength;             }
  // amount of trianges in buffer (some polygons could be quads, poly etc.)
  inline long numTris()
  {
    long numTris = 0;
    for (long i = 0; i < m_nLength; i++)
      numTris += at(i).tris();
    return numTris;
  }
  // sets new length for the buffer
  void length(long newLength);
  // reallocates buffer of supplied length with supplied stride
  // old buffer content is copied into new buffer. the rest is
  // left uninitialized(!), so at(i, type) call required.
  void reallocate(const long dwLength, const DWORD dwNewStride);
  //add single item at the end of the buffer
  void add(const ZPoly& poly);
  //adds a nCount items of type to the buffer. increase length to nCount.
  //items are initialized and no call to at(i, type) required
  void extend(const long nCount, const ZPoly::ePolyType type);
  //inserts single item at specified position
  //pos is zero-based; call with pos == m_nLength
  //equal to add(item);
  void insert(const ZPoly& poly, long pos);
  //erases single item at specified position.
  void erase(long pos);
  //clears the buffer.
  void clear(bool bForceRelease=false);
  //sets 'invalid' flag to indicate that vertex buffer or poly-buffer was changed
  void invalidate();

  //
  // mass status alter:
  //
  inline void selectAll(bool bSelect=true) 
    { massStatus(bSelect ? STATUS_SELECTED : 0, bSelect ? 0 : STATUS_SELECTED); }
  inline void showAll(bool bShow=true)
    { massStatus(bShow ? 0 : STATUS_HIDDEN, bShow ? STATUS_HIDDEN : 0); }
  inline void enableAll(bool bEnable=true)
    { massStatus(bEnable ? STATUS_ENABLED : 0, bEnable ? 0 : STATUS_ENABLED); }
  inline void acitvateAll(bool bActivate=true)
    { massStatus(bActivate ? STATUS_ACTIVE : 0, bActivate ? 0 : STATUS_ACTIVE); }
  inline void selectActive() 
    { massStatusChange(STATUS_SELECTED, 0, STATUS_ENABLED | STATUS_ACTIVE); }
  inline void hideSelected() 
    { massStatusChange(STATUS_HIDDEN, 0, STATUS_ENABLED | STATUS_SELECTED); }
  void massStatus(const DWORD dwAdd, const DWORD dwRemove); 
  void massStatusChange(const DWORD dwAdd, const DWORD dwRemove, 
                        const DWORD dwIfHasStatus = STATUS_ENABLED,
                        const DWORD dwIfHasntStatus = STATUS_HIDDEN); 

private:
  //
  // data members
  //
  ZPoly::ePolyType        m_polyType;
  BYTE*                   m_pBuffer;    //buffer for storing the data
  DWORD                   m_dwBufSize;  //allocated size (data)
  long                    m_nLength;    //used length (amount of polygons)
  DWORD                   m_dwStride;   //stride of polygons in the buffer
};


#endif //zpolygonbuffer_h_included

