source: cpp/frams/param/mutableparam.cpp @ 824

Last change on this file since 824 was 824, checked in by Maciej Komosinski, 5 years ago

MutableParam? property definition can be changed

  • Property svn:eol-style set to native
File size: 8.8 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2018  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "mutableparam.h"
6#include <frams/util/extvalue.h>
7
8#define FIELDSTRUCT MutableParam
9ParamEntry MutableParam::pe_tab[] =
10{ //TODO: these names are visible for scripts in ExpProperties, ShowProperties, etc. add some reserved prefix to avoid conflicts with script-defined properties!
11        { "clear", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN, "remove all properties", "p", PROCEDURE(p_clear), },
12        { "add", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN, "add property (id,type,name,help)", "p", PROCEDURE(p_addprop), },
13        { "remove", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN, "remove property (index)", "p", PROCEDURE(p_remprop), },
14        { "change", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN, "change property (id,type,name,flags,help)", "p", PROCEDURE(p_changeprop), },
15        { "addGroup", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN, "add group (name)", "p", PROCEDURE(p_addgroup), },
16        { "removeGroup", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN, "remove group (index)", "p", PROCEDURE(p_remgroup), },
17        { "changedProperty", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN | PARAM_READONLY, "last changed property #", "d", FIELD(changed), },
18        { "changedPropertyId", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN | PARAM_READONLY, "last changed property id", "s", GETONLY(changedname), },
19};
20#undef FIELDSTRUCT
21
22MutableParam::MutableParam(const char*n, const char*g, int gr0)
23        :SimpleAbstractParam(this, n), persistgroup0(gr0), grprefix(g)
24{
25        if (persistgroup0)
26                addGroup(grprefix, 1);
27}
28
29int MutableParam::findGroup(const SString name, int ignoreprefix)
30{
31        int skipprefix = grprefix.len() ? grprefix.len() + 2 : 0;
32        for (int i = 0; i < groups.size(); i++)
33        {
34                if (ignoreprefix)
35                {
36                        const char *noprefix = groupname(i).c_str();
37                        if ((int)strlen(noprefix) < skipprefix) continue;
38                        noprefix += skipprefix;
39                        if (!strcmp(noprefix, name.c_str())) return i;
40                }
41                else
42                        if (groupname(i) == name) return i;
43        }
44        return -1;
45}
46
47int MutableParam::addGroup(const SString& gname, int noprefix)
48{
49        SString tmp;
50        if (noprefix)
51                tmp = gname;
52        else
53        {
54                tmp = grprefix;
55                if (tmp.len()) tmp += ": ";
56                tmp += gname;
57        }
58        groups += new SString(tmp);
59        int position = groups.size() - 1;
60        ongroupadd.action(position);
61        return position;
62}
63
64void MutableParam::removeGroup(int g)
65{
66        if ((g < 0) || (g >= MutableParam::getGroupCount())) return;
67        ParamEntry *e;
68        for (int i = MutableParam::getPropCount() - 1; i >= staticprops; i--)
69        {
70                e = entry(i);
71                if (g == e->group)
72                        removeProperty(i);
73        }
74        SString *s = (SString *)groups(g);
75        if (s) delete s;
76        groups -= g;
77        ongroupdelete.action(g);
78}
79
80int MutableParam::grmember(int g, int a)
81{
82        if (g == 0)
83        {
84                if (getGroupCount() < 2)
85                        return (a < getPropCount()) ? a : -9999;
86                if (a < staticprops) return a;
87                a -= staticprops;
88        }
89        ParamEntry *e;
90        for (int i = staticprops; e = entry(i); i++)
91                if (g == e->group)
92                        if (!a--) return i;
93        return -9999;
94}
95
96int MutableParam::addProperty(ParamEntry *pe, int position)
97{
98        DB(printf("MutableParam::add(%s)\n", pe->id));
99        if (position < 0)
100                position = entries.size() + staticprops;
101        entries.insert(position - staticprops, pe);
102
103        if (pe->offset)
104                pe->flags &= ~MUTPARAM_ALLOCDATA;
105        else
106        {
107                pe->flags |= MUTPARAM_ALLOCDATA;
108                void *d = 0;
109                switch (pe->type[0])
110                {
111                case 'd': d = new paInt(); *((paInt*)d) = 0; break;
112                case 'f': d = new double(); *((double*)d) = 0; break;
113                case 's': d = new SString(); break;
114                case 'x': d = new ExtValue(); break;
115                case 'o': d = new ExtObject(); break;
116                }
117                pe->offset = (intptr_t)d;
118        }
119        onadd.action(position);
120        return position;
121}
122
123ParamEntry * MutableParam::removeProperty(ParamEntry *pe)
124{
125        int index = entries.find(pe);
126        if (index >= 0) return removeProperty(index); else return pe;
127}
128
129ParamEntry * MutableParam::removeProperty(int i)
130{
131        ParamEntry *pe = (ParamEntry *)entries(i - staticprops);
132        DB(printf("MutableParam::remove(%d)\n", i));
133        void *d = (void*)pe->offset;
134        if (d && (pe->flags & MUTPARAM_ALLOCDATA))
135                switch (pe->type[0])
136                {
137                case 'd': delete (paInt*)d; break;
138                case 'f': delete (double*)d; break;
139                case 's': delete (SString*)d; break;
140                case 'x': delete (ExtValue*)d; break;
141                case 'o': delete (ExtObject*)d; break;
142                }
143        entries -= i - staticprops;
144        if (pe->flags & MUTPARAM_ALLOCENTRY)
145        {
146                if (pe->name) free((void*)pe->name);
147                if (pe->id) free((void*)pe->id);
148                if (pe->help) free((void*)pe->help);
149                if (pe->type) free((void*)pe->type);
150                delete pe;
151        }
152        ondelete.action(i);
153        return pe;
154}
155
156void MutableParam::clear(int everything)
157{
158        DB(printf("MutableParam::clear\n"));
159        for (int i = entries.size() - 1; i >= 0; i--)
160                removeProperty(i + staticprops);
161        int lastgroup = (everything || (persistgroup0 == 0)) ? 0 : 1;
162        for (int i = groups.size() - 1; i >= lastgroup; i--)
163                removeGroup(i);
164}
165
166void MutableParam::p_clear(ExtValue *args, ExtValue *ret)
167{
168        clear();
169}
170
171int MutableParam::addProperty(void* data, const char* id, const char* type, const char* name, const char* help, int flags, int group, int position)
172{
173        if ((!id) && (!type)) return -1;
174        if (!isValidTypeDescription(type)) return -1;
175        ParamEntry *pe = new ParamEntry();
176        pe->fun1 = 0; pe->fun2 = 0;
177        pe->group = (paInt)group;
178        pe->flags = (paInt)(flags | MUTPARAM_ALLOCENTRY);
179        pe->offset = (intptr_t)data;
180        pe->id = strdup(id);
181        pe->type = strdup(type);
182        pe->name = name ? strdup(name) : 0;
183        pe->help = help ? strdup(help) : 0;
184        return addProperty(pe, position);
185}
186
187static void changeString(const char* (&s), const char* newstr)
188{
189        if ((newstr != NULL) && (newstr[0] == 0)) newstr = NULL;
190        if ((s == NULL) && (newstr == NULL)) return;
191        if ((s != NULL) && (newstr != NULL) && (strcmp(s, newstr) == 0)) return;
192        if (s != NULL) { free((void*)s); s = NULL; }
193        if (newstr != NULL) s = strdup(newstr);
194}
195
196bool MutableParam::changeProperty(int i, const char* id, const char* type, const char* name, const char* help, int flags, int group)
197{
198        ParamEntry *pe = entry(i);
199        if ((!id) && (!type)) return false;
200        if (!isValidTypeDescription(type)) return false;
201        pe->group = (paInt)group;
202        pe->flags = (pe->flags & (MUTPARAM_ALLOCENTRY | MUTPARAM_ALLOCDATA)) | (flags & ~(MUTPARAM_ALLOCENTRY | MUTPARAM_ALLOCDATA));
203        changeString(pe->id, id);
204        changeString(pe->name, name);
205        changeString(pe->type, type);
206        changeString(pe->help, help);
207        onchange.action(i);
208        return true;
209}
210
211void MutableParam::p_addprop(ExtValue *args, ExtValue *ret)
212{
213        int i = addProperty(0, args[2].getString().c_str(), args[1].getString().c_str(), args[0].getString().c_str());
214        ret->setInt(i);
215}
216
217void MutableParam::p_changeprop(ExtValue *args, ExtValue *ret)
218{
219        int i = findId(args[4].getString().c_str());
220        if (i >= staticprops)
221        {
222                changeProperty(i, args[4].getString().c_str(), args[3].getString().c_str(), args[2].getString().c_str(), args[0].getString().c_str(), args[1].getInt(), entry(i)->group);
223                ret->setInt(i);
224        }
225        else
226                ret->setEmpty();
227}
228
229void MutableParam::p_remprop(ExtValue *args, ExtValue *ret)
230{
231        removeProperty(args[0].getInt());
232}
233
234void MutableParam::p_addgroup(ExtValue *args, ExtValue *ret)
235{
236        int i = addGroup(args[0].getString());
237        ret->setInt(i);
238}
239
240void MutableParam::p_remgroup(ExtValue *args, ExtValue *ret)
241{
242        removeGroup(args[0].getInt());
243}
244
245void MutableParam::notify(int id)
246{
247        changed = id;
248        onactivate.action(id);
249}
250
251int MutableParam::setInt(int i, paInt v)
252{
253        int ret = SimpleAbstractParam::setInt(i, v);
254        if (ret & PSET_CHANGED) notify(i);
255        return ret;
256}
257
258int MutableParam::setDouble(int i, double v)
259{
260        int ret = SimpleAbstractParam::setDouble(i, v);
261        if (ret & PSET_CHANGED) notify(i);
262        return ret;
263}
264
265int MutableParam::setString(int i, const SString &v)
266{
267        int ret = SimpleAbstractParam::setString(i, v);
268        if (ret & PSET_CHANGED) notify(i);
269        return ret;
270}
271
272int MutableParam::setObject(int i, const ExtObject &v)
273{
274        int ret = SimpleAbstractParam::setObject(i, v);
275        if (ret & PSET_CHANGED) notify(i);
276        return ret;
277}
278
279int MutableParam::setExtValue(int i, const ExtValue &v)
280{
281        int ret = SimpleAbstractParam::setExtValue(i, v);
282        if (ret & PSET_CHANGED) notify(i);
283        return ret;
284}
285
286void MutableParam::call(int i, ExtValue* args, ExtValue *ret)
287{
288        if (i < staticprops) return SimpleAbstractParam::call(i, args, ret);
289        notify(i);
290}
291
292///////////////////
293
294void ParamSaver::clear()
295{
296        for (int i = 0; i < store.size(); i += 2)
297        {
298                SString *n = (SString*)store(i);
299                ExtValue *v = (ExtValue*)store(i + 1);
300                delete n;
301                delete v;
302        }
303        store.clear();
304}
305
306void ParamSaver::loadFrom(ParamInterface& p)
307{
308        int N = p.getPropCount();
309        for (int i = 0; i < N; i++)
310        {
311                if (shouldLoad(p, i))
312                {
313                        ExtValue v;
314                        p.get(i, v);
315                        store += new SString(p.id(i));
316                        store += new ExtValue(v);
317                }
318        }
319}
320
321void ParamSaver::saveTo(MutableParam& p)
322{
323        for (int i = 0; i < store.size(); i += 2)
324        {
325                SString *n = (SString*)store(i);
326                int prop = p.findId(n->c_str());
327                if (prop < 0)
328                        prop = p.addProperty(0, n->c_str(), "x", 0, 0, 0, 0, -1);
329                p.setExtValue(prop, *(ExtValue*)store(i + 1));
330        }
331}
Note: See TracBrowser for help on using the repository browser.