/*
Copyright (C) 1997, 1998, 1999 by Alex Pfaffe
(Digital Dawn Graphics Inc)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _ddgParam_Class_
#define _ddgParam_Class_
#include "util/ddgutil.h"
#include "util/ddgstr.h"
/*
* Class which supports control of a number of parameters.
* ddgParams can be controlled via keys.
*/
class WEXP ddgParam
{
public:
float _value;
float _default;
float _min;
float _max;
float _step;
float _fstep;
float _sstep;
float *_vaddr;
void (*_update)(ddgParam *p);
bool _bool:1;
bool _int:1;
bool _wrap:1;
int _ikey;
int _dkey;
unsigned char _key;
ddgStr _desc;
float _adjust( float v, float a, float b)
{ return (_wrap?ddgUtil::wrap(v,a,b): ddgUtil::clamp(v,a,b)); }
public:
ddgParam() { init(' ',"--",0.0,0.0,1.0,0.1,0.01,1.0); }
ddgParam(unsigned char k, char *d, float v, float i = 0.0, float a = 1.0,
float s = 0.1, float ss = 0.01, float fs = 1.0)
{
init(k,d,v,i,a,s,ss,fs);
}
ddgParam(unsigned char k, char *d, float* va, float i = 0.0, float a = 1.0,
float s = 0.1, float ss = 0.01, float fs = 1.0)
{
init(k,d,*va,i,a,s,ss,fs,va);
}
void setBool(void) { _bool = true; _min = 0.0; _max = 1.0; _step = _sstep = _fstep = 1.0; }
bool isBool(void) { return _bool; }
void setInt(void) { _int = true; }
bool isInt(void) { return _int; }
float get(void) { return *_vaddr; }
float set(float v)
{
*_vaddr = ddgUtil::clamp(v,_min,_max);
doUpdate();
return *_vaddr;
}
void init( unsigned char k, char *d = "--",
float v = 0.0, float i = 0.0, float a = 1.0,
float s = 0.1, float ss = 0.01, float fs = 1.0, float *vaddr = NULL)
{
if (vaddr)
_vaddr = vaddr;
else
_vaddr = &_value;
_key = k; *_vaddr = _default = v;
_min = i; _max = a;
_step = s; _sstep = ss; _fstep = fs;
_bool = _int = _wrap = false;
_ikey = _dkey = 0;
_desc.assign(d);
_update = NULL;
}
float reset(void) { return set(_default); }
float incr(void) { return set(_adjust(get()+_step,_min,_max)); }
float decr(void) { return set(_adjust(get()-_step,_min,_max)); }
float sincr(void) { return set(_adjust(get()+_sstep,_min,_max)); }
float sdecr(void) { return set(_adjust(get()-_sstep,_min,_max)); }
float fincr(void) { return set(_adjust(get()+_fstep,_min,_max)); }
float fdecr(void) { return set(_adjust(get()-_fstep,_min,_max)); }
void max( float max ) { _max = max; }
void min( float min ) { _min = min; }
unsigned char key(void) { return _key; }
void desc( char *d ) { _desc.assign(d); }
char *desc( void ) { return (_desc.s); }
void control( int d, int i = 0) { _ikey = i; _dkey = d; }
int controlI( void ) { return _ikey; }
int controlD( void ) { return _dkey; }
void wrap( bool w ) { _wrap = w; }
bool wrap( void ) { return _wrap; }
void update( void (*u)(ddgParam*p)) { _update = u; }
void doUpdate (void ) { if (_update) _update(this); }
};
class WEXP ddgParamF : public ddgParam
{
public:
ddgParamF(unsigned char k, char *d, float v, float i = 0.0, float a = 1.0,
float s = 0.1, float ss = 0.01, float fs = 1.0) : ddgParam(k,d,v,i,a,s,ss,fs)
{
}
};
class WEXP ddgParamB : public ddgParam
{
public:
ddgParamB(unsigned char k, char *d, bool v ) : ddgParam(k,d,v?1.0:0.0,0.0,1.0,1.0) { setBool(); }
ddgParamB() { setBool(); }
void init( unsigned char k, char *d, bool v = false)
{
ddgParam::init(k,d,v); setBool();
}
void set(bool v) { ddgParam::set(v?1.0:0.0); }
bool get(void)
{
return (ddgParam::get() != 0.0);
}
};
class WEXP ddgParamI : public ddgParam
{
public:
ddgParamI(unsigned char k, char *d, int v, int i, int a, int s = 1, int ss = 1 ) : ddgParam(k,d,v,i,a,s,ss) { setInt(); }
ddgParamI() { setInt(); }
void init( unsigned char k, char *d, int v, int i, int a, int s = 1, int ss = 1, int fs = 10)
{
ddgParam::init(k,d,v,i,a,s,ss,fs); setInt();
}
int get(void)
{
return (int) ddgParam::get();
}
};
class WEXP ddgParamR : public ddgParamB
{
public:
bool get(void)
{
bool retval = ddgParam::get() != 0.0;
reset();
return retval;
}
};
class WEXP ddgParamSetNode : public ddgListNode
{
ddgParam* _p;
public:
operator ddgParam* () { return _p; }
ddgParamSetNode( ddgParam *p ) : _p(p) {}
ddgParam *p() { return _p; }
};
class WEXP ddgParamSet : public ddgList
{
typedef ddgList super;
public:
void add( ddgParam *p );
ddgParam *find(unsigned char k, int sk ) // Search for parameter k
{
ddgParamSetNode *psn = (ddgParamSetNode *) head();
while( psn && ((k && psn->p()->key() != k)
||(sk != psn->p()->controlI()
&& sk != psn->p()->controlD()))
) psn = (ddgParamSetNode *) psn->next();
return psn ? psn->p() : 0;
}
float get(unsigned char k )
{
ddgParamSetNode *psn = (ddgParamSetNode *) head();
while( psn && psn->p()->key() != k) psn = (ddgParamSetNode *) psn->next();
return psn ? psn->p()->get() : 0.0f;
}
void report(void)
{
ddgParamSetNode *psn = (ddgParamSetNode *) head();
while(psn)
{
ddgParam *p = psn->p();
cerr << '[';
cerr << (p->key() == 0 ? '#' : p->key() );
cerr << ']';
if (p->isBool())
cerr << (p->get() > 0.5 ? 'T':'F');
else if (p->isInt()) cerr << (int) p->get();
else cerr << (float)p->get();
cerr << " " << p->desc() << '\n';
psn = (ddgParamSetNode *) psn->next();
}
}
void help(void);
bool key(unsigned char key, int x, int y, int sk = 0 );
// Add the entries in the given param set to this one.
void append ( ddgParamSet *ps )
{
ddgParamSetNode *psn = (ddgParamSetNode *) ps->head();
while (psn)
{
add(psn->p());
psn = (ddgParamSetNode *) psn->next();
}
}
};
#endif