#pragma once #include "base.h" #include #include #include "lib_begin.h" using namespace cgv::type; /// the cgv namespace namespace cgv { /// the base namespace holds the base hierarchy, support for plugin registration and signals namespace base { struct CGV_API abst_property_access { bool has_changed; abst_property_access(); virtual const char* get_type_name() const = 0; virtual bool set(const std::string& value_type, const void* value_ptr) = 0; virtual bool get(const std::string& value_type, void* value_ptr) = 0; }; template struct standard_type_property_access : public abst_property_access { T* ptr; standard_type_property_access(T* _ptr) : ptr(_ptr) {} const char* get_type_name() const { return cgv::type::info::type_name::get_name(); } bool set(const std::string& value_type, const void* value_ptr) { get_variant(*ptr,value_type,value_ptr); has_changed = true; return true; } bool get(const std::string& value_type, void* value_ptr) { set_variant(*ptr,value_type,value_ptr); return true; } }; template struct emulated_property_access : public abst_property_access { T* ptr; emulated_property_access(T* _ptr) : ptr(_ptr) {} const char* get_type_name() const { return cgv::type::info::type_name::get_name(); } bool set(const std::string& value_type, const void* value_ptr) { if (value_type == get_type_name()) { *ptr = *((const T*) value_ptr); has_changed = true; return true; } else if (value_type == "string") { return has_changed = cgv::utils::from_string(*ptr, *((std::string*)value_ptr)); } return false; } bool get(const std::string& value_type, void* value_ptr) { if (value_type == get_type_name()) { *((T*) value_ptr) = *ptr; return true; } else if (value_type == "string") { *((std::string*)value_ptr) = cgv::utils::to_string(*ptr); } return false; } }; template struct property_access : public emulated_property_access { property_access(T* _ptr) : emulated_property_access(_ptr) {} }; template <> struct property_access : public standard_type_property_access { property_access( int8_type* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(int16_type* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(int32_type* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(int64_type* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access( uint8_type* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(uint16_type* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(uint32_type* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(uint64_type* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(float* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(double* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(bool* _ptr) : standard_type_property_access(_ptr) {}; }; template <> struct property_access : public standard_type_property_access { property_access(std::string* _ptr) : standard_type_property_access(_ptr) {}; }; /** implements a dynamic object, that can be composed of independent variables, which are handled as properties of the base_generator and published through the property interface of the base class. */ class CGV_API base_generator : public cgv::base::base { protected: typedef std::map map_type; typedef map_type::iterator iter_type; typedef map_type::const_iterator const_iter_type; /// store the properties as map from property name to type and pointer to instance map_type property_map; public: /// overload to return the type name of this object. By default the type interface is queried over get_type. std::string get_type_name() const; /// add a new property void add_void(const std::string& name, abst_property_access* apa); /// add a property by deriving property access from type of reference value template void add(const std::string& property, T& value) { add_void(property, new property_access(&value)); } /// remove a property void del(const std::string& property); /// return whether property has changed bool changed(const std::string& property) const; //! returns a semicolon separated list of property declarations std::string get_property_declarations(); //! abstract interface for the setter of a dynamic property. bool set_void(const std::string& property, const std::string& value_type, const void* value_ptr); //! abstract interface for the getter of a dynamic property. bool get_void(const std::string& property, const std::string& value_type, void* value_ptr); }; //! simple parsing support to access values of properties in a string of property assignment /*! Given an option string (first parameter) with name-value-pairs, i.e. "x=10.4;tooltip='help'" and a property name (second parameter), the function returns whether the option string contains an assignment of the queried property and if yes, the value is stored in the reference given in the third parameter. The type casts supported by the cgv::type::variant type are used when converting to the reference type. Examples: true == has_property("x=10.4;tooltip='help'", "x", dbl_var)" ==> dbl_var = 10.4 true == has_property("x=10.4;tooltip='help'", "x", str_var)" ==> str_var = "10.4" true == has_property("x=10.4;tooltip='help'", "tooltip", str_var)" ==> str_var = "help" false == has_property("x=10.4;tooltip='help'", "y", int_var)" ==> int_var ... not changed */ template bool has_property(const std::string& options, const std::string& property, T& value, bool report_error = true) { base_generator bg; bg.add(property, value); bg.multi_set(options, report_error); return bg.changed(property); } } } #include