Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions addons/ofxGui/src/ofxSlider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ void ofxSlider<Type>::generateDraw(){
bg.setFillColor(thisBackgroundColor);
bg.setExtents(b);

float valAsPct = ofMap( value, value.getMin(), value.getMax(), 0, b.width-2, true );
float valAsPct = ofClamp(value.getPctScaled(),0,1);
bar.setFillColor(thisFillColor);
bar.setExtents(b.x+1, b.y+1, valAsPct, b.height-2);

Expand Down Expand Up @@ -314,7 +314,7 @@ bool ofxSlider<Type>::setValue(float mx, float my, bool bCheck){
}
}
if( bGuiActive ){
value = ofMap(mx, b.x, b.x + b.width, value.getMin(), value.getMax(), true);
value.setPctScaled(ofMap(mx, b.x, b.x + b.width, 0, 1, true));
return true;
}
return false;
Expand Down
229 changes: 196 additions & 33 deletions libs/openFrameworks/types/ofParameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,11 @@ typename std::enable_if<!of::priv::has_loading_support<ParameterType>::value, Pa
}
/*! \endcond */

enum class ofParameterScale{
Linear,
Logarithmic,
};

/// \brief ofParameter holds a value and notifies its listeners when it changes.
///
/// ofParameter can be used as the value itself. For example an `ofParameter<int>`
Expand All @@ -501,8 +506,9 @@ class ofParameter : public ofAbstractParameter {
ofParameter();
ofParameter(const ofParameter<ParameterType> & v);
ofParameter(const ParameterType & v);
ofParameter(const std::string & name, const ParameterType & v);
ofParameter(const std::string & name, const ParameterType & v, const ParameterType & min, const ParameterType & max);
ofParameter(const std::string& name, const ParameterType & v);
ofParameter(const std::string& name, const ParameterType & v, const ParameterType & min, const ParameterType & max);
ofParameter(const std::string& name, const ParameterType & v, const ParameterType & min, const ParameterType & max, ofParameterScale scale);

const ParameterType & get() const;
const ParameterType * operator->() const;
Expand Down Expand Up @@ -543,6 +549,11 @@ class ofParameter : public ofAbstractParameter {
return obj->changedE.newListener(args...);
}

template<typename... Args>
void ownListener(Args...args) {
obj->ownListeners.push_back(obj->changedE.newListener(args...));
}

void enableEvents();
void disableEvents();
bool isSerializable() const;
Expand Down Expand Up @@ -592,6 +603,15 @@ class ofParameter : public ofAbstractParameter {
void setInit(const ParameterType & init);
bool isInit() const;

template<typename T=ParameterType>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type setScale(ofParameterScale scale);
template<typename T=ParameterType>
typename std::enable_if<std::is_arithmetic<T>::value, ofParameterScale>::type getScale() const;
template<typename T=ParameterType>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type setPctScaled(double value);
template<typename T=ParameterType>
typename std::enable_if<std::is_arithmetic<T>::value, double>::type getPctScaled() const;

void setSerializable(bool serializable);
std::shared_ptr<ofAbstractParameter> newReference() const;

Expand All @@ -613,7 +633,38 @@ class ofParameter : public ofAbstractParameter {

protected:
private:
class Value {
template<typename T, typename Enable = void>
class Scale;

template<typename T>
class Scale<T, typename std::enable_if<std::is_arithmetic<T>::value, T>::type>{
public:
ofParameterScale scale;
Scale():scale(ofParameterScale::Linear){}
Scale(ofParameterScale scale):scale(scale){}
Scale<T,T> & operator=(ofParameterScale scale){
this->scale = scale;
return *this;
}
operator ofParameterScale(){
return scale;
}
};

template<typename T>
class Scale<T, typename std::enable_if<!std::is_arithmetic<T>::value, T>::type>{
public:
Scale(){}
Scale(ofParameterScale){}
Scale<T,T> & operator=(ofParameterScale){
return *this;
}
operator ofParameterScale(){
return ofParameterScale::Linear;
}
};

class Value{
public:
Value()
: init(of::priv::TypeInfo<ParameterType>::min())
Expand All @@ -623,37 +674,50 @@ class ofParameter : public ofAbstractParameter {
, serializable(true) { }

Value(ParameterType v)
: init(v)
, value(v)
, min(of::priv::TypeInfo<ParameterType>::min())
, max(of::priv::TypeInfo<ParameterType>::max())
, bInNotify(false)
, serializable(true) { }

Value(std::string name, ParameterType v)
: name(name)
, init(v)
, value(v)
, min(of::priv::TypeInfo<ParameterType>::min())
, max(of::priv::TypeInfo<ParameterType>::max())
, bInNotify(false)
, serializable(true) { }

Value(std::string name, ParameterType v, ParameterType min, ParameterType max)
: name(name)
, init(v)
, value(v)
, min(min)
, max(max)
, bInNotify(false)
, serializable(true) { }
:value(v)
,init(v)
,min(of::priv::TypeInfo<ParameterType>::min())
,max(of::priv::TypeInfo<ParameterType>::max())
,bInNotify(false)
,serializable(true){}

Value(string name, ParameterType v)
:name(name)
,init(v)
,value(v)
,min(of::priv::TypeInfo<ParameterType>::min())
,max(of::priv::TypeInfo<ParameterType>::max())
,bInNotify(false)
,serializable(true){}

Value(string name, ParameterType v, ParameterType min, ParameterType max)
:name(name)
,init(v)
,value(v)
,min(min)
,max(max)
,bInNotify(false)
,serializable(true){}

Value(string name, ParameterType v, ParameterType min, ParameterType max, ofParameterScale scale)
:name(name)
,init(v)
,value(v)
,min(min)
,max(max)
,bInNotify(false)
,serializable(true)
,scale(scale){}

std::string name;
ParameterType init, value, min, max;
ParameterType value;
ParameterType min, max;
ofEvent<ParameterType> changedE;
bool bInNotify;
bool serializable;
std::vector<std::weak_ptr<ofParameterGroup::Value>> parents;
std::vector<weak_ptr<ofParameterGroup::Value>> parents;
std::vector<ofEventListener> ownListeners;
Scale<ParameterType,ParameterType> scale;
};

std::shared_ptr<Value> obj;
Expand Down Expand Up @@ -691,8 +755,13 @@ ofParameter<ParameterType>::ofParameter(const std::string & name, const Paramete
: obj(std::make_shared<Value>(name, v, min, max))
, setMethod(std::bind(&ofParameter<ParameterType>::eventsSetValue, this, std::placeholders::_1)) { }

template <typename ParameterType>
inline ofParameter<ParameterType> & ofParameter<ParameterType>::operator=(const ofParameter<ParameterType> & v) {
template<typename ParameterType>
ofParameter<ParameterType>::ofParameter(const string& name, const ParameterType & v, const ParameterType & min, const ParameterType & max, ofParameterScale scale)
:obj(std::make_shared<Value>(name, v, min, max, scale))
,setMethod(std::bind(&ofParameter<ParameterType>::eventsSetValue, this, std::placeholders::_1)){}

template<typename ParameterType>
inline ofParameter<ParameterType> & ofParameter<ParameterType>::operator=(const ofParameter<ParameterType> & v){
set(v);
return *this;
}
Expand Down Expand Up @@ -889,8 +958,59 @@ void ofParameter<ParameterType>::disableEvents() {
setMethod = std::bind(&ofParameter<ParameterType>::noEventsSetValue, this, std::placeholders::_1);
}

template <typename ParameterType>
inline ParameterType ofParameter<ParameterType>::operator++(int) {

template<typename ParameterType>
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type ofParameter<ParameterType>::setScale(ofParameterScale scale){
obj->scale = scale;
}

template<typename ParameterType>
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, ofParameterScale>::type ofParameter<ParameterType>::getScale() const{
return obj->scale;
}

template<typename ParameterType>
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, void>::type ofParameter<ParameterType>::setPctScaled(double pct){
switch(static_cast<ofParameterScale>(obj->scale)){
case ofParameterScale::Linear:
set(ofMap(pct, 0, 1, obj->min, obj->max));
break;
case ofParameterScale::Logarithmic:{
auto offset = obj->min > 0 ? 0 : 1 - obj->min;
auto min = obj->min + offset;
auto max = obj->max + offset;
auto minv = log(min);
auto maxv = log(max);
auto scale = (maxv - minv);
set(exp(minv + scale * pct) - offset);
}break;
}
}

template<typename ParameterType>
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value, double>::type ofParameter<ParameterType>::getPctScaled() const{
switch(static_cast<ofParameterScale>(obj->scale)){
case ofParameterScale::Logarithmic:{
auto offset = obj->min > 0 ? 0 : 1 - obj->min;
auto min = obj->min + offset;
auto max = obj->max + offset;
auto minv = log(min);
auto maxv = log(max);
auto scale = (maxv - minv);
return (log(obj->value + offset) - minv) / scale;
}
case ofParameterScale::Linear:
default:
return ofMap(obj->value, obj->min, obj->max, 0, 1);
}
}

template<typename ParameterType>
inline ParameterType ofParameter<ParameterType>::operator++(int){
ParameterType r = obj->value;
obj->value++;
set(obj->value);
Expand Down Expand Up @@ -1516,3 +1636,46 @@ template <typename ParameterType, typename Friend>
void ofReadOnlyParameter<ParameterType, Friend>::setParent(ofParameterGroup & _parent) {
parameter.setParent(_parent);
}


/// Sets to false every other parameter when one of them is set to true
template<typename ...Args>
inline void ofSetMutuallyExclusive(ofParameter<bool> & p1, ofParameter<bool> & p2, Args&... parameters){
ofSetMutuallyExclusive(p1, p2);
ofSetMutuallyExclusive(p1, parameters...);
ofSetMutuallyExclusive(p2, parameters...);
}

/// Sets to false every other parameter when one of them is set to true
template<>
inline void ofSetMutuallyExclusive(ofParameter<bool> & p1, ofParameter<bool> & p2){
p1.ownListener([p2](bool & enabled) mutable{
if(enabled){
p2.set(false);
}
});
p2.ownListener([p1](bool & enabled) mutable{
if(enabled){
p1.set(false);
}
});
}

/// Sets the same value to every other passed parameter when any changes
template<typename T, typename ...Args>
inline void ofParameterLink(ofParameter<T> & p1, ofParameter<T> & p2, Args&... parameters){
ofParameterLink(p1, p2);
ofParameterLink(p1, parameters...);
ofParameterLink(p2, parameters...);
}

/// Sets the same value to every other passed parameter when any changes
template<typename T>
inline void ofParameterLink(ofParameter<T> & p1, ofParameter<T> & p2){
p1.ownListener([p2](T & v) mutable{
p2.set(v);
});
p2.ownListener([p1](T & v) mutable{
p1.set(v);
});
}