text: // Filename: eggGroupNode.h
  // Created by:  drose (16Jan99)
  //
  ////////////////////////////////////////////////////////////////////
  //
  // PANDA 3D SOFTWARE
  // Copyright (c) Carnegie Mellon University.  All rights reserved.
  //
  // All use of this software is subject to the terms of the revised BSD
  // license.  You should have received a copy of this license along
  // with this source code in a file named "LICENSE."
  //
  ////////////////////////////////////////////////////////////////////
  
  #ifndef EGGGROUPNODE_H
  #define EGGGROUPNODE_H
  
  #include "pandabase.h"
  
  #include "eggNode.h"
  #include "eggVertexPool.h"
  
  #include "coordinateSystem.h"
  #include "typedObject.h"
  #include "pointerTo.h"
  #include "luse.h"
  #include "globPattern.h"
  #include "plist.h"
  #include "bamCacheRecord.h"
  
  class EggTextureCollection;
  class EggMaterialCollection;
  class EggPolygon;
  class EggVertex;
  class EggVertexPool;
  class DSearchPath;
  
  ////////////////////////////////////////////////////////////////////
  //       Class : EggGroupNode
  // Description : A base class for nodes in the hierarchy that are not
  //               leaf nodes.  (See also EggGroup, which is
  //               specifically the "<Group>" node in egg.)
  //
  //               An EggGroupNode is an STL-style container of pointers
  //               to EggNodes, like a vector.  Functions
  //               push_back()/pop_back() and insert()/erase() are
  //               provided to manipulate the list.  The list may also
  //               be operated on (read-only) via iterators and
  //               begin()/end().
  ////////////////////////////////////////////////////////////////////
  class EXPCL_PANDAEGG EggGroupNode : public EggNode {
  
    // This is a bit of private interface stuff that must be here as a
    // forward reference.  This allows us to define the EggGroupNode as
    // an STL container.
  
  private:
    // We define the list of children as a list and not a vector, so we
    // can avoid the bad iterator-invalidating properties of vectors as
    // we insert/delete elements.
    typedef plist< PT(EggNode) > Children;
  
    // Here begins the actual public interface to EggGroupNode.
  
  PUBLISHED:
    EggGroupNode(const string &name = "") : EggNode(name) { }
    EggGroupNode(const EggGroupNode &copy);
    EggGroupNode &operator = (const EggGroupNode &copy);
    virtual ~EggGroupNode();
  
    virtual void write(ostream &out, int indent_level) const;
  
    // The EggGroupNode itself appears to be an STL container of
    // pointers to EggNodes.  The set of children is read-only, however,
    // except through the limited add_child/remove_child or insert/erase
    // interface.  The following implements this.
  public:
  #if defined(WIN32_VC) || defined(WIN64_VC)
    typedef const PT(EggNode) *pointer;
    typedef const PT(EggNode) *const_pointer;
  #else
    typedef Children::const_pointer pointer;
    typedef Children::const_pointer const_pointer;
  #endif
    typedef Children::const_reference reference;
    typedef Children::const_reference const_reference;
    typedef Children::const_iterator iterator;
    typedef Children::const_iterator const_iterator;
    typedef Children::const_reverse_iterator reverse_iterator;
    typedef Children::const_reverse_iterator const_reverse_iterator;
    typedef Children::size_type size_type;
    typedef Children::difference_type difference_type;
  
    iterator begin() const;
    iterator end() const;
    reverse_iterator rbegin() const;
    reverse_iterator rend() const;
  
    iterator insert(iterator position, PT(EggNode) x);
    iterator erase(iterator position);
    iterator erase(iterator first, iterator last);
    void replace(iterator position, PT(EggNode) x);
  
  PUBLISHED:
    bool empty() const;
    size_type size() const;
    void clear();
  
    // This is an alternate way to traverse the list of children.  It is
    // mainly provided for scripting code, which can't use the iterators
    // defined above (they don't export through interrogate very well).
    // These are, of course, non-thread-safe.
    EggNode *get_first_child();
    EggNode *get_next_child();
  
    EXTENSION(PyObject *get_children() const);
  
    EggNode *add_child(EggNode *node);
    PT(EggNode) remove_child(EggNode *node);
    void steal_children(EggGroupNode &other);
  
    EggNode *find_child(const string &name) const;
  
    bool has_absolute_pathnames() const;
    void resolve_filenames(const DSearchPath &searchpath);
    void force_filenames(const Filename &directory);
    void reverse_vertex_ordering();
  
    void recompute_vertex_normals(double threshold, CoordinateSystem cs = CS_default);
    void recompute_polygon_normals(CoordinateSystem cs = CS_default);
    void strip_normals();
  
    bool recompute_tangent_binormal(const GlobPattern &uv_name);
    bool recompute_tangent_binormal(const vector_string &names);
    bool recompute_tangent_binormal_auto();
  
    enum TriangulateFlags {
      T_polygon     = 0x001,
      T_convex      = 0x002,
      T_composite   = 0x004,
      T_recurse     = 0x008,
      T_flat_shaded = 0x010,
    };
  
    int triangulate_polygons(int flags);
    void mesh_triangles(int flags);
    void make_point_primitives();
  
    int rename_nodes(vector_string strip_prefix, bool recurse);
  
    int remove_unused_vertices(bool recurse);
    int remove_invalid_primitives(bool recurse);
    void clear_connected_shading();
    void get_connected_shading();
    void unify_attributes(bool use_connected_shading, bool allow_per_primitive,
                          bool recurse);
    void apply_last_attribute(bool recurse);
    void apply_first_attribute(bool recurse);
    void post_apply_flat_attribute(bool recurse);
    virtual bool has_primitives() const;
    virtual bool joint_has_primitives() const;
    virtual bool has_normals() const;
  
  public:
    void rebuild_vertex_pools(EggVertexPools &vertex_pools, 
                              unsigned int max_vertices,
                              bool recurse);
  
  protected:
    virtual void update_under(int depth_offset);
  
    virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
                             CoordinateSystem to_cs);
    virtual void r_transform_vertices(const LMatrix4d &mat);
    virtual void r_mark_coordsys(CoordinateSystem cs);
    virtual void r_flatten_transforms();
    virtual void r_apply_texmats(EggTextureCollection &textures);
  
  
    CoordinateSystem find_coordsys_entry();
    int find_textures(EggTextureCollection *collection);
    int find_materials(EggMaterialCollection *collection);
    bool r_load_externals(const DSearchPath &searchpath, 
                          CoordinateSystem coordsys,
                          BamCacheRecord *record);
  
  PUBLISHED:
    INLINE static bool is_right(const LVector2d &v1, const LVector2d &v2);
  
  private:
    Children _children;
    const_iterator _gnc_iterator;
  
    // Don't try to use these private functions.  User code should add
    // and remove children via add_child()/remove_child(), or via the
    // STL-like push_back()/pop_back() or insert()/erase(), above.
    void prepare_add_child(EggNode *node);
    void prepare_remove_child(EggNode *node);
  
    // This bit is in support of recompute_vertex_normals().
    class NVertexReference {
    public:
      EggPolygon *_polygon;
      LNormald _normal;
      size_t _vertex;
    };
    typedef pvector<NVertexReference> NVertexGroup;
    typedef pmap<LVertexd, NVertexGroup> NVertexCollection;
  
    void r_collect_vertex_normals(NVertexCollection &collection,
                                  double threshold, CoordinateSystem cs);
    void do_compute_vertex_normals(const NVertexGroup &group);
  
    // This bit is in support of recompute_tangent_binormal().
    class TBNVertexReference {
    public:
      EggPolygon *_polygon;
      size_t _vertex;
      LVector3d _sdir;
      LVector3d _tdir;
    };
    class TBNVertexValue {
    public:
      INLINE bool operator < (const TBNVertexValue &other) const;
      LVertexd _pos;
      LNormald _normal;
      string _uv_name;
      LTexCoordd _uv;
      bool _facing;
    };
    typedef pvector<TBNVertexReference> TBNVertexGroup;
    typedef pmap<TBNVertexValue, TBNVertexGroup> TBNVertexCollection;
  
    void r_collect_tangent_binormal(const GlobPattern &uv_name,
                                    TBNVertexCollection &collection);
    void do_compute_tangent_binormal(const TBNVertexValue &value,
                                     const TBNVertexGroup &group);
  
  public:
    static TypeHandle get_class_type() {
      return _type_handle;
    }
    static void init_type() {
      EggNode::init_type();
      register_type(_type_handle, "EggGroupNode",
                    EggNode::get_class_type());
    }
    virtual TypeHandle get_type() const {
      return get_class_type();
    }
    virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
  
  private:
    static TypeHandle _type_handle;
  
    friend class EggTextureCollection;
    friend class EggMaterialCollection;
  };
  
  #include "eggGroupNode.I"
  
  #endif
  
  