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 : result = [ResourceManager paths];
150 : break;
151 :
152 : case kOolite_colorSaturation:
153 : return JS_NewNumberValue(context, [gameView colorSaturation], value);
154 :
155 : case kOolite_postFX:
156 : *value = INT_TO_JSVAL([UNIVERSE currentPostFX]);
157 : return YES;
158 :
159 : case kOolite_hdrToneMapper:
160 : {
161 : NSString *toneMapperStr = @"OOHDR_TONEMAPPER_UNDEFINED";
162 : #if OOLITE_WINDOWS
163 : if ([gameView hdrOutput])
164 : {
165 : toneMapperStr = OOStringFromHDRToneMapper([gameView hdrToneMapper]);
166 : }
167 : #endif
168 : result = toneMapperStr;
169 : break;
170 : }
171 :
172 : case kOolite_sdrToneMapper:
173 : {
174 : NSString *toneMapperStr = @"OOSDR_TONEMAPPER_UNDEFINED";
175 : if (![gameView hdrOutput])
176 : {
177 : toneMapperStr = OOStringFromSDRToneMapper([gameView sdrToneMapper]);
178 : }
179 : result = toneMapperStr;
180 : break;
181 : }
182 :
183 : #ifndef NDEBUG
184 : case kOolite_timeAccelerationFactor:
185 : return JS_NewNumberValue(context, [UNIVERSE timeAccelerationFactor], value);
186 : #endif
187 :
188 : default:
189 : OOJSReportBadPropertySelector(context, this, propID, sOoliteProperties);
190 : return NO;
191 : }
192 :
193 : *value = OOJSValueFromNativeObject(context, result);
194 : return YES;
195 :
196 : OOJS_NATIVE_EXIT
197 : }
198 :
199 :
200 0 : static JSBool OoliteSetProperty(JSContext *context, JSObject *this, jsid propID, JSBool strict, jsval *value)
201 : {
202 : if (!JSID_IS_INT(propID)) return YES;
203 :
204 : OOJS_NATIVE_ENTER(context)
205 :
206 : jsdouble fValue;
207 : int32 iValue;
208 : NSString *sValue = nil;
209 : MyOpenGLView *gameView = [UNIVERSE gameView];
210 :
211 : switch (JSID_TO_INT(propID))
212 : {
213 : case kOolite_colorSaturation:
214 : if (JS_ValueToNumber(context, *value, &fValue))
215 : {
216 : float currentColorSaturation = [gameView colorSaturation];
217 : [gameView adjustColorSaturation:fValue - currentColorSaturation];
218 : return YES;
219 : }
220 : break;
221 :
222 : case kOolite_postFX:
223 : if (JS_ValueToInt32(context, *value, &iValue))
224 : {
225 : iValue = MAX(iValue, 0);
226 : [UNIVERSE setCurrentPostFX:iValue];
227 : return YES;
228 : }
229 : break;
230 :
231 : case kOolite_hdrToneMapper:
232 : if (!JSVAL_IS_STRING(*value)) break; // non-string is not allowed
233 : sValue = OOStringFromJSValue(context,*value);
234 : if (sValue != nil)
235 : {
236 : #if OOLITE_WINDOWS
237 : if ([gameView hdrOutput]) [gameView setHDRToneMapper:OOHDRToneMapperFromString(sValue)];
238 : else OOJSReportWarning(context, @"hdrToneMapper cannot be set if not running in HDR mode");
239 : #endif
240 : return YES;
241 : }
242 : break;
243 :
244 : case kOolite_sdrToneMapper:
245 : if (!JSVAL_IS_STRING(*value)) break; // non-string is not allowed
246 : sValue = OOStringFromJSValue(context,*value);
247 : if (sValue != nil)
248 : {
249 : if (![gameView hdrOutput]) [gameView setSDRToneMapper:OOSDRToneMapperFromString(sValue)];
250 : else OOJSReportWarning(context, @"sdrToneMapper cannot be set if not running in SDR mode");
251 : return YES;
252 : }
253 : break;
254 :
255 : #ifndef NDEBUG
256 : case kOolite_timeAccelerationFactor:
257 : if (JS_ValueToNumber(context, *value, &fValue))
258 : {
259 : [UNIVERSE setTimeAccelerationFactor:fValue];
260 : return YES;
261 : }
262 : break;
263 : #endif
264 :
265 : default:
266 : OOJSReportBadPropertySelector(context, this, propID, sOoliteProperties);
267 : return NO;
268 : }
269 :
270 : OOJSReportBadPropertyValue(context, this, propID, sOoliteProperties, *value);
271 : return NO;
272 :
273 : OOJS_NATIVE_EXIT
274 : }
275 :
276 :
277 0 : static NSString *VersionString(void)
278 : {
279 : return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
280 : }
281 :
282 :
283 0 : static NSArray *VersionComponents(void)
284 : {
285 : return ComponentsFromVersionString(VersionString());
286 : }
287 :
288 :
289 : /* oolite.compareVersion(versionSpec) : Number
290 : returns -1 if the current version of Oolite is less than versionSpec, 0 if
291 : they are equal, and 1 if the current version is newer. versionSpec may be
292 : a string or an array. Example:
293 : if (0 < oolite.compareVersion("1.70")) log("Old version of Oolite!")
294 : else this.doStuffThatRequires170()
295 : */
296 0 : static JSBool OoliteCompareVersion(JSContext *context, uintN argc, jsval *vp)
297 : {
298 : OOJS_NATIVE_ENTER(context)
299 :
300 : id components = nil;
301 : NSEnumerator *componentEnum = nil;
302 : id component = nil;
303 :
304 : if (argc == 0) OOJS_RETURN_VOID; // Backwards-compatibility: be overly lenient.
305 :
306 : components = OOJSNativeObjectFromJSValue(context, OOJS_ARGV[0]);
307 : if ([components isKindOfClass:[NSArray class]])
308 : {
309 : // Require each element to be a number
310 : for (componentEnum = [components objectEnumerator]; (component = [componentEnum nextObject]); )
311 : {
312 : if (![component isKindOfClass:[NSNumber class]])
313 : {
314 : components = nil;
315 : break;
316 : }
317 : }
318 : }
319 : else if ([components isKindOfClass:[NSString class]])
320 : {
321 : components = ComponentsFromVersionString(components);
322 : }
323 : else components = nil;
324 :
325 : if (components != nil)
326 : {
327 : OOJS_RETURN_INT((int32_t)CompareVersions(components, VersionComponents()));
328 : }
329 : else
330 : {
331 : OOJS_RETURN_VOID;
332 : }
333 :
334 : OOJS_NATIVE_EXIT
335 : }
|