Browse Source

default values

David Rose 21 years ago
parent
commit
9222e02084

+ 43 - 0
direct/src/dcparser/dcArrayParameter.cxx

@@ -54,6 +54,10 @@ DCArrayParameter(DCParameter *element_type, const DCUnsignedIntRange &size) :
     _has_range_limits = true;
   }
 
+  if (_element_type->has_default_value()) {
+    _has_default_value = true;
+  }
+
   _has_nested_fields = true;
   _num_nested_fields = _array_size;
   _pack_type = PT_array;
@@ -223,3 +227,42 @@ generate_hash(HashGenerator &hashgen) const {
   _element_type->generate_hash(hashgen);
   _array_size_range.generate_hash(hashgen);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCArrayParameter::pack_default_value
+//       Access: Public, Virtual
+//  Description: Packs the arrayParameter's specified default value (or a
+//               sensible default if no value is specified) into the
+//               stream.  Returns true if the default value is packed,
+//               false if the arrayParameter doesn't know how to pack its
+//               default value.
+////////////////////////////////////////////////////////////////////
+bool DCArrayParameter::
+pack_default_value(DCPackData &pack_data, bool &pack_error) const {
+  if (has_default_value()) {
+    return DCField::pack_default_value(pack_data, pack_error);
+  }
+
+  // If a default value is not specified for a variable-length array,
+  // the default is the minimum array.
+  unsigned int minimum_length = 0;
+  if (!_array_size_range.is_empty()) {
+    minimum_length = _array_size_range.get_min(0);
+  }
+
+  DCPacker packer;
+  packer.begin_pack(this);
+  packer.push();
+  for (unsigned int i = 0; i < minimum_length; i++) {
+    packer.pack_default_value();
+  }
+  packer.pop();
+  if (!packer.end_pack()) {
+    pack_error = true;
+
+  } else {
+    pack_data.append_data(packer.get_data(), packer.get_length());
+  }
+
+  return true;
+}

+ 1 - 0
direct/src/dcparser/dcArrayParameter.h

@@ -53,6 +53,7 @@ public:
   virtual void output_instance(ostream &out, bool brief, const string &prename, 
                                const string &name, const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
+  virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
 private:
   DCParameter *_element_type;

+ 48 - 87
direct/src/dcparser/dcAtomicField.cxx

@@ -33,6 +33,20 @@ DCAtomicField::
 DCAtomicField(const string &name) : DCField(name) {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+DCAtomicField::
+~DCAtomicField() {
+  Elements::iterator ei;  
+  for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
+    delete (*ei);
+  }
+  _elements.clear();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCAtomicField::as_atomic_field
 //       Access: Published, Virtual
@@ -65,7 +79,7 @@ get_num_elements() const {
 DCParameter *DCAtomicField::
 get_element(int n) const {
   nassertr(n >= 0 && n < (int)_elements.size(), NULL);
-  return _elements[n]._param;
+  return _elements[n];
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -80,13 +94,13 @@ get_element(int n) const {
 //               If the element is an array-type element, the returned
 //               value will include the two-byte length preceding the
 //               array data.
+//
+//               This is deprecated; use get_element() instead.
 ////////////////////////////////////////////////////////////////////
 string DCAtomicField::
 get_element_default(int n) const {
-  nassertr(has_element_default(n), string());
   nassertr(n >= 0 && n < (int)_elements.size(), string());
-
-  return _elements[n]._default_value;
+  return _elements[n]->get_default_value();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -94,11 +108,13 @@ get_element_default(int n) const {
 //       Access: Published
 //  Description: Returns true if the nth element of the field has a
 //               default value specified, false otherwise.
+//
+//               This is deprecated; use get_element() instead.
 ////////////////////////////////////////////////////////////////////
 bool DCAtomicField::
 has_element_default(int n) const {
   nassertr(n >= 0 && n < (int)_elements.size(), false);
-  return _elements[n]._has_default_value;
+  return _elements[n]->has_default_value();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -115,7 +131,7 @@ has_element_default(int n) const {
 string DCAtomicField::
 get_element_name(int n) const {
   nassertr(n >= 0 && n < (int)_elements.size(), string());
-  return _elements[n]._param->get_name();
+  return _elements[n]->get_name();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -128,7 +144,7 @@ get_element_name(int n) const {
 DCSubatomicType DCAtomicField::
 get_element_type(int n) const {
   nassertr(n >= 0 && n < (int)_elements.size(), ST_invalid);
-  DCSimpleParameter *simple_parameter = _elements[n]._param->as_simple_parameter();
+  DCSimpleParameter *simple_parameter = _elements[n]->as_simple_parameter();
   nassertr(simple_parameter != (DCSimpleParameter *)NULL, ST_invalid);
   return simple_parameter->get_type();
 }
@@ -148,7 +164,7 @@ get_element_type(int n) const {
 int DCAtomicField::
 get_element_divisor(int n) const {
   nassertr(n >= 0 && n < (int)_elements.size(), 1);
-  DCSimpleParameter *simple_parameter = _elements[n]._param->as_simple_parameter();
+  DCSimpleParameter *simple_parameter = _elements[n]->as_simple_parameter();
   nassertr(simple_parameter != (DCSimpleParameter *)NULL, 1);
   return simple_parameter->get_divisor();
 }
@@ -164,11 +180,11 @@ output(ostream &out, bool brief) const {
 
   if (!_elements.empty()) {
     Elements::const_iterator ei = _elements.begin();
-    (*ei).output(out, brief);
+    output_element(out, brief, *ei);
     ++ei;
     while (ei != _elements.end()) {
       out << ", ";
-      (*ei).output(out, brief);
+      output_element(out, brief, *ei);
       ++ei;
     }
   }
@@ -207,8 +223,7 @@ generate_hash(HashGenerator &hashgen) const {
   hashgen.add_int(_elements.size());
   Elements::const_iterator ei;
   for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
-    const ElementType &element = (*ei);
-    element._param->generate_hash(hashgen);
+    (*ei)->generate_hash(hashgen);
   }
   hashgen.add_int(get_flags());
 }
@@ -224,107 +239,53 @@ generate_hash(HashGenerator &hashgen) const {
 DCPackerInterface *DCAtomicField::
 get_nested_field(int n) const {
   nassertr(n >= 0 && n < (int)_elements.size(), NULL);
-  return _elements[n]._param;
+  return _elements[n];
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCAtomicField::add_element
 //       Access: Public
 //  Description: Adds a new element (parameter) to the field.
-//               Normally this is called only during parsing.
+//               Normally this is called only during parsing.  The
+//               DCAtomicField object becomes the owner of the new
+//               pointer and will delete it upon destruction.
 ////////////////////////////////////////////////////////////////////
 void DCAtomicField::
-add_element(const DCAtomicField::ElementType &element) {
+add_element(DCParameter *element) {
   _elements.push_back(element);
   _num_nested_fields = (int)_elements.size();
 
   // See if we still have a fixed byte size.
   if (_has_fixed_byte_size) {
-    _has_fixed_byte_size = element._param->has_fixed_byte_size();
-    _fixed_byte_size += element._param->get_fixed_byte_size();
+    _has_fixed_byte_size = element->has_fixed_byte_size();
+    _fixed_byte_size += element->get_fixed_byte_size();
   }
   if (_has_fixed_structure) {
-    _has_fixed_structure = element._param->has_fixed_structure();
+    _has_fixed_structure = element->has_fixed_structure();
   }
   if (!_has_range_limits) {
-    _has_range_limits = element._param->has_range_limits();
+    _has_range_limits = element->has_range_limits();
   }
+  if (!_has_default_value) {
+    _has_default_value = element->has_default_value();
+  }
+  _default_value_stale = true;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: DCAtomicField::ElementType::Constructor
-//       Access: Public
-//  Description: The type parameter should be a newly-allocated DCParameter
-//               object; it will eventually be freed with delete when
-//               this object destructs.
-////////////////////////////////////////////////////////////////////
-DCAtomicField::ElementType::
-ElementType(DCParameter *param) {
-  _param = param;
-  _has_default_value = false;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCAtomicField::ElementType::Copy Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-DCAtomicField::ElementType::
-ElementType(const DCAtomicField::ElementType &copy) :
-  _param(copy._param->make_copy()),
-  _default_value(copy._default_value),
-  _has_default_value(copy._has_default_value)
-{
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCAtomicField::ElementType::Copy Assignment Operator
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-void DCAtomicField::ElementType::
-operator = (const DCAtomicField::ElementType &copy) {
-  delete _param;
-  _param = copy._param->make_copy();
-  _default_value = copy._default_value;
-  _has_default_value = copy._has_default_value;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCAtomicField::ElementType::Destructor
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-DCAtomicField::ElementType::
-~ElementType() {
-  delete _param;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCAtomicField::ElementType::set_default_value
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void DCAtomicField::ElementType::
-set_default_value(const string &default_value) {
-  _default_value = default_value;
-  _has_default_value = true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: DCAtomicField::ElementType::output
-//       Access: Public
+//     Function: DCAtomicField::output_element
+//       Access: Private
 //  Description: 
 ////////////////////////////////////////////////////////////////////
-void DCAtomicField::ElementType::
-output(ostream &out, bool brief) const {
-  _param->output(out, brief);
+void DCAtomicField::
+output_element(ostream &out, bool brief, DCParameter *element) const {
+  element->output(out, brief);
 
-  if (!brief && _has_default_value) {
+  if (!brief && element->has_default_value()) {
     out << " = ";
     DCPacker packer;
-    packer.set_unpack_data(_default_value);
-    packer.begin_unpack(_param);
+    packer.set_unpack_data(element->get_default_value());
+    packer.begin_unpack(element);
     packer.unpack_and_format(out);
     packer.end_unpack();
   }

+ 8 - 22
direct/src/dcparser/dcAtomicField.h

@@ -38,48 +38,34 @@
 class EXPCL_DIRECT DCAtomicField : public DCField {
 public:
   DCAtomicField(const string &name);
+  virtual ~DCAtomicField();
 
 PUBLISHED:
   virtual DCAtomicField *as_atomic_field();
 
   int get_num_elements() const;
   DCParameter *get_element(int n) const;
+
+  // These five methods are deprecated and will be removed soon.
   string get_element_default(int n) const;
   bool has_element_default(int n) const;
-
-  // These three methods are deprecated and will be removed soon.
   string get_element_name(int n) const;
   DCSubatomicType get_element_type(int n) const;
   int get_element_divisor(int n) const;
   
 public:
+  void add_element(DCParameter *element);
+
   virtual void output(ostream &out, bool brief) const;
   virtual void write(ostream &out, bool brief, int indent_level) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
 
   virtual DCPackerInterface *get_nested_field(int n) const;
 
-public:
-  class ElementType {
-  public:
-    ElementType(DCParameter *param);
-    ElementType(const ElementType &copy);
-    void operator = (const ElementType &copy);
-    ~ElementType();
-
-    void set_default_value(const string &default_value);
-
-    void output(ostream &out, bool brief) const;
-
-    DCParameter *_param;
-    string _default_value;
-    bool _has_default_value;
-  };
-
-  void add_element(const ElementType &element);
-
 private:
-  typedef pvector<ElementType> Elements;
+  void output_element(ostream &out, bool brief, DCParameter *element) const;
+
+  typedef pvector<DCParameter *> Elements;
   Elements _elements;
 };
 

+ 6 - 2
direct/src/dcparser/dcClassParameter.cxx

@@ -42,11 +42,15 @@ DCClassParameter(const DCClass *dclass) :
 
   _nested_fields.reserve(_num_nested_fields);
   if (_dclass->has_constructor()) {
-    _nested_fields.push_back(_dclass->get_constructor());
+    DCField *field = _dclass->get_constructor();
+    _nested_fields.push_back(field);
+    _has_default_value = _has_default_value || field->has_default_value();
   }
   int i;
   for (i = 0 ; i < num_fields; i++) {
-    _nested_fields.push_back(_dclass->get_inherited_field(i));
+    DCField *field = _dclass->get_inherited_field(i);
+    _nested_fields.push_back(field);
+    _has_default_value = _has_default_value || field->has_default_value();
   }
 
   // If all of the nested fields have a fixed byte size, then so does

+ 83 - 0
direct/src/dcparser/dcField.cxx

@@ -30,6 +30,8 @@ DCField::
 DCField(const string &name) : DCPackerInterface(name) {
   _number = -1;
   _flags = 0;
+  _has_default_value = false;
+  _default_value_stale = true;
 
   _has_nested_fields = true;
   _num_nested_fields = 0;
@@ -180,6 +182,34 @@ validate_ranges(const string &packed_data) const {
   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
@@ -488,6 +518,28 @@ generate_hash(HashGenerator &hashgen) const {
   hashgen.add_string(_name);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::pack_default_value
+//       Access: Public, Virtual
+//  Description: Packs the field's specified default value (or a
+//               sensible default if no value is specified) into the
+//               stream.  Returns true if the default value is packed,
+//               false if the field doesn't know how to pack its
+//               default value.
+////////////////////////////////////////////////////////////////////
+bool DCField::
+pack_default_value(DCPackData &pack_data, bool &) const {
+  // The default behavior is to pack the default value if we got it;
+  // otherwise, to return false and let the packer visit our nested
+  // elements.
+  if (!_default_value_stale) {
+    pack_data.append_data(_default_value.data(), _default_value.length());
+    return true;
+  }
+
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCField::set_number
 //       Access: Public
@@ -500,6 +552,18 @@ set_number(int number) {
   _number = number;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::set_default_value
+//       Access: Public
+//  Description: Establishes a default value for this field.
+////////////////////////////////////////////////////////////////////
+void DCField::
+set_default_value(const string &default_value) {
+  _default_value = default_value;
+  _has_default_value = true;
+  _default_value_stale = false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCField::add_flag
 //       Access: Public
@@ -530,6 +594,25 @@ get_flags() const {
   return _flags;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCField::refresh_default_value
+//       Access: Protected
+//  Description: Recomputes the default value of the field by
+//               repacking it.
+////////////////////////////////////////////////////////////////////
+void DCField::
+refresh_default_value() {
+  DCPacker packer;
+  packer.begin_pack(this);
+  packer.pack_default_value();
+  if (!packer.end_pack()) {
+    cerr << "Error while packing default value for " << get_name() << "\n";
+  } else {
+    _default_value.assign(packer.get_data(), packer.get_length());
+  }
+  _default_value_stale = false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCField::output_flags
 //       Access: Protected

+ 10 - 0
direct/src/dcparser/dcField.h

@@ -54,6 +54,9 @@ PUBLISHED:
 
   bool validate_ranges(const string &packed_data) const;
 
+  bool has_default_value() const;
+  const string &get_default_value() const;
+
   bool is_required() const;
   bool is_broadcast() const;
   bool is_p2p() const;
@@ -81,8 +84,10 @@ public:
   virtual void output(ostream &out, bool brief) const=0;
   virtual void write(ostream &out, bool brief, int indent_level) const=0;
   virtual void generate_hash(HashGenerator &hashgen) const;
+  virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
   void set_number(int number);
+  void set_default_value(const string &default_value);
 
   enum Flags {
     F_required        = 0x0001,
@@ -100,13 +105,18 @@ public:
   int get_flags() const;
 
 protected:
+  void refresh_default_value();
   void output_flags(ostream &out) const;
 
 protected:
   int _number;
+  bool _default_value_stale;
+  bool _has_default_value;
 
 private:
   int _flags;  // A bitmask union of any of the above values.
+
+  string _default_value;
 };
 
 #endif

+ 4 - 0
direct/src/dcparser/dcMolecularField.cxx

@@ -105,6 +105,10 @@ add_atomic(DCAtomicField *atomic) {
   if (!_has_range_limits) {
     _has_range_limits = atomic->has_range_limits();
   }
+  if (!_has_default_value) {
+    _has_default_value = atomic->has_default_value();
+  }
+  _default_value_stale = true;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 29 - 1
direct/src/dcparser/dcPacker.cxx

@@ -560,6 +560,34 @@ pop() {
   advance();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPacker::pack_default_value
+//       Access: Published
+//  Description: Adds the default value for the current element into
+//               the stream.  If no default has been set for the
+//               current element, creates a sensible default.
+////////////////////////////////////////////////////////////////////
+void DCPacker::
+pack_default_value() {
+  nassertv(_mode == M_pack || _mode == M_repack);
+  if (_current_field == NULL) {
+    _pack_error = true;
+  } else {
+    if (_current_field->pack_default_value(_pack_data, _pack_error)) {
+      advance();
+
+    } else {
+      // If the single field didn't know how to pack a default value,
+      // try packing nested fields.
+      push();
+      while (more_nested_fields()) {
+        pack_default_value();
+      }
+      pop();
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPacker::unpack_validate
 //       Access: Published
@@ -938,7 +966,7 @@ unpack_and_format(ostream &out) {
       }
 
       push();
-      while (more_nested_fields()) {
+      while (more_nested_fields() && !had_pack_error()) {
         unpack_and_format(out);
 
         if (more_nested_fields()) {

+ 1 - 0
direct/src/dcparser/dcPacker.h

@@ -82,6 +82,7 @@ PUBLISHED:
   INLINE void pack_uint64(PN_uint64 value);
   INLINE void pack_string(const string &value);
   INLINE void pack_literal_value(const string &value);
+  void pack_default_value();
 
   INLINE double unpack_double();
   INLINE int unpack_int();

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

@@ -210,6 +210,20 @@ pack_string(DCPackData &, const string &, bool &pack_error, bool &) const {
   pack_error = true;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCPackerInterface::pack_default_value
+//       Access: Public, Virtual
+//  Description: Packs the field's specified default value (or a
+//               sensible default if no value is specified) into the
+//               stream.  Returns true if the default value is packed,
+//               false if the field doesn't know how to pack its
+//               default value.
+////////////////////////////////////////////////////////////////////
+bool DCPackerInterface::
+pack_default_value(DCPackData &, bool &) const {
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCPackerInterface::unpack_double
 //       Access: Public, Virtual

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

@@ -109,6 +109,7 @@ public:
                            bool &pack_error, bool &range_error) const;
   virtual void pack_string(DCPackData &pack_data, const string &value,
                            bool &pack_error, bool &range_error) const;
+  virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
   virtual void unpack_double(const char *data, size_t length, size_t &p, 
                              double &value, bool &pack_error, bool &range_error) const;

+ 1 - 1
direct/src/dcparser/dcParameter.cxx

@@ -120,7 +120,7 @@ get_typedef() const {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: DCParameter::set_typedef
-//       Access: Published
+//       Access: Public
 //  Description: Records the DCTypedef object that generated this
 //               parameter.  This is normally called only from
 //               DCTypedef::make_new_parameter().

+ 3 - 6
direct/src/dcparser/dcParser.yxx

@@ -32,7 +32,6 @@ static DCClass *current_class = (DCClass *)NULL;
 static DCSwitch *current_switch = (DCSwitch *)NULL;
 static DCAtomicField *current_atomic = (DCAtomicField *)NULL;
 static DCMolecularField *current_molecular = (DCMolecularField *)NULL;
-static DCAtomicField::ElementType atomic_element(new DCSimpleParameter(ST_invalid));
 static DCParameter *current_parameter = (DCParameter *)NULL;
 static DCPacker default_packer;
 static DCPacker *current_packer;
@@ -424,8 +423,7 @@ nonempty_parameter_list:
 atomic_element:
         parameter
 {
-  atomic_element = DCAtomicField::ElementType($1);
-  current_atomic->add_element(atomic_element);
+  current_atomic->add_element($1);
 }
 	| parameter '=' 
 {
@@ -436,9 +434,8 @@ atomic_element:
 	parameter_value
 {
   bool is_valid = $1->is_valid();
-  atomic_element = DCAtomicField::ElementType($1);
   if (current_packer->end_pack()) {
-    atomic_element.set_default_value(current_packer->get_string());
+    $1->set_default_value(current_packer->get_string());
 
   } else {
     if (is_valid) {
@@ -448,7 +445,7 @@ atomic_element:
     // error (there's no way for us to validate the syntax).  So we'll
     // just ignore the default value in this case.
   }
-  current_atomic->add_element(atomic_element);
+  current_atomic->add_element($1);
 }
 	;
 

+ 98 - 1
direct/src/dcparser/dcSimpleParameter.cxx

@@ -666,7 +666,7 @@ pack_int(DCPackData &pack_data, int value,
 ////////////////////////////////////////////////////////////////////
 void DCSimpleParameter::
 pack_uint(DCPackData &pack_data, unsigned int value,
-            bool &pack_error, bool &range_error) const {
+          bool &pack_error, bool &range_error) const {
   unsigned int int_value = value * _divisor;
 
   switch (_type) {
@@ -912,6 +912,103 @@ pack_string(DCPackData &pack_data, const string &value,
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSimpleParameter::pack_default_value
+//       Access: Public, Virtual
+//  Description: Packs the simpleParameter's specified default value (or a
+//               sensible default if no value is specified) into the
+//               stream.  Returns true if the default value is packed,
+//               false if the simpleParameter doesn't know how to pack its
+//               default value.
+////////////////////////////////////////////////////////////////////
+bool DCSimpleParameter::
+pack_default_value(DCPackData &pack_data, bool &pack_error) const {
+  if (has_default_value()) {
+    return DCField::pack_default_value(pack_data, pack_error);
+  }
+
+  if (_has_nested_fields) {
+    // If the simple type is an array (or string) type, pack the
+    // appropriate length array, with code similar to
+    // DCArrayParameter::pack_default_value().
+
+    unsigned int minimum_length = 0;
+    if (!_uint_range.is_empty()) {
+      minimum_length = _uint_range.get_min(0);
+    }
+    
+    DCPacker packer;
+    packer.begin_pack(this);
+    packer.push();
+    for (unsigned int i = 0; i < minimum_length; i++) {
+      packer.pack_default_value();
+    }
+    packer.pop();
+    if (!packer.end_pack()) {
+      pack_error = true;
+      
+    } else {
+      pack_data.append_data(packer.get_data(), packer.get_length());
+    }
+
+  } else {
+    // Otherwise, if it's just a simple numeric type, pack a zero or
+    // the minimum value.
+    switch (_type) {
+    case ST_int8:
+    case ST_int16:
+    case ST_int32:
+      if (_int_range.is_in_range(0)) {
+        pack_int(pack_data, 0, pack_error, pack_error);
+      } else {
+        pack_int(pack_data, _int_range.get_min(0), pack_error, pack_error);
+      }
+      break;
+
+    case ST_int64:
+      if (_int64_range.is_in_range(0)) {
+        pack_int64(pack_data, 0, pack_error, pack_error);
+      } else {
+        pack_int64(pack_data, _int64_range.get_min(0), pack_error, pack_error);
+      }
+      break;
+
+    case ST_char:
+    case ST_uint8:
+    case ST_uint16:
+    case ST_uint32:
+      if (_uint_range.is_in_range(0)) {
+        pack_uint(pack_data, 0, pack_error, pack_error);
+      } else {
+        pack_uint(pack_data, _uint_range.get_min(0), pack_error, pack_error);
+      }
+      break;
+
+    case ST_uint64:
+      if (_uint64_range.is_in_range(0)) {
+        pack_uint64(pack_data, 0, pack_error, pack_error);
+      } else {
+        pack_uint64(pack_data, _uint64_range.get_min(0), pack_error, pack_error);
+      }
+      break;
+      
+    case ST_float64:
+      if (_double_range.is_in_range(0.0)) {
+        pack_double(pack_data, 0.0, pack_error, pack_error);
+      } else {
+        pack_double(pack_data, _double_range.get_min(0), pack_error, pack_error);
+      }
+      break;
+      
+    default:
+      pack_error = true;
+    }
+  }
+  return true;
+}
+
+
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSimpleParameter::unpack_double
 //       Access: Public, Virtual

+ 1 - 0
direct/src/dcparser/dcSimpleParameter.h

@@ -65,6 +65,7 @@ public:
                            bool &pack_error, bool &range_error) const;
   virtual void pack_string(DCPackData &pack_data, const string &value,
                            bool &pack_error, bool &range_error) const;
+  virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
   virtual void unpack_double(const char *data, size_t length, size_t &p, 
                              double &value, bool &pack_error, bool &range_error) const;

+ 42 - 0
direct/src/dcparser/dcSwitch.cxx

@@ -361,6 +361,44 @@ generate_hash(HashGenerator &hashgen) const {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitch::pack_default_value
+//       Access: Public
+//  Description: Packs the switchParameter's specified default value (or a
+//               sensible default if no value is specified) into the
+//               stream.  Returns true if the default value is packed,
+//               false if the switchParameter doesn't know how to pack its
+//               default value.
+////////////////////////////////////////////////////////////////////
+bool DCSwitch::
+pack_default_value(DCPackData &pack_data, bool &pack_error) const {
+  if (_cases.empty()) {
+    pack_error = true;
+    return true;
+  }
+
+  // The default value for a switch is the first case.
+
+  DCPacker packer;
+  packer.begin_pack(_cases[0]);
+  packer.pack_literal_value(_cases[0]->_value);
+  if (!packer.end_pack()) {
+    pack_error = true;
+  }
+
+  // Then everything within the case gets its normal default.
+  for (size_t i = 1; i < _cases[0]->_fields.size(); i++) {
+    packer.begin_pack(_cases[0]->_fields[i]);
+    packer.pack_default_value();
+    if (!packer.end_pack()) {
+      pack_error = true;
+    }
+  }
+  pack_data.append_data(packer.get_data(), packer.get_length());
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DCSwitch::SwitchCase::Constructor
 //       Access: Public
@@ -379,6 +417,7 @@ SwitchCase(const string &name, const string &value) :
   _fixed_byte_size = 0;
   _has_fixed_structure = true;
   _has_range_limits = false;
+  _has_default_value = false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -449,5 +488,8 @@ add_field(DCField *field) {
   if (!_has_range_limits) {
     _has_range_limits = field->has_range_limits();
   }
+  if (!_has_default_value) {
+    _has_default_value = field->has_default_value();
+  }
   return true;
 }

+ 7 - 4
direct/src/dcparser/dcSwitch.h

@@ -67,11 +67,9 @@ public:
                       const string &prename, const string &name,
                       const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
+  virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
-private:
-  string _name;
-  DCParameter *_key_parameter;
-
+public:
   typedef pvector<DCField *> Fields;
   typedef pmap<string, DCField *> FieldsByName;
 
@@ -86,8 +84,13 @@ private:
     string _value;
     Fields _fields;
     FieldsByName _fields_by_name;
+    bool _has_default_value;
   };
 
+private:
+  string _name;
+  DCParameter *_key_parameter;
+
   typedef pvector<SwitchCase *> Cases;
   Cases _cases;
 

+ 21 - 1
direct/src/dcparser/dcSwitchParameter.cxx

@@ -47,13 +47,14 @@ DCSwitchParameter(const DCSwitch *dswitch) :
   DCParameter *key_parameter = dswitch->get_key_parameter();
   _has_fixed_byte_size = _has_fixed_byte_size && key_parameter->has_fixed_byte_size();
   _has_range_limits = _has_range_limits || key_parameter->has_range_limits();
+  _has_default_value = _has_default_value || key_parameter->has_default_value();
 
   int num_cases = _dswitch->get_num_cases();
   if (num_cases > 0) {
     _fixed_byte_size = _dswitch->get_case(0)->get_fixed_byte_size();
     
     for (int i = 0; i < num_cases; i++) {
-      const DCPackerInterface *dcase = _dswitch->get_case(i);
+      const DCSwitch::SwitchCase *dcase = (const DCSwitch::SwitchCase *)_dswitch->get_case(i);
       if (!dcase->has_fixed_byte_size() || 
           dcase->get_fixed_byte_size() != _fixed_byte_size) {
         
@@ -62,6 +63,7 @@ DCSwitchParameter(const DCSwitch *dswitch) :
       }
 
       _has_range_limits = _has_range_limits || dcase->has_range_limits();
+      _has_default_value = _has_default_value || dcase->_has_default_value;
     }
   }
 
@@ -194,3 +196,21 @@ generate_hash(HashGenerator &hashgen) const {
   DCParameter::generate_hash(hashgen);
   _dswitch->generate_hash(hashgen);
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCSwitchParameter::pack_default_value
+//       Access: Public, Virtual
+//  Description: Packs the switchParameter's specified default value (or a
+//               sensible default if no value is specified) into the
+//               stream.  Returns true if the default value is packed,
+//               false if the switchParameter doesn't know how to pack its
+//               default value.
+////////////////////////////////////////////////////////////////////
+bool DCSwitchParameter::
+pack_default_value(DCPackData &pack_data, bool &pack_error) const {
+  if (has_default_value()) {
+    return DCField::pack_default_value(pack_data, pack_error);
+  }
+
+  return _dswitch->pack_default_value(pack_data, pack_error);
+}

+ 1 - 0
direct/src/dcparser/dcSwitchParameter.h

@@ -53,6 +53,7 @@ public:
                               const string &prename, const string &name,
                               const string &postname) const;
   virtual void generate_hash(HashGenerator &hashgen) const;
+  virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
 
 private:
   const DCSwitch *_dswitch;