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

Last change on this file since 645 was 645, checked in by Maciej Komosinski, 7 years ago

f0 is strict now, will not accept float when int is expected

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