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

Last change on this file since 247 was 247, checked in by Maciej Komosinski, 8 years ago

Sources support both 32-bit and 64-bit, and more compilers

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