Line data Source code
1 0 : /*
2 :
3 : OOJSOolite.h
4 :
5 : JavaScript proxy for Oolite (for version checking and similar).
6 :
7 :
8 : Oolite
9 : Copyright (C) 2004-2013 Giles C Williams and contributors
10 :
11 : This program is free software; you can redistribute it and/or
12 : modify it under the terms of the GNU General Public License
13 : as published by the Free Software Foundation; either version 2
14 : of the License, or (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program; if not, write to the Free Software
23 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 : MA 02110-1301, USA.
25 :
26 : */
27 :
28 : #import "OOJSOolite.h"
29 : #import "OOJavaScriptEngine.h"
30 : #import "OOStringParsing.h"
31 : #import "OOJSPlayer.h"
32 : #import "ResourceManager.h"
33 : #import "MyOpenGLView.h"
34 : #import "OOConstToString.h"
35 :
36 :
37 : static JSBool OoliteGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value);
38 : static JSBool OoliteSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value);
39 :
40 : static NSString *VersionString(void);
41 : static NSArray *VersionComponents(void);
42 :
43 : static JSBool OoliteCompareVersion(JSContext *context, uintN argc, jsval *vp);
44 :
45 :
46 0 : static JSClass sOoliteClass =
47 : {
48 : "Oolite",
49 : 0,
50 :
51 : JS_PropertyStub,
52 : JS_PropertyStub,
53 : OoliteGetProperty,
54 : OoliteSetProperty,
55 : //JS_StrictPropertyStub,
56 : JS_EnumerateStub,
57 : JS_ResolveStub,
58 : JS_ConvertStub,
59 : JS_FinalizeStub
60 : };
61 :
62 :
63 0 : enum
64 : {
65 : // Property IDs
66 : kOolite_version, // version number components, array, read-only
67 : kOolite_versionString, // version number as string, string, read-only
68 : kOolite_jsVersion, // JavaScript version, integer, read-only
69 : kOolite_jsVersionString, // JavaScript version as string, string, read-only
70 : kOolite_gameSettings, // Various game settings, object, read-only
71 : kOolite_resourcePaths, // Paths containing resources, built-in plus oxp/oxz, read-only
72 : kOolite_colorSaturation, // Color saturation, integer, read/write
73 : kOolite_postFX, // current post processing effect, integer, read/write
74 : kOolite_hdrToneMapper, // currently active HDR tone mapper, string, read/write
75 : kOolite_sdrToneMapper, // currently active SDR tone mapper, string, read/write
76 : #ifndef NDEBUG
77 : kOolite_timeAccelerationFactor, // time acceleration, float, read/write
78 : #endif
79 : };
80 :
81 :
82 0 : static JSPropertySpec sOoliteProperties[] =
83 : {
84 : // JS name ID flags
85 : { "gameSettings", kOolite_gameSettings, OOJS_PROP_READONLY_CB },
86 : { "jsVersion", kOolite_jsVersion, OOJS_PROP_READONLY_CB },
87 : { "jsVersionString", kOolite_jsVersionString, OOJS_PROP_READONLY_CB },
88 : { "version", kOolite_version, OOJS_PROP_READONLY_CB },
89 : { "versionString", kOolite_versionString, OOJS_PROP_READONLY_CB },
90 : { "resourcePaths", kOolite_resourcePaths, OOJS_PROP_READONLY_CB },
91 : { "colorSaturation", kOolite_colorSaturation, OOJS_PROP_READWRITE_CB },
92 : { "postFX", kOolite_postFX, OOJS_PROP_READWRITE_CB },
93 : { "hdrToneMapper", kOolite_hdrToneMapper, OOJS_PROP_READWRITE_CB },
94 : { "sdrToneMapper", kOolite_sdrToneMapper, OOJS_PROP_READWRITE_CB },
95 : #ifndef NDEBUG
96 : { "timeAccelerationFactor", kOolite_timeAccelerationFactor, OOJS_PROP_READWRITE_CB },
97 : #endif
98 : { 0 }
99 : };
100 :
101 :
102 0 : static JSFunctionSpec sOoliteMethods[] =
103 : {
104 : // JS name Function min args
105 : { "compareVersion", OoliteCompareVersion, 1 },
106 : { 0 }
107 : };
108 :
109 :
110 0 : void InitOOJSOolite(JSContext *context, JSObject *global)
111 : {
112 : JSObject *oolitePrototype = JS_InitClass(context, global, NULL, &sOoliteClass, OOJSUnconstructableConstruct, 0, sOoliteProperties, sOoliteMethods, NULL, NULL);
113 : JS_DefineObject(context, global, "oolite", &sOoliteClass, oolitePrototype, OOJS_PROP_READONLY);
114 : }
115 :
116 :
117 0 : static JSBool OoliteGetProperty(JSContext *context, JSObject *this, jsid propID, jsval *value)
118 : {
119 : if (!JSID_IS_INT(propID)) return YES;
120 :
121 : OOJS_NATIVE_ENTER(context)
122 :
123 : id result = nil;
124 : MyOpenGLView *gameView = [UNIVERSE gameView];
125 :
126 : switch (JSID_TO_INT(propID))
127 : {
128 : case kOolite_version:
129 : result = VersionComponents();
130 : break;
131 :
132 : case kOolite_versionString:
133 : result = VersionString();
134 : break;
135 :
136 : case kOolite_jsVersion:
137 : *value = INT_TO_JSVAL(JS_GetVersion(context));
138 : return YES;
139 :
140 : case kOolite_jsVersionString:
141 : *value = STRING_TO_JSVAL(JS_NewStringCopyZ(context, JS_VersionToString(JS_GetVersion(context))));
142 : return YES;
143 :
144 : case kOolite_gameSettings:
145 : result = [UNIVERSE gameSettings];
146 : break;
147 :
148 : case kOolite_resourcePaths:
149 : // user name in displayed paths masked for privacy - remember that the console can be run remotely too
150 : result = [ResourceManager maskUserNameInPathArray:[ResourceManager paths]];
151 : break;
152 :
153 : case kOolite_colorSaturation:
154 : return JS_NewNumberValue(context, [gameView colorSaturation], value);
155 :
156 : case kOolite_postFX:
157 : *value = INT_TO_JSVAL([UNIVERSE currentPostFX]);
158 : return YES;
159 :
160 : case kOolite_hdrToneMapper:
161 : {
162 : NSString *toneMapperStr = @"OOHDR_TONEMAPPER_UNDEFINED";
163 : #if OOLITE_WINDOWS
164 : if ([gameView hdrOutput])
165 : {
166 : toneMapperStr = OOStringFromHDRToneMapper([gameView hdrToneMapper]);
167 : }
168 : #endif
169 : result = toneMapperStr;
170 : break;
171 : }
172 :
173 : case kOolite_sdrToneMapper:
174 : {
175 : NSString *toneMapperStr = @"OOSDR_TONEMAPPER_UNDEFINED";
176 : if (![gameView hdrOutput])
177 : {
178 : toneMapperStr = OOStringFromSDRToneMapper([gameView sdrToneMapper]);
179 : }
180 : result = toneMapperStr;
181 : break;
182 : }
183 :
184 : #ifndef NDEBUG
185 : case kOolite_timeAccelerationFactor:
186 : return JS_NewNumberValue(context, [UNIVERSE timeAccelerationFactor], value);
187 : #endif
188 :
189 : default:
190 : OOJSReportBadPropertySelector(context, this, propID, sOoliteProperties);
191 : return NO;
192 : }
193 :
194 : *value = OOJSValueFromNativeObject(context, result);
195 : return YES;
196 :
197 : OOJS_NATIVE_EXIT
198 : }
199 :
200 :
201 0 : static JSBool OoliteSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
202 : {
203 : if (!JSID_IS_INT(propID)) return YES;
204 :
205 : OOJS_NATIVE_ENTER(context)
206 :
207 : jsdouble fValue;
208 : int32 iValue;
209 : NSString *sValue = nil;
210 : MyOpenGLView *gameView = [UNIVERSE gameView];
211 :
212 : switch (JSID_TO_INT(propID))
213 : {
214 : case kOolite_colorSaturation:
215 : if (JS_ValueToNumber(context, *value, &fValue))
216 : {
217 : float currentColorSaturation = [gameView colorSaturation];
218 : [gameView adjustColorSaturation:fValue - currentColorSaturation];
219 : return YES;
220 : }
221 : break;
222 :
223 : case kOolite_postFX:
224 : if (JS_ValueToInt32(context, *value, &iValue))
225 : {
226 : iValue = MAX(iValue, 0);
227 : [UNIVERSE setCurrentPostFX:iValue];
228 : return YES;
229 : }
230 : break;
231 :
232 : case kOolite_hdrToneMapper:
233 : if (!JSVAL_IS_STRING(*value)) break; // non-string is not allowed
234 : sValue = OOStringFromJSValue(context,*value);
235 : if (sValue != nil)
236 : {
237 : #if OOLITE_WINDOWS
238 : if ([gameView hdrOutput]) [gameView setHDRToneMapper:OOHDRToneMapperFromString(sValue)];
239 : else OOJSReportWarning(context, @"hdrToneMapper cannot be set if not running in HDR mode");
240 : #endif
241 : return YES;
242 : }
243 : break;
244 :
245 : case kOolite_sdrToneMapper:
246 : if (!JSVAL_IS_STRING(*value)) break; // non-string is not allowed
247 : sValue = OOStringFromJSValue(context,*value);
248 : if (sValue != nil)
249 : {
250 : if (![gameView hdrOutput]) [gameView setSDRToneMapper:OOSDRToneMapperFromString(sValue)];
251 : else OOJSReportWarning(context, @"sdrToneMapper cannot be set if not running in SDR mode");
252 : return YES;
253 : }
254 : break;
255 :
256 : #ifndef NDEBUG
257 : case kOolite_timeAccelerationFactor:
258 : if (JS_ValueToNumber(context, *value, &fValue))
259 : {
260 : [UNIVERSE setTimeAccelerationFactor:fValue];
261 : return YES;
262 : }
263 : break;
264 : #endif
265 :
266 : default:
267 : OOJSReportBadPropertySelector(context, this, propID, sOoliteProperties);
268 : return NO;
269 : }
270 :
271 : OOJSReportBadPropertyValue(context, this, propID, sOoliteProperties, *value);
272 : return NO;
273 :
274 : OOJS_NATIVE_EXIT
275 : }
276 :
277 :
278 0 : static NSString *VersionString(void)
279 : {
280 : return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
281 : }
282 :
283 :
284 0 : static NSArray *VersionComponents(void)
285 : {
286 : return ComponentsFromVersionString(VersionString());
287 : }
288 :
289 :
290 : /* oolite.compareVersion(versionSpec) : Number
291 : returns -1 if the current version of Oolite is less than versionSpec, 0 if
292 : they are equal, and 1 if the current version is newer. versionSpec may be
293 : a string or an array. Example:
294 : if (0 < oolite.compareVersion("1.70")) log("Old version of Oolite!")
295 : else this.doStuffThatRequires170()
296 : */
297 0 : static JSBool OoliteCompareVersion(JSContext *context, uintN argc, jsval *vp)
298 : {
299 : OOJS_NATIVE_ENTER(context)
300 :
301 : id components = nil;
302 : NSEnumerator *componentEnum = nil;
303 : id component = nil;
304 :
305 : if (argc == 0) OOJS_RETURN_VOID; // Backwards-compatibility: be overly lenient.
306 :
307 : components = OOJSNativeObjectFromJSValue(context, OOJS_ARGV[0]);
308 : if ([components isKindOfClass:[NSArray class]])
309 : {
310 : // Require each element to be a number
311 : for (componentEnum = [components objectEnumerator]; (component = [componentEnum nextObject]); )
312 : {
313 : if (![component isKindOfClass:[NSNumber class]])
314 : {
315 : components = nil;
316 : break;
317 : }
318 : }
319 : }
320 : else if ([components isKindOfClass:[NSString class]])
321 : {
322 : components = ComponentsFromVersionString(components);
323 : }
324 : else components = nil;
325 :
326 : if (components != nil)
327 : {
328 : OOJS_RETURN_INT((int32_t)CompareVersions(components, VersionComponents()));
329 : }
330 : else
331 : {
332 : OOJS_RETURN_VOID;
333 : }
334 :
335 : OOJS_NATIVE_EXIT
336 : }
|