source: cpp/frams/param/param.h @ 348

Last change on this file since 348 was 348, checked in by Maciej Komosinski, 9 years ago
  • explicit c_str() in SString instead of (const char*) cast
  • genetic converters and GenMan? are now thread-local which enables multi-threaded simulator separation
  • Property svn:eol-style set to native
File size: 13.0 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
[109]4
5#ifndef _PARAM_H_
6#define _PARAM_H_
7
8#include <stdio.h>
[247]9#include <stdint.h>
[109]10#include <frams/util/sstring.h>
11#include <frams/util/list.h>
12#include <frams/util/statrick.h>
13#include <frams/virtfile/virtfile.h>
14#include <common/framsg.h>
15
16class ExtValue;
17class ExtObject;
18
19// ParamInterface flags:
[316]20#define PARAM_READONLY       1  //< Param is not able to change this member
21#define PARAM_DONTSAVE       2  //< Param will not save this member
22#define PARAM_SETLEVEL(x) (((x)&3)<<2)  //< internal use
23#define PARAM_LEVEL(x)    (((x)>>2)&3)  //< internal use
24#define PARAM_USERREADONLY  16  //< GUI should not change this member (even if Param can)
25#define PARAM_USERHIDDEN    32  //< GUI should not display this member
26#define MUTPARAM_ALLOCENTRY 64  //< for mutableparam (private!)
27#define MUTPARAM_ALLOCDATA 128  //< for mutableparam (private!)
28#define PARAM_NOSTATIC  256     //< (FramScript) don't access this member in a static object (ClassName.field)
29#define PARAM_CONST     512     //< (FramScript) constant value
30#define PARAM_CANOMITNAME 1024  //< affects Param::save2()/load2() - for example one-liners in f0 genetic encoding
31#define PARAM_DONTLOAD    2048  //< Param::load() skips this field
32#define PARAM_NOISOLATION 4096  //< don't use proxy object in master/slave interactions
33#define PARAM_DEPRECATED  8192  //< this member is deprecated
[333]34#define PARAM_LINECOMMENT 16384 //< Param::load() adds "@line ..." comment when loading multiline (internal use)
[109]35
[247]36typedef int32_t paInt;
37#define PA_INT_SCANF "%d"
[284]38#define PA_INT_SCANF_X "%x"
[247]39
[154]40// the result of param::set() is a combination of bits:
[109]41
[154]42// read-only: cannot modify
[109]43#define PSET_RONLY      1
44
[154]45// value has been modified
[109]46#define PSET_CHANGED    2
47
[154]48//value has been adjusted because it tried to exceed min or max
[109]49#define PSET_HITMIN     4
50#define PSET_HITMAX     8
51
[154]52// useful combination: need to get and display the value so that a user knows that the value they tried to set has been rejected or changed
[109]53#define PSET_WARN (PSET_RONLY | PSET_HITMIN | PSET_HITMAX)
54
55#define PSET_NOPROPERTY 16
56
57struct ParamEntry;
58
59/** Property get/set interface - runtime access to named properties */
60class ParamInterface
61{
62public:
[319]63        virtual ~ParamInterface() {}
64
[154]65        virtual int getGroupCount() = 0; ///< @return the number of property groups
66        virtual int getPropCount() = 0; ///< @return the number of properties
[109]67
[154]68        virtual const char* getName() = 0;
69        virtual const char* getDescription() { return 0; }
70        virtual ParamEntry *getParamTab() const { return NULL; }
[109]71
[154]72        int findId(const char *n);      ///< find id number for internal name
73        int findIdn(const char *naz, int n);
[109]74
[154]75        virtual const char *id(int i) = 0;      ///< get internal name
76        virtual const char *name(int i) = 0;    ///< get the human-readable name
[109]77
[154]78        /** get type description.
79                first character defines basic datatype:
80                - d = integer
81                - f = floating point
82                - s = string
83                - o = ExtObject
84                - x = ExtValue (universal datatype)
85                */
86        virtual const char *type(int i) = 0;
[109]87
[154]88        virtual const char *help(int i) = 0;    ///< get long description (tooltip)
[109]89
[154]90        virtual int flags(int i) = 0;           ///< get flags
[109]91
[154]92        virtual int group(int i) = 0;           ///< get group id for a property
93        virtual const char *grname(int gi) = 0; ///< get group name
94        virtual int grmember(int gi, int n) = 0;        ///< get property id for n'th member of group "gi"
[109]95
[154]96        virtual void call(int i, ExtValue* args, ExtValue *ret) = 0;
[109]97
[154]98        void get(int, ExtValue &retval);        ///< most universal get, can be used for every datatype
[109]99
[154]100        virtual SString getString(int) = 0;     ///< get string value, you can only use this for "s" type property
[247]101        virtual paInt getInt(int) = 0;  ///< get long value, you can only use this for "d" type property
[154]102        virtual double getDouble(int) = 0;      ///< get double value, you can only use this for "f" type property
103        virtual ExtObject getObject(int) = 0;   ///< get object reference, you can only use this for "o" type property
104        virtual ExtValue getExtValue(int) = 0;  ///< get extvalue object, you can only use this for "x" type property
[109]105
[154]106        SString get(int);               ///< old style get, can convert long or double to string
107        SString getText(int);           ///< like getString, returns enumeration label for subtype "d 0 n ~enum1~enum2...
[109]108
[154]109        SString getStringById(const char*prop);  ///< get string value, you can only use this for "s" type property
[247]110        paInt getIntById(const char* prop);    ///< get long value, you can only use this for "d" type property
[154]111        double getDoubleById(const char* prop);///< get double value, you can only use this for "f" type property
112        ExtObject getObjectById(const char* prop);///< get object reference, you can only use this for "o" type property
113        ExtValue getExtValueById(const char* prop);///< get extvalue object, you can only use this for "x" type property
114        ExtValue getById(const char* prop);
[109]115
[154]116        int setInt(int i, const char* str);
117        int setDouble(int i, const char* str);
[247]118        virtual int setInt(int, paInt) = 0;             ///< set long value, you can only use this for "d" type prop
[154]119        virtual int setDouble(int, double) = 0; ///< set double value, you can only use this for "f" type prop
120        virtual int setString(int, const SString &) = 0;        ///< set string value, you can only use this for "s" type prop
121        virtual int setObject(int, const ExtObject &) = 0;      ///< set object reference, you can only use this for "o" type prop
122        virtual int setExtValue(int, const ExtValue &) = 0;     ///< 4 in 1
[109]123
[154]124        int set(int, const ExtValue &);///< most universal set, can be used for every datatype
[109]125
[154]126        int set(int, const char*);              ///< oldstyle set, can convert string to long or double
[109]127
[247]128        int setIntById(const char* prop, paInt);///< set long value, you can only use this for "d" type prop
[154]129        int setDoubleById(const char* prop, double);///< set double value, you can only use this for "f" type prop
130        int setStringById(const char* prop, const SString &);///< set string value, you can only use this for "s" type prop
131        int setObjectById(const char* prop, const ExtObject &);///< set object reference, you can only use this for "o" type prop
132        int setExtValueById(const char* prop, const ExtValue &); ///< for ExtValue types only
133        int setById(const char* prop, const ExtValue &);///< can be used for all property types
[109]134
[154]135        /** get valid minimum, maximum and default value for property 'prop'
136                @return 0 if min/max/def information is not available */
[247]137        int getMinMax(int prop, paInt& minumum, paInt& maximum, paInt& def);
[154]138        /** get valid minimum, maximum and default value for property 'prop'
139                @return 0 if min/max/def information is not available */
140        int getMinMax(int prop, double& minumum, double& maximum, double& def);
[253]141        int getMinMax(int prop, int& minumum, int& maximum, SString& def);
[109]142
[278]143        virtual void setDefault();
144        virtual void setDefault(int i);
[154]145        void setMin();
146        void setMax();
147        void setMin(int i);
148        void setMax(int i);
[109]149
[154]150        /** copy all property values from other ParamInterface object */
151        void copyFrom(ParamInterface *src);
[109]152
[154]153        /** Copy all property values from compatible ParamInterface object.
154                This method is more efficient than copyFrom,
155                but can be used only if the other object has the same properties sequence, e.g.:
156                - any two Param objects having common paramtab
157                - any ParamInterface object and the Param with paramtab constructed by ParamObject::makeParamTab
158                */
159        void quickCopyFrom(ParamInterface *src);
[109]160
[154]161        int save(VirtFILE*, const char* altname = NULL, bool force = 0);
162        int saveprop(VirtFILE*, int i, const char* p, bool force = 0);
[333]163        int load(VirtFILE*, bool warn_unknown_fields = true, bool *abortable = NULL, int *linenum = NULL);///< @return the number of fields loaded
[154]164        int load2(const SString &, int &);///< @return the number of fields loaded
[109]165
[154]166        static const char* SERIALIZATION_PREFIX;
[230]167
168#ifdef DEBUG
169        virtual void sanityCheck(int i) {}
170#endif
[109]171};
172
173// implementations:
174
175extern char MakeCodeGuardHappy;
176
177#define PROCOFFSET(_proc_) ( (void (*)(void*,ExtValue*,ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
178#define STATICPROCOFFSET(_proc_) ( (void (*)(void*,ExtValue*,ExtValue*)) &(FIELDSTRUCT :: _proc_))
179#define GETOFFSET(_proc_) ( (void (*)(void*,ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
180#define SETOFFSET(_proc_) ( (int (*)(void*,const ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
181
[247]182#define FIELDOFFSET(_fld_) ((intptr_t)((char*)(&((FIELDSTRUCT*)&MakeCodeGuardHappy)->_fld_)-((char*)((FIELDSTRUCT*)&MakeCodeGuardHappy))))
[109]183
[230]184#ifdef DEBUG
[247]185#define PARAM_ILLEGAL_OFFSET ((intptr_t)0xdeadbeef)
[230]186#else
187#define PARAM_ILLEGAL_OFFSET 0
188#endif
189
[109]190#define FIELD(_fld_) FIELDOFFSET(_fld_),0,0
191#define LONGOFFSET(_o_) (_o_),0,0
[230]192#define PROCEDURE(_proc_) PARAM_ILLEGAL_OFFSET,(void*)PROCOFFSET(_proc_),0
193#define STATICPROCEDURE(_proc_) PARAM_ILLEGAL_OFFSET,(void*)STATICPROCOFFSET(_proc_),0
194#define GETSET(_proc_) PARAM_ILLEGAL_OFFSET,(void*)GETOFFSET(get_ ## _proc_),(void*)SETOFFSET(set_ ## _proc_)
[109]195#define GETFIELD(_proc_) FIELDOFFSET(_proc_),(void*)GETOFFSET(get_ ## _proc_),0
196#define SETFIELD(_proc_) FIELDOFFSET(_proc_),0,(void*)SETOFFSET(set_ ## _proc_)
[230]197#define GETONLY(_proc_) PARAM_ILLEGAL_OFFSET,(void*)GETOFFSET(get_ ## _proc_),0
198#define SETONLY(_proc_) PARAM_ILLEGAL_OFFSET,0,(void*)SETOFFSET(set_ ## _proc_)
[109]199
200#define PARAMPROCARGS ExtValue* args,ExtValue* ret
201#define PARAMSETARGS const ExtValue* arg
202#define PARAMGETARGS ExtValue* ret
203
204#define PARAMPROCDEF(name) STATRICKDEF2(name,ExtValue*,ExtValue*)
205#define PARAMGETDEF(name) STATRICKDEF1(get_ ## name,ExtValue*)
206#define PARAMSETDEF(name) STATRICKRDEF1(int,set_ ## name,const ExtValue*)
207
208///////////////////////////////
209
210struct ParamEntry
211{
[154]212        const char *id;
213        short group, flags;
214        const char *name, *type;
[247]215        intptr_t offset;
[154]216        void *fun1; ///< procedure or get
217        void *fun2; ///< set
218        const char *help;
[109]219};
220
[154]221struct ParamEntryConstructor : public ParamEntry
[109]222{
223public:
[247]224        ParamEntryConstructor(const char *_id, short _group = 0, short _flags = 0, const char *_name = 0, const char *_type = 0, intptr_t _offset = 0, void *_fun1 = 0, void *_fun2 = 0, const char *_help = 0)
[154]225        {
226                id = _id; group = _group; flags = _flags; name = _name; type = _type; offset = _offset; fun1 = _fun1; fun2 = _fun2; help = _help;
227        }
[109]228};
229
[154]230class SimpleAbstractParam : public virtual ParamInterface
[109]231{
232protected:
[154]233        virtual void *getTarget(int i);
234        const char* myname;
235        bool dontcheckchanges;
[109]236
237public:
[154]238        void *object;
[109]239
[154]240        const char* getName() { return myname; }
241        void setName(const char* n) { myname = n; }
[109]242
[154]243        /**
244                @param t ParamEntry table
245                @param o controlled object
246                @param n Param's name
247                */
248        SimpleAbstractParam(void* o = 0, const char*n = 0) :myname(n), dontcheckchanges(0), object(o) {}
249        void setDontCheckChanges(bool x) { dontcheckchanges = x; }
[109]250
[154]251        void select(void *o) { object = o; }
252        void* getSelected() { return object; }
[109]253
[253]254        virtual ParamEntry *entry(int i) = 0;
[154]255        const char *id(int i) { return (i >= getPropCount()) ? 0 : entry(i)->id; }
256        const char *name(int i) { return entry(i)->name; }
257        const char *type(int i) { return entry(i)->type; }
258        const char *help(int i) { return entry(i)->help; }
259        int flags(int i) { return entry(i)->flags; }
260        int group(int i) { return entry(i)->group; }
261        void call(int i, ExtValue* args, ExtValue *ret);
[109]262
[154]263        SString getString(int);
[247]264        paInt getInt(int);
[154]265        double getDouble(int);
266        ExtObject getObject(int);
267        ExtValue getExtValue(int);
[109]268
[154]269        template<typename T> void messageOnExceedRange(int i, int setflags, T valuetoset) ///< prints a warning when setflags indicates that allowed param range has been exceeded during set
270        {
271                if (setflags & (PSET_HITMIN | PSET_HITMAX))
272                {
273                        SString svaluetoset = SString::valueOf(valuetoset); //converts any type to SString
274                        SString actual = get(i);
275                        FMprintf("Param", "set", FMLV_WARN, "Setting '%s.%s = %s' exceeded allowed range (too %s). Adjusted to %s.",
[348]276                                getName(), id(i), svaluetoset.c_str(), (setflags&PSET_HITMAX) ? "big" : "small", actual.c_str());
[154]277                }
278        }
[109]279
[247]280        int setInt(int, paInt);
[154]281        int setDouble(int, double);
282        int setString(int, const SString &);
283        int setObject(int, const ExtObject &);
284        int setExtValue(int, const ExtValue &);
[109]285
[154]286        int isequal(int i, void* defdata);
287        void save2(SString&, void *defdata, bool addcr = true, bool all_names = true);
[109]288
[278]289        virtual void setDefault();
290        virtual void setDefault(int i);
[230]291
292#ifdef DEBUG
293        void sanityCheck(int i);
294#endif
[109]295};
296
[154]297class Param : public SimpleAbstractParam
[109]298{
299protected:
[154]300        ParamEntry *entry(int i) { return tab + tab[0].group + i; }
[109]301public:
[154]302        ParamEntry *tab;
303        /**
304                @param t ParamEntry table
305                @param o controlled object
306                @param n Param's name
307                */
[109]308
[154]309        Param(ParamEntry *t = 0, void* o = 0, const char*n = 0) :SimpleAbstractParam(o, n), tab(t)
310        {
311                if (!n&&tab) myname = tab[0].name;
312        }
[109]313
[154]314        Param(const Param& p) :SimpleAbstractParam(p.object, p.myname), tab(p.tab) {}
315        void operator=(const Param&p) { object = p.object; myname = p.myname; tab = p.tab; }
[109]316
[154]317        const char* getDescription() { return tab[0].type; }
[109]318
[154]319        int getGroupCount() { return tab[0].group; }
320        int getPropCount() { return tab[0].flags; }
321        const char *grname(int i) { return (i < getGroupCount()) ? tab[i].id : 0; }
322        int grmember(int, int);
323        void setParamTab(ParamEntry *t, int dontupdatename = 0) { tab = t; if ((!dontupdatename) && tab) myname = tab[0].name; }
324        ParamEntry *getParamTab() const { return tab; }
[109]325};
326
327extern ParamEntry empty_paramtab[];
328
329#endif
Note: See TracBrowser for help on using the repository browser.