Bläddra i källkod

add virtual inheritance

David Rose 20 år sedan
förälder
incheckning
68bdff57eb

+ 2 - 1
direct/src/dcparser/Sources.pp

@@ -18,7 +18,8 @@
   #define SOURCES \
   #define SOURCES \
      dcAtomicField.h dcClass.h dcClass.I \
      dcAtomicField.h dcClass.h dcClass.I \
      dcDeclaration.h \
      dcDeclaration.h \
-     dcField.h dcFile.h \
+     dcField.h dcField.I \
+     dcFile.h dcFile.I \
      dcKeyword.h dcKeywordList.h \
      dcKeyword.h dcKeywordList.h \
      dcLexer.lxx  \
      dcLexer.lxx  \
      dcLexerDefs.h dcMolecularField.h dcParser.yxx dcParserDefs.h  \
      dcLexerDefs.h dcMolecularField.h dcParser.yxx dcParserDefs.h  \

+ 22 - 0
direct/src/dcparser/dcClass.I

@@ -27,6 +27,28 @@ get_dc_file() const {
   return _dc_file;
   return _dc_file;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::get_name
+//       Access: Published
+//  Description: Returns the name of this class.
+////////////////////////////////////////////////////////////////////
+INLINE const string &DCClass::
+get_name() const {
+  return _name;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::get_number
+//       Access: Published
+//  Description: Returns a unique index number associated with this
+//               class.  This is defined implicitly when the .dc
+//               file(s) are read.
+////////////////////////////////////////////////////////////////////
+INLINE int DCClass::
+get_number() const {
+  return _number;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::is_struct
 //     Function: DCClass::is_struct
 //       Access: Published
 //       Access: Published

+ 138 - 48
direct/src/dcparser/dcClass.cxx

@@ -40,8 +40,22 @@ ConfigVariableBool dc_multiple_inheritance
           "supported, but field numbers will be numbered sequentially, "
           "supported, but field numbers will be numbered sequentially, "
           "which may be required to support old code that assumed this."));
           "which may be required to support old code that assumed this."));
 
 
+ConfigVariableBool dc_virtual_inheritance
+("dc-virtual-inheritance", false,
+ PRC_DESC("Set this true to support proper virtual inheritance in the "
+	  "dc file, so that diamond-of-death type constructs can be used.  "
+	  "This also enables shadowing (overloading) of inherited method "
+	  "names from a base class."));
+
 #endif  // WITHIN_PANDA
 #endif  // WITHIN_PANDA
 
 
+class SortFieldsByIndex {
+public:
+  inline bool operator ()(const DCField *a, const DCField *b) const {
+    return a->get_number() < b->get_number();
+  }
+};
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::Constructor
 //     Function: DCClass::Constructor
 //       Access: Public
 //       Access: Public
@@ -110,49 +124,26 @@ as_class() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: DCClass::get_name
-//       Access: Published
-//  Description: Returns the name of this class.
-////////////////////////////////////////////////////////////////////
-const string &DCClass::
-get_name() const {
-  return _name;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCClass::get_number
+//     Function: DCClass::get_num_parents
 //       Access: Published
 //       Access: Published
-//  Description: Returns a unique index number associated with this
-//               class.  This is defined implicitly when the .dc
-//               file(s) are read.
+//  Description: Returns the number of base classes this class
+//               inherits from.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int DCClass::
 int DCClass::
-get_number() const {
-  return _number;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCClass::has_parent
-//       Access: Published
-//  Description: Returns true if this class inherits from some other
-//               class, false if it does not.
-////////////////////////////////////////////////////////////////////
-bool DCClass::
-has_parent() const {
-  return !_parents.empty();
+get_num_parents() const {
+  return _parents.size();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::get_parent
 //     Function: DCClass::get_parent
 //       Access: Published
 //       Access: Published
-//  Description: Returns the parent class this class inherits from, if
-//               any.  It is an error to call this unless has_parent()
-//               returned true.
+//  Description: Returns the nth parent class this class inherits
+//               from.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DCClass *DCClass::
 DCClass *DCClass::
-get_parent() const {
-  nassertr(has_parent(), NULL);
-  return _parents.front();
+get_parent(int n) const {
+  nassertr(n >= 0 && n < (int)_parents.size(), NULL);
+  return _parents[n];
 }
 }
   
   
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -283,14 +274,25 @@ get_field_by_index(int index_number) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int DCClass::
 int DCClass::
 get_num_inherited_fields() const {
 get_num_inherited_fields() const {
-  int num_fields = get_num_fields();
+  if (dc_virtual_inheritance) {
+    if (_dc_file != (DCFile *)NULL) {
+      _dc_file->check_inherited_fields();
+    }
+    if (_inherited_fields.empty()) {
+      ((DCClass *)this)->rebuild_inherited_fields();
+    }
+    return (int)_inherited_fields.size();
 
 
-  Parents::const_iterator pi;
-  for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
-    num_fields += (*pi)->get_num_inherited_fields();
-  }
+  } else {
+    int num_fields = get_num_fields();
 
 
-  return num_fields;
+    Parents::const_iterator pi;
+    for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
+      num_fields += (*pi)->get_num_inherited_fields();
+    }
+    
+    return num_fields;
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -307,17 +309,29 @@ get_num_inherited_fields() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DCField *DCClass::
 DCField *DCClass::
 get_inherited_field(int n) const {
 get_inherited_field(int n) const {
-  Parents::const_iterator pi;
-  for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
-    int psize = (*pi)->get_num_inherited_fields();
-    if (n < psize) {
-      return (*pi)->get_inherited_field(n);
+  if (dc_virtual_inheritance) {
+    if (_dc_file != (DCFile *)NULL) {
+      _dc_file->check_inherited_fields();
+    }
+    if (_inherited_fields.empty()) {
+      ((DCClass *)this)->rebuild_inherited_fields();
     }
     }
+    nassertr(n >= 0 && n < (int)_inherited_fields.size(), NULL);
+    return _inherited_fields[n];
 
 
-    n -= psize;
+  } else {
+    Parents::const_iterator pi;
+    for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
+      int psize = (*pi)->get_num_inherited_fields();
+      if (n < psize) {
+	return (*pi)->get_inherited_field(n);
+      }
+      
+      n -= psize;
+    }
+    
+    return get_field(n);
   }
   }
-
-  return get_field(n);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -1263,6 +1277,75 @@ generate_hash(HashGenerator &hashgen) const {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::clear_inherited_fields
+//       Access: Public
+//  Description: Empties the list of inherited fields for the class,
+//               so that it may be rebuilt.  This is normally only
+//               called by DCFile::rebuild_inherited_fields().
+////////////////////////////////////////////////////////////////////
+void DCClass::
+clear_inherited_fields() {
+  _inherited_fields.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCClass::rebuild_inherited_fields
+//       Access: Public
+//  Description: Recomputes the list of inherited fields for the class.
+////////////////////////////////////////////////////////////////////
+void DCClass::
+rebuild_inherited_fields() {
+  typedef pset<string> Names;
+  Names names;
+
+  _inherited_fields.clear();
+  
+  // First, get a list of all of the inherited field names.
+  Parents::const_iterator pi;
+  for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
+    const DCClass *parent = (*pi);
+    int num_inherited_fields = parent->get_num_inherited_fields();
+    for (int i = 0; i < num_inherited_fields; ++i) {
+      const DCField *field = parent->get_inherited_field(i);
+      names.insert(field->get_name());
+    }
+  }
+
+  // Also get the local field names.  Any local unnamed fields are
+  // immediately added to the _inherited_fields list, since the
+  // unnamed fields are not inherited.
+  Fields::const_iterator fi;
+  for (fi = _fields.begin(); fi != _fields.end(); ++fi) {
+    DCField *field = (*fi);
+    if (field->get_name().empty()) {
+      _inherited_fields.push_back(field);
+    } else {
+      names.insert(field->get_name());
+    }
+  }
+
+  // And now build up the table.  We use get_field_by_name() to
+  // extract each one, to guarantee that the index we build exactly
+  // matches the return value of get_field_by_name().
+  
+  Names::const_iterator ni;
+  for (ni = names.begin(); ni != names.end(); ++ni) {
+    // Note that we only list the named fields in the inherited field
+    // list.  Thus, the unnamed fields, if any, are not inherited.
+    if (!(*ni).empty()) {
+      DCField *field = get_field_by_name(*ni);
+      nassertv(field != (DCField *)NULL);
+      _inherited_fields.push_back(field);
+    }
+  }
+
+  // Finally, sort the list in global field index order.  This will
+  // put the inherited fields at the top of the list.
+  ::sort(_inherited_fields.begin(), _inherited_fields.end(),
+	 SortFieldsByIndex());
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCClass::add_field
 //     Function: DCClass::add_field
 //       Access: Public
 //       Access: Public
@@ -1270,10 +1353,16 @@ generate_hash(HashGenerator &hashgen) const {
 //               class becomes the owner of the pointer and will
 //               class becomes the owner of the pointer and will
 //               delete it when it destructs.  Returns true if the
 //               delete it when it destructs.  Returns true if the
 //               field is successfully added, or false if there was a
 //               field is successfully added, or false if there was a
-//               name conflict.
+//               name conflict or some other problem.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool DCClass::
 bool DCClass::
 add_field(DCField *field) {
 add_field(DCField *field) {
+  nassertr(field->get_class() == this || field->get_class() == NULL, false);
+  field->set_class(this);
+  if (_dc_file != (DCFile *)NULL) {
+    _dc_file->mark_inherited_fields_stale();
+  }
+
   if (!field->get_name().empty()) {
   if (!field->get_name().empty()) {
     if (field->get_name() == _name) {
     if (field->get_name() == _name) {
       // This field is a constructor.
       // This field is a constructor.
@@ -1326,6 +1415,7 @@ add_field(DCField *field) {
 void DCClass::
 void DCClass::
 add_parent(DCClass *parent) {
 add_parent(DCClass *parent) {
   _parents.push_back(parent);
   _parents.push_back(parent);
+  _dc_file->mark_inherited_fields_stale();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 10 - 5
direct/src/dcparser/dcClass.h

@@ -29,10 +29,12 @@
 #include "configVariableBool.h"
 #include "configVariableBool.h"
 
 
 extern ConfigVariableBool dc_multiple_inheritance;
 extern ConfigVariableBool dc_multiple_inheritance;
+extern ConfigVariableBool dc_virtual_inheritance;
 
 
 #else  // WITHIN_PANDA
 #else  // WITHIN_PANDA
 
 
 static const bool dc_multiple_inheritance = true;
 static const bool dc_multiple_inheritance = true;
+static const bool dc_virtual_inheritance = true;
 
 
 #endif  // WITHIN_PANDA
 #endif  // WITHIN_PANDA
 
 
@@ -56,17 +58,18 @@ PUBLISHED:
 
 
   INLINE DCFile *get_dc_file() const;
   INLINE DCFile *get_dc_file() const;
 
 
-  const string &get_name() const;
-  int get_number() const;
+  INLINE const string &get_name() const;
+  INLINE int get_number() const;
 
 
-  bool has_parent() const;
-  DCClass *get_parent() const;
+  int get_num_parents() const;
+  DCClass *get_parent(int n) const;
   
   
   bool has_constructor() const;
   bool has_constructor() const;
   DCField *get_constructor() const;
   DCField *get_constructor() const;
 
 
   int get_num_fields() const;
   int get_num_fields() const;
   DCField *get_field(int n) const;
   DCField *get_field(int n) const;
+
   DCField *get_field_by_name(const string &name) const;
   DCField *get_field_by_name(const string &name) const;
   DCField *get_field_by_index(int index_number) const;
   DCField *get_field_by_index(int index_number) const;
 
 
@@ -129,6 +132,8 @@ public:
   void output_instance(ostream &out, bool brief, const string &prename, 
   void output_instance(ostream &out, bool brief, const string &prename, 
                        const string &name, const string &postname) const;
                        const string &name, const string &postname) const;
   void generate_hash(HashGenerator &hashgen) const;
   void generate_hash(HashGenerator &hashgen) const;
+  void clear_inherited_fields();
+  void rebuild_inherited_fields();
 
 
   bool add_field(DCField *field);
   bool add_field(DCField *field);
   void add_parent(DCClass *parent);
   void add_parent(DCClass *parent);
@@ -155,7 +160,7 @@ private:
   DCField *_constructor;
   DCField *_constructor;
 
 
   typedef pvector<DCField *> Fields;
   typedef pvector<DCField *> Fields;
-  Fields _fields;
+  Fields _fields, _inherited_fields;
 
 
   typedef pmap<string, DCField *> FieldsByName;
   typedef pmap<string, DCField *> FieldsByName;
   FieldsByName _fields_by_name;
   FieldsByName _fields_by_name;

+ 226 - 0
direct/src/dcparser/dcField.I

@@ -0,0 +1,226 @@
+// Filename: dcField.I
+// Created by:  drose (10Jan06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::get_number
+//       Access: Published
+//  Description: Returns a unique index number associated with this
+//               field.  This is defined implicitly when the .dc
+//               file(s) are read.
+////////////////////////////////////////////////////////////////////
+INLINE int DCField::
+get_number() const {
+  return _number;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::get_class
+//       Access: Published
+//  Description: Returns the DCClass pointer for the class that
+//               contains this field.
+////////////////////////////////////////////////////////////////////
+INLINE DCClass *DCField::
+get_class() const {
+  return _dclass;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::has_default_value
+//       Access: Published
+//  Description: Returns true if a default value has been explicitly
+//               established for this field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+has_default_value() const {
+  return _has_default_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::get_default_value
+//       Access: Published
+//  Description: Returns the default value for this field.  If a
+//               default value has been explicitly set
+//               (e.g. has_default_value() returns true), returns that
+//               value; otherwise, returns an implicit default for the
+//               field.
+////////////////////////////////////////////////////////////////////
+INLINE const string &DCField::
+get_default_value() const {
+  if (_default_value_stale) {
+    ((DCField *)this)->refresh_default_value();
+  }
+  return _default_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_required
+//       Access: Published
+//  Description: Returns true if the "required" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_required() const {
+  return has_keyword("required");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_broadcast
+//       Access: Published
+//  Description: Returns true if the "broadcast" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_broadcast() const {
+  return has_keyword("broadcast");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_ram
+//       Access: Published
+//  Description: Returns true if the "ram" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_ram() const {
+  return has_keyword("ram");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_db
+//       Access: Published
+//  Description: Returns true if the "db" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_db() const {
+  return has_keyword("db");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_clsend
+//       Access: Published
+//  Description: Returns true if the "clsend" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_clsend() const {
+  return has_keyword("clsend");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_clrecv
+//       Access: Published
+//  Description: Returns true if the "clrecv" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_clrecv() const {
+  return has_keyword("clrecv");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_ownsend
+//       Access: Published
+//  Description: Returns true if the "ownsend" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_ownsend() const {
+  return has_keyword("ownsend");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_ownrecv
+//       Access: Published
+//  Description: Returns true if the "ownrecv" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_ownrecv() const {
+  return has_keyword("ownrecv");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::is_airecv
+//       Access: Published
+//  Description: Returns true if the "airecv" flag is set for this
+//               field, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCField::
+is_airecv() const {
+  return has_keyword("airecv");
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function : DCField::output
+//       Access : Published
+//  Description : Write a string representation of this instance to
+//                <out>.
+////////////////////////////////////////////////////////////////////
+INLINE void DCField::
+output(ostream &out) const {
+  output(out, true);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function : DCField::
+//       Access : Published
+//  Description : Write a string representation of this instance to
+//                <out>.
+////////////////////////////////////////////////////////////////////
+INLINE void DCField::
+write(ostream &out, int indent_level) const {
+  write(out, false, indent_level);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::set_number
+//       Access: Public
+//  Description: Assigns the unique number to this field.  This is
+//               normally called only by the DCClass interface as the
+//               field is added.
+////////////////////////////////////////////////////////////////////
+INLINE void DCField::
+set_number(int number) {
+  _number = number;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::set_class
+//       Access: Public
+//  Description: Assigns the class pointer to this field.  This is
+//               normally called only by the DCClass interface as the
+//               field is added.
+////////////////////////////////////////////////////////////////////
+INLINE void DCField::
+set_class(DCClass *dclass) {
+  _dclass = dclass;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::set_default_value
+//       Access: Public
+//  Description: Establishes a default value for this field.
+////////////////////////////////////////////////////////////////////
+INLINE void DCField::
+set_default_value(const string &default_value) {
+  _default_value = default_value;
+  _has_default_value = true;
+  _default_value_stale = false;
+}

+ 14 - 184
direct/src/dcparser/dcField.cxx

@@ -32,9 +32,11 @@
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DCField::
 DCField::
-DCField()
+DCField() : 
+  _dclass(NULL)
 #ifdef WITHIN_PANDA
 #ifdef WITHIN_PANDA
-  : _field_update_pcollector("DCField")
+  ,
+  _field_update_pcollector("DCField")
 #endif
 #endif
 {
 {
   _number = -1;
   _number = -1;
@@ -57,7 +59,8 @@ DCField()
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 DCField::
 DCField::
 DCField(const string &name, DCClass *dclass) : 
 DCField(const string &name, DCClass *dclass) : 
-  DCPackerInterface(name) 
+  DCPackerInterface(name),
+  _dclass(dclass)
 #ifdef WITHIN_PANDA
 #ifdef WITHIN_PANDA
   ,
   ,
   _field_update_pcollector(dclass->_class_update_pcollector, name)
   _field_update_pcollector(dclass->_class_update_pcollector, name)
@@ -85,18 +88,6 @@ DCField::
 ~DCField() {
 ~DCField() {
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::get_number
-//       Access: Published
-//  Description: Returns a unique index number associated with this
-//               field.  This is defined implicitly when the .dc
-//               file(s) are read.
-////////////////////////////////////////////////////////////////////
-int DCField::
-get_number() const {
-  return _number;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCField::as_field
 //     Function: DCField::as_field
 //       Access: Published, Virtual
 //       Access: Published, Virtual
@@ -250,155 +241,6 @@ validate_ranges(const string &packed_data) const {
   return (packer.get_num_unpacked_bytes() == packed_data.length());
   return (packer.get_num_unpacked_bytes() == packed_data.length());
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::has_default_value
-//       Access: Published
-//  Description: Returns true if a default value has been explicitly
-//               established for this field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-has_default_value() const {
-  return _has_default_value;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::get_default_value
-//       Access: Published
-//  Description: Returns the default value for this field.  If a
-//               default value has been explicitly set
-//               (e.g. has_default_value() returns true), returns that
-//               value; otherwise, returns an implicit default for the
-//               field.
-////////////////////////////////////////////////////////////////////
-const string &DCField::
-get_default_value() const {
-  if (_default_value_stale) {
-    ((DCField *)this)->refresh_default_value();
-  }
-  return _default_value;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_required
-//       Access: Published
-//  Description: Returns true if the "required" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_required() const {
-  return has_keyword("required");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_broadcast
-//       Access: Published
-//  Description: Returns true if the "broadcast" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_broadcast() const {
-  return has_keyword("broadcast");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_ram
-//       Access: Published
-//  Description: Returns true if the "ram" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_ram() const {
-  return has_keyword("ram");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_db
-//       Access: Published
-//  Description: Returns true if the "db" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_db() const {
-  return has_keyword("db");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_clsend
-//       Access: Published
-//  Description: Returns true if the "clsend" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_clsend() const {
-  return has_keyword("clsend");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_clrecv
-//       Access: Published
-//  Description: Returns true if the "clrecv" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_clrecv() const {
-  return has_keyword("clrecv");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_ownsend
-//       Access: Published
-//  Description: Returns true if the "ownsend" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_ownsend() const {
-  return has_keyword("ownsend");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_ownrecv
-//       Access: Published
-//  Description: Returns true if the "ownrecv" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_ownrecv() const {
-  return has_keyword("ownrecv");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::is_airecv
-//       Access: Published
-//  Description: Returns true if the "airecv" flag is set for this
-//               field, false otherwise.
-////////////////////////////////////////////////////////////////////
-bool DCField::
-is_airecv() const {
-  return has_keyword("airecv");
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function : DCField::output
-//       Access : Published
-//  Description : Write a string representation of this instance to
-//                <out>.
-////////////////////////////////////////////////////////////////////
-void DCField::
-output(ostream &out) const {
-  output(out, true);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function : DCField::
-//       Access : Published
-//  Description : Write a string representation of this instance to
-//                <out>.
-////////////////////////////////////////////////////////////////////
-void DCField::
-write(ostream &out, int indent_level) const {
-  write(out, false, indent_level);
-}
-
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCField::pack_args
 //     Function: DCField::pack_args
@@ -623,7 +465,6 @@ ai_format_update(int do_id, CHANNEL_TYPE to_id, CHANNEL_TYPE from_id, PyObject *
   packer.raw_pack_uint8(1);
   packer.raw_pack_uint8(1);
   packer.RAW_PACK_CHANNEL(to_id);
   packer.RAW_PACK_CHANNEL(to_id);
   packer.RAW_PACK_CHANNEL(from_id);
   packer.RAW_PACK_CHANNEL(from_id);
-  //packer.raw_pack_uint8('A');
   packer.raw_pack_uint16(STATESERVER_OBJECT_UPDATE_FIELD);
   packer.raw_pack_uint16(STATESERVER_OBJECT_UPDATE_FIELD);
   packer.raw_pack_uint32(do_id);
   packer.raw_pack_uint32(do_id);
   packer.raw_pack_uint16(_number);
   packer.raw_pack_uint16(_number);
@@ -683,27 +524,16 @@ pack_default_value(DCPackData &pack_data, bool &) const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: DCField::set_number
-//       Access: Public
-//  Description: Assigns the unique number to this field.  This is
-//               normally called only by the DCClass interface as the
-//               field is added.
-////////////////////////////////////////////////////////////////////
-void DCField::
-set_number(int number) {
-  _number = number;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCField::set_default_value
-//       Access: Public
-//  Description: Establishes a default value for this field.
+//     Function: DCField::set_name
+//       Access: Public, Virtual
+//  Description: Sets the name of this field.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DCField::
 void DCField::
-set_default_value(const string &default_value) {
-  _default_value = default_value;
-  _has_default_value = true;
-  _default_value_stale = false;
+set_name(const string &name) {
+  DCPackerInterface::set_name(name);
+  if (_dclass != (DCClass *)NULL) {
+    _dclass->_dc_file->mark_inherited_fields_stale();
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 22 - 16
direct/src/dcparser/dcField.h

@@ -48,7 +48,8 @@ public:
   virtual ~DCField();
   virtual ~DCField();
 
 
 PUBLISHED:
 PUBLISHED:
-  int get_number() const;
+  INLINE int get_number() const;
+  INLINE DCClass *get_class() const;
 
 
   virtual DCField *as_field();
   virtual DCField *as_field();
   virtual const DCField *as_field() const;
   virtual const DCField *as_field() const;
@@ -64,21 +65,21 @@ PUBLISHED:
 
 
   bool validate_ranges(const string &packed_data) const;
   bool validate_ranges(const string &packed_data) const;
 
 
-  bool has_default_value() const;
-  const string &get_default_value() const;
+  INLINE bool has_default_value() const;
+  INLINE const string &get_default_value() const;
 
 
-  bool is_required() const;
-  bool is_broadcast() const;
-  bool is_ram() const;
-  bool is_db() const;
-  bool is_clsend() const;
-  bool is_clrecv() const;
-  bool is_ownsend() const;
-  bool is_ownrecv() const;
-  bool is_airecv() const;
+  INLINE bool is_required() const;
+  INLINE bool is_broadcast() const;
+  INLINE bool is_ram() const;
+  INLINE bool is_db() const;
+  INLINE bool is_clsend() const;
+  INLINE bool is_clrecv() const;
+  INLINE bool is_ownsend() const;
+  INLINE bool is_ownrecv() const;
+  INLINE bool is_airecv() const;
 
 
-  void output(ostream &out) const;
-  void write(ostream &out, int indent_level) const;
+  INLINE void output(ostream &out) const;
+  INLINE void write(ostream &out, int indent_level) const;
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   bool pack_args(DCPacker &packer, PyObject *sequence) const;
   bool pack_args(DCPacker &packer, PyObject *sequence) const;
@@ -96,14 +97,17 @@ public:
   virtual void write(ostream &out, bool brief, int indent_level) const=0;
   virtual void write(ostream &out, bool brief, int indent_level) const=0;
   virtual void generate_hash(HashGenerator &hashgen) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
+  virtual void set_name(const string &name);
 
 
-  void set_number(int number);
-  void set_default_value(const string &default_value);
+  INLINE void set_number(int number);
+  INLINE void set_class(DCClass *dclass);
+  INLINE void set_default_value(const string &default_value);
 
 
 protected:
 protected:
   void refresh_default_value();
   void refresh_default_value();
 
 
 protected:
 protected:
+  DCClass *_dclass;
   int _number;
   int _number;
   bool _default_value_stale;
   bool _default_value_stale;
   bool _has_default_value;
   bool _has_default_value;
@@ -121,4 +125,6 @@ INLINE ostream &operator << (ostream &out, const DCField &field) {
   return out;
   return out;
 }
 }
 
 
+#include "dcField.I"
+
 #endif
 #endif

+ 58 - 0
direct/src/dcparser/dcFile.I

@@ -0,0 +1,58 @@
+// Filename: dcFile.I
+// Created by:  drose (10Jan06)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCFile::all_objects_valid
+//       Access: Published
+//  Description: Returns true if all of the classes read from the DC
+//               file were defined and valid, or false if any of them
+//               were undefined ("bogus classes").  If this is true,
+//               we might have read a partial file.
+////////////////////////////////////////////////////////////////////
+INLINE bool DCFile::
+all_objects_valid() const {
+  return _all_objects_valid;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCFile::check_inherited_fields
+//       Access: Public
+//  Description: Rebuilds all of the inherited fields tables, if
+//               necessary.
+////////////////////////////////////////////////////////////////////
+INLINE void DCFile::
+check_inherited_fields() {
+  if (_inherited_fields_stale) {
+    rebuild_inherited_fields();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCFile::mark_inherited_fields_stale
+//       Access: Public
+//  Description: Indicates that something has changed in one or more
+//               of the inheritance chains or the set of fields; the
+//               next time check_inherited_fields() is called, the
+//               inherited fields tables of all classes will be
+//               rebuilt.
+////////////////////////////////////////////////////////////////////
+INLINE void DCFile::
+mark_inherited_fields_stale() {
+  _inherited_fields_stale = true;
+}

+ 27 - 14
direct/src/dcparser/dcFile.cxx

@@ -42,6 +42,7 @@
 DCFile::
 DCFile::
 DCFile() {
 DCFile() {
   _all_objects_valid = true;
   _all_objects_valid = true;
+  _inherited_fields_stale = false;
 
 
   setup_default_keywords();
   setup_default_keywords();
 }
 }
@@ -83,6 +84,7 @@ clear() {
   setup_default_keywords();
   setup_default_keywords();
 
 
   _all_objects_valid = true;
   _all_objects_valid = true;
+  _inherited_fields_stale = false;
 }
 }
 
 
 #ifdef WITHIN_PANDA
 #ifdef WITHIN_PANDA
@@ -342,19 +344,6 @@ get_field_by_index(int index_number) const {
   return NULL;
   return NULL;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DCFile::all_objects_valid
-//       Access: Published
-//  Description: Returns true if all of the classes read from the DC
-//               file were defined and valid, or false if any of them
-//               were undefined ("bogus classes").  If this is true,
-//               we might have read a partial file.
-////////////////////////////////////////////////////////////////////
-bool DCFile::
-all_objects_valid() const {
-  return _all_objects_valid;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::get_num_import_modules
 //     Function: DCFile::get_num_import_modules
 //       Access: Published
 //       Access: Published
@@ -510,6 +499,11 @@ get_hash() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void DCFile::
 void DCFile::
 generate_hash(HashGenerator &hashgen) const {
 generate_hash(HashGenerator &hashgen) const {
+  if (dc_virtual_inheritance) {
+    // Just to make the hash number change in this case.
+    hashgen.add_int(1);
+  }
+
   hashgen.add_int(_classes.size());
   hashgen.add_int(_classes.size());
   Classes::const_iterator ci;
   Classes::const_iterator ci;
   for (ci = _classes.begin(); ci != _classes.end(); ++ci) {
   for (ci = _classes.begin(); ci != _classes.end(); ++ci) {
@@ -696,7 +690,7 @@ set_new_index_number(DCField *field) {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCFile::setup_default_keywords
 //     Function: DCFile::setup_default_keywords
-//       Access: Public
+//       Access: Private
 //  Description: Adds an entry for each of the default keywords that
 //  Description: Adds an entry for each of the default keywords that
 //               are defined for every DCFile for legacy reasons.
 //               are defined for every DCFile for legacy reasons.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -729,3 +723,22 @@ setup_default_keywords() {
     _things_to_delete.push_back(keyword);
     _things_to_delete.push_back(keyword);
   }
   }
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCFile::rebuild_inherited_fields
+//       Access: Private
+//  Description: Reconstructs the inherited fields table of all
+//               classes.
+////////////////////////////////////////////////////////////////////
+void DCFile::
+rebuild_inherited_fields() {
+  _inherited_fields_stale = false;
+
+  Classes::iterator ci;
+  for (ci = _classes.begin(); ci != _classes.end(); ++ci) {
+    (*ci)->clear_inherited_fields();
+  }
+  for (ci = _classes.begin(); ci != _classes.end(); ++ci) {
+    (*ci)->rebuild_inherited_fields();
+  }
+}

+ 7 - 1
direct/src/dcparser/dcFile.h

@@ -59,7 +59,7 @@ PUBLISHED:
 
 
   DCField *get_field_by_index(int index_number) const;
   DCField *get_field_by_index(int index_number) const;
 
 
-  bool all_objects_valid() const;
+  INLINE bool all_objects_valid() const;
 
 
   int get_num_import_modules() const;
   int get_num_import_modules() const;
   string get_import_module(int n) const;
   string get_import_module(int n) const;
@@ -87,9 +87,12 @@ public:
   void add_thing_to_delete(DCDeclaration *decl);
   void add_thing_to_delete(DCDeclaration *decl);
 
 
   void set_new_index_number(DCField *field);
   void set_new_index_number(DCField *field);
+  INLINE void check_inherited_fields();
+  INLINE void mark_inherited_fields_stale();
 
 
 private:
 private:
   void setup_default_keywords();
   void setup_default_keywords();
+  void rebuild_inherited_fields();
 
 
   typedef pvector<DCClass *> Classes;
   typedef pvector<DCClass *> Classes;
   Classes _classes;
   Classes _classes;
@@ -124,8 +127,11 @@ private:
   FieldsByIndex _fields_by_index;
   FieldsByIndex _fields_by_index;
 
 
   bool _all_objects_valid;
   bool _all_objects_valid;
+  bool _inherited_fields_stale;
 };
 };
 
 
+#include "dcFile.I"
+
 #endif
 #endif
 
 
 
 

+ 0 - 10
direct/src/dcparser/dcPackerInterface.I

@@ -41,16 +41,6 @@ check_match(const DCPackerInterface *other) const {
   return do_check_match(other);
   return do_check_match(other);
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: DCPackerInterface::set_name
-//       Access: Public
-//  Description: Sets the name of this field.
-////////////////////////////////////////////////////////////////////
-INLINE void DCPackerInterface::
-set_name(const string &name) {
-  _name = name;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::has_fixed_byte_size
 //     Function: DCPackerInterface::has_fixed_byte_size
 //       Access: Public
 //       Access: Public

+ 10 - 0
direct/src/dcparser/dcPackerInterface.cxx

@@ -190,6 +190,16 @@ check_match(const string &description, DCFile *dcfile) const {
   return false;
   return false;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::set_name
+//       Access: Public, Virtual
+//  Description: Sets the name of this field.
+////////////////////////////////////////////////////////////////////
+void DCPackerInterface::
+set_name(const string &name) {
+  _name = name;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::calc_num_nested_fields
 //     Function: DCPackerInterface::calc_num_nested_fields
 //       Access: Public, Virtual
 //       Access: Public, Virtual

+ 1 - 1
direct/src/dcparser/dcPackerInterface.h

@@ -93,7 +93,7 @@ PUBLISHED:
   bool check_match(const string &description, DCFile *dcfile = NULL) const;
   bool check_match(const string &description, DCFile *dcfile = NULL) const;
 
 
 public:
 public:
-  INLINE void set_name(const string &name);
+  virtual void set_name(const string &name);
   INLINE bool has_fixed_byte_size() const;
   INLINE bool has_fixed_byte_size() const;
   INLINE size_t get_fixed_byte_size() const;
   INLINE size_t get_fixed_byte_size() const;
   INLINE bool has_fixed_structure() const;
   INLINE bool has_fixed_structure() const;