| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- #ifndef PROPERTIES_H_
- #define PROPERTIES_H_
- #include "Base.h"
- #include "Matrix.h"
- #include "Vector2.h"
- namespace gameplay
- {
- /**
- * Defines a utility for loading text files in the GamePlay "properties" files
- * and reading primitive types and GamePlay math classes out of them.
- *
- * This class is used by ParticleEmitter, Animation and Materials to create objects
- * of these types from text files.
- *
- * A properties file has very simple syntax and can contain only namespaces and
- * name/value pairs (the properties of a namespace).
- * The file can have any file extension a user specifies.
- *
- * Here's an example of a simple
- * file that uses all the available features of the markup language:
-
- @verbatim
- // This is a comment.
-
- // This property is in the default namespace:
- integerProperty = 5
-
- // This line defines a namespace of type "mynamespace" without an ID:
- mynamespace
- {
- // This namespace can be retrieved by searching for its ID, "spriteTexture",
- // or by its name "texture":
- texture spriteTexture
- {
- fileName = sprite.png
- width = 64
- height = 64
- }
-
- // This property is in the "space" namespace:
- booleanProperty = true
-
- // It's legal to have a name without a value if you leave out the '=' character:
- foo
-
- // In fact, the '=' character is optional if you'd rather write:
- bar 23
-
- // But don't write this or you'll get an error:
- // illegalProperty =
-
- // Or this:
- // = 15
-
- // Properties objects let you retrieve values as various types.
- floatProperty = 3.333
- stringProperty = This is a string.
- vector3Property = 1.0, 5.0, 3.55
- colorProperty = 1.0, 0.4, 0.0, 1.0
- }
- @endverbatim
-
- * Retrieving information out of a file like this could be done in two ways. If the
- * available namespaces and name/value pairs are known in advance they can be queried by ID or name.
- * For example, if the namespace "spriteTexture" and its properties are required then they can
- * be retrieved with a call to getNamespace() followed by calls to getString() and getInt().
- * A namespace is stored and retrieved as a Properties object.
- * Reading the spriteTexture properties out of the file above in this way could be done with the following code:
-
- @verbatim
- // Create the top-level Properties object.
- Properties* properties = Properties::create("example.properties");
- // Retrieve the "spriteTexture" namespace.
- Properties* spriteTexture = properties->getNamespace("spriteTexture");
-
- // Get the values of known texture properties out of the namespace.
- const char* fileName = spriteTexture->getString("fileName");
- int width = spriteTexture->getInt("width");
- int height = spriteTexture->getInt("height");
-
- // Deleting the top-level Properties object will clean up all nested namespaces.
- SAFE_DELETE(properties);
- @endverbatim
- * On the other hand, if the structure of the file is not known in advance its
- * namespaces and name/value pairs can be retrieved one by one using the getNextNamespace()
- * and getNextProperty() methods. The following method prints the contents of any properties file
- * to the console:
-
- @verbatim
- void printProperties(Properties* properties)
- {
- // Print the name and ID of the current namespace.
- const char* spacename = properties->getNamespace();
- const char* id = properties->getId();
- GP_WARN("Namespace: %s ID: %s\n{", spacename, id);
-
- // Print all properties in this namespace.
- const char* name = properties->getNextProperty();
- const char* value = NULL;
- while (name != NULL)
- {
- value = properties->getString(name);
- GP_WARN("%s = %s", name, value);
- name = properties->getNextProperty();
- }
- GP_WARN("}\n");
-
- // Print the properties of every namespace within this one.
- Properties* space = properties->getNextNamespace();
- while (space != NULL)
- {
- printProperties(space);
- space = properties->getNextNamespace();
- }
- }
- @endverbatim
- * Note that this method does not keep track of the namespace hierarchy, but could be
- * modified to do so. Also note that nothing in a properties file indicates the type
- * of a property. If the type is unknown, its string can be retrieved and interpreted
- * as necessary.
- */
- class Properties
- {
- friend class Game;
- public:
- /**
- * Data types supported by the properties class.
- */
- enum Type
- {
- NONE,
- STRING,
- NUMBER,
- VECTOR2,
- VECTOR3,
- VECTOR4,
- MATRIX
- };
- /**
- * Creates a Properties runtime settings from the specified URL, where the URL is of
- * the format "<file-path>.<extension>#<namespace-id>/<namespace-id>/.../<namespace-id>"
- * (and "#<namespace-id>/<namespace-id>/.../<namespace-id>" is optional).
- *
- * @param url The URL to create the properties from.
- */
- static Properties* create(const char* url);
- /**
- * Destructor.
- */
- ~Properties();
- /**
- * Get the name of the next property.
- *
- * @param value Optional pointer to a const char* to store the value of the next property in.
- *
- * @return The name of the next property, or NULL if there are no properties remaining.
- */
- const char* getNextProperty(char** value = NULL);
- /**
- * Get the next namespace.
- */
- Properties* getNextNamespace();
- /**
- * Rewind the getNextProperty() and getNextNamespace() iterators
- * to the beginning of the file.
- */
- void rewind();
- /**
- * Get a specific namespace by ID or name. This method will perform
- * a depth-first search on all namespaces and inner namespaces within
- * this Property.
- *
- * @param id The ID or name of the namespace to find.
- * @param searchNames If true, namespace names are used in the search,
- * instead of namespace IDs. By default this parameter is false
- * and namespace IDs are searched.
- *
- * @return A properties object with the given ID or name.
- */
- Properties* getNamespace(const char* id, bool searchNames = false) const;
- /**
- * Get the name of this Property's namespace.
- *
- * @return The name of this Property's namespace.
- */
- const char* getNamespace() const;
- /**
- * Get the ID of this Property's namespace. The ID should be a unique identifier,
- * but its uniqueness is not enforced.
- *
- * @return The ID of this Property's namespace.
- */
- const char* getId() const;
- /**
- * Check if a property with the given name is specified in this Properties object.
- *
- * @param name The name of the property to query.
- *
- * @return True if the property exists, false otherwise.
- */
- bool exists(const char* name) const;
- /**
- * Returns the type of a property.
- *
- * @param name The name of hte property to interpret, or NULL to return the current property's type.
- *
- * @return The type of the property.
- */
- Type getType(const char* name = NULL) const;
- /**
- * Get the value of the given property as a string. This can always be retrieved,
- * whatever the intended type of the property.
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- *
- * @return The value of the given property as a string, or the empty string if no property with that name exists.
- */
- const char* getString(const char* name = NULL) const;
- /**
- * Interpret the value of the given property as a boolean.
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- *
- * @return true if the property exists and its value is "true", otherwise false.
- */
- bool getBool(const char* name = NULL) const;
- /**
- * Interpret the value of the given property as an integer.
- * If the property does not exist, zero will be returned.
- * If the property exists but could not be scanned, an error will be logged and zero will be returned.
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- *
- * @return The value of the given property interpreted as an integer.
- * Zero if the property does not exist or could not be scanned.
- */
- int getInt(const char* name = NULL) const;
- /**
- * Interpret the value of the given property as a floating-point number.
- * If the property does not exist, zero will be returned.
- * If the property exists but could not be scanned, an error will be logged and zero will be returned.
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- *
- * @return The value of the given property interpreted as a float.
- * Zero if the property does not exist or could not be scanned.
- */
- float getFloat(const char* name = NULL) const;
- /**
- * Interpret the value of the given property as a long integer.
- * If the property does not exist, zero will be returned.
- * If the property exists but could not be scanned, an error will be logged and zero will be returned.
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- *
- * @return The value of the given property interpreted as a long.
- * Zero if the property does not exist or could not be scanned.
- */
- long getLong(const char* name = NULL) const;
- /**
- * Interpret the value of the given property as a Matrix.
- * If the property does not exist, out will be set to the identity matrix.
- * If the property exists but could not be scanned, an error will be logged and out will be set
- * to the identity matrix.
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- * @param out The matrix to set to this property's interpreted value.
- *
- * @return True on success, false if the property does not exist or could not be scanned.
- */
- bool getMatrix(const char* name, Matrix* out) const;
- /**
- * Interpret the value of the given property as a Vector2.
- * If the property does not exist, out will be set to Vector2(0.0f, 0.0f).
- * If the property exists but could not be scanned, an error will be logged and out will be set
- * to Vector2(0.0f, 0.0f).
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- * @param out The vector to set to this property's interpreted value.
- *
- * @return True on success, false if the property does not exist or could not be scanned.
- */
- bool getVector2(const char* name, Vector2* out) const;
- /**
- * Interpret the value of the given property as a Vector3.
- * If the property does not exist, out will be set to Vector3(0.0f, 0.0f, 0.0f).
- * If the property exists but could not be scanned, an error will be logged and out will be set
- * to Vector3(0.0f, 0.0f, 0.0f).
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- * @param out The vector to set to this property's interpreted value.
- *
- * @return True on success, false if the property does not exist or could not be scanned.
- */
- bool getVector3(const char* name, Vector3* out) const;
- /**
- * Interpret the value of the given property as a Vector4.
- * If the property does not exist, out will be set to Vector4(0.0f, 0.0f, 0.0f, 0.0f).
- * If the property exists but could not be scanned, an error will be logged and out will be set
- * to Vector4(0.0f, 0.0f, 0.0f, 0.0f).
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- * @param out The vector to set to this property's interpreted value.
- *
- * @return True on success, false if the property does not exist or could not be scanned.
- */
- bool getVector4(const char* name, Vector4* out) const;
- /**
- * Interpret the value of the given property as a Quaternion specified as an axis angle.
- * If the property does not exist, out will be set to Quaternion().
- * If the property exists but could not be scanned, an error will be logged and out will be set
- * to Quaternion().
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- * @param out The quaternion to set to this property's interpreted value.
- *
- * @return True on success, false if the property does not exist or could not be scanned.
- */
- bool getQuaternionFromAxisAngle(const char* name, Quaternion* out) const;
- /**
- * Interpret the value of the given property as an RGB color in hex and write this color to a Vector3.
- * E.g. 0xff0000 represents red and sets the vector to (1, 0, 0).
- * If the property does not exist, out will be set to Vector3(0.0f, 0.0f, 0.0f).
- * If the property exists but could not be scanned, an error will be logged and out will be set
- * to Vector3(0.0f, 0.0f, 0.0f).
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- * @param out The vector to set to this property's interpreted value.
- *
- * @return True on success, false if the property does not exist or could not be scanned.
- */
- bool getColor(const char* name, Vector3* out) const;
- /**
- * Interpret the value of the given property as an RGBA color in hex and write this color to a Vector4.
- * E.g. 0xff0000ff represents opaque red and sets the vector to (1, 0, 0, 1).
- * If the property does not exist, out will be set to Vector4(0.0f, 0.0f, 0.0f, 0.0f).
- * If the property exists but could not be scanned, an error will be logged and out will be set
- * to Vector4(0.0f, 0.0f, 0.0f, 0.0f).
- *
- * @param name The name of the property to interpret, or NULL to return the current property's value.
- * @param out The vector to set to this property's interpreted value.
- *
- * @return True on success, false if the property does not exist or could not be scanned.
- */
- bool getColor(const char* name, Vector4* out) const;
- private:
-
- /**
- * Constructors.
- */
- Properties();
- Properties(FILE* file);
- Properties(const Properties& copy);
- /**
- * Constructor. Read from the beginning of namespace specified
- */
- Properties(FILE* file, const char* name, const char* id = NULL, const char* parentID = NULL);
- void readProperties(FILE* file);
- void skipWhiteSpace(FILE* file);
- char* trimWhiteSpace(char* str);
- // Called after create(); copies info from parents into derived namespaces.
- void resolveInheritance(const char* id = NULL);
- // Called by resolveInheritance().
- void mergeWith(Properties* overrides);
- // Clones the Properties object.
- Properties* clone();
- std::string _namespace;
- std::string _id;
- std::string _parentID;
- std::map<std::string, std::string> _properties;
- std::map<std::string, std::string>::const_iterator _propertiesItr;
- std::vector<Properties*> _namespaces;
- std::vector<Properties*>::const_iterator _namespacesItr;
- };
- }
- #endif
|