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

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

GDK used by developers since 1999, distributed on the web since 2002

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