2
0
Эх сурвалжийг харах

define ConfigVariableManager::make_variable_template()

David Rose 21 жил өмнө
parent
commit
3410413ae5

+ 3 - 3
dtool/src/prc/configVariableBase.cxx

@@ -33,10 +33,10 @@ ConfigVariableBase(const string &name,
   if (value_type != VT_undefined) {
     _core->set_value_type(value_type);
   }
-  if (flags != 0) {
-    _core->set_flags(flags);
-  }
   if (!description.empty()) {
     _core->set_description(description);
   }
+  if (flags != 0) {
+    _core->set_flags(flags);
+  }
 }

+ 25 - 0
dtool/src/prc/configVariableCore.cxx

@@ -46,6 +46,31 @@ ConfigVariableCore(const string &name) :
 {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ConfigVariableCore::Copy Constructor
+//       Access: Private
+//  Description: This is used by ConfigVariableManager to create the
+//               variable from a template--basically, another variable
+//               with all of the initial properties pre-defined.
+////////////////////////////////////////////////////////////////////
+ConfigVariableCore::
+ConfigVariableCore(const ConfigVariableCore &templ, const string &name) :
+  _name(name),
+  _is_used(templ._is_used),
+  _value_type(templ._value_type),
+  _description(templ._description),
+  _flags(templ._flags),
+  _default_value(NULL),
+  _local_value(NULL),
+  _declarations_sorted(false),
+  _value_queried(false),
+  _value_seq(0)
+{
+  if (templ._default_value != (ConfigDeclaration *)NULL) {
+    set_default_value(templ._default_value->get_string_value());
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ConfigVariableCore::Destructor
 //       Access: Private

+ 1 - 0
dtool/src/prc/configVariableCore.h

@@ -42,6 +42,7 @@ class ConfigDeclaration;
 class EXPCL_DTOOLCONFIG ConfigVariableCore : public ConfigFlags {
 private:
   ConfigVariableCore(const string &name);
+  ConfigVariableCore(const ConfigVariableCore &templ, const string &name);
   ~ConfigVariableCore();
 
 public:

+ 102 - 1
dtool/src/prc/configVariableManager.cxx

@@ -66,12 +66,113 @@ make_variable(const string &name) {
     return (*ni).second;
   }
 
-  ConfigVariableCore *variable = new ConfigVariableCore(name);
+  ConfigVariableCore *variable = NULL;
+
+  // See if there's a template that matches this name.
+  VariableTemplates::const_iterator ti;
+  for (ti = _variable_templates.begin();
+       ti != _variable_templates.end() && variable == (ConfigVariableCore *)NULL;
+       ++ti) {
+    const GlobPattern &pattern = (*ti).first;
+    ConfigVariableCore *templ = (*ti).second;
+    if (pattern.matches(name)) {
+      variable = new ConfigVariableCore(*templ, name);
+    }
+  }
+
+  if (variable == (ConfigVariableCore *)NULL) {
+    variable = new ConfigVariableCore(name);
+  }
+
   _variables_by_name[name] = variable;
   _variables.push_back(variable);
   return variable;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: ConfigVariableManager::make_variable_template
+//       Access: Published
+//  Description: Defines a variable "template" to match against
+//               dynamically-defined variables that may or may not be
+//               created in the future.
+//
+//               The template consists of a glob pattern,
+//               e.g. "notify-level-*", which will be tested against
+//               any config variable passed to a future call to
+//               make_variable().  If the pattern matches, the
+//               returned ConfigVariableCore is copied to define the
+//               new variable, instead of creating a default, empty
+//               one.
+//
+//               This is useful to pre-specify default values for a
+//               family of variables that all have similar properties,
+//               and all may not be created at the same time.  It is
+//               especially useful to avoid cluttering up the list of
+//               available variables with user-declared variables that
+//               have not been defined yet by the application
+//               (e.g. "egg-object-type-*").
+//
+//               This method basically pre-defines all variables that
+//               match the specified glob pattern.
+////////////////////////////////////////////////////////////////////
+ConfigVariableCore *ConfigVariableManager::
+make_variable_template(const string &pattern, 
+                       ConfigFlags::ValueType value_type,
+                       const string &default_value,
+                       const string &description, int flags) {
+  ConfigVariableCore *core;
+
+  GlobPattern gp(pattern);
+  VariableTemplates::const_iterator ti = _variable_templates.find(gp);
+  if (ti != _variable_templates.end()) {
+    core = (*ti).second;
+
+  } else {
+    core = new ConfigVariableCore(pattern);
+    _variable_templates[gp] = core;
+  }
+
+  if (value_type != ConfigFlags::VT_undefined) {
+    core->set_value_type(value_type);
+  }
+  if (!default_value.empty() || 
+      core->get_default_value() == (ConfigDeclaration *)NULL) {
+    core->set_default_value(default_value);
+  }
+  if (!description.empty()) {
+    core->set_description(description);
+  }
+  if (flags != 0) {
+    core->set_flags(flags);
+  }
+  core->set_used();
+
+  // Also apply the same changes to any previously-defined variables
+  // that match the pattern.
+  Variables::iterator vi;
+  for (vi = _variables.begin(); vi != _variables.end(); ++vi) {
+    ConfigVariableCore *variable = (*vi);
+    if (gp.matches(variable->get_name())) {
+      if (value_type != ConfigFlags::VT_undefined) {
+        variable->set_value_type(value_type);
+      }
+      if (!default_value.empty() || 
+          variable->get_default_value() == (ConfigDeclaration *)NULL) {
+        variable->set_default_value(default_value);
+      }
+      if (!description.empty()) {
+        variable->set_description(description);
+      }
+      if (flags != 0) {
+        variable->set_flags(flags);
+      }
+      variable->set_used();
+    }
+  }
+
+  return core;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ConfigVariableManager::get_variable_name
 //       Access: Published

+ 11 - 0
dtool/src/prc/configVariableManager.h

@@ -20,7 +20,9 @@
 #define CONFIGVARIABLEMANAGER_H
 
 #include "dtoolbase.h"
+#include "configFlags.h"
 #include "notify.h"
+#include "globPattern.h"
 #include "pvector.h"
 #include "pmap.h"
 
@@ -39,6 +41,12 @@ protected:
 
 PUBLISHED:
   ConfigVariableCore *make_variable(const string &name);
+  ConfigVariableCore *make_variable_template(const string &pattern, 
+                                             ConfigFlags::ValueType type,
+                                             const string &default_value,
+                                             const string &description = string(), 
+                                             int flags = 0);
+
 
   INLINE int get_num_variables() const;
   INLINE ConfigVariableCore *get_variable(int n) const;
@@ -64,6 +72,9 @@ private:
   typedef pmap<string, ConfigVariableCore *> VariablesByName;
   VariablesByName _variables_by_name;
 
+  typedef pmap<GlobPattern, ConfigVariableCore *> VariableTemplates;
+  VariableTemplates _variable_templates;
+
   static ConfigVariableManager *_global_ptr;
 };
 

+ 33 - 0
dtool/src/prc/globPattern.I

@@ -50,6 +50,39 @@ operator = (const GlobPattern &copy) {
   _case_sensitive = copy._case_sensitive;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GlobPattern::operator ==
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool GlobPattern::
+operator == (const GlobPattern &other) const {
+  return (_pattern == other._pattern && _case_sensitive == other._case_sensitive);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GlobPattern::operator !=
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool GlobPattern::
+operator != (const GlobPattern &other) const {
+  return !operator == (other);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GlobPattern::operator <
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool GlobPattern::
+operator < (const GlobPattern &other) const {
+  if (_case_sensitive != other._case_sensitive) {
+    return (int)_case_sensitive < (int)other._case_sensitive;
+  }
+  return _pattern < other._pattern;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GlobPattern::set_pattern
 //       Access: Public

+ 4 - 0
dtool/src/prc/globPattern.h

@@ -44,6 +44,10 @@ PUBLISHED:
   INLINE GlobPattern(const GlobPattern &copy);
   INLINE void operator = (const GlobPattern &copy);
 
+  INLINE bool operator == (const GlobPattern &other) const;
+  INLINE bool operator != (const GlobPattern &other) const;
+  INLINE bool operator < (const GlobPattern &other) const;
+
   INLINE void set_pattern(const string &pattern);
   INLINE const string &get_pattern() const;
 

+ 13 - 0
panda/src/egg2pg/config_egg2pg.cxx

@@ -22,6 +22,8 @@
 #include "get_config_path.h"
 #include "loaderFileTypeEgg.h"
 #include "loaderFileTypeRegistry.h"
+#include "configVariableManager.h"
+#include "configVariableCore.h"
 
 ConfigureDef(config_egg2pg);
 NotifyCategoryDef(egg2pg, "");
@@ -108,6 +110,17 @@ init_libegg2pg() {
   }
   initialized = true;
 
+  // Define a template for all egg-object-type-* variables, so the
+  // system knows that these variables are defined when it finds them
+  // in a user's prc file, even if we haven't actually read an egg
+  // file that uses the particular <ObjectType> field.
+  ConfigVariableManager *cv_mgr = ConfigVariableManager::get_global_ptr();
+  cv_mgr->make_variable_template
+    ("egg-object-type-*",
+     ConfigVariableCore::VT_string, "",
+     "Defines egg syntax for the named object type.",
+     ConfigVariableCore::F_dynamic);
+
   // Get egg-coordinate-system
   string csstr = config_egg2pg.GetString("egg-coordinate-system", "default");
   CoordinateSystem cs = parse_coordinate_system_string(csstr);

+ 5 - 3
panda/src/egg2pg/eggLoader.cxx

@@ -80,6 +80,7 @@
 #include "ropeNode.h"
 #include "sheetNode.h"
 #include "look_at.h"
+#include "configVariableString.h"
 
 #include <ctype.h>
 #include <algorithm>
@@ -2773,10 +2774,11 @@ do_expand_object_type(EggGroup *egg_group, const pset<string> &expanded,
   // Try to find the egg syntax that the given objecttype is
   // shorthand for.  First, look in the config file.
 
-  string egg_syntax =
-    config_egg2pg.GetString("egg-object-type-" + downcase(object_type), "none");
+  ConfigVariableString egg_object_type
+    ("egg-object-type-" + downcase(object_type), "");
+  string egg_syntax = egg_object_type;
 
-  if (egg_syntax == "none") {
+  if (!egg_object_type.has_value()) {
     // It wasn't defined in a config file.  Maybe it's built in?
     
     if (cmp_nocase_uh(object_type, "barrier") == 0) {