define ConfigVariableManager::make_variable_template()

This commit is contained in:
David Rose 2004-10-26 00:27:31 +00:00
parent b937aef183
commit 3410413ae5
9 changed files with 197 additions and 7 deletions

View File

@ -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);
}
}

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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;
};

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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) {