]> git.mxchange.org Git - flightgear.git/blob - Scripting/nasal-props.cxx
de0efca33fac241c29c8835dcc481b41663fb243
[flightgear.git] / Scripting / nasal-props.cxx
1 #include <simgear/nasal/nasal.h>
2 #include <simgear/props/props.hxx>
3
4 #include <Main/globals.hxx>
5
6 #include "NasalSys.hxx"
7
8 // Implementation of a Nasal wrapper for the SGPropertyNode class,
9 // using the Nasal "ghost" (er... Garbage collection Handle for
10 // OutSide Thingy) facility.
11 //
12 // Note that these functions appear in Nasal with prepended
13 // underscores.  They work on the low-level "ghost" objects and aren't
14 // intended for use from user code, but from Nasal code you will find
15 // in props.nas.  That is where the Nasal props.Node class is defined,
16 // which provides a saner interface along the lines of SGPropertyNode.
17
18 static void propNodeGhostDestroy(void* ghost)
19 {
20     SGPropertyNode_ptr* prop = (SGPropertyNode_ptr*)ghost;
21     delete prop;
22 }
23
24 naGhostType PropNodeGhostType = { propNodeGhostDestroy };
25
26 static naRef propNodeGhostCreate(naContext c, SGPropertyNode* n)
27 {
28     SGPropertyNode_ptr* ghost = new SGPropertyNode_ptr(n);
29     return naNewGhost(c, &PropNodeGhostType, ghost);
30 }
31
32 naRef FGNasalSys::propNodeGhost(SGPropertyNode* handle)
33 {
34     return propNodeGhostCreate(_context, handle);
35 }
36
37 #define NASTR(s) s ? naStr_fromdata(naNewString(c),(char*)(s),strlen(s)) : naNil()
38
39 //
40 // Standard header for the extension functions.  It turns the "ghost"
41 // found in arg[0] into a SGPropertyNode_ptr*, and then "unwraps" the
42 // vector found in the second argument into a normal-looking args
43 // array.  This allows the Nasal handlers to do things like:
44 //   Node.getChild = func { _getChild(me.ghost, arg) }
45 //
46 #define NODEARG() \
47     naRef ghost = naVec_get(args, 0); \
48     SGPropertyNode_ptr* node = (SGPropertyNode_ptr*)naGhost_ptr(ghost); \
49     if(!node || naGhost_type(ghost) != &PropNodeGhostType) \
50         return naNil(); \
51     if(naVec_size(args) > 1) { \
52         args = naVec_get(args, 1); \
53         if(!naIsVector(args)) return naNil(); \
54     } else { args = naNil(); }
55
56 static naRef f_getType(naContext c, naRef args)
57 {
58     NODEARG();
59     char* t = "unknown";
60     switch((*node)->getType()) {
61     case SGPropertyNode::NONE:   t = "NONE";   break;
62     case SGPropertyNode::ALIAS:  t = "ALIAS";  break;
63     case SGPropertyNode::BOOL:   t = "BOOL";   break;
64     case SGPropertyNode::INT:    t = "INT";    break;
65     case SGPropertyNode::LONG:   t = "LONG";   break;
66     case SGPropertyNode::FLOAT:  t = "FLOAT";  break;
67     case SGPropertyNode::DOUBLE: t = "DOUBLE"; break;
68     case SGPropertyNode::STRING: t = "STRING"; break;
69     case SGPropertyNode::UNSPECIFIED: t = "UNSPECIFIED"; break;
70     }
71     return NASTR(t);
72 }
73
74 static naRef f_getName(naContext c, naRef args)
75 {
76     NODEARG();
77     return NASTR((*node)->getName());
78 }
79
80 static naRef f_getIndex(naContext c, naRef args)
81 {
82     NODEARG();
83     return naNum((*node)->getIndex());
84 }
85
86 static naRef f_getValue(naContext c, naRef args)
87 {
88     NODEARG();
89     switch((*node)->getType()) {
90     case SGPropertyNode::BOOL:   case SGPropertyNode::INT:
91     case SGPropertyNode::LONG:   case SGPropertyNode::FLOAT:
92     case SGPropertyNode::DOUBLE:
93         return naNum((*node)->getDoubleValue());
94     case SGPropertyNode::STRING:
95     case SGPropertyNode::UNSPECIFIED:
96         return NASTR((*node)->getStringValue());
97     }
98     return naNil();
99 }
100
101 static naRef f_setValue(naContext c, naRef args)
102 {
103     NODEARG();
104     naRef val = naVec_get(args, 0);
105     if(naIsString(val)) (*node)->setStringValue(naStr_data(val));
106     else                (*node)->setDoubleValue(naNumValue(val).num);
107     return naNil();
108 }
109
110 static naRef f_setIntValue(naContext c, naRef args)
111 {
112     NODEARG();
113     int iv = (int)naNumValue(naVec_get(args, 0)).num;
114     (*node)->setIntValue(iv);
115     return naNil();
116 }
117
118 static naRef f_setBoolValue(naContext c, naRef args)
119 {
120     NODEARG();
121     naRef val = naVec_get(args, 0);
122     (*node)->setBoolValue(naTrue(val) ? true : false);
123     return naNil();
124 }
125
126 static naRef f_setDoubleValue(naContext c, naRef args)
127 {
128     NODEARG();
129     (*node)->setDoubleValue(naNumValue(naVec_get(args, 0)).num);
130     return naNil();
131 }
132
133 static naRef f_getParent(naContext c, naRef args)
134 {
135     NODEARG();
136     SGPropertyNode* n = (*node)->getParent();
137     if(!n) return naNil();
138     return propNodeGhostCreate(c, n);
139 }
140
141 static naRef f_getChild(naContext c, naRef args)
142 {
143     NODEARG();
144     naRef child = naVec_get(args, 0);
145     if(!naIsString(child)) return naNil();
146     SGPropertyNode* n = (*node)->getChild(naStr_data(child));
147     if(!n) return naNil();
148     return propNodeGhostCreate(c, n);
149 }
150
151 static naRef f_getChildren(naContext c, naRef args)
152 {
153     NODEARG();
154     naRef result = naNewVector(c);
155     if(naIsNil(args) || naVec_size(args) == 0) {
156         // Get all children
157         for(int i=0; i<(*node)->nChildren(); i++)
158             naVec_append(result, propNodeGhostCreate(c, (*node)->getChild(i)));
159     } else {
160         // Get all children of a specified name
161         naRef name = naVec_get(args, 0);
162         if(!naIsString(name)) return naNil();
163         vector<SGPropertyNode_ptr> children
164             = (*node)->getChildren(naStr_data(name));
165         for(int i=0; i<children.size(); i++)
166             naVec_append(result, propNodeGhostCreate(c, children[i]));
167     }
168     return result;
169 }
170
171 static naRef f_removeChild(naContext c, naRef args)
172 {
173     NODEARG();
174     naRef child = naVec_get(args, 0);
175     naRef index = naVec_get(args, 1);
176     if(!naIsString(child) || !naIsNum(index)) return naNil();
177     (*node)->removeChild(naStr_data(child), (int)index.num);
178     return naNil();
179 }
180
181 static naRef f_getNode(naContext c, naRef args)
182 {
183     NODEARG();
184     naRef path = naVec_get(args, 0);
185     bool create = naTrue(naVec_get(args, 1));
186     if(!naIsString(path)) return naNil();
187     SGPropertyNode* n = (*node)->getNode(naStr_data(path), create);
188     return propNodeGhostCreate(c, n);
189 }
190
191 static naRef f_new(naContext c, naRef args)
192 {
193     return propNodeGhostCreate(c, new SGPropertyNode());
194 }
195
196 static naRef f_globals(naContext c, naRef args)
197 {
198     return propNodeGhostCreate(c, globals->get_props());
199 }
200
201 struct {
202     naCFunction func;
203     char* name;
204 } propfuncs[] = {
205     { f_getType, "_getType" },
206     { f_getName, "_getName" },
207     { f_getIndex, "_getIndex" },
208     { f_getValue, "_getValue" },
209     { f_setValue, "_setValue" },
210     { f_setIntValue, "_setIntValue" },
211     { f_setBoolValue, "_setBoolValue" },
212     { f_setDoubleValue, "_setDoubleValue" },
213     { f_getParent, "_getParent" },
214     { f_getChild, "_getChild" },
215     { f_getChildren, "_getChildren" },
216     { f_removeChild, "_removeChild" },
217     { f_getNode, "_getNode" },
218     { f_new, "_new" },
219     { f_globals, "_globals" },
220     { 0, 0 }
221 };
222
223 naRef FGNasalSys::genPropsModule()
224 {
225     naRef namespc = naNewHash(_context);
226     for(int i=0; propfuncs[i].name; i++)
227         hashset(namespc, propfuncs[i].name,
228                 naNewFunc(_context, naNewCCode(_context, propfuncs[i].func)));
229     return namespc;
230 }