141 lines
7.2 KiB
C
141 lines
7.2 KiB
C
|
#pragma once
|
||
|
|
||
|
#include "base.h"
|
||
|
#include <cgv/type/variant.h>
|
||
|
#include <map>
|
||
|
|
||
|
#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 <typename T>
|
||
|
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<T>::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 <typename T>
|
||
|
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<T>::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 <typename T>
|
||
|
struct property_access : public emulated_property_access<T>
|
||
|
{
|
||
|
property_access(T* _ptr) : emulated_property_access<T>(_ptr) {}
|
||
|
};
|
||
|
|
||
|
template <> struct property_access<int8_type> : public standard_type_property_access<int8_type> { property_access<int8_type>( int8_type* _ptr) : standard_type_property_access<int8_type>(_ptr) {}; };
|
||
|
template <> struct property_access<int16_type> : public standard_type_property_access<int16_type> { property_access<int16_type>(int16_type* _ptr) : standard_type_property_access<int16_type>(_ptr) {}; };
|
||
|
template <> struct property_access<int32_type> : public standard_type_property_access<int32_type> { property_access<int32_type>(int32_type* _ptr) : standard_type_property_access<int32_type>(_ptr) {}; };
|
||
|
template <> struct property_access<int64_type> : public standard_type_property_access<int64_type> { property_access<int64_type>(int64_type* _ptr) : standard_type_property_access<int64_type>(_ptr) {}; };
|
||
|
template <> struct property_access<uint8_type> : public standard_type_property_access<uint8_type> { property_access<uint8_type>( uint8_type* _ptr) : standard_type_property_access<uint8_type>(_ptr) {}; };
|
||
|
template <> struct property_access<uint16_type> : public standard_type_property_access<uint16_type> { property_access<uint16_type>(uint16_type* _ptr) : standard_type_property_access<uint16_type>(_ptr) {}; };
|
||
|
template <> struct property_access<uint32_type> : public standard_type_property_access<uint32_type> { property_access<uint32_type>(uint32_type* _ptr) : standard_type_property_access<uint32_type>(_ptr) {}; };
|
||
|
template <> struct property_access<uint64_type> : public standard_type_property_access<uint64_type> { property_access<uint64_type>(uint64_type* _ptr) : standard_type_property_access<uint64_type>(_ptr) {}; };
|
||
|
template <> struct property_access<float> : public standard_type_property_access<float> { property_access<float>(float* _ptr) : standard_type_property_access<float>(_ptr) {}; };
|
||
|
template <> struct property_access<double> : public standard_type_property_access<double> { property_access<double>(double* _ptr) : standard_type_property_access<double>(_ptr) {}; };
|
||
|
template <> struct property_access<bool> : public standard_type_property_access<bool> { property_access<bool>(bool* _ptr) : standard_type_property_access<bool>(_ptr) {}; };
|
||
|
template <> struct property_access<std::string> : public standard_type_property_access<std::string> { property_access<std::string>(std::string* _ptr) : standard_type_property_access<std::string>(_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<std::string,abst_property_access*> 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 <typename T>
|
||
|
void add(const std::string& property, T& value) { add_void(property, new property_access<T>(&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 <typename T>
|
||
|
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 <cgv/config/lib_end.h>
|