Skip to content

Instantly share code, notes, and snippets.

@kirel
Created November 13, 2008 23:19
Show Gist options
  • Save kirel/24683 to your computer and use it in GitHub Desktop.
Save kirel/24683 to your computer and use it in GitHub Desktop.
/*
* CONDITIONS AND ACTIONS
*/
// gimme some Properties
FloatProp foo();
GroupProp group();
// now certain conditions regarding properties can trigger actions but see yourself
group.conditioned_by( foo.valueEqual(7.3).Do(SetVisibleAction()).Else(SetInvisibleAction()) );
// or more succinct
group.conditioned_by( foo.valueEqual(7.3, SetVisibleAction(), SetInvisibleAction()) );
// another fava (there is more than one way to do it!)
foo.valueEqual(7.3)
.Do(SetVisibleAction())
.Else(SetInvisibleAction())
.targeting(group);
// example for sets
float myfloats[]= {1.1,1.2,1.3,1.4};
std::set<float> myset(myfloats,myfloats+5);
group.conditioned_by( foo.valueIn(myset).Do(IncredibleAction()) );
// on any change recompile Shaders
foo.onChange().Do(RecompileShaderAction());
// equivalent
foo.onChange(RecompileShaderAction());
// Actions are chainable
foo.onChange()
.Do(ThisAction())
.Do(ThatAction())
.Do(ThirdAction())
.Else(AnotherAction())
.Else(SomeAction());
// manual version which you are not encouraged to use
foo.addCondition(EqualCondition(&enu, &foo, 7.3, SetVisibleAction(), SetInvisibleAction));
// this is crazy shit
class HuntingSeasonProp : public BoolProp {};
HuntingSeasonProp huntallowed();
Rabbit cutelittlerabbit();
Rabbit sweetwhiterabbit();
huntallowed.valueEqual(true).Do(ShootRabbitAction().targeting(cutelittlerabbit));
huntallowed.valueEqual(true, ShootRabbitAction(sweetwhiterabbit));
DateProp date();
StringProp st();
date.valueEqual(24,12,2008)
.Do(SetAction("Merry christmas!"))
.targeting(st);
date.set(24,12,2008);
st.get() // => "Merry christmas!"
/*
* VALIDATIONS
*/
// validations make sure a (Template)Property is only set when certain conditions are met
std::vector<Date> holidays = ...
date.verifies(date.valueIn(holidays));
date.set(24,12,2008); // => true
date.get() // => 24.12.2008
date.set(12,12,2008) // => false
date.get() // => 24.12.2008
//Note: Validations do not trigger any actions
/**********************************************************************
* *
* Voreen - The Volume Rendering Engine *
* *
* Copyright (C) 2005-2008 Visualization and Computer Graphics Group, *
* Department of Computer Science, University of Muenster, Germany. *
* <http://viscg.uni-muenster.de> *
* *
* This file is part of the Voreen software package. Voreen is free *
* software: you can redistribute it and/or modify it under the terms *
* of the GNU General Public License version 2 as published by the *
* Free Software Foundation. *
* *
* Voreen is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* in the file "LICENSE.txt" along with this program. *
* If not, see <http://www.gnu.org/licenses/>. *
* *
* The authors reserve all rights not expressly granted herein. For *
* non-commercial academic use see the license exception specified in *
* the file "LICENSE-academic.txt". To get information about *
* commercial licensing please contact the authors. *
* *
**********************************************************************/
#include "voreen/core/vis/property.h"
namespace voreen {
Property::Property() : Serializable(), owner_(0) {
guiText_ = "empty";
}
Property::~Property() {};
std::string Property::getGuiText() const {
return guiText_;
}
const std::string Property::XmlElementName = "Property";
std::string Property::getXmlElementName() const {
return XmlElementName;
}
TiXmlElement* Property::serializeToXml() const {
serializableSanityChecks();
TiXmlElement* propElem = new TiXmlElement(XmlElementName);
// FIXME: Why do we not serialize the guiText_? (tr)
//propElem->SetAttribute("Property_text" , getGuiText());
// TODO: use type_info instead of own type defines
//propElem->SetAttribute("type", PropertyType());
//propElem->SetAttribute("autochange", getAutoChange() ? "true" : "false");
return propElem;
}
void Property::setOwner(Processor* owner) {
owner_ = owner;
}
Processor* Property::getOwner() const {
return owner_;
}
//-----------------------------------------------------------------------------------------------
FloatProperty::FloatProperty(std::string guiText, float value, float minValue, float maxValue)
: NumericProperty<float>(value, minValue, maxValue)
, decimals_(2)
{
guiText_ = guiText;
minValue_ = minValue;
maxValue_ = maxValue;
}
void FloatProperty::setDecimals(int decimals) {
decimals_ = decimals;
}
int FloatProperty::getDecimals() const {
return decimals_;
}
void FloatProperty::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
float value;
if (propElem->QueryFloatAttribute("value", &value) == TIXML_SUCCESS)
set(value);
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* FloatProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetDoubleAttribute("value", get());
return propElem;
}
//-----------------------------------------------------------------------------------------------
IntProperty::IntProperty(std::string guiText, int value, int minValue, int maxValue)
: NumericProperty<int>(value, minValue, maxValue) {
guiText_ = guiText;
minValue_ = minValue;
maxValue_ = maxValue;
}
void IntProperty::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
int value;
if (propElem->QueryIntAttribute("value", &value) == TIXML_SUCCESS)
set(value);
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* IntProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetAttribute("value", get());
return propElem;
}
//-----------------------------------------------------------------------------------------------
BoolProperty::BoolProperty(std::string guiText, bool value) : TemplateProperty<bool>(value) {
guiText_ = guiText;
}
void BoolProperty::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
if (propElem->Attribute("value"))
set(std::string("true").compare(propElem->Attribute("value")) == 0 ? true : false);
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* BoolProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetAttribute("value", get() ? "true" : "false");
return propElem;
}
//-----------------------------------------------------------------------------------------------
StringProperty::StringProperty(std::string guiText, std::string value) : TemplateProperty<std::string>(value) {
guiText_ = guiText;
}
void StringProperty::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
if (propElem->Attribute("value"))
set(propElem->Attribute("value"));
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* StringProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetAttribute("value", get());
return propElem;
}
//-----------------------------------------------------------------------------------------------
StringVectorProperty::StringVectorProperty(std::string guiText, std::vector<std::string> value) : TemplateProperty<std::vector<std::string> >(value) {
guiText_ = guiText;
}
//FIXME: needs serialization methods (tr)
//-----------------------------------------------------------------------------------------------
ColorProperty::ColorProperty(std::string guiText, tgt::Color value) : TemplateProperty<tgt::vec4>(value) {
guiText_ = guiText;
}
void ColorProperty::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
float r, g, b, a;
if (propElem->QueryFloatAttribute("r", &r) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("g", &g) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("b", &b) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("a", &a) == TIXML_SUCCESS)
set(tgt::Color(r,g,b,a));
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* ColorProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetDoubleAttribute("r", get().r);
propElem->SetDoubleAttribute("g", get().g);
propElem->SetDoubleAttribute("b", get().b);
propElem->SetDoubleAttribute("a", get().a);
return propElem;
}
//-----------------------------------------------------------------------------------------------
EnumProperty::EnumProperty(std::string guiText, std::vector<std::string>& strings, int startindex) : TemplateProperty<int>(startindex) {
guiText_ = guiText;
strings_ = strings;
}
std::vector<std::string> EnumProperty::getStrings() {
return strings_;
}
void EnumProperty::setStrings(const std::vector<std::string>& strings) {
strings_ = strings;
}
void EnumProperty::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
if (propElem->Attribute("value")) {
for (size_t j = 0; j < strings_.size(); j++) {
if (strings_.at(j).compare(propElem->Attribute("value")) == 0) {
set(j); // The compiler might complain about size_t to int conversion
break;
}
}
}
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* EnumProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetAttribute("value", strings_.at(get()));
return propElem;
}
//-----------------------------------------------------------------------------------------------
ButtonProperty::ButtonProperty(std::string guiText, std::string buttonText,
std::string iconFilename)
: TemplateProperty<bool>()
{
guiText_ = guiText;
}
std::string ButtonProperty::getButtonText() {
return buttonText_;
}
std::string ButtonProperty::getIconFilename() {
return iconFilename_;
}
//FIXME: Do we not need an updateFromXML method? (tr)
TiXmlElement* ButtonProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
return propElem;
}
//-----------------------------------------------------------------------------------------------
FileDialogProperty::FileDialogProperty(std::string guiText,
std::string caption, std::string directory,
std::string filter)
: TemplateProperty<std::string>()
, caption_(caption)
, directory_(directory)
, filter_(filter)
{
guiText_ = guiText;
}
std::string FileDialogProperty::getCaption() const {
return caption_;
}
std::string FileDialogProperty::getDirectory() const {
return directory_;
}
std::string FileDialogProperty::getFilter() const {
return filter_;
}
//FIXME: Do we not need an updateFromXML method? (tr)
TiXmlElement* FileDialogProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetAttribute("value", get());
propElem->SetAttribute("caption", getDialogCaption());
propElem->SetAttribute("directory", getDirectory());
propElem->SetAttribute("filefilter", getFileFilter());
return propElem;
}
//-----------------------------------------------------------------------------------------------
TransFuncAlphaProperty::TransFuncAlphaProperty(std::string guiText, TransFunc tf, const std::string& yAxisLabel)
: TemplateProperty<TransFunc>(tf)
, yAxisLabel_(yAxisLabel)
{
guiText_ = guiText;
}
//-----------------------------------------------------------------------------------------------
TransFuncProperty::TransFuncProperty(std::string guiText, TransFunc tf, bool showThreshold)
: TemplateProperty<TransFunc>(tf)
, showThreshold_(showThreshold) {
guiText_ = guiText;
}
bool TransFuncProperty::getShowThreshold() {
return showThreshold_;
}
void TransFuncProperty::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
TransFuncIntensityKeys* tf = new TransFuncIntensityKeys();
tf->clearKeys();
//iterate through all markers
TiXmlElement* markerElem;
for (markerElem = propElem->FirstChildElement("Marker");
markerElem;
markerElem = markerElem->NextSiblingElement("Marker"))
{
//first get the color
float value, dest;
tgt::col4 color;
tgt::ivec4 tmp;
if (markerElem->QueryFloatAttribute("source", &value) == TIXML_SUCCESS &&
markerElem->QueryFloatAttribute("dest", &dest) == TIXML_SUCCESS &&
markerElem->QueryIntAttribute("r", &tmp.r) == TIXML_SUCCESS &&
markerElem->QueryIntAttribute("g", &tmp.g) == TIXML_SUCCESS &&
markerElem->QueryIntAttribute("b", &tmp.b) == TIXML_SUCCESS &&
markerElem->QueryIntAttribute("a", &tmp.a) == TIXML_SUCCESS)
{
color.r = (uint8_t)tmp.r;
color.g = (uint8_t)tmp.g;
color.b = (uint8_t)tmp.b;
color.a = (uint8_t)tmp.a;
TransFuncMappingKey* myKey = new TransFuncMappingKey(value, color);
myKey->setAlphaL(dest);
if (markerElem->QueryFloatAttribute("splitdest", &dest) == TIXML_SUCCESS &&
markerElem->QueryIntAttribute("splitr", &tmp.r) == TIXML_SUCCESS &&
markerElem->QueryIntAttribute("splitg", &tmp.g) == TIXML_SUCCESS &&
markerElem->QueryIntAttribute("splitb", &tmp.b) == TIXML_SUCCESS &&
markerElem->QueryIntAttribute("splita", &tmp.a) == TIXML_SUCCESS)
{
myKey->setSplit(true);
color.r = (uint8_t)tmp.r;
color.g = (uint8_t)tmp.g;
color.b = (uint8_t)tmp.b;
color.a = (uint8_t)tmp.a;
myKey->setColorR(color);
myKey->setAlphaR(dest);
} else {
myKey->setSplit(false);
}
tf->addKey(myKey);
}
else
errors_.store(XmlElementException("A Key in a TransFunc is messed up"));
} // for ( pElem; pElem; pElem=pElem->NextSiblingElement())
tf->updateTexture();
set(&tf);
}
TiXmlElement* TransFuncProperty::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
TransFuncIntensityKeys* tf = dynamic_cast<TransFuncIntensityKeys*>(&get());
if (tf) {
// iterate through all markers
for (int m = 0; m < tf->getNumKeys(); ++m) {
// prepare xml
TiXmlElement *xmlMarker = new TiXmlElement("Marker");
//save markers to xml
xmlMarker->SetDoubleAttribute("source", tf->getKey(m)->getIntensity());
xmlMarker->SetDoubleAttribute("dest", tf->getKey(m)->getAlphaL());
xmlMarker->SetAttribute("r", tf->getKey(m)->getColorL().r);
xmlMarker->SetAttribute("g", tf->getKey(m)->getColorL().g);
xmlMarker->SetAttribute("b", tf->getKey(m)->getColorL().b);
xmlMarker->SetAttribute("a", tf->getKey(m)->getColorL().a);
if (tf->getKey(m)->isSplit()) {
xmlMarker->SetDoubleAttribute("splitdest", tf->getKey(m)->getAlphaR());
xmlMarker->SetAttribute("splitr", tf->getKey(m)->getColorR().r);
xmlMarker->SetAttribute("splitg", tf->getKey(m)->getColorR().g);
xmlMarker->SetAttribute("splitb", tf->getKey(m)->getColorR().b);
xmlMarker->SetAttribute("splita", tf->getKey(m)->getColorR().a);
}
propElem->LinkEndChild(xmlMarker);
} // for (size_t m=0; m<transfer->getNumKeys(); ++m)
}
return propElem;
}
//-----------------------------------------------------------------------------------------------
FloatVec2Property::FloatVec2Property(std::string guiText, tgt::vec2 value,
tgt::vec2 minValue, tgt::vec2 maxValue)
: NumericProperty<tgt::vec2>(value, minValue, maxValue) {
guiText_ = guiText;
minValue_ = minValue;
maxValue_ = maxValue;
}
void FloatVec2Property::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
tgt::vec2 vector;
if (propElem->QueryFloatAttribute("x", &vector.x) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("y", &vector.y) == TIXML_SUCCESS) {
set(vector);
}
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* FloatVec2Property::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetDoubleAttribute("x", get().x);
propElem->SetDoubleAttribute("y", get().y);
return propElem;
}
//-----------------------------------------------------------------------------------------------
FloatVec3Property::FloatVec3Property(std::string guiText, tgt::vec3 value,
tgt::vec3 minValue, tgt::vec3 maxValue)
: NumericProperty<tgt::vec3>(value, minValue, maxValue) {
guiText_ = guiText;
minValue_ = minValue;
maxValue_ = maxValue;
}
void FloatVec3Property::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
tgt::vec3 vector;
if (propElem->QueryFloatAttribute("x", &vector.x) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("y", &vector.y) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("z", &vector.z) == TIXML_SUCCESS) {
set(vector);
}
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* FloatVec3Property::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetDoubleAttribute("x", get().x);
propElem->SetDoubleAttribute("y", get().y);
propElem->SetDoubleAttribute("z", get().z);
return propElem;
}
//-----------------------------------------------------------------------------------------------
FloatVec4Property::FloatVec4Property(std::string guiText, tgt::vec4 value,
tgt::vec4 minValue, tgt::vec4 maxValue)
: NumericProperty<tgt::vec4>(value, minValue, maxValue) {
guiText_ = guiText;
minValue_ = minValue;
maxValue_ = maxValue;
}
void FloatVec4Property::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
tgt::vec4 vector;
if (propElem->QueryFloatAttribute("x", &vector.x) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("y", &vector.y) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("z", &vector.z) == TIXML_SUCCESS &&
propElem->QueryFloatAttribute("z", &vector.w) == TIXML_SUCCESS) {
set(vector);
}
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* FloatVec4Property::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetDoubleAttribute("x", get().x);
propElem->SetDoubleAttribute("y", get().y);
propElem->SetDoubleAttribute("z", get().z);
propElem->SetDoubleAttribute("w", get().w);
return propElem;
}
//-----------------------------------------------------------------------------------------------
IntVec2Property::IntVec2Property(std::string guiText, tgt::ivec2 value,
tgt::ivec2 minValue, tgt::ivec2 maxValue)
: NumericProperty<tgt::ivec2>(value, minValue, maxValue) {
guiText_ = guiText;
minValue_ = minValue;
maxValue_ = maxValue;
}
void IntVec2Property::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
tgt::ivec2 vector;
if (propElem->QueryIntAttribute("x", &vector.x) == TIXML_SUCCESS &&
propElem->QueryIntAttribute("y", &vector.y) == TIXML_SUCCESS) {
set(vector);
}
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* IntVec2Property::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetAttribute("x", get().x);
propElem->SetAttribute("y", get().y);
return propElem;
}
//-----------------------------------------------------------------------------------------------
IntVec3Property::IntVec3Property(std::string guiText, tgt::ivec3 value,
tgt::ivec3 minValue, tgt::ivec3 maxValue)
: NumericProperty<tgt::ivec3>(value, minValue, maxValue) {
guiText_ = guiText;
minValue_ = minValue;
maxValue_ = maxValue;
}
void IntVec3Property::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
tgt::ivec3 vector;
if (propElem->QueryIntAttribute("x", &vector.x) == TIXML_SUCCESS &&
propElem->QueryIntAttribute("y", &vector.y) == TIXML_SUCCESS &&
propElem->QueryIntAttribute("z", &vector.z) == TIXML_SUCCESS) {
set(vector);
}
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* IntVec3Property::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetAttribute("x", get().x);
propElem->SetAttribute("y", get().y);
propElem->SetAttribute("z", get().z);
return propElem;
}
//-----------------------------------------------------------------------------------------------
IntVec4Property::IntVec4Property(std::string guiText, tgt::ivec4 value,
tgt::ivec4 minValue, tgt::ivec4 maxValue)
: NumericProperty<tgt::ivec4>(value, minValue, maxValue) {
guiText_ = guiText;
minValue_ = minValue;
maxValue_ = maxValue;
}
void IntVec4Property::updateFromXml(TiXmlElement* propElem) {
Property::updateFromXml(propElem);
tgt::ivec4 vector;
if (propElem->QueryIntAttribute("x", &vector.x) == TIXML_SUCCESS &&
propElem->QueryIntAttribute("y", &vector.y) == TIXML_SUCCESS &&
propElem->QueryIntAttribute("z", &vector.z) == TIXML_SUCCESS &&
propElem->QueryIntAttribute("z", &vector.w) == TIXML_SUCCESS) {
set(vector);
}
else
errors_.store(XmlAttributeException("Attribute 'value' missing in Property element!"));
}
TiXmlElement* IntVec4Property::serializeToXml() const {
TiXmlElement* propElem = Property::serializeToXml();
propElem->SetAttribute("x", get().x);
propElem->SetAttribute("y", get().y);
propElem->SetAttribute("z", get().z);
propElem->SetAttribute("w", get().w);
return propElem;
}
} //namespace Voreen
/**********************************************************************
* *
* Voreen - The Volume Rendering Engine *
* *
* Copyright (C) 2005-2008 Visualization and Computer Graphics Group, *
* Department of Computer Science, University of Muenster, Germany. *
* <http://viscg.uni-muenster.de> *
* *
* This file is part of the Voreen software package. Voreen is free *
* software: you can redistribute it and/or modify it under the terms *
* of the GNU General Public License version 2 as published by the *
* Free Software Foundation. *
* *
* Voreen is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* in the file "LICENSE.txt" along with this program. *
* If not, see <http://www.gnu.org/licenses/>. *
* *
* The authors reserve all rights not expressly granted herein. For *
* non-commercial academic use see the license exception specified in *
* the file "LICENSE-academic.txt". To get information about *
* commercial licensing please contact the authors. *
* *
**********************************************************************/
#ifndef VRN_PROPERTY_H
#define VRN_PROPERTY_H
#include "voreen/core/xml/serializable.h"
#include "voreen/core/vis/transfunc/transfunc.h"
namespace voreen {
class Processor;
class Property : public Serializable {
public:
Property();
virtual ~Property();
std::string getGuiText() const;
void setOwner(Processor* processor);
Processor* getOwner() const;
protected:
std::string guiText_;
Processor* owner_;
};
typedef std::vector<Property*> Properties;
//-----------------------------------------------------------------------------------------------
template<class T>
class PropertyWidget {
public:
virtual ~PropertyWidget() {}
inline virtual void updateValue(T value);
protected:
Property* myProperty_;
};
template<class T>
void PropertyWidget<T>::updateValue(T /*value*/) {};
//-----------------------------------------------------------------------------------------------
template<class T>
class TemplateProperty : public Property {
public:
TemplateProperty();
TemplateProperty(const T& value); // third constructor version with needRecompileShader needed?
inline void set(const T& value);
T get() const;
protected:
T value_;
PropertyWidget<T>* myWidget_;
};
template<class T>
TemplateProperty<T>::TemplateProperty()
: myWidget_(0)
{
}
template<class T>
TemplateProperty<T>::TemplateProperty(const T& value)
: myWidget_(0)
, value_(value)
{
}
template<class T>
void TemplateProperty<T>::set(const T& value) {
//if (value_ != value) {
value_ = value;
if (myWidget_)
myWidget_->updateValue();
//}
}
template<class T>
T TemplateProperty<T>::get() const {
return value_;
}
//-----------------------------------------------------------------------------------------------
template<class T>
class NumericProperty : public TemplateProperty<T> {
public:
NumericProperty();
NumericProperty(const T& value, const T& minValue, const T& maxValue);
T getMinValue() const;
void setMinValue(const T& minValue);
T getMaxValue() const;
void setMaxValue(const T& maxValue);
protected:
T minValue_;
T maxValue_;
};
template<class T>
NumericProperty<T>::NumericProperty() {
}
template<class T>
NumericProperty<T>::NumericProperty(const T& value, const T& minValue, const T& maxValue)
: TemplateProperty<T>(value)
, minValue_(minValue)
, maxValue_(maxValue) {
}
template<class T>
T NumericProperty<T>::getMinValue() const {
return minValue_;
}
template<class T>
void NumericProperty<T>::setMinValue(const T& minValue) {
minValue_ = minValue;
}
template<class T>
T NumericProperty<T>::getMaxValue() const {
return maxValue_;
}
template<class T>
void NumericProperty<T>::setMaxValue(const T& maxValue) {
maxValue_ = maxValue;
}
//-----------------------------------------------------------------------------------------------
class FloatProperty : public NumericProperty<float> {
public:
FloatProperty(std::string guiText, float value=0.f, float minValue=0.f, float maxValue=1.f);
void setDecimals(int decimals);
int getDecimals() const;
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
protected:
int decimals_;
};
//-----------------------------------------------------------------------------------------------
class IntProperty : public NumericProperty<int> {
public:
IntProperty(std::string guiText, int value=0, int minValue=0, int maxValue=100);
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class BoolProperty : public TemplateProperty<bool> {
public:
BoolProperty(std::string guiText, bool value=false);
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class StringProperty : public TemplateProperty<std::string> {
public:
StringProperty(std::string guiText, std::string value = "");
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class StringVectorProperty : public TemplateProperty<std::vector<std::string> > {
public:
StringVectorProperty(std::string guiText, std::vector<std::string> value);
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class ColorProperty : public TemplateProperty<tgt::vec4> {
public:
ColorProperty(std::string guiText, tgt::Color value=tgt::Color(0.0));
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class EnumProperty : public TemplateProperty<int> {
public:
EnumProperty(std::string guiText, std::vector<std::string>& strings, int startIndex=0);
std::vector<std::string> getStrings();
void setStrings(const std::vector<std::string>& strings);
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
protected:
std::vector<std::string> strings_;
};
//-----------------------------------------------------------------------------------------------
class ButtonProperty : public TemplateProperty<bool> {
public:
ButtonProperty(std::string guiText, std::string buttonText, std::string iconFilename="");
std::string getButtonText();
std::string getIconFilename();
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
protected:
std::string buttonText_;
std::string iconFilename_;
};
//-----------------------------------------------------------------------------------------------
class FileDialogProperty : public TemplateProperty<std::string> {
public:
FileDialogProperty(std::string guiText, std::string caption, std::string directory, std::string filter);
std::string getCaption() const;
std::string getDirectory() const;
std::string getFilter() const;
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
protected:
std::string caption_;
std::string directory_;
std::string filter_;
};
//-----------------------------------------------------------------------------------------------
class TransFuncAlphaProperty : public TemplateProperty<TransFunc> {
public:
TransFuncAlphaProperty(std::string guiText, TransFunc tf, const std::string& yAxisLabel="intensity");
std::string getYAxisText() { return yAxisLabel_; };
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
protected:
std::string yAxisLabel_;
};
//-----------------------------------------------------------------------------------------------
class TransFuncProperty : public TemplateProperty<TransFunc> {
public:
TransFuncProperty(std::string guiText, TransFunc tf, bool showThreshold=true);
bool getShowThreshold();
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
protected:
bool showThreshold_;
};
//-----------------------------------------------------------------------------------------------
class FloatVec2Property : public NumericProperty<tgt::vec2> {
public:
FloatVec2Property(std::string guiText, tgt::vec2 value, tgt::vec2 minValue=tgt::vec2(0.0f), tgt::vec2 maxValue=tgt::vec2(1.0f));
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class FloatVec3Property : public NumericProperty<tgt::vec3> {
public:
FloatVec3Property(std::string guiText, tgt::vec3 value, tgt::vec3 minValue=tgt::vec3(0.0f), tgt::vec3 maxValue=tgt::vec3(1.0f));
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class FloatVec4Property : public NumericProperty<tgt::vec4> {
public:
FloatVec4Property(std::string guiText, tgt::vec4 value, tgt::vec4 minValue=tgt::vec4(0.0f), tgt::vec4 maxValue=tgt::vec4(1.0f));
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class IntVec2Property : public NumericProperty<tgt::ivec2> {
public:
IntVec2Property(std::string guiText, tgt::ivec2 value, tgt::ivec2 minValue=tgt::ivec2(0), tgt::ivec2 maxValue=tgt::ivec2(100));
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class IntVec3Property : public NumericProperty<tgt::ivec3> {
public:
IntVec3Property(std::string guiText, tgt::ivec3 value, tgt::ivec3 minValue=tgt::ivec3(0), tgt::ivec3 maxValue=tgt::ivec3(100));
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
//-----------------------------------------------------------------------------------------------
class IntVec4Property : public NumericProperty<tgt::ivec4> {
public:
IntVec4Property(std::string guiText, tgt::ivec4 value, tgt::ivec4 minValue=tgt::ivec4(0), tgt::ivec4 maxValue=tgt::ivec4(100));
void updateFromXml(TiXmlElement* propElem);
TiXmlElement* serializeToXml() const;
};
} // namespace voreen
#endif // VRN_PROPERTY_H
// add methods to existing
template<class T>
class TemplateProperty<T> {
public:
// convenience methods
EqualCondition& valueEqual(const T& value, const ConditionalAction& action = NoAction(), const ConditionalAction& elseaction = NoAction()) {
return dynamic_cast<EqualCondition&>(addCondition(EqualCondition<T>(0, this, value, action, elseaction)));
}
LessCondition& valueLess(const T& value, const ConditionalAction& action = NoAction(), const ConditionalAction& elseaction = NoAction()) {
return dynamic_cast<LessCondition&>(addCondition(LessCondition<T>(0, this, value, action, elseaction)));
}
InCondition& valueIn(const std::set<T>& values, const ConditionalAction& action = NoAction(), const ConditionalAction& elseaction = NoAction()) {
return dynamic_cast<InCondition&>(addCondition(InCondition<T>(0, this, values, action, elseaction)));
}
TrueCondition& onChange(const &ConditionalAction action = NoAction()) {
return dynamic_cast<TrueCondition&>(addCondition(TrueCondition(0, action)));
}
// etc
PropertyCondition& addCondition(const PropertyCondition& condition) {
conditions_.push_back(condition);
return *conditions_.back();
}
// this replaces the old method
void set(const T& value) {
value_ = value;
if (myWidget_)
myWidget_->updateValue();
// check if conditions met and fire actions
for(std::vector<PropertyCondition>::iterator cond = conditions_.begin(); cond != conditions_.end(); ++cond) {
cond->check();
}
}
// TODO way to remove conditions (especially if conditioned Properties are gone)
private:
std::vector<PropertyCondition> conditions_;
// + existing methods
};
// add methods to existing
class Property {
public:
Property& addCondition(PropertyCondition& condition) {
condition.setConditioned(this);
return *this;
}
Property& conditioned_by(PropertyCondition& condition) { return addCondition(condition); }
// + existing methods
// TODO Property needs to know its Conditions to remove them on destruction
};
/**
* A PropertyCondition can check any Condition and trigger ConditionalActions
* if the condition is met. The foremost purpose is to monitor the state of
* a Property (the conditioner ?better: controller?) and react to its changes.
*/
class PropertyCondition {
public:
PropertyCondition(Property* conditioned = 0, const ConditionalAction& action = NoAction(), const ConditionalAction& elseaction = NoAction() ) : conditioned_(conditioned), addAction(action), addElseAction(elseaction) {}
// TODO Destructor
PropertyCondition& setConditioned(Property& conditioned) {
conditioned_ = &conditioned;
return *this;
}
PropertyCondition& targeting(Property& conditioned) { setConditioned(conditioned); }
Property* getConditioned() const {
return conditioned_;
}
PropertyCondition& addAction(const ConditionalAction& action) {
action_.push_back(action);
action_.back()->setCondition(this);
return *this;
}
PropertyCondition& Do(const ConditionalAction& action) { return addAction(action); }
PropertyCondition& addElseAction(const ConditionalAction& action) {
elseaction_.push_back(action);
elseaction_.back()->setCondition(this);
return *this;
}
PropertyCondition& Else(ConditionalAction action) { return addElseAction(action); }
virtual bool met() = 0; // implement this
void check() {
if (conditioned_) {
if (met()) {
for (size_t i; i < action_.size(); ++i)
action_.at(i)->fire();
}
else {
for (size_t i; i < elseaction_.size(); ++i)
elseaction_.at(i)->fire();
}
}
}
private:
Property* conditioned_;
std::vector<ConditionalAction> action_;
std::vector<ConditionalAction> elseaction_;
};
class TrueCondition : public PropertyCondition {
TrueCondition(Property* conditioned, const ConditionalAction& action = NoAction()) : PropertyCondition(conditioned, action) {}
bool met() { return true; }
};
/* Can be accomplished by simply exchanging action and elseaction
class NotCondition {};
*/
class HasObamaWonCondition : public TrueCondition {};
template<class T>
class TemplateCondition : public PropertyCondition {
public:
TemplateCondition(Property* conditioned, TemplateProperty<T>* conditioner, T value, const ConditionalAction& action = NoAction(), const ConditionalAction& elseaction = NoAction())
: PropertyCondition(conditioned, action, elseaction), conditioner_(conditioner), value_(value) {}
bool met() = 0;
private:
TemplateProperty<T>* conditioner_;
T value_;
};
template<class T>
class EqualCondition : public TemplateCondition<T> {
public:
bool met() {
if (!conditioner_) return false;
return (conditioner_->get() == value_);
}
};
template<class T>
class LessCondition : public TemplateCondition<T> {
public:
bool met() {
if (!conditioner_) return false;
return (conditioner_->get() < value_);
}
};
template<class T>
class SetCondition : public PropertyCondition {
public:
SetCondition(Property* conditioned, TemplateProperty<T>* conditioner, std::set<T> values, const ConditionalAction& action = NoAction(), const ConditionalAction& elseaction = NoAction())
: PropertyCondition(conditioned, action, elseaction), conditioner_(conditioner), values_(values) {}
virtual bool met() = 0;
private:
TemplateProperty<T>* conditioner_;
std::set<T> values_;
};
template<class T>
class InCondition : public SetCondition<T> {
bool met() {
return (values_.find(conditioner_->get()) != values_.end());
}
}
// etc
/**
* A ConditionalAction can be set to fire when a PropertyCondition is met.
* The action can be anything but the foremost purpose is to change the state
* of the Property conditioned by the PropertyCondition the action belongs to.
*/
class ConditionalAction {
public:
ConditionalAction(PropertyCondition* condition = 0) : condition_(condition) {}
void setCondition(PropertyCondition* condition) { condition_ = condition; }
virtual void fire() = 0; // implement
Property* conditioned() {
if (condition_) {
return condition_->getConditioned(); // might be NULL
}
return 0;
}
private:
PropertyCondition* condition_;
};
struct NoAction : public ConditionalAction {
void fire() {} // do nothing
}
struct SetVisibleAction : public ConditionalAction {
void fire() {
conditioned()->setVisible();
}
};
struct SetInvisibleAction : public ConditionalAction {
void fire() {
conditioned()->setInvisible();
}
};
template<class T>
class SetAction : public ConditionalAction {
public:
SetAction(T value) : value_(value) {}
void fire() {
dynamic_cast< TemplateProperty<T>* >(conditioned())->set(value); // Nullcheck?
}
private:
T value_;
};
struct RecompileShaderAction : public ConditionalAction {
void fire() {
// notify system that shaders have to be recompiled
}
}
struct CureCancerAction : public ConditionalAction {
void fire() {
// cure cancer
}
}
template<class T>
class TargetAction : ConditionalAction {
public:
TargetAction() : ConditionalAction(0), target_(0) {}
TargetAction(T& target) : ConditionalAction(0), target_(&target) {}
TargetAction& setTarget(T* target) {
target_ = target;
return *this;
}
TargetAction& targeting(T& target) { return setTarget(&target); }
T* target() {
return target_;
}
virtual void fire() = 0;
}
class ShootRabbitAction : TargetAction<Rabbit> {
void fire() {
shoot(target());
}
void shoot(Rabbit* rabbit) {
// pewpew - lazergunz!
}
}
Let ConditionalActions have their own target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment