Oolite
Loading...
Searching...
No Matches
HeadUpDisplay.m
Go to the documentation of this file.
1/*
2
3HeadUpDisplay.m
4
5Oolite
6Copyright (C) 2004-2013 Giles C Williams and contributors
7
8This program is free software; you can redistribute it and/or
9modify it under the terms of the GNU General Public License
10as published by the Free Software Foundation; either version 2
11of the License, or (at your option) any later version.
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with this program; if not, write to the Free Software
20Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21MA 02110-1301, USA.
22
23*/
24
25#import "OOCocoa.h"
26#import "HeadUpDisplay.h"
27#import "GameController.h"
28#import "ResourceManager.h"
29#import "PlayerEntity.h"
30#import "OOSunEntity.h"
31#import "OOPlanetEntity.h"
32#import "StationEntity.h"
35#import "OOWaypointEntity.h"
36#import "Universe.h"
37#import "OOTrumble.h"
38#import "OOColor.h"
39#import "GuiDisplayGen.h"
40#import "OOTexture.h"
41#import "OOTextureSprite.h"
42#import "OOPolygonSprite.h"
45#import "OOCrosshairs.h"
46#import "OOConstToString.h"
47#import "OOStringParsing.h"
48#import "OOJoystickManager.h"
50#import "OOStringExpander.h"
51
52
53#define ONE_SIXTEENTH 0.0625
54#define ONE_SIXTYFOURTH 0.015625
55#define DEFAULT_OVERALL_ALPHA 0.75
56#define GLYPH_SCALE_FACTOR 0.13 // 0.13 is an inherited magic number
57#define IDENTIFY_SCANNER_LOLLIPOPS ( 0 && OOLITE_DEBUG)
58
59
60#define NOT_DEFINED INFINITY
61#define WIDGET_INFO 0
62#define WIDGET_CACHE 1
63#define WIDGET_SELECTOR 2
64#define WIDGET_SELECTOR_NAME 3
65
66/* Convenience macros to make set-colour-or-default quicker. 'info' must be the NSDictionary and 'alpha' must be the overall alpha or these won't work */
67#define DO_SET_COLOR(t,d) SetGLColourFromInfo(info,t,d,alpha)
68#define SET_COLOR(d) DO_SET_COLOR(COLOR_KEY,d)
69#define SET_COLOR_LOW(d) DO_SET_COLOR(COLOR_KEY_LOW,d)
70#define SET_COLOR_MEDIUM(d) DO_SET_COLOR(COLOR_KEY_MEDIUM,d)
71#define SET_COLOR_HIGH(d) DO_SET_COLOR(COLOR_KEY_HIGH,d)
72#define SET_COLOR_CRITICAL(d) DO_SET_COLOR(COLOR_KEY_CRITICAL,d)
73#define SET_COLOR_SURROUND(d) DO_SET_COLOR(COLOR_KEY_SURROUND,d)
74
76{
77 float x, y, x0, y0;
79};
80
81static NSArray *sCurrentDrawItem;
82
83OOINLINE float useDefined(float val, float validVal)
84{
85 return (val == NOT_DEFINED) ? validVal : val;
86}
87
88
89static void DrawSpecialOval(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat step, GLfloat* color4v);
90
91static void SetGLColourFromInfo(NSDictionary *info, NSString *key, const GLfloat defaultColor[4], GLfloat alpha);
92static void GetRGBAArrayFromInfo(NSDictionary *info, GLfloat ioColor[4]);
93
94static void hudDrawIndicatorAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount);
95static void hudDrawMarkerAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount);
96static void hudDrawBarAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount);
97static void hudDrawSurroundAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz);
98static void hudDrawStatusIconAt(int x, int y, int z, NSSize siz);
99static void hudDrawReticleOnTarget(Entity* target, PlayerEntity* player1, GLfloat z1,
100 GLfloat alpha, BOOL reticleTargetSensitive, NSMutableDictionary *propertiesReticleTargetSensitive,
101 BOOL colourFromScannerColour, BOOL showText, NSDictionary *info, NSMutableArray *reticleColors);
102static void hudDrawWaypoint(OOWaypointEntity *waypoint, PlayerEntity *player1, GLfloat z1, GLfloat alpha, BOOL selected, GLfloat scale);
103static void hudRotateViewpointForVirtualDepth(PlayerEntity * player1, Vector p1);
104static void drawScannerGrid(GLfloat x, GLfloat y, GLfloat z, NSSize siz, int v_dir, GLfloat thickness, GLfloat zoom, BOOL nonlinear, BOOL minimalistic);
105static GLfloat nonlinearScannerFunc(GLfloat distance, GLfloat zoom, GLfloat scale);
106static void GLDrawNonlinearCascadeWeapon( GLfloat x, GLfloat y, GLfloat z, NSSize siz, Vector centre, GLfloat radius, GLfloat zoom, GLfloat alpha );
107
110
111
112enum
113{
116
117
118@interface HeadUpDisplay (Private)
119
120- (void) drawCrosshairs;
121- (void) drawLegends;
122- (void) drawDials;
123- (void) drawMFDs;
124
125- (void) drawLegend:(NSDictionary *)info;
126- (void) drawHUDItem:(NSDictionary *)info;
127
128- (void) drawScanner:(NSDictionary *)info;
129- (void) drawScannerZoomIndicator:(NSDictionary *)info;
130
131- (void) drawCompass:(NSDictionary *)info;
132- (void) drawCompassPlanetBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha;
133- (void) drawCompassStationBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha;
134- (void) drawCompassSunBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha;
135- (void) drawCompassTargetBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha;
136- (void) drawCompassBeaconBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha;
137
138- (void) drawAegis:(NSDictionary *)info;
139- (void) drawSpeedBar:(NSDictionary *)info;
140- (void) drawRollBar:(NSDictionary *)info;
141- (void) drawPitchBar:(NSDictionary *)info;
142- (void) drawYawBar:(NSDictionary *)info;
143- (void) drawEnergyGauge:(NSDictionary *)info;
144- (void) drawForwardShieldBar:(NSDictionary *)info;
145- (void) drawAftShieldBar:(NSDictionary *)info;
146- (void) drawFuelBar:(NSDictionary *)info;
147- (void) drawWitchspaceDestination:(NSDictionary *)info;
148- (void) drawCabinTempBar:(NSDictionary *)info;
149- (void) drawWeaponTempBar:(NSDictionary *)info;
150- (void) drawAltitudeBar:(NSDictionary *)info;
151- (void) drawMissileDisplay:(NSDictionary *)info;
152- (void) drawTargetReticle:(NSDictionary *)info;
153- (void) drawSecondaryTargetReticle:(NSDictionary *)info;
154- (void) drawWaypoints:(NSDictionary *)info;
155- (void) drawStatusLight:(NSDictionary *)info;
156- (void) drawDirectionCue:(NSDictionary *)info;
157- (void) drawClock:(NSDictionary *)info;
158- (void) drawPrimedEquipmentText:(NSDictionary *)info;
159- (void) drawASCTarget:(NSDictionary *)info;
160- (void) drawWeaponsOfflineText:(NSDictionary *)info;
161- (void) drawMultiFunctionDisplay:(NSDictionary *)info withText:(NSString *)text asIndex:(NSUInteger)index;
162- (void) drawFPSInfoCounter:(NSDictionary *)info;
163- (void) drawScoopStatus:(NSDictionary *)info;
164- (void) drawStickSensitivityIndicator:(NSDictionary *)info;
165- (void) drawCustomBar:(NSDictionary *)info;
166- (void) drawCustomText:(NSDictionary *)info;
167- (void) drawCustomIndicator:(NSDictionary *)info;
168- (void) drawCustomLight:(NSDictionary *)info;
169- (void) drawCustomImage:(NSDictionary *)info;
170
171- (void) drawSurroundInternal:(NSDictionary *)info color:(const GLfloat[4])color;
172- (void) drawSurround:(NSDictionary *)info;
173- (void) drawGreenSurround:(NSDictionary *)info;
174- (void) drawYellowSurround:(NSDictionary *)info;
175
176- (void) drawTrumbles:(NSDictionary *)info;
177
178- (NSArray *) crosshairDefinitionForWeaponType:(OOWeaponType)weapon;
179
180- (BOOL) checkPlayerInFlight;
182
183- (void) resetGui:(GuiDisplayGen*)gui withInfo:(NSDictionary *)gui_info;
184- (void) resetGuiPosition:(GuiDisplayGen*)gui withInfo:(NSDictionary *)gui_info;
185
186
187@end
188
189
190@implementation HeadUpDisplay
191
192static const GLfloat red_color[4] = {1.0, 0.0, 0.0, 1.0};
193static const GLfloat redplus_color[4] = {1.0, 0.0, 0.5, 1.0};
194static const GLfloat yellow_color[4] = {1.0, 1.0, 0.0, 1.0};
195static const GLfloat green_color[4] = {0.0, 1.0, 0.0, 1.0};
196static const GLfloat darkgreen_color[4] = {0.0, 0.75, 0.0, 1.0};
197static const GLfloat blue_color[4] = {0.0, 0.0, 1.0, 1.0};
198static const GLfloat black_color[4] = {0.0, 0.0, 0.0, 1.0};
199static const GLfloat lightgray_color[4] = {0.25, 0.25, 0.25, 1.0};
200
201static float sGlyphWidths[256];
202static float sF6KernGovt;
203static float sF6KernTL;
204static BOOL _compassUpdated;
205
206
207static GLfloat drawCharacterQuad(uint8_t chr, GLfloat x, GLfloat y, GLfloat z, NSSize siz);
208
209static void InitTextEngine(void);
210
211static void prefetchData(NSDictionary *info, struct CachedInfo *data);
212
213
214OOINLINE void GLColorWithOverallAlpha(const GLfloat *color, GLfloat alpha)
215{
216 // NO OOGL(), this is called within immediate mode blocks.
217 glColor4f(color[0], color[1], color[2], color[3] * alpha);
218}
219
220
221- (id) initWithDictionary:(NSDictionary *)hudinfo
222{
223 return [self initWithDictionary:hudinfo inFile:nil];
224}
225
226
227- (id) initWithDictionary:(NSDictionary *)hudinfo inFile:(NSString *)hudFileName
228{
229 unsigned i;
230 BOOL isCompassToBeDrawn = NO;
231 BOOL areTrumblesToBeDrawn = NO;
232
233 self = [super init];
234
235 lineWidth = 1.0;
236
237 if (sFontTexture == nil) InitTextEngine();
238
239 deferredHudName = nil; // if not nil, it means that we have a deferred HUD which is to be drawn at first available opportunity
240 hudName = [hudFileName copy];
241
242 // init arrays
243 dialArray = [[NSMutableArray alloc] initWithCapacity:16]; // alloc retains
244 legendArray = [[NSMutableArray alloc] initWithCapacity:16]; // alloc retains
245 mfdArray = [[NSMutableArray alloc] initWithCapacity:8]; // alloc retains
246
247 _reticleColors = nil;
248
249 // populate arrays
250 NSArray *dials = [hudinfo oo_arrayForKey:DIALS_KEY];
251 for (i = 0; i < [dials count]; i++)
252 {
253 NSDictionary *dial_info = [dials oo_dictionaryAtIndex:i];
254 if (!areTrumblesToBeDrawn && [[dial_info oo_stringForKey:SELECTOR_KEY] isEqualToString:@"drawTrumbles:"]) areTrumblesToBeDrawn = YES;
255 if (!isCompassToBeDrawn && [[dial_info oo_stringForKey:SELECTOR_KEY] isEqualToString:@"drawCompass:"]) isCompassToBeDrawn = YES;
256 if ([[dial_info oo_stringForKey:SELECTOR_KEY] isEqualToString:@"drawTargetReticle:"])
257 {
258 _reticleColors = [[NSMutableArray arrayWithObjects:[OOColor colorWithDescription:[dial_info oo_objectForKey:@"target_rgba" defaultValue:@"greenColor"]],
259 [OOColor colorWithDescription:[dial_info oo_objectForKey:@"target_sensitive_rgba" defaultValue:@"redColor"]],
260 [OOColor colorWithDescription:[dial_info oo_objectForKey:@"wormhole_rgba" defaultValue:@"cyanColor"]],
261 nil] retain];
262 }
263 [self addDial:dial_info];
264 }
265
266 // reticle colors should be set at this point, but just be safe in case they are not
267 if (!_reticleColors)
268 {
269 _reticleColors = [[NSMutableArray arrayWithObjects:[OOColor greenColor], [OOColor redColor], [OOColor cyanColor], nil] retain];
270 }
271
272 if (!areTrumblesToBeDrawn) // naughty - a hud with no built-in drawTrumbles: - one must be added!
273 {
274 NSDictionary *trumble_dial_info = [NSDictionary dictionaryWithObjectsAndKeys: @"drawTrumbles:", SELECTOR_KEY, nil];
275 [self addDial:trumble_dial_info];
276 }
277
278 _compassActive = isCompassToBeDrawn;
279
280 _lastWeaponType = nil;
281
282 NSArray *legends = [hudinfo oo_arrayForKey:LEGENDS_KEY];
283 for (i = 0; i < [legends count]; i++)
284 {
285 [self addLegend:[legends oo_dictionaryAtIndex:i]];
286 }
287
288 NSArray *mfds = [hudinfo oo_arrayForKey:MFDS_KEY];
289 for (i = 0; i < [mfds count]; i++)
290 {
291 [self addMFD:[mfds oo_dictionaryAtIndex:i]];
292 }
293
294
295 hudHidden = NO;
296
297 _hiddenSelectors = [[NSMutableSet alloc] initWithCapacity:16];
298
299 hudUpdating = NO;
300
301 overallAlpha = [hudinfo oo_floatForKey:@"overall_alpha" defaultValue:DEFAULT_OVERALL_ALPHA];
302
303 reticleTargetSensitive = [hudinfo oo_boolForKey:@"reticle_target_sensitive" defaultValue:NO];
304 propertiesReticleTargetSensitive = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
305 [NSNumber numberWithBool:YES], @"isAccurate",
306 [NSNumber numberWithDouble:[UNIVERSE getTime]], @"timeLastAccuracyProbabilityCalculation",
307 nil];
308
309 cloakIndicatorOnStatusLight = [hudinfo oo_boolForKey:@"cloak_indicator_on_status_light" defaultValue:YES];
310
311 allowBigGui = [hudinfo oo_boolForKey:@"allow_big_gui" defaultValue:NO];
312
313 last_transmitter = NO_TARGET;
314
315 [crosshairDefinition release];
316
317 NSString *crossfile = [[hudinfo oo_stringForKey:@"crosshair_file"] retain];
318 if (crossfile == nil)
319 {
320 _crosshairOverrides = [[hudinfo oo_dictionaryForKey:@"crosshairs"] retain];
321 crosshairDefinition = nil;
322 }
323 else
324 {
325 [self setCrosshairDefinition:crossfile];
326 }
327 [crossfile release];
328
329 id crosshairColor = [hudinfo oo_objectForKey:@"crosshair_color" defaultValue:@"greenColor"];
330 _crosshairColor = [[OOColor colorWithDescription:crosshairColor] retain];
331 _crosshairScale = [hudinfo oo_floatForKey:@"crosshair_scale" defaultValue:32.0f];
332 _crosshairWidth = [hudinfo oo_floatForKey:@"crosshair_width" defaultValue:1.5f];
333
334 minimalistic_scanner = [hudinfo oo_boolForKey:@"scanner_minimalistic" defaultValue:NO];
335
336 nonlinear_scanner = [hudinfo oo_boolForKey:@"scanner_non_linear" defaultValue:NO];
337 scanner_ultra_zoom = [hudinfo oo_boolForKey:@"scanner_ultra_zoom" defaultValue:NO];
338
339 return self;
340}
341
342
343- (void) dealloc
344{
345 DESTROY(legendArray);
346 DESTROY(dialArray);
347 DESTROY(mfdArray);
348 DESTROY(hudName);
349 DESTROY(deferredHudName);
350 DESTROY(propertiesReticleTargetSensitive);
351 DESTROY(_crosshairOverrides);
352 DESTROY(_crosshairColor);
353 DESTROY(_reticleColors);
354 DESTROY(crosshairDefinition);
355 DESTROY(_hiddenSelectors);
356
357 [super dealloc];
358}
359
360//------------------------------------------------------------------------------------//
361
362
363- (void) resetGui:(GuiDisplayGen*)gui withInfo:(NSDictionary *)gui_info
364{
365 [self resetGuiPosition:gui withInfo:gui_info];
366
367 NSSize siz = [gui size];
368 int rht = [gui rowHeight];
369 NSString* title = [gui title];
370 if ([gui_info objectForKey:WIDTH_KEY])
371 siz.width = [gui_info oo_floatForKey:WIDTH_KEY];
372 if ([gui_info objectForKey:HEIGHT_KEY])
373 siz.height = [gui_info oo_floatForKey:HEIGHT_KEY];
374 if ([gui_info objectForKey:ROW_HEIGHT_KEY])
375 rht = [gui_info oo_floatForKey:ROW_HEIGHT_KEY];
376 if ([gui_info objectForKey:TITLE_KEY])
377 title = [gui_info oo_stringForKey:TITLE_KEY];
378 [gui resizeTo:siz characterHeight:rht title:title];
379 if ([gui_info objectForKey:BACKGROUND_RGBA_KEY])
380 [gui setBackgroundColor:[OOColor colorFromString:[gui_info oo_stringForKey:BACKGROUND_RGBA_KEY]]];
381 if ([gui_info objectForKey:ALPHA_KEY])
382 [gui setMaxAlpha: OOClamp_0_max_f([gui_info oo_floatForKey:ALPHA_KEY],1.0f)];
383 else
384 [gui setMaxAlpha: 1.0f];
385}
386
387
388- (void) resetGuiPosition:(GuiDisplayGen*)gui withInfo:(NSDictionary *)gui_info
389{
390 Vector pos = [gui drawPosition];
391 if ([gui_info objectForKey:X_KEY])
392 pos.x = [gui_info oo_floatForKey:X_KEY] +
393 [[UNIVERSE gameView] x_offset] *
394 [gui_info oo_floatForKey:X_ORIGIN_KEY defaultValue:0.0];
395 if ([gui_info objectForKey:Y_KEY])
396 pos.y = [gui_info oo_floatForKey:Y_KEY] +
397 [[UNIVERSE gameView] y_offset] *
398 [gui_info oo_floatForKey:Y_ORIGIN_KEY defaultValue:0.0];
399
400 [gui setDrawPosition:pos];
401}
402
403
404- (void) resetGuiPositions
405{
406 NSDictionary *hudDict = [ResourceManager dictionaryFromFilesNamed:[self hudName] inFolder:@"Config" andMerge:YES];
407
408 GuiDisplayGen* gui = [UNIVERSE messageGUI];
409 NSDictionary* gui_info = [hudDict oo_dictionaryForKey:@"message_gui"];
410 if (gui && gui_info)
411 {
412 [self resetGuiPosition:gui withInfo:gui_info];
413 }
414
415 gui = [UNIVERSE commLogGUI];
416 gui_info = [hudDict oo_dictionaryForKey:@"comm_log_gui"];
417 if (gui && gui_info)
418 {
419 [self resetGuiPosition:gui withInfo:gui_info];
420 }
421
422}
423
424
425- (void) resetGuis:(NSDictionary *)info
426{
427 // check for entries in hud.plist for message_gui and comm_log_gui
428 // then resize and reposition them accordingly.
429
430 GuiDisplayGen* gui = [UNIVERSE messageGUI];
431 NSDictionary* gui_info = [info oo_dictionaryForKey:@"message_gui"];
432 if (gui && [gui_info count] > 0)
433 {
434 /*
435 If switching message guis, remember the last 2 message lines.
436 Present GUI limitations make it impractical to transfer anything
437 more...
438
439 TODO: a more usable GUI code! - Kaks 2011.11.05
440 */
441
442 NSArray* lastLines = [gui getLastLines]; // text, colour, fade time - text, colour, fade time
443 BOOL line1 = ![[lastLines oo_stringAtIndex:0] isEqualToString:@""];
444 [self resetGui:gui withInfo:gui_info];
445
446 BOOL permanent = [gui_info oo_boolForKey:@"permanent" defaultValue:NO];
447 [UNIVERSE setPermanentMessageLog:permanent];
448
449 BOOL automaticBg = [gui_info oo_boolForKey:@"background_automatic" defaultValue:YES];
450 [UNIVERSE setAutoMessageLogBg:automaticBg];
451
452 // set message gui text colors - one for standard messages, one for incoming comms
453 // incoming comms message color must default to green for compatibility with older huds that
454 // don't have this key
455 [gui setTextColor:[OOColor colorWithDescription:[gui_info objectForKey:@"text_color"]]];
456 OOColor *textCommsColor = [OOColor colorWithDescription:[gui_info objectForKey:@"text_comms_color"]];
457 if (!textCommsColor) textCommsColor = [OOColor greenColor];
458 [gui setTextCommsColor:textCommsColor];
459
460 if (line1)
461 {
462 [gui printLongText:[lastLines oo_stringAtIndex:0] align:GUI_ALIGN_CENTER
463 color:[OOColor colorFromString:[lastLines oo_stringAtIndex:1]]
464 fadeTime:(permanent?0.0:[lastLines oo_floatAtIndex:2]) key:nil addToArray:nil];
465 }
466 if ([lastLines count] > 3 && (line1 || ![[lastLines oo_stringAtIndex:3] isEqualToString:@""]))
467 {
468 [gui printLongText:[lastLines oo_stringAtIndex:3] align:GUI_ALIGN_CENTER
469 color:[OOColor colorFromString:[lastLines oo_stringAtIndex:4]]
470 fadeTime:(permanent?0.0:[lastLines oo_floatAtIndex:5]) key:nil addToArray:nil];
471 }
472 }
473
474 if (gui_info != nil && [gui_info count] == 0)
475 {
476 // exists and it's empty. complete reset.
477 [gui setCurrentRow:8];
478 [gui setDrawPosition: make_vector(0.0, -40.0, 640.0)];
479 [gui resizeTo:NSMakeSize(480, 160) characterHeight:19 title:nil];
480 [gui setCharacterSize:NSMakeSize(16,20)]; // narrow characters
483 [UNIVERSE setPermanentMessageLog:NO];
484 [UNIVERSE setAutoMessageLogBg:YES];
485 }
486
487 [gui setAlpha: 1.0f]; // message_gui is always visible.
488
489 // And now set up the comms log
490
491 gui = [UNIVERSE commLogGUI];
492 gui_info = [info oo_dictionaryForKey:@"comm_log_gui"];
493
494 if (gui && [gui_info count] > 0)
495 {
496 [UNIVERSE setAutoCommLog:[gui_info oo_boolForKey:@"automatic" defaultValue:YES]];
497 [UNIVERSE setPermanentCommLog:[gui_info oo_boolForKey:@"permanent" defaultValue:NO]];
498
499 /*
500 We need to repopulate the comms log after resetting it.
501
502 At the moment the colour information is set on a per-line basis, rather than a per-text basis.
503 A comms message can span multiple lines, and two consecutive messages can share the same colour,
504 so trying to match the colour information from the GUI with each message won't work.
505
506 Bottom line: colour information is lost on comms log gui reset.
507 And yes, this is yet another reason for the following
508
509 TODO: a more usable GUI code! - Kaks 2011.11.05
510 */
511
512 NSArray *cLog = [PLAYER commLog];
513 NSUInteger i, commCount = [cLog count];
514
515 [self resetGui:gui withInfo:gui_info];
516
517 for (i = 0; i < commCount; i++)
518 {
519 [gui printLongText:[cLog oo_stringAtIndex:i] align:GUI_ALIGN_LEFT color:nil
520 fadeTime:0.0 key:nil addToArray:nil];
521 }
522 }
523
524 if (gui_info != nil && [gui_info count] == 0)
525 {
526 // exists and it's empty. complete reset.
527 [UNIVERSE setAutoCommLog:YES];
528 [UNIVERSE setPermanentCommLog:NO];
529 [gui setCurrentRow:9];
530 [gui setDrawPosition: make_vector(0.0, 180.0, 640.0)];
531 [gui resizeTo:NSMakeSize(360, 120) characterHeight:12 title:nil];
532 [gui setBackgroundColor:[OOColor colorWithRed:0.0 green:0.05 blue:0.45 alpha:0.5]];
534 [gui printLongText:DESC(@"communications-log-string") align:GUI_ALIGN_CENTER color:[OOColor yellowColor] fadeTime:0 key:nil addToArray:nil];
535 }
536
537 if ([UNIVERSE permanentCommLog])
538 {
539 [gui stopFadeOuts];
540 [gui setAlpha:1.0];
541 }
542 else
543 {
544 [gui setAlpha:0.0];
545 }
546}
547
548
549- (NSString *) hudName
550{
551 return hudName;
552}
553
554
555- (void) setHudName:(NSString *)newHudName
556{
557 if (newHudName != nil)
558 {
559 [hudName release];
560 hudName = [newHudName copy];
561 }
562}
563
564
565- (OOColor *) reticleColorForIndex:(NSUInteger)idx
566{
567 if (idx < [_reticleColors count])
568 {
569 return [_reticleColors objectAtIndex:idx];
570 }
571 return nil;
572}
573
574
575- (BOOL) setReticleColorForIndex:(NSUInteger)idx toColor:(OOColor *)newColor
576{
577 if (newColor && idx < [_reticleColors count])
578 {
579 [_reticleColors replaceObjectAtIndex:idx withObject:newColor];
580 return YES;
581 }
582 return NO;
583}
584
585
586- (GLfloat) scannerZoom
587{
588 return scanner_zoom;
589}
590
591
592- (void) setScannerZoom:(GLfloat)value
593{
594 scanner_zoom = value;
595}
596
597- (GLfloat) overallAlpha
598{
599 return overallAlpha;
600}
601
602
603- (void) setOverallAlpha:(GLfloat) newAlphaValue
604{
605 overallAlpha = OOClamp_0_1_f(newAlphaValue);
606}
607
608
609- (BOOL) reticleTargetSensitive
610{
611 return reticleTargetSensitive;
612}
613
614
615- (void) setReticleTargetSensitive:(BOOL) newReticleTargetSensitiveValue
616{
617 reticleTargetSensitive = !!newReticleTargetSensitiveValue; // ensure YES or NO.
618}
619
620
621- (NSMutableDictionary *) propertiesReticleTargetSensitive
622{
623 return propertiesReticleTargetSensitive;
624}
625
626
627- (BOOL) isHidden
628{
629 return hudHidden;
630}
631
632
633- (void) setHidden:(BOOL)newValue
634{
635 hudHidden = !!newValue; // ensure YES or NO
636}
637
638
639- (BOOL) allowBigGui
640{
641 return allowBigGui || hudHidden;
642}
643
644
645- (BOOL) hasHidden:(NSString *)selectorName
646{
647 if (selectorName == nil)
648 {
649 return NO;
650 }
651 return [_hiddenSelectors containsObject:selectorName];
652}
653
654
655- (void) setHiddenSelector:(NSString *)selectorName hidden:(BOOL)hide
656{
657 if (hide)
658 {
659 [_hiddenSelectors addObject:selectorName];
660 }
661 else
662 {
663 [_hiddenSelectors removeObject:selectorName];
664 }
665}
666
667
668- (void) clearHiddenSelectors
669{
670 [_hiddenSelectors removeAllObjects];
671}
672
673
674- (BOOL) isCompassActive
675{
676 return _compassActive;
677}
678
679
680- (void) setCompassActive:(BOOL)newValue
681{
682 _compassActive = !!newValue;
683}
684
685
686- (BOOL) isUpdating
687{
688 return hudUpdating;
689}
690
691
692- (void) setDeferredHudName:(NSString *)newDeferredHudName
693{
694 [deferredHudName release];
695 deferredHudName = [newDeferredHudName copy];
696}
697
698
699- (NSString *) deferredHudName
700{
701 return deferredHudName;
702}
703
704
705- (void) addLegend:(NSDictionary *)info
706{
707 NSString *imageName = nil;
708 OOTexture *texture = nil;
709 NSSize imageSize;
710 OOTextureSprite *legendSprite = nil;
711 NSMutableDictionary *legendDict = nil;
712 struct CachedInfo cache;
713
714 // prefetch data associated with this legend
715 prefetchData(info, &cache);
716
717 imageName = [info oo_stringForKey:IMAGE_KEY];
718 if (imageName != nil)
719 {
720 texture = [OOTexture textureWithName:imageName
721 inFolder:@"Images"
722 options:kOOTextureDefaultOptions | kOOTextureNoShrink
723 anisotropy:kOOTextureDefaultAnisotropy
724 lodBias:kOOTextureDefaultLODBias];
725 if (texture == nil)
726 {
727 OOLogERR(kOOLogFileNotFound, @"HeadUpDisplay couldn't get an image texture name for %@", imageName);
728 return;
729 }
730
731 imageSize = [texture dimensions];
732 imageSize.width = [info oo_floatForKey:WIDTH_KEY defaultValue:imageSize.width];
733 imageSize.height = [info oo_floatForKey:HEIGHT_KEY defaultValue:imageSize.height];
734
735 legendSprite = [[OOTextureSprite alloc] initWithTexture:texture size:imageSize];
736
737 legendDict = [info mutableCopy];
738 [legendDict setObject:legendSprite forKey:SPRITE_KEY];
739 // add WIDGET_INFO, WIDGET_CACHE to array
740 [legendArray addObject:[NSArray arrayWithObjects:legendDict, [NSValue valueWithBytes:&cache objCType:@encode(struct CachedInfo)], nil]];
741 [legendDict release];
742 [legendSprite release];
743 }
744 else if ([info oo_stringForKey:TEXT_KEY] != nil)
745 {
746 // add WIDGET_INFO, WIDGET_CACHE to array
747 [legendArray addObject:[NSArray arrayWithObjects:info, [NSValue valueWithBytes:&cache objCType:@encode(struct CachedInfo)], nil]];
748
749 }
750}
751
752
753- (void) addDial:(NSDictionary *)info
754{
755 static NSSet *allowedSelectors = nil;
756 if (allowedSelectors == nil)
757 {
758 NSDictionary *whitelist = [ResourceManager whitelistDictionary];
759 allowedSelectors = [[NSSet alloc] initWithArray:[whitelist oo_arrayForKey:@"hud_dial_methods"]];
760 }
761
762 NSString *selectorString = [info oo_stringForKey:SELECTOR_KEY];
763 if (selectorString == nil)
764 {
765 OOLogERR(@"hud.dial.noSelector", @"HUD dial in %@ is missing selector.", hudName);
766 return;
767 }
768
769 if (![allowedSelectors containsObject:selectorString])
770 {
771 OOLogERR(@"hud.dial.invalidSelector", @"HUD dial in %@ uses selector \"%@\" which is not in whitelist, and will be ignored.", hudName, selectorString);
772 return;
773 }
774
775 SEL selector = NSSelectorFromString(selectorString);
776
777 NSAssert2([self respondsToSelector:selector], @"HUD dial in %@ uses selector \"%@\" which is in whitelist, but not implemented.", hudName, selectorString);
778
779 // handle the case above with NS_BLOCK_ASSERTIONS too.
780 if (![self respondsToSelector:selector])
781 {
782 OOLogERR(@"hud.dial.invalidSelector", @"HUD dial in %@ uses selector \"%@\" which is in whitelist, but not implemented, and will be ignored.", hudName, selectorString);
783 return;
784 }
785
786 // valid dial, now prefetch data
787 struct CachedInfo cache;
788 prefetchData(info, &cache);
789 // add WIDGET_INFO, WIDGET_CACHE, WIDGET_SELECTOR, WIDGET_SELECTOR_NAME to array
790 [dialArray addObject:[NSArray arrayWithObjects:info, [NSValue valueWithBytes:&cache objCType:@encode(struct CachedInfo)],
791 [NSValue valueWithPointer:selector], selectorString, nil]];
792}
793
794
795- (void) addMFD:(NSDictionary *)info
796{
797 struct CachedInfo cache;
798 prefetchData(info, &cache);
799 [mfdArray addObject:[NSArray arrayWithObjects:info, [NSValue valueWithBytes:&cache objCType:@encode(struct CachedInfo)],nil]];
800}
801
802
803- (NSUInteger) mfdCount
804{
805 return [mfdArray count];
806}
807
808/*
809 SLOW_CODE
810 As of 2012-09-13 (r5320), HUD rendering is taking 25%-30% of rendering time,
811 or 15%-20% of game tick time, as tested on a couple of Macs using the
812 default HUD and models. This could be worse - there used to be a note here
813 saying 30%-40% of tick time - but could still improve.
814
815 In a top-down perspective, of HUD rendering time, 67% is in -drawDials and
816 27% is in -drawLegends.
817
818 Bottom-up, one profile shows:
819 21.2% OODrawString()
820 (Caching the glyph conversion here was a win, but caching geometry
821 in vertex arrays/VBOs would be better.)
822 8.9% -[HeadUpDisplay drawHudItem:]
823 5.1% OOFloatFromObject
824 (Reifying HUD info instead of parsing plists each frame would be
825 a win.)
826 4.4% hudDrawBarAt()
827 (Using fixed geometery and a vertex shader could help here,
828 especially if bars are grouped together and drawn at once if
829 possible.)
830 4.3% -[OOCrosshairs render]
831 (Uses vertex arrays, but does more GL state manipulation than
832 strictly necessary.)
833
834*/
835- (void) renderHUD
836{
837 hudUpdating = YES;
838
840
841 if ((_crosshairWidth * lineWidth) > 0)
842 {
843 OOGL(GLScaledLineWidth(_crosshairWidth * lineWidth));
844 [self drawCrosshairs];
845 }
846
847 if (lineWidth > 0)
848 {
849 OOGL(GLScaledLineWidth(lineWidth));
850 [self drawLegends];
851 }
852
853 [self drawDials];
854 [self drawMFDs];
855 OOCheckOpenGLErrors(@"After drawing HUD");
856
858
859 hudUpdating = NO;
860}
861
862
863- (void) drawLegends
864{
865 /* Since the order of legend drawing is significant, this loop must be kept
866 * as an incrementing one for compatibility with previous Oolite versions.
867 * CIM: 28/9/12 */
868 z1 = [[UNIVERSE gameView] display_z];
869 NSUInteger i, nLegends = [legendArray count];
870 for (i = 0; i < nLegends; i++)
871 {
872 sCurrentDrawItem = [legendArray oo_arrayAtIndex:i];
873 [self drawLegend:[sCurrentDrawItem oo_dictionaryAtIndex:WIDGET_INFO]];
874 }
875}
876
877
878- (void) drawDials
879{
880 z1 = [[UNIVERSE gameView] display_z];
881 // reset drawScanner flag.
882 _compassUpdated = NO;
883
884 // tight loop, we assume dialArray doesn't change in mid-draw.
885 NSUInteger i, nDials = [dialArray count];
886 for (i = 0; i < nDials; i++)
887 {
888 sCurrentDrawItem = [dialArray oo_arrayAtIndex:i];
889 [self drawHUDItem:[sCurrentDrawItem oo_dictionaryAtIndex:WIDGET_INFO]];
890 }
891
892 if (EXPECT_NOT(!_compassUpdated && _compassActive && [self checkPlayerInSystemFlight])) // compass gone / broken / disabled ?
893 {
894 // trigger the targetChanged event with whom == null
895 _compassActive = NO;
896 [PLAYER doScriptEvent:OOJSID("compassTargetChanged") withArguments:[NSArray arrayWithObjects:[NSNull null], OOStringFromCompassMode([PLAYER compassMode]), nil]];
897 }
898
899}
900
901
902- (void) drawMFDs
903{
904 NSUInteger i, nMFDs = [mfdArray count];
905 NSString *text = nil;
906 for (i = 0; i < nMFDs; i++)
907 {
908 text = [PLAYER multiFunctionText:i];
909 if (text != nil)
910 {
911 sCurrentDrawItem = [mfdArray oo_arrayAtIndex:i];
912 [self drawMultiFunctionDisplay:[sCurrentDrawItem oo_dictionaryAtIndex:WIDGET_INFO] withText:text asIndex:i];
913 }
914 }
915}
916
917
918- (void) drawCrosshairs
919{
920 OOViewID viewID = [UNIVERSE viewDirection];
921 OOWeaponType weapon = [PLAYER currentWeapon];
922 BOOL weaponsOnline = [PLAYER weaponsOnline];
923 NSArray *points = nil;
924
925 if (viewID == VIEW_CUSTOM ||
926 overallAlpha == 0.0f ||
927 !([PLAYER status] == STATUS_IN_FLIGHT || [PLAYER status] == STATUS_WITCHSPACE_COUNTDOWN) ||
928 [UNIVERSE displayGUI]
929 )
930 {
931 // Don't draw crosshairs
932 return;
933 }
934
935 if (weapon != _lastWeaponType || overallAlpha != _lastOverallAlpha || weaponsOnline != _lastWeaponsOnline)
936 {
937 DESTROY(_crosshairs);
938 }
939
940 if (_crosshairs == nil)
941 {
942 GLfloat useAlpha = weaponsOnline ? overallAlpha : overallAlpha * 0.5f;
943
944 // Make new crosshairs object
945 points = [self crosshairDefinitionForWeaponType:weapon];
946
947 _crosshairs = [[OOCrosshairs alloc] initWithPoints:points
948 scale:_crosshairScale
949 color:_crosshairColor
950 overallAlpha:useAlpha];
951 _lastWeaponType = weapon;
952 _lastOverallAlpha = useAlpha;
953 _lastWeaponsOnline = weaponsOnline;
954 }
955
956 [_crosshairs render];
957}
958
959
960- (NSString *) crosshairDefinition
961{
962 return crosshairDefinition;
963}
964
965
966- (BOOL) setCrosshairDefinition:(NSString *)newDefinition
967{
968 // force crosshair redraw
969 [_crosshairs release];
970 _crosshairs = nil;
971
972 [_crosshairOverrides release];
973 _crosshairOverrides = [[ResourceManager dictionaryFromFilesNamed:newDefinition
974 inFolder:@"Config"
975 andMerge:YES] retain];
976 if (_crosshairOverrides == nil || [_crosshairOverrides count] == 0)
977 { // invalid file
978 [_crosshairOverrides release];
979 _crosshairOverrides = [[ResourceManager dictionaryFromFilesNamed:@"crosshairs.plist"
980 inFolder:@"Config"
981 andMerge:YES] retain];
982 crosshairDefinition = @"crosshairs.plist";
983 return NO;
984 }
985 crosshairDefinition = [newDefinition copy];
986 return YES;
987}
988
989
990- (NSArray *) crosshairDefinitionForWeaponType:(OOWeaponType)weapon
991{
992 NSString *weaponName = nil;
993 NSString *weaponName2 = nil;
994 static NSDictionary *crosshairDefs = nil;
995 NSArray *result = nil;
996
997 /* Search order:
998 (hud.plist).crosshairs.WEAPON_NAME
999 (hud.plist).crosshairs.OTHER
1000 (crosshairs.plist).WEAPON_NAME
1001 (crosshairs.plist).OTHER
1002 */
1003
1004 weaponName = OOStringFromWeaponType(weapon);
1005 weaponName2 = [weaponName substringFromIndex:3]; // strip "EQ_"
1006 result = [_crosshairOverrides oo_arrayForKey:weaponName];
1007 if (result == nil)
1008 {
1009 result = [_crosshairOverrides oo_arrayForKey:weaponName2];
1010 }
1011 if (result == nil) result = [_crosshairOverrides oo_arrayForKey:@"OTHER"];
1012 if (result == nil)
1013 {
1014 if (crosshairDefs == nil)
1015 {
1016 crosshairDefs = [ResourceManager dictionaryFromFilesNamed:@"crosshairs.plist"
1017 inFolder:@"Config"
1018 andMerge:YES];
1019 [crosshairDefs retain];
1020 }
1021
1022 result = [crosshairDefs oo_arrayForKey:weaponName];
1023 if (result == nil)
1024 {
1025 result = [crosshairDefs oo_arrayForKey:weaponName2];
1026 }
1027 if (result == nil) result = [crosshairDefs oo_arrayForKey:@"OTHER"];
1028 }
1029
1030 return result;
1031}
1032
1033
1034- (void) drawLegend:(NSDictionary *)info
1035{
1036 // check if equipment is required
1037 NSString *equipmentRequired = [info oo_stringForKey:EQUIPMENT_REQUIRED_KEY];
1038 if (equipmentRequired != nil && ![PLAYER hasEquipmentItemProviding:equipmentRequired])
1039 {
1040 return;
1041 }
1042
1043 // check alert condition
1044 NSUInteger alertMask = [info oo_unsignedIntForKey:ALERT_CONDITIONS_KEY defaultValue:15];
1045 // 1=docked, 2=green, 4=yellow, 8=red
1046 if (alertMask < 15)
1047 {
1048 OOAlertCondition alertCondition = [PLAYER alertCondition];
1049 if (~alertMask & (1 << alertCondition)) {
1050 return;
1051 }
1052 }
1053
1054 BOOL viewOnly = [info oo_boolForKey:VIEWSCREEN_KEY defaultValue:NO];
1055 // 1=docked, 2=green, 4=yellow, 8=red
1056 if (viewOnly && [PLAYER guiScreen] != GUI_SCREEN_MAIN)
1057 {
1058 return;
1059 }
1060
1061 // check association with hidden dials
1062 if ([self hasHidden:[info oo_stringForKey:DIAL_REQUIRED_KEY defaultValue:nil]])
1063 {
1064 return;
1065 }
1066
1067 OOTextureSprite *legendSprite = nil;
1068 NSString *legendText = nil;
1069 float x, y;
1070 NSSize size;
1071 GLfloat alpha = overallAlpha;
1072 struct CachedInfo cached;
1073
1074 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1075
1076 // if either x or y is missing, use 0 instead
1077
1078 x = useDefined(cached.x, 0.0f) + [[UNIVERSE gameView] x_offset] * cached.x0;
1079 y = useDefined(cached.y, 0.0f) + [[UNIVERSE gameView] y_offset] * cached.y0;
1080 alpha *= cached.alpha;
1081
1082 legendSprite = [info objectForKey:SPRITE_KEY];
1083 if (legendSprite != nil)
1084 {
1085 [legendSprite blitCentredToX:x Y:y Z:z1 alpha:alpha];
1086 }
1087 else
1088 {
1089 legendText = [info oo_stringForKey:TEXT_KEY];
1090 if (legendText != nil)
1091 {
1092 // randomly chosen default width & height
1093 size.width = useDefined(cached.width, 14.0f);
1094 size.height = useDefined(cached.height, 8.0f);
1096 if ([info oo_intForKey:@"align"] == 1)
1097 {
1098 OODrawStringAligned(legendText, x, y, z1, size, YES);
1099 }
1100 else
1101 {
1102 OODrawStringAligned(legendText, x, y, z1, size, NO);
1103 }
1104 }
1105 }
1106}
1107
1108
1109- (void) drawHUDItem:(NSDictionary *)info
1110{
1111 NSString *equipment = [info oo_stringForKey:EQUIPMENT_REQUIRED_KEY];
1112
1113 if (equipment != nil && ![PLAYER hasEquipmentItemProviding:equipment])
1114 {
1115 return;
1116 }
1117
1118 // check alert condition
1119 NSUInteger alertMask = [info oo_unsignedIntForKey:ALERT_CONDITIONS_KEY defaultValue:15];
1120 // 1=docked, 2=green, 4=yellow, 8=red
1121 if (alertMask < 15)
1122 {
1123 OOAlertCondition alertCondition = [PLAYER alertCondition];
1124 if (~alertMask & (1 << alertCondition)) {
1125 return;
1126 }
1127 }
1128
1129 BOOL viewOnly = [info oo_boolForKey:VIEWSCREEN_KEY defaultValue:NO];
1130
1131 // 1=docked, 2=green, 4=yellow, 8=red
1132 if (viewOnly && [PLAYER guiScreen] != GUI_SCREEN_MAIN)
1133 {
1134 return;
1135 }
1136
1137 if (EXPECT_NOT([self hasHidden:[sCurrentDrawItem objectAtIndex:WIDGET_SELECTOR_NAME]]))
1138 {
1139 return;
1140 }
1141
1142 // use the selector value stored during init.
1143 [self performSelector:[(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_SELECTOR] pointerValue] withObject:info];
1144 OOCheckOpenGLErrors(@"HeadUpDisplay after drawHUDItem %@", info);
1145
1147}
1148
1149
1150- (BOOL) checkPlayerInFlight
1151{
1152 return [PLAYER isInSpace] && [PLAYER status] != STATUS_DOCKING;
1153}
1154
1155
1157{
1158 OOSunEntity *the_sun = [UNIVERSE sun];
1159 OOPlanetEntity *the_planet = [UNIVERSE planet];
1160
1161 return [self checkPlayerInFlight] // be in the right mode
1162 && the_sun && the_planet // and be in a system
1163 && ![the_sun goneNova];
1164}
1165
1166
1167static void prefetchData(NSDictionary *info, struct CachedInfo *data)
1168{
1169 data->x = [info oo_floatForKey:X_KEY defaultValue:NOT_DEFINED];
1170 data->x0 = [info oo_floatForKey:X_ORIGIN_KEY defaultValue:0.0];
1171 data->y = [info oo_floatForKey:Y_KEY defaultValue:NOT_DEFINED];
1172 data->y0 = [info oo_floatForKey:Y_ORIGIN_KEY defaultValue:0.0];
1173 data->width = [info oo_floatForKey:WIDTH_KEY defaultValue:NOT_DEFINED];
1174 data->height = [info oo_floatForKey:HEIGHT_KEY defaultValue:NOT_DEFINED];
1175 data->alpha = [info oo_nonNegativeFloatForKey:ALPHA_KEY defaultValue:1.0f];
1176}
1177
1178//---------------------------------------------------------------------//
1179
1180- (void) drawScanner:(NSDictionary *)info
1181{
1182 int i, x, y;
1183 NSSize siz;
1184 GLfloat scanner_color[4] = { 1.0, 0.0, 0.0, 1.0 };
1185
1186 BOOL emptyDial = ([info oo_floatForKey:ALPHA_KEY] == 0.0f);
1187
1188 BOOL isHostile = NO;
1189
1190 BOOL inColorBlindMode = [UNIVERSE colorblindMode] != OO_POSTFX_NONE;
1191
1192 if (emptyDial)
1193 {
1194 // we can skip a lot of code.
1195 x = y = 0;
1196 scanner_color[3] = 0.0; // nothing to see!
1197 siz = NSMakeSize(1.0, 1.0); // avoid divide by 0s
1198 }
1199 else
1200 {
1201 struct CachedInfo cached;
1202
1203 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1204
1205 x = useDefined(cached.x, SCANNER_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
1206 y = useDefined(cached.y, SCANNER_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
1207 siz.width = useDefined(cached.width, SCANNER_WIDTH);
1208 siz.height = useDefined(cached.height, SCANNER_HEIGHT);
1209
1210 GetRGBAArrayFromInfo(info, scanner_color);
1211
1212 scanner_color[3] *= overallAlpha;
1213 }
1214
1215 GLfloat alpha = scanner_color[3];
1216 GLfloat col[4] = { 1.0, 1.0, 1.0, alpha }; // temporary colour variable
1217
1218 GLfloat z_factor = siz.height / siz.width; // approx 1/4
1219 GLfloat y_factor = 1.0 - sqrt(z_factor); // approx 1/2
1220
1221 int scanner_cx = x;
1222 int scanner_cy = y;
1223
1224 int scannerFootprint = SCANNER_MAX_RANGE * 2.5 / siz.width;
1225
1226 GLfloat zoom = scanner_zoom;
1227 if (scanner_ultra_zoom)
1228 zoom = pow(2, zoom - 1.0);
1229 GLfloat max_zoomed_range2 = SCANNER_SCALE * SCANNER_SCALE * 10000.0;
1230 if (!nonlinear_scanner)
1231 {
1232 max_zoomed_range2 /= zoom * zoom;
1233 }
1234 GLfloat max_zoomed_range = sqrt(max_zoomed_range2);
1235
1236 if (PLAYER == nil) return;
1237
1238 OOMatrix rotMatrix = [PLAYER rotationMatrix];
1239 Vector relativePosition;
1240 int flash = ((int)([UNIVERSE getTime] * 4))&1;
1241
1242 // use a non-mutable copy so this can't be changed under us.
1243 int ent_count = UNIVERSE->n_entities;
1244 Entity **uni_entities = UNIVERSE->sortedEntities; // grab the public sorted list
1245 Entity *my_entities[ent_count];
1246 Entity *scannedEntity = nil;
1247
1248 for (i = 0; i < ent_count; i++)
1249 {
1250 my_entities[i] = [uni_entities[i] retain]; // retained
1251 }
1252
1253 if (!emptyDial)
1254 {
1255 OOGL(glColor4fv(scanner_color));
1256 drawScannerGrid(x, y, z1, siz, [UNIVERSE viewDirection], lineWidth, zoom, nonlinear_scanner, minimalistic_scanner);
1257 }
1258
1259 if ([self checkPlayerInFlight])
1260 {
1261 GLfloat upscale = zoom * 1.25 / scannerFootprint;
1262 GLfloat max_blip = 0.0;
1263 int drawClass;
1264
1266
1267 // Debugging code for nonlinear scanner - draws three fake cascade weapons, which looks pretty and enables me
1268 // to debug the code without the mass slaughter of innocent civillians.
1269 //if (nonlinear_scanner)
1270 //{
1271 // Vector p = OOVectorMultiplyMatrix(make_vector(10000.0, 0.0, 0.0), rotMatrix);
1272 // GLDrawNonlinearCascadeWeapon( scanner_cx, scanner_cy, z1, siz, p, 5000, zoom, alpha );
1273 // p = OOVectorMultiplyMatrix(make_vector(10000.0, 4500.0, 0.0), rotMatrix);
1274 // GLDrawNonlinearCascadeWeapon( scanner_cx, scanner_cy, z1, siz, p, 2000, zoom, alpha );
1275 // p = OOVectorMultiplyMatrix(make_vector(0.0, 0.0, 20000.0), rotMatrix);
1276 // GLDrawNonlinearCascadeWeapon( scanner_cx, scanner_cy, z1, siz, p, 6000, zoom, alpha );
1277 //}
1278 for (i = 0; i < ent_count; i++) // scanner lollypops
1279 {
1280 scannedEntity = my_entities[i];
1281
1282 drawClass = [scannedEntity scanClass];
1283
1284 // cloaked ships - and your own one - don't show up on the scanner.
1285 if (EXPECT_NOT(drawClass == CLASS_PLAYER || ([scannedEntity isShip] && [(ShipEntity *)scannedEntity isCloaked])))
1286 {
1287 drawClass = CLASS_NO_DRAW;
1288 }
1289
1290 if (drawClass != CLASS_NO_DRAW)
1291 {
1292 GLfloat x1,y1,y2;
1293 float ms_blip = 0.0;
1294
1295 if (emptyDial) continue;
1296
1297 if (isnan(scannedEntity->zero_distance))
1298 continue;
1299
1300 // exit if it's too far away
1301 GLfloat act_dist = sqrt(scannedEntity->zero_distance);
1302 GLfloat lim_dist = act_dist - scannedEntity->collision_radius;
1303
1304 // for efficiency, assume no scannable entity > 10km radius
1305 if (act_dist > max_zoomed_range + 10000.0)
1306 break;
1307
1308 if (lim_dist > max_zoomed_range)
1309 continue;
1310
1311 // has it sent a recent message
1312 //
1313 if ([scannedEntity isShip])
1314 ms_blip = 2.0 * [(ShipEntity *)scannedEntity messageTime];
1315 if (ms_blip > max_blip)
1316 {
1317 max_blip = ms_blip;
1318 last_transmitter = [scannedEntity universalID];
1319 }
1320 ms_blip -= floor(ms_blip);
1321
1322 relativePosition = [PLAYER vectorTo:scannedEntity];
1323 double fuzz = [PLAYER scannerFuzziness];
1324 if (fuzz > 0 && ![[UNIVERSE gameController] isGamePaused])
1325 {
1326 relativePosition = vector_add(relativePosition,OOVectorRandomRadial(fuzz));
1327 }
1328
1329 Vector rp = relativePosition;
1330
1331 if (act_dist > max_zoomed_range)
1332 scale_vector(&relativePosition, max_zoomed_range / act_dist);
1333
1334 // rotate the view
1335 relativePosition = OOVectorMultiplyMatrix(relativePosition, rotMatrix);
1336 Vector rrp = relativePosition;
1337 // scale the view
1338 if (nonlinear_scanner)
1339 {
1340 relativePosition = [HeadUpDisplay nonlinearScannerScale: relativePosition Zoom: zoom Scale: 0.5*siz.width];
1341 }
1342 else
1343 {
1344 scale_vector(&relativePosition, upscale);
1345 }
1346
1347 x1 = relativePosition.x;
1348 y1 = z_factor * relativePosition.z;
1349 y2 = y1 + y_factor * relativePosition.y;
1350
1351 isHostile = NO;
1352 if ([scannedEntity isShip])
1353 {
1354 ShipEntity *ship = (ShipEntity *)scannedEntity;
1355 isHostile = (([ship hasHostileTarget])&&([ship primaryTarget] == PLAYER));
1356 GLfloat *base_col = [ship scannerDisplayColorForShip:PLAYER :isHostile :flash
1359 ];
1360 col[0] = base_col[0]; col[1] = base_col[1]; col[2] = base_col[2]; col[3] = alpha * base_col[3];
1361 }
1362 else if ([scannedEntity isVisualEffect])
1363 {
1364 OOVisualEffectEntity *vis = (OOVisualEffectEntity *)scannedEntity;
1365 GLfloat* base_col = [vis scannerDisplayColorForShip:flash :[vis scannerDisplayColor1] :[vis scannerDisplayColor2]];
1366 col[0] = base_col[0]; col[1] = base_col[1]; col[2] = base_col[2]; col[3] = alpha * base_col[3];
1367 }
1368
1369 if ([scannedEntity isWormhole])
1370 {
1371 col[0] = blue_color[0]; col[1] = (flash)? 1.0 : blue_color[1]; col[2] = blue_color[2]; col[3] = alpha * blue_color[3];
1372 }
1373
1374 // position the scanner
1375 x1 += scanner_cx; y1 += scanner_cy; y2 += scanner_cy;
1376
1377 if ([scannedEntity isShip])
1378 {
1379 ShipEntity* ship = (ShipEntity*)scannedEntity;
1380 if ((!nonlinear_scanner && ship->collision_radius * upscale > 4.5) ||
1381 (nonlinear_scanner && nonlinearScannerFunc(act_dist, zoom, siz.width) - nonlinearScannerFunc(lim_dist, zoom, siz.width) > 4.5 ))
1382 {
1383 Vector bounds[6];
1384 BoundingBox bb = ship->totalBoundingBox;
1385 bounds[0] = ship->v_forward; scale_vector(&bounds[0], bb.max.z);
1386 bounds[1] = ship->v_forward; scale_vector(&bounds[1], bb.min.z);
1387 bounds[2] = ship->v_right; scale_vector(&bounds[2], bb.max.x);
1388 bounds[3] = ship->v_right; scale_vector(&bounds[3], bb.min.x);
1389 bounds[4] = ship->v_up; scale_vector(&bounds[4], bb.max.y);
1390 bounds[5] = ship->v_up; scale_vector(&bounds[5], bb.min.y);
1391 // rotate the view
1392 int i;
1393 for (i = 0; i < 6; i++)
1394 {
1395 bounds[i] = OOVectorMultiplyMatrix(vector_add(bounds[i], rp), rotMatrix);
1396 if (nonlinear_scanner)
1397 {
1398 bounds[i] = [HeadUpDisplay nonlinearScannerScale:bounds[i] Zoom: zoom Scale: 0.5*siz.width];
1399 }
1400 else
1401 {
1402 scale_vector(&bounds[i], upscale);
1403 }
1404 bounds[i] = make_vector(bounds[i].x + scanner_cx, bounds[i].z * z_factor + bounds[i].y * y_factor + scanner_cy, z1 );
1405 }
1406 // draw the diamond
1407 //
1408 OOGLBEGIN(GL_QUADS);
1409 glColor4f(col[0], col[1], col[2], 0.33333 * col[3]);
1410 glVertex3f(bounds[0].x, bounds[0].y, bounds[0].z); glVertex3f(bounds[4].x, bounds[4].y, bounds[4].z);
1411 glVertex3f(bounds[1].x, bounds[1].y, bounds[1].z); glVertex3f(bounds[5].x, bounds[5].y, bounds[5].z);
1412 glVertex3f(bounds[2].x, bounds[2].y, bounds[2].z); glVertex3f(bounds[4].x, bounds[4].y, bounds[4].z);
1413 glVertex3f(bounds[3].x, bounds[3].y, bounds[3].z); glVertex3f(bounds[5].x, bounds[5].y, bounds[5].z);
1414 glVertex3f(bounds[2].x, bounds[2].y, bounds[2].z); glVertex3f(bounds[0].x, bounds[0].y, bounds[0].z);
1415 glVertex3f(bounds[3].x, bounds[3].y, bounds[3].z); glVertex3f(bounds[1].x, bounds[1].y, bounds[1].z);
1416 OOGLEND();
1417 }
1418 }
1419
1420 if (ms_blip > 0.0)
1421 {
1422 DrawSpecialOval(x1 - 0.5, y2 + 1.5, z1, NSMakeSize(16.0 * (1.0 - ms_blip), 8.0 * (1.0 - ms_blip)), 30, col);
1423 }
1424 if ([scannedEntity isCascadeWeapon])
1425 {
1426 if (nonlinear_scanner)
1427 {
1428 GLDrawNonlinearCascadeWeapon( scanner_cx, scanner_cy, z1, siz, rrp, scannedEntity->collision_radius, zoom, alpha );
1429 }
1430 else
1431 {
1432 GLfloat r1 = 2.5 + scannedEntity->collision_radius * upscale;
1433 GLfloat l2 = r1 * r1 - relativePosition.y * relativePosition.y;
1434 GLfloat r0 = (l2 > 0)? sqrt(l2): 0;
1435 if (r0 > 0)
1436 {
1437 OOGL(glColor4f(1.0, 0.5, 1.0, alpha));
1438 GLDrawOval(x1 - 0.5, y1 + 1.5, z1, NSMakeSize(r0, r0 * siz.height / siz.width), 20);
1439 }
1440 OOGL(glColor4f(0.5, 0.0, 1.0, 0.33333 * alpha));
1441 GLDrawFilledOval(x1 - 0.5, y2 + 1.5, z1, NSMakeSize(r1, r1), 15);
1442 }
1443 }
1444 else
1445 {
1446
1447#if IDENTIFY_SCANNER_LOLLIPOPS
1448 if ([scannedEntity isShip])
1449 {
1450 glColor4f(1.0, 1.0, 0.5, alpha);
1451 OODrawString([(ShipEntity *)scannedEntity displayName], x1 + 2, y2 + 2, z1, NSMakeSize(8, 8));
1452 }
1453#endif
1454 glColor4fv(col);
1455 if (inColorBlindMode && isHostile)
1456 {
1457 // in colorblind mode turn hostile blips into X shapes for easier recognition
1458 OOGLBEGIN(GL_LINES);
1459 glVertex3f(x1+2, y2+3, z1); glVertex3f(x1-3, y2, z1); glVertex3f(x1+2, y2, z1); glVertex3f(x1-3, y2+3, z1);
1460 OOGLEND();
1461 }
1462 else
1463 {
1464 OOGLBEGIN(GL_QUADS);
1465 glVertex3f(x1-3, y2, z1); glVertex3f(x1+2, y2, z1); glVertex3f(x1+2, y2+3, z1); glVertex3f(x1-3, y2+3, z1);
1466 OOGLEND();
1467 }
1468 OOGLBEGIN(GL_QUADS); // lollipop tail
1469 col[3] *= 0.3333; // one third the alpha
1470 glColor4fv(col);
1471 glVertex3f(x1, y1, z1); glVertex3f(x1+2, y1, z1); glVertex3f(x1+2, y2, z1); glVertex3f(x1, y2, z1);
1472 OOGLEND();
1473 }
1474 }
1475 }
1476
1477 }
1478
1479 for (i = 0; i < ent_count; i++)
1480 {
1481 [my_entities[i] release]; // released
1482 }
1483
1485
1486}
1487
1488
1489- (BOOL) minimalisticScanner
1490{
1491 return minimalistic_scanner;
1492}
1493
1494
1495- (void) setMinimalisticScanner: (BOOL) newValue
1496{
1497 minimalistic_scanner = !!newValue;
1498}
1499
1500
1501+ (Vector) nonlinearScannerScale: (Vector) V Zoom:(GLfloat)zoom Scale:(double) scale
1502{
1503 OOScalar mag = magnitude(V);
1504 Vector unit = vector_normal(V);
1505 return vector_multiply_scalar(unit, nonlinearScannerFunc(mag, zoom, scale));
1506}
1507
1508
1509- (BOOL) nonlinearScanner
1510{
1511 return nonlinear_scanner;
1512}
1513
1514
1515- (void) setNonlinearScanner: (BOOL) newValue
1516{
1517 nonlinear_scanner = !!newValue;
1518}
1519
1520
1521- (BOOL) scannerUltraZoom
1522{
1523 return scanner_ultra_zoom;
1524}
1525
1526
1527- (void) setScannerUltraZoom: (BOOL) newValue
1528{
1529 scanner_ultra_zoom = !!newValue;
1530}
1531
1532
1533- (void) refreshLastTransmitter
1534{
1535 Entity* lt = [UNIVERSE entityForUniversalID:last_transmitter];
1536 if ((lt == nil)||(!(lt->isShip)))
1537 return;
1538 ShipEntity* st = (ShipEntity*)lt;
1539 if ([st messageTime] <= 0.0)
1540 [st setMessageTime:2.5];
1541}
1542
1543
1544- (void) drawScannerZoomIndicator:(NSDictionary *)info
1545{
1546 int x, y;
1547 NSSize siz;
1548 GLfloat alpha;
1549 GLfloat zoom_color[4] = { 1.0f, 0.1f, 0.0f, 1.0f };
1550 struct CachedInfo cached;
1551
1552 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1553
1554 x = useDefined(cached.x, ZOOM_INDICATOR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
1555 y = useDefined(cached.y, ZOOM_INDICATOR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
1557 siz.height = useDefined(cached.height, ZOOM_INDICATOR_HEIGHT);
1558
1559 GetRGBAArrayFromInfo(info, zoom_color);
1560 zoom_color[3] *= overallAlpha;
1561 alpha = zoom_color[3];
1562
1563 GLfloat cx = x - 0.3 * siz.width;
1564 GLfloat cy = y - 0.75 * siz.height;
1565
1566 int zl = scanner_zoom;
1567 if (zl < 1) zl = 1;
1569 if (zl == 1) zoom_color[3] *= 0.75;
1570 if (scanner_ultra_zoom)
1571 zl = pow(2, zl - 1);
1572 GLColorWithOverallAlpha(zoom_color, alpha);
1573 OOGL(glEnable(GL_TEXTURE_2D));
1574 [sFontTexture apply];
1575
1576 OOGLBEGIN(GL_QUADS);
1577 if (zl / 10 > 0)
1578 drawCharacterQuad(48 + zl / 10, cx - 0.8 * siz.width, cy, z1, siz);
1579 drawCharacterQuad(48 + zl % 10, cx - 0.4 * siz.width, cy, z1, siz);
1580 drawCharacterQuad(58, cx, cy, z1, siz);
1581 drawCharacterQuad(49, cx + 0.3 * siz.width, cy, z1, siz);
1582 OOGLEND();
1583
1585 OOGL(glDisable(GL_TEXTURE_2D));
1586}
1587
1588
1589- (void) drawCompass:(NSDictionary *)info
1590{
1591 int x, y;
1592 NSSize siz;
1593 GLfloat alpha;
1594 GLfloat compass_color[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
1595 struct CachedInfo cached;
1596
1597 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1598
1599 x = useDefined(cached.x, COMPASS_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
1600 y = useDefined(cached.y, COMPASS_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
1601 siz.width = useDefined(cached.width, COMPASS_HALF_SIZE);
1602 siz.height = useDefined(cached.height, COMPASS_HALF_SIZE);
1603
1604 GetRGBAArrayFromInfo(info, compass_color);
1605 compass_color[3] *= overallAlpha;
1606 alpha = compass_color[3];
1607
1608 // draw the compass
1609 OOMatrix rotMatrix = [PLAYER rotationMatrix];
1610
1611 GLfloat h1 = siz.height * 0.125;
1612 GLfloat h3 = siz.height * 0.375;
1613 GLfloat w1 = siz.width * 0.125;
1614 GLfloat w3 = siz.width * 0.375;
1615 OOGL(GLScaledLineWidth(2.0 * lineWidth)); // thicker
1616 OOGL(glColor4f(compass_color[0], compass_color[1], compass_color[2], alpha));
1617 GLDrawOval(x, y, z1, siz, 12);
1618 OOGL(glColor4f(compass_color[0], compass_color[1], compass_color[2], 0.5f * alpha));
1619 OOGLBEGIN(GL_LINES);
1620 glVertex3f(x - w1, y, z1); glVertex3f(x - w3, y, z1);
1621 glVertex3f(x + w1, y, z1); glVertex3f(x + w3, y, z1);
1622 glVertex3f(x, y - h1, z1); glVertex3f(x, y - h3, z1);
1623 glVertex3f(x, y + h1, z1); glVertex3f(x, y + h3, z1);
1624 OOGLEND();
1625 OOGL(GLScaledLineWidth(lineWidth)); // thinner
1626
1627 if ([self checkPlayerInSystemFlight] && [PLAYER status] != STATUS_LAUNCHING) // normal system
1628 {
1629 Entity *reference = [PLAYER compassTarget];
1630
1631 // translate and rotate the view
1632
1633 Vector relativePosition = [PLAYER vectorTo:reference];
1634 relativePosition = OOVectorMultiplyMatrix(relativePosition, rotMatrix);
1635 relativePosition = vector_normal_or_fallback(relativePosition, kBasisZVector);
1636
1637 relativePosition.x *= siz.width * 0.4;
1638 relativePosition.y *= siz.height * 0.4;
1639 relativePosition.x += x;
1640 relativePosition.y += y;
1641
1642 siz.width *= 0.2;
1643 siz.height *= 0.2;
1644 OOGL(GLScaledLineWidth(2.0*lineWidth));
1645 switch ([PLAYER compassMode])
1646 {
1647 case COMPASS_MODE_INACTIVE:
1648 break;
1649
1650 case COMPASS_MODE_BASIC:
1651 if ([reference isStation]) // validateCompassTarget in PlayerEntity.m changes COMPASS_BASIC_MODE target to the main station when inside the planetary aegis or in docking range of the main station
1652 [self drawCompassStationBlipAt:relativePosition Size:siz Alpha:alpha];
1653 else
1654 [self drawCompassPlanetBlipAt:relativePosition Size:siz Alpha:alpha];
1655 break;
1656
1657 case COMPASS_MODE_PLANET:
1658 [self drawCompassPlanetBlipAt:relativePosition Size:siz Alpha:alpha];
1659 break;
1660
1661 case COMPASS_MODE_STATION:
1662 [self drawCompassStationBlipAt:relativePosition Size:siz Alpha:alpha];
1663 break;
1664
1665 case COMPASS_MODE_SUN:
1666 [self drawCompassSunBlipAt:relativePosition Size:siz Alpha:alpha];
1667 break;
1668
1669 case COMPASS_MODE_TARGET:
1670 [self drawCompassTargetBlipAt:relativePosition Size:siz Alpha:alpha];
1671 break;
1672
1673 case COMPASS_MODE_BEACONS:
1674 [self drawCompassBeaconBlipAt:relativePosition Size:siz Alpha:alpha];
1675 Entity <OOBeaconEntity> *beacon = [PLAYER nextBeacon];
1676 [[beacon beaconDrawable] oo_drawHUDBeaconIconAt:NSMakePoint(x, y) size:siz alpha:alpha z:z1];
1677 break;
1678 }
1679 OOGL(GLScaledLineWidth(lineWidth)); // reset
1680
1681 _compassUpdated = YES;
1682 _compassActive = YES;
1683 }
1684}
1685
1686
1687OOINLINE void SetCompassBlipColor(GLfloat relativeZ, GLfloat alpha)
1688{
1689 if (relativeZ >= 0.0f)
1690 {
1691 OOGL(glColor4f(0.0f, 1.0f, 0.0f, alpha));
1692 }
1693 else
1694 {
1695 OOGL(glColor4f(1.0f, 0.0f, 0.0f, alpha));
1696 }
1697}
1698
1699
1700- (void) drawCompassPlanetBlipAt:(Vector)relativePosition Size:(NSSize)siz Alpha:(GLfloat)alpha
1701{
1702 if (relativePosition.z >= 0)
1703 {
1704 OOGL(glColor4f(0.0,1.0,0.0,0.75 * alpha));
1705 GLDrawFilledOval(relativePosition.x, relativePosition.y, z1, siz, 30);
1706 OOGL(glColor4f(0.0,1.0,0.0,alpha));
1707 GLDrawOval(relativePosition.x, relativePosition.y, z1, siz, 30);
1708 }
1709 else
1710 {
1711 OOGL(glColor4f(1.0,0.0,0.0,alpha));
1712 GLDrawOval(relativePosition.x, relativePosition.y, z1, siz, 30);
1713 }
1714}
1715
1716
1717- (void) drawCompassStationBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha
1718{
1719 SetCompassBlipColor(relativePosition.z, alpha);
1720
1721 OOGLBEGIN(GL_LINE_LOOP);
1722 glVertex3f(relativePosition.x - 0.5 * siz.width, relativePosition.y - 0.5 * siz.height, z1);
1723 glVertex3f(relativePosition.x + 0.5 * siz.width, relativePosition.y - 0.5 * siz.height, z1);
1724 glVertex3f(relativePosition.x + 0.5 * siz.width, relativePosition.y + 0.5 * siz.height, z1);
1725 glVertex3f(relativePosition.x - 0.5 * siz.width, relativePosition.y + 0.5 * siz.height, z1);
1726 OOGLEND();
1727}
1728
1729
1730- (void) drawCompassSunBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha
1731{
1732 OOGL(glColor4f(1.0, 1.0, 0.0, 0.75 * alpha));
1733 GLDrawFilledOval(relativePosition.x, relativePosition.y, z1, siz, 30);
1734
1735 SetCompassBlipColor(relativePosition.z, alpha);
1736
1737 GLDrawOval(relativePosition.x, relativePosition.y, z1, siz, 30);
1738}
1739
1740
1741- (void) drawCompassTargetBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha
1742{
1743 SetCompassBlipColor(relativePosition.z, alpha);
1744
1745 OOGLBEGIN(GL_LINES);
1746 glVertex3f(relativePosition.x - siz.width, relativePosition.y, z1);
1747 glVertex3f(relativePosition.x + siz.width, relativePosition.y, z1);
1748 glVertex3f(relativePosition.x, relativePosition.y - siz.height, z1);
1749 glVertex3f(relativePosition.x, relativePosition.y + siz.height, z1);
1750 OOGLEND();
1751
1752 GLDrawOval(relativePosition.x, relativePosition.y, z1, siz, 30);
1753}
1754
1755
1756- (void) drawCompassBeaconBlipAt:(Vector) relativePosition Size:(NSSize) siz Alpha:(GLfloat) alpha
1757{
1758 SetCompassBlipColor(relativePosition.z, alpha);
1759
1760 OOGLBEGIN(GL_LINES);
1761 /* glVertex3f(relativePosition.x - 0.5 * siz.width, relativePosition.y - 0.5 * siz.height, z1);
1762 glVertex3f(relativePosition.x, relativePosition.y + 0.5 * siz.height, z1);
1763
1764 glVertex3f(relativePosition.x + 0.5 * siz.width, relativePosition.y - 0.5 * siz.height, z1);
1765 glVertex3f(relativePosition.x, relativePosition.y + 0.5 * siz.height, z1);
1766
1767 glVertex3f(relativePosition.x - 0.5 * siz.width, relativePosition.y - 0.5 * siz.height, z1);
1768 glVertex3f(relativePosition.x + 0.5 * siz.width, relativePosition.y - 0.5 * siz.height, z1); */
1769 glVertex3f(relativePosition.x + 0.6 * siz.width, relativePosition.y, z1);
1770 glVertex3f(relativePosition.x, relativePosition.y + 0.6 * siz.height, z1);
1771
1772 glVertex3f(relativePosition.x - 0.6 * siz.width, relativePosition.y, z1);
1773 glVertex3f(relativePosition.x, relativePosition.y + 0.6 * siz.height, z1);
1774
1775 glVertex3f(relativePosition.x + 0.6 * siz.width, relativePosition.y, z1);
1776 glVertex3f(relativePosition.x, relativePosition.y - 0.6 * siz.height, z1);
1777
1778 glVertex3f(relativePosition.x - 0.6 * siz.width, relativePosition.y, z1);
1779 glVertex3f(relativePosition.x, relativePosition.y - 0.6 * siz.height, z1);
1780
1781 OOGLEND();
1782}
1783
1784
1785- (void) drawAegis:(NSDictionary *)info
1786{
1787 if (([UNIVERSE viewDirection] == VIEW_GUI_DISPLAY)||([UNIVERSE sun] == nil)||([PLAYER checkForAegis] != AEGIS_IN_DOCKING_RANGE))
1788 return; // don't draw
1789
1790 int x, y;
1791 NSSize siz;
1792 GLfloat alpha = 0.5f * overallAlpha;
1793 struct CachedInfo cached;
1794
1795 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1796
1797 x = useDefined(cached.x, AEGIS_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
1798 y = useDefined(cached.y, AEGIS_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
1799 siz.width = useDefined(cached.width, AEGIS_WIDTH);
1800 siz.height = useDefined(cached.height, AEGIS_HEIGHT);
1801 alpha *= cached.alpha;
1802
1803 // draw the aegis indicator
1804 //
1805 GLfloat w = siz.width / 16.0;
1806 GLfloat h = siz.height / 16.0;
1807
1808 GLfloat strip[] = { -7,8, -6,5, 5,8, 3,5, 7,2, 4,2, 6,-1, 4,2, -4,-1, -6,2, -4,-1, -7,-1, -3,-4, -5,-7, 6,-4, 7,-7 };
1809
1810#if 1
1811 OOGL(glColor4f(0.0f, 1.0f, 0.0f, alpha));
1812 OOGLBEGIN(GL_QUAD_STRIP);
1813 int i;
1814 for (i = 0; i < 32; i += 2)
1815 {
1816 glVertex3f(x + w * strip[i], y - h * strip[i + 1], z1);
1817 }
1818 OOGLEND();
1819#else
1821 OOGLTranslateModelView(make_vector(x, y, z1));
1822 OOGLScaleModelView(make_vector(w, -h, 1.0f));
1823
1824 OOGL(glColor4f(0.0f, 1.0f, 0.0f, alpha));
1825 OOGL(glVertexPointer(2, GL_FLOAT, 0, strip));
1826 OOGL(glEnableClientState(GL_VERTEX_ARRAY));
1827 OOGL(glDisableClientState(GL_COLOR_ARRAY));
1828
1829 OOGL(glDrawArrays(GL_QUAD_STRIP, 0, sizeof strip / sizeof *strip / 2));
1830 OOGL(glDisableClientState(GL_VERTEX_ARRAY));
1831
1833#endif
1834}
1835
1836
1837- (void) drawCustomBar:(NSDictionary *)info
1838{
1839 int x, y;
1840 NSSize siz;
1841 BOOL draw_surround;
1842 GLfloat alpha = overallAlpha;
1843 GLfloat ds = OOClamp_0_1_f([PLAYER dialCustomFloat:[info oo_stringForKey:CUSTOM_DIAL_KEY]]);
1844 struct CachedInfo cached;
1845
1846 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1847
1848 x = useDefined(cached.x, 0) + [[UNIVERSE gameView] x_offset] * cached.x0;
1849 y = useDefined(cached.y, 0) + [[UNIVERSE gameView] y_offset] * cached.y0;
1850 siz.width = useDefined(cached.width, 50);
1851 siz.height = useDefined(cached.height, 8);
1852 alpha *= cached.alpha;
1853
1854 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:NO];
1855
1857 if (draw_surround)
1858 {
1859 // draw custom surround
1860 hudDrawSurroundAt(x, y, z1, siz);
1861 }
1862 // draw custom bar
1863 if (ds > .75)
1864 {
1866 }
1867 else if (ds > .25)
1868 {
1870 }
1871 else
1872 {
1874 }
1875
1876 hudDrawBarAt(x, y, z1, siz, ds);
1877}
1878
1879
1880- (void) drawCustomText:(NSDictionary *)info
1881{
1882 int x, y;
1883 NSSize size;
1884 GLfloat alpha = overallAlpha;
1885 NSString *text = [PLAYER dialCustomString:[info oo_stringForKey:CUSTOM_DIAL_KEY]];
1886 struct CachedInfo cached;
1887
1888 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1889
1890 x = useDefined(cached.x, 0) + [[UNIVERSE gameView] x_offset] * cached.x0;
1891 y = useDefined(cached.y, 0) + [[UNIVERSE gameView] y_offset] * cached.y0;
1892 alpha *= cached.alpha;
1893
1895
1896 size.width = useDefined(cached.width, 10.0f);
1897 size.height = useDefined(cached.height, 10.0f);
1898
1899 if ([info oo_intForKey:@"align"] == 1)
1900 {
1901 OODrawStringAligned(text, x, y, z1, size, YES);
1902 }
1903 else
1904 {
1905 OODrawStringAligned(text, x, y, z1, size, NO);
1906 }
1907
1908}
1909
1910
1911- (void) drawCustomIndicator:(NSDictionary *)info
1912{
1913 int x, y;
1914 NSSize siz;
1915 BOOL draw_surround;
1916 GLfloat alpha = overallAlpha;
1917 GLfloat iv = OOClamp_n1_1_f([PLAYER dialCustomFloat:[info oo_stringForKey:CUSTOM_DIAL_KEY]]);
1918
1919 struct CachedInfo cached;
1920
1921 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1922
1923 x = useDefined(cached.x, 0) + [[UNIVERSE gameView] x_offset] * cached.x0;
1924 y = useDefined(cached.y, 0) + [[UNIVERSE gameView] y_offset] * cached.y0;
1925 siz.width = useDefined(cached.width, 50);
1926 siz.height = useDefined(cached.height, 8);
1927 alpha *= cached.alpha;
1928 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:NO];
1929
1930 if (draw_surround)
1931 {
1932 // draw custom surround
1934 hudDrawSurroundAt(x, y, z1, siz);
1935 }
1936 // draw custom indicator
1938 hudDrawIndicatorAt(x, y, z1, siz, iv);
1939}
1940
1941
1942- (void) drawCustomLight:(NSDictionary *)info
1943{
1944 int x, y;
1945 NSSize siz;
1946 GLfloat alpha = overallAlpha;
1947
1948 struct CachedInfo cached;
1949
1950 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1951
1952 x = useDefined(cached.x, 0) + [[UNIVERSE gameView] x_offset] * cached.x0;
1953 y = useDefined(cached.y, 0) + [[UNIVERSE gameView] y_offset] * cached.y0;
1954 siz.width = useDefined(cached.width, 8);
1955 siz.height = useDefined(cached.height, 8);
1956 alpha *= cached.alpha;
1957
1958 GLfloat light_color[4] = { 0.25, 0.25, 0.25, 0.0};
1959
1960 OOColor *color = [PLAYER dialCustomColor:[info oo_stringForKey:CUSTOM_DIAL_KEY]];
1961 [color getRed:&light_color[0]
1962 green:&light_color[1]
1963 blue:&light_color[2]
1964 alpha:&light_color[3]];
1965
1966 GLColorWithOverallAlpha(light_color, alpha);
1967 OOGLBEGIN(GL_POLYGON);
1968 hudDrawStatusIconAt(x, y, z1, siz);
1969 OOGLEND();
1970 OOGL(glColor4f(0.25, 0.25, 0.25, alpha));
1971 OOGLBEGIN(GL_LINE_LOOP);
1972 hudDrawStatusIconAt(x, y, z1, siz);
1973 OOGLEND();
1974}
1975
1976
1977- (void) drawCustomImage:(NSDictionary *)info
1978{
1979 int x, y;
1980 GLfloat alpha = overallAlpha;
1981
1982 struct CachedInfo cached;
1983
1984 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
1985
1986 x = useDefined(cached.x, 0) + [[UNIVERSE gameView] x_offset] * cached.x0;
1987 y = useDefined(cached.y, 0) + [[UNIVERSE gameView] y_offset] * cached.y0;
1988 alpha *= cached.alpha;
1989
1990 NSString *textureFile = [PLAYER dialCustomString:[info oo_stringForKey:CUSTOM_DIAL_KEY]];
1991 if (textureFile == nil || [textureFile length] == 0) {
1992 return;
1993 }
1994
1995 OOTexture *texture = [OOTexture textureWithName:textureFile
1996 inFolder:@"Images"
1997 options:kOOTextureDefaultOptions | kOOTextureNoShrink
1998 anisotropy:kOOTextureDefaultAnisotropy
1999 lodBias:kOOTextureDefaultLODBias];
2000 if (texture == nil)
2001 {
2002 OOLogERR(kOOLogFileNotFound, @"HeadUpDisplay couldn't get an image texture name for %@", textureFile);
2003 return;
2004 }
2005
2006 NSSize imageSize = [texture dimensions];
2007 imageSize.width = useDefined(cached.width, imageSize.width);
2008 imageSize.height = useDefined(cached.height, imageSize.height);
2009
2010 /* There's possibly some optimisation which could be done by
2011 * caching the sprite, but regenerating it each frame doesn't
2012 * appear to take any significant amount of time compared with the
2013 * time taken to actually render it and the texture will be
2014 * returned from the cache anyway. - CIM */
2015 OOTextureSprite *sprite = [[OOTextureSprite alloc] initWithTexture:texture size:imageSize];
2016
2017 [sprite blitCentredToX:x Y:y Z:z1 alpha:alpha];
2018 [sprite release];
2019
2020}
2021
2022
2023- (void) drawSpeedBar:(NSDictionary *)info
2024{
2025 int x, y;
2026 NSSize siz;
2027 BOOL draw_surround;
2028 GLfloat alpha = overallAlpha;
2029 GLfloat ds = [PLAYER dialSpeed];
2030 struct CachedInfo cached;
2031
2032 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2033
2034 x = useDefined(cached.x, SPEED_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2035 y = useDefined(cached.y, SPEED_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2036 siz.width = useDefined(cached.width, SPEED_BAR_WIDTH);
2037 siz.height = useDefined(cached.height, SPEED_BAR_HEIGHT);
2038 alpha *= cached.alpha;
2039
2040 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:SPEED_BAR_DRAW_SURROUND];
2041
2042
2044 if (draw_surround)
2045 {
2046 // draw speed surround
2047 hudDrawSurroundAt(x, y, z1, siz);
2048 }
2049 // draw speed bar
2050 if (ds > .80)
2051 {
2053 }
2054 else if (ds > .25)
2055 {
2057 }
2058 else
2059 {
2061 }
2062
2063 hudDrawBarAt(x, y, z1, siz, ds);
2064}
2065
2066
2067- (void) drawRollBar:(NSDictionary *)info
2068{
2069 int x, y;
2070 NSSize siz;
2071 BOOL draw_surround;
2072 GLfloat alpha = overallAlpha;
2073 struct CachedInfo cached;
2074
2075 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2076
2077 x = useDefined(cached.x, ROLL_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2078 y = useDefined(cached.y, ROLL_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2079 siz.width = useDefined(cached.width, ROLL_BAR_WIDTH);
2080 siz.height = useDefined(cached.height, ROLL_BAR_HEIGHT);
2081 alpha *= cached.alpha;
2082 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:ROLL_BAR_DRAW_SURROUND];
2083
2084 if (draw_surround)
2085 {
2086 // draw ROLL surround
2088 hudDrawSurroundAt(x, y, z1, siz);
2089 }
2090 // draw ROLL bar
2092 hudDrawIndicatorAt(x, y, z1, siz, [PLAYER dialRoll]);
2093}
2094
2095
2096- (void) drawPitchBar:(NSDictionary *)info
2097{
2098 int x, y;
2099 NSSize siz;
2100 BOOL draw_surround;
2101 GLfloat alpha = overallAlpha;
2102 struct CachedInfo cached;
2103
2104 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2105
2106 x = useDefined(cached.x, PITCH_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2107 y = useDefined(cached.y, PITCH_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2108 siz.width = useDefined(cached.width, PITCH_BAR_WIDTH);
2109 siz.height = useDefined(cached.height, PITCH_BAR_HEIGHT);
2110 alpha *= cached.alpha;
2111 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:PITCH_BAR_DRAW_SURROUND];
2112
2113 if (draw_surround)
2114 {
2115 // draw PITCH surround
2117 hudDrawSurroundAt(x, y, z1, siz);
2118 }
2119 // draw PITCH bar
2121 hudDrawIndicatorAt(x, y, z1, siz, [PLAYER dialPitch]);
2122}
2123
2124
2125- (void) drawYawBar:(NSDictionary *)info
2126{
2127 int x, y;
2128 NSSize siz;
2129 BOOL draw_surround;
2130 GLfloat alpha = overallAlpha;
2131 struct CachedInfo cached;
2132
2133 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2134
2135 // No standard YAW definitions - using PITCH ones instead.
2136 x = useDefined(cached.x, PITCH_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2137 y = useDefined(cached.y, PITCH_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2138 siz.width = useDefined(cached.width, PITCH_BAR_WIDTH);
2139 siz.height = useDefined(cached.height, PITCH_BAR_HEIGHT);
2140 alpha *= cached.alpha;
2141 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:PITCH_BAR_DRAW_SURROUND];
2142
2143 if (draw_surround)
2144 {
2145 // draw YAW surround
2147 hudDrawSurroundAt(x, y, z1, siz);
2148 }
2149 // draw YAW bar
2151 hudDrawIndicatorAt(x, y, z1, siz, [PLAYER dialYaw]);
2152}
2153
2154
2155- (void) drawEnergyGauge:(NSDictionary *)info
2156{
2157 int x, y;
2158 unsigned i;
2159 NSSize siz;
2160 BOOL drawSurround, labelled, energyCritical = NO;
2161 GLfloat alpha = overallAlpha;
2162 GLfloat bankHeight, bankY;
2163 PlayerEntity *player = PLAYER;
2164
2165 unsigned n_bars = [player dialMaxEnergy]/64.0;
2166 n_bars = [info oo_unsignedIntForKey:N_BARS_KEY defaultValue:n_bars];
2167 if (n_bars < 1)
2168 {
2169 n_bars = 1;
2170 }
2171 GLfloat energy = [player dialEnergy] * n_bars;
2172 struct CachedInfo cached;
2173
2174 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2175
2176 x = useDefined(cached.x, ENERGY_GAUGE_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2177 y = useDefined(cached.y, ENERGY_GAUGE_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2179 siz.height = useDefined(cached.height, ENERGY_GAUGE_HEIGHT);
2180 alpha *= cached.alpha;
2181 drawSurround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:ENERGY_GAUGE_DRAW_SURROUND];
2182 labelled = [info oo_boolForKey:LABELLED_KEY defaultValue:YES];
2183 if (n_bars > 8) labelled = NO;
2184
2185 if (drawSurround)
2186 {
2187 // draw energy surround
2189 hudDrawSurroundAt(x, y, z1, siz);
2190 }
2191
2192 bankHeight = siz.height / n_bars;
2193 // draw energy banks
2194 NSSize barSize = NSMakeSize(siz.width, bankHeight - 2.0); // leave a gap between bars
2195 GLfloat midBank = bankHeight / 2.0f;
2196 bankY = y - (n_bars - 1) * midBank - 1.0;
2197
2198 // avoid constant colour switching...
2199 if (labelled)
2200 {
2201 GLColorWithOverallAlpha(green_color, alpha);
2202 GLfloat labelStartX = x + 0.5f * barSize.width + 3.0f;
2203 NSSize labelSize = NSMakeSize(9.0, (bankHeight < 18.0)? bankHeight : 18.0);
2204 for (i = 0; i < n_bars; i++)
2205 {
2206 OODrawString([NSString stringWithFormat:@"E%x", n_bars - i], labelStartX, bankY - midBank, z1, labelSize);
2207 bankY += bankHeight;
2208 }
2209 }
2210
2211 if (energyCritical)
2212 {
2214 }
2215 else
2216 {
2218 }
2219 bankY = y - (n_bars - 1) * midBank;
2220 for (i = 0; i < n_bars; i++)
2221 {
2222 if (energy > 1.0)
2223 {
2224 hudDrawBarAt(x, bankY, z1, barSize, 1.0);
2225 }
2226 else if (energy > 0.0)
2227 {
2228 hudDrawBarAt(x, bankY, z1, barSize, energy);
2229 }
2230
2231 energy -= 1.0;
2232 bankY += bankHeight;
2233 }
2234}
2235
2236
2237- (void) drawForwardShieldBar:(NSDictionary *)info
2238{
2239 int x, y;
2240 NSSize siz;
2241 BOOL draw_surround;
2242 GLfloat alpha = overallAlpha;
2243 GLfloat shield = [PLAYER dialForwardShield];
2244 struct CachedInfo cached;
2245
2246 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2247
2248 x = useDefined(cached.x, FORWARD_SHIELD_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2249 y = useDefined(cached.y, FORWARD_SHIELD_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2251 siz.height = useDefined(cached.height, FORWARD_SHIELD_BAR_HEIGHT);
2252 alpha *= cached.alpha;
2253 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:FORWARD_SHIELD_BAR_DRAW_SURROUND];
2254
2255 if (draw_surround)
2256 {
2257 // draw forward_shield surround
2259 hudDrawSurroundAt(x, y, z1, siz);
2260 }
2261 // draw forward_shield bar
2262 if (shield < .25)
2263 {
2265 }
2266 else if (shield < .80)
2267 {
2269 }
2270 else
2271 {
2273 }
2274 hudDrawBarAt(x, y, z1, siz, shield);
2275}
2276
2277
2278- (void) drawAftShieldBar:(NSDictionary *)info
2279{
2280 int x, y;
2281 NSSize siz;
2282 BOOL draw_surround;
2283 GLfloat alpha = overallAlpha;
2284 GLfloat shield = [PLAYER dialAftShield];
2285 struct CachedInfo cached;
2286
2287 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2288
2289 x = useDefined(cached.x, AFT_SHIELD_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2290 y = useDefined(cached.y, AFT_SHIELD_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2292 siz.height = useDefined(cached.height, AFT_SHIELD_BAR_HEIGHT);
2293 alpha *= cached.alpha;
2294 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:AFT_SHIELD_BAR_DRAW_SURROUND];
2295
2296 if (draw_surround)
2297 {
2298 // draw forward_shield surround
2300 hudDrawSurroundAt(x, y, z1, siz);
2301 }
2302 // draw forward_shield bar
2303 if (shield < .25)
2304 {
2306 }
2307 else if (shield < .80)
2308 {
2310 }
2311 else
2312 {
2314 }
2315 hudDrawBarAt(x, y, z1, siz, shield);
2316}
2317
2318
2319- (void) drawFuelBar:(NSDictionary *)info
2320{
2321 int x, y;
2322 NSSize siz;
2323 BOOL draw_surround;
2324 float fu, hr;
2325 GLfloat alpha = overallAlpha;
2326 struct CachedInfo cached;
2327
2328 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2329
2330 x = useDefined(cached.x, FUEL_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2331 y = useDefined(cached.y, FUEL_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2332 siz.width = useDefined(cached.width, FUEL_BAR_WIDTH);
2333 siz.height = useDefined(cached.height, FUEL_BAR_HEIGHT);
2334 alpha *= cached.alpha;
2335 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:NO];
2336
2337 if (draw_surround)
2338 {
2340 hudDrawSurroundAt(x, y, z1, siz);
2341 }
2342
2343 fu = [PLAYER dialFuel];
2344 hr = [PLAYER dialHyperRange];
2345
2346 // draw fuel bar
2348 hudDrawBarAt(x, y, z1, siz, fu);
2349
2350 // draw range indicator
2351 if (hr > 0.0f && hr <= 1.0f)
2352 {
2353 if ([PLAYER hasSufficientFuelForJump])
2354 {
2356 }
2357 else
2358 {
2360 }
2361 hudDrawMarkerAt(x, y, z1, siz, hr);
2362 }
2363
2364}
2365
2366
2367- (void) drawWitchspaceDestination:(NSDictionary *)info
2368{
2369 // A zero-distance jump counts as 0.1LY
2370 if ([PLAYER dialHyperRange] == 0.0f)
2371 {
2372 return;
2373 }
2374
2375 int x, y;
2376 NSSize siz;
2377 GLfloat alpha = overallAlpha;
2378
2379 struct CachedInfo cached;
2380
2381 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2382
2383 x = useDefined(cached.x, WITCHDEST_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2384 y = useDefined(cached.y, WITCHDEST_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2385 siz.width = useDefined(cached.width, WITCHDEST_WIDTH);
2386 siz.height = useDefined(cached.height, WITCHDEST_HEIGHT);
2387 alpha *= cached.alpha;
2388 NSString *dest = [UNIVERSE getSystemName:[PLAYER targetSystemID]];
2389 NSInteger concealment = [[[UNIVERSE systemManager] getPropertiesForSystem:[PLAYER targetSystemID] inGalaxy:[PLAYER galaxyNumber]] oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
2390 if (concealment >= OO_SYSTEMCONCEALMENT_NONAME) dest = DESC(@"status-unknown-system");
2391
2393
2394 if ([info oo_intForKey:@"align"] == 1)
2395 {
2396 OODrawStringAligned(dest, x, y, z1, siz, YES);
2397 }
2398 else
2399 {
2400 OODrawStringAligned(dest, x, y, z1, siz, NO);
2401 }
2402
2403}
2404
2405
2406- (void) drawCabinTempBar:(NSDictionary *)info
2407{
2408 int x, y;
2409 NSSize siz;
2410 BOOL draw_surround;
2411 GLfloat temp = [PLAYER hullHeatLevel];
2412 GLfloat alpha = overallAlpha;
2413 struct CachedInfo cached;
2414
2415 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2416
2417 x = useDefined(cached.x, CABIN_TEMP_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2418 y = useDefined(cached.y, CABIN_TEMP_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2420 siz.height = useDefined(cached.height, CABIN_TEMP_BAR_HEIGHT);
2421 alpha *= cached.alpha;
2422 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:NO];
2423
2424 if (draw_surround)
2425 {
2427 hudDrawSurroundAt(x, y, z1, siz);
2428 }
2429
2430 int flash = (int)([UNIVERSE getTime] * 4);
2431 flash &= 1;
2432 // what color are we?
2433 if (temp > .80)
2434 {
2435 if (temp > .90 && flash)
2437 else
2439 }
2440 else
2441 {
2442 if (temp > .25)
2444 else
2446 }
2447
2448
2449 hudDrawBarAt(x, y, z1, siz, temp);
2450}
2451
2452
2453- (void) drawWeaponTempBar:(NSDictionary *)info
2454{
2455 int x, y;
2456 NSSize siz;
2457 BOOL draw_surround;
2458 GLfloat temp = [PLAYER laserHeatLevel];
2459 GLfloat alpha = overallAlpha;
2460 struct CachedInfo cached;
2461
2462 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2463
2464 x = useDefined(cached.x, WEAPON_TEMP_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2465 y = useDefined(cached.y, WEAPON_TEMP_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2467 siz.height = useDefined(cached.height, WEAPON_TEMP_BAR_HEIGHT);
2468 alpha *= cached.alpha;
2469 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:NO];
2470
2471 if (draw_surround)
2472 {
2474 hudDrawSurroundAt(x, y, z1, siz);
2475 }
2476
2477 // draw weapon_temp bar (only need to call GLColor() once!)
2478 if (temp > .80)
2480 else if (temp > .25)
2482 else
2484 hudDrawBarAt(x, y, z1, siz, temp);
2485}
2486
2487
2488- (void) drawAltitudeBar:(NSDictionary *)info
2489{
2490 int x, y;
2491 NSSize siz;
2492 BOOL draw_surround;
2493 GLfloat alt = [PLAYER dialAltitude];
2494 GLfloat alpha = overallAlpha;
2495 struct CachedInfo cached;
2496
2497 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2498
2499 x = useDefined(cached.x, ALTITUDE_BAR_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2500 y = useDefined(cached.y, ALTITUDE_BAR_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2502 siz.height = useDefined(cached.height, ALTITUDE_BAR_HEIGHT);
2503 alpha *= cached.alpha;
2504 draw_surround = [info oo_boolForKey:DRAW_SURROUND_KEY defaultValue:NO];
2505
2506 if (draw_surround)
2507 {
2509 hudDrawSurroundAt(x, y, z1, siz);
2510 }
2511
2512 int flash = (int)([UNIVERSE getTime] * 4);
2513 flash &= 1;
2514
2515 // draw altitude bar (evaluating the least amount of ifs per go)
2516 if (alt < .25)
2517 {
2518 if (alt < .10 && flash)
2520 else
2522 }
2523 else
2524 {
2525 if (alt < .75)
2527 else
2529 }
2530
2531 hudDrawBarAt(x, y, z1, siz, alt);
2532
2533}
2534
2535
2536static NSString * const kDefaultMissileIconKey = @"oolite-default-missile-icon";
2537static NSString * const kDefaultMineIconKey = @"oolite-default-mine-icon";
2538static const GLfloat kOutlineWidth = 0.5f;
2539
2540
2541static OOPolygonSprite *IconForMissileRole(NSString *role)
2542{
2543 static NSMutableDictionary *sIcons = nil;
2544 OOPolygonSprite *result = nil;
2545
2546 result = [sIcons objectForKey:role];
2547 if (result == nil)
2548 {
2549 NSString *key = role;
2550 NSArray *iconDef = [[UNIVERSE descriptions] oo_arrayForKey:key];
2551 if (iconDef != nil) result = [[OOPolygonSprite alloc] initWithDataArray:iconDef outlineWidth:kOutlineWidth name:key];
2552 if (result == nil) // No custom icon or bad data
2553 {
2554 /* Backwards compatibility note:
2555 The old implementation used suffixes "MISSILE" and "MINE" (without
2556 the underscore), and didn't draw anything if neither was found. I
2557 believe any difference in practical behavour due to the change here
2558 will be positive.
2559 -- Ahruman 2009-10-09
2560 */
2561 if ([role hasSuffix:@"_MISSILE"]) key = kDefaultMissileIconKey;
2562 else key = kDefaultMineIconKey;
2563
2564 iconDef = [[UNIVERSE descriptions] oo_arrayForKey:key];
2565 result = [[OOPolygonSprite alloc] initWithDataArray:iconDef outlineWidth:kOutlineWidth name:key];
2566 }
2567
2568 if (result != nil)
2569 {
2570 if (sIcons == nil) sIcons = [[NSMutableDictionary alloc] init];
2571 [sIcons setObject:result forKey:role];
2572 [result release]; // Balance alloc
2573 }
2574 }
2575
2576 return result;
2577}
2578
2579
2580- (void) drawIconForMissile:(ShipEntity *)missile
2581 selected:(BOOL)selected
2582 status:(OOMissileStatus)status
2583 x:(int)x y:(int)y
2584 width:(GLfloat)width height:(GLfloat)height alpha:(GLfloat)alpha
2585{
2586 OOPolygonSprite *sprite = IconForMissileRole([missile primaryRole]);
2587
2588 if (selected)
2589 {
2590 // Draw yellow outline.
2592 OOGLTranslateModelView(make_vector(x - width * 2.0f, y - height * 2.0f, z1));
2593 OOGLScaleModelView(make_vector(width, height, 1.0f));
2594 GLColorWithOverallAlpha(yellow_color, alpha);
2595 [sprite drawOutline];
2597
2598 // Draw black backing, so outline colour isn’t blended into missile colour.
2600 OOGLTranslateModelView(make_vector(x - width * 2.0f, y - height * 2.0f, z1));
2601 OOGLScaleModelView(make_vector(width, height, 1.0f));
2602 GLColorWithOverallAlpha(black_color, alpha);
2603 [sprite drawFilled];
2605
2606 switch (status)
2607 {
2609 GLColorWithOverallAlpha(green_color, alpha); break;
2611 GLColorWithOverallAlpha(yellow_color, alpha); break;
2613 GLColorWithOverallAlpha(red_color, alpha); break;
2614 }
2615 }
2616 else
2617 {
2618 if ([missile primaryTarget] == nil) GLColorWithOverallAlpha(green_color, alpha);
2619 else GLColorWithOverallAlpha(red_color, alpha);
2620 }
2621
2623 OOGLTranslateModelView(make_vector(x - width * 2.0f, y - height * 2.0f, z1));
2624 OOGLScaleModelView(make_vector(width, height, 1.0f));
2625 [sprite drawFilled];
2627}
2628
2629
2630
2631- (void) drawIconForEmptyPylonAtX:(int)x y:(int)y
2632 width:(GLfloat)width height:(GLfloat)height alpha:(GLfloat)alpha
2633{
2634 OOPolygonSprite *sprite = IconForMissileRole(kDefaultMissileIconKey);
2635
2636 // Draw gray outline.
2638 OOGLTranslateModelView(make_vector(x - width * 2.0f, y - height * 2.0f, z1));
2639 OOGLScaleModelView(make_vector(width, height, 1.0f));
2640 GLColorWithOverallAlpha(lightgray_color, alpha);
2641 [sprite drawOutline];
2643}
2644
2645
2646- (void) drawMissileDisplay:(NSDictionary *)info
2647{
2648 int x, y, sp;
2649 NSSize siz;
2650 GLfloat alpha = overallAlpha;
2651 struct CachedInfo cached;
2652
2653 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2654
2655 x = useDefined(cached.x, MISSILES_DISPLAY_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2656 y = useDefined(cached.y, MISSILES_DISPLAY_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2658 siz.height = useDefined(cached.height, MISSILE_ICON_HEIGHT);
2659 alpha *= cached.alpha;
2660 sp = [info oo_unsignedIntForKey:SPACING_KEY defaultValue:MISSILES_DISPLAY_SPACING];
2661
2662 BOOL weaponsOnline = [PLAYER weaponsOnline];
2663 if (!weaponsOnline) alpha *= 0.2f; // darken missile display if weapons are offline
2664
2665 if (![PLAYER dialIdentEngaged])
2666 {
2667 OOMissileStatus status = [PLAYER dialMissileStatus];
2668 NSUInteger i, n_mis = [PLAYER dialMaxMissiles];
2669 for (i = 0; i < n_mis; i++)
2670 {
2671 ShipEntity *missile = [PLAYER missileForPylon:i];
2672 if (missile)
2673 {
2674 [self drawIconForMissile:missile
2675 selected:weaponsOnline && i == [PLAYER activeMissile]
2676 status:status
2677 x:x + (int)i * sp + 2 y:y
2678 width:siz.width * 0.25f height:siz.height * 0.25f
2679 alpha:alpha];
2680 }
2681 else
2682 {
2683 [self drawIconForEmptyPylonAtX:x + (int)i * sp + 2 y:y
2684 width:siz.width * 0.25f height:siz.height * 0.25f alpha:alpha];
2685 }
2686 }
2687 }
2688 else
2689 {
2690 x -= siz.width;
2691 y -= siz.height * 0.75;
2692 siz.width *= 0.80;
2693 sp *= 0.75;
2694 switch ([PLAYER dialMissileStatus])
2695 {
2697 GLColorWithOverallAlpha(green_color, alpha); break;
2699 GLColorWithOverallAlpha(yellow_color, alpha); break;
2701 GLColorWithOverallAlpha(red_color, alpha); break;
2702 }
2703 OOGLBEGIN(GL_QUADS);
2704 glVertex3i(x , y, z1);
2705 glVertex3i(x + siz.width, y, z1);
2706 glVertex3i(x + siz.width, y + siz.height, z1);
2707 glVertex3i(x , y + siz.height, z1);
2708 OOGLEND();
2709 GLColorWithOverallAlpha(green_color, alpha);
2710 OODrawString([PLAYER dialTargetName], x + sp, y - 1, z1, NSMakeSize(siz.width, siz.height));
2711 }
2712
2713}
2714
2715
2716- (void) drawTargetReticle:(NSDictionary *)info
2717{
2718 GLfloat alpha = [info oo_nonNegativeFloatForKey:ALPHA_KEY defaultValue:1.0f] * overallAlpha;
2719
2720 if ([PLAYER primaryTarget] != nil)
2721 {
2722 hudDrawReticleOnTarget([PLAYER primaryTarget], PLAYER, z1, alpha, reticleTargetSensitive, propertiesReticleTargetSensitive, NO, YES, info, _reticleColors);
2723 [self drawDirectionCue:info];
2724 }
2725 // extra feature if extra equipment installed
2726 if ([PLAYER hasEquipmentItemProviding:@"EQ_INTEGRATED_TARGETING_SYSTEM"])
2727 {
2728 [self drawSecondaryTargetReticle:info];
2729 }
2730}
2731
2732
2733- (void) drawSecondaryTargetReticle:(NSDictionary *)info
2734{
2735 GLfloat alpha = [info oo_nonNegativeFloatForKey:ALPHA_KEY defaultValue:1.0f] * overallAlpha * 0.4;
2736
2737 PlayerEntity *player = PLAYER;
2738 if ([player hasEquipmentItemProviding:@"EQ_TARGET_MEMORY"])
2739 {
2740 // needs target memory to be working in addition to any other equipment
2741 // this item may be bound to
2742 NSMutableArray *targetMemory = [player targetMemory];
2743 ShipEntity *primary = [player primaryTarget];
2744 for (unsigned i = 0; i < PLAYER_TARGET_MEMORY_SIZE; i++)
2745 {
2746 id sec_id = [targetMemory objectAtIndex:i];
2747 // isProxy = weakref ; not = NSNull (in this case...)
2748 // can't use isKindOfClass because that throws
2749 // NSInvalidArgumentException when called on a weakref
2750 // with a dropped object.
2751 // TODO: fix OOWeakReference so isKindOfClass works
2752 if (sec_id != nil && [sec_id isProxy])
2753 {
2754 ShipEntity *secondary = [(OOWeakReference *)sec_id weakRefUnderlyingObject];
2755 if (secondary != nil && secondary != primary)
2756 {
2757 if ([secondary zeroDistance] <= SCANNER_MAX_RANGE2 && [secondary isInSpace])
2758 {
2759 hudDrawReticleOnTarget(secondary, PLAYER, z1, alpha, NO, nil, YES, NO, info, _reticleColors);
2760 }
2761 }
2762 }
2763 }
2764 }
2765}
2766
2767
2768- (void) drawWaypoints:(NSDictionary *)info
2769{
2770 GLfloat alpha = [info oo_nonNegativeFloatForKey:ALPHA_KEY defaultValue:1.0f] * overallAlpha;
2771 GLfloat scale = [info oo_floatForKey:@"reticle_scale" defaultValue:ONE_SIXTYFOURTH];
2772
2773 OOWaypointEntity *waypoint = nil;
2774 Entity *compass = [PLAYER compassTarget];
2775
2776 foreach (waypoint, [[UNIVERSE currentWaypoints] allValues])
2777 {
2778 hudDrawWaypoint(waypoint, PLAYER, z1, alpha, waypoint==compass, scale);
2779 }
2780
2781}
2782
2783
2784- (void) drawStatusLight:(NSDictionary *)info
2785{
2786 int x, y;
2787 NSSize siz;
2788 GLfloat alpha = overallAlpha;
2789 BOOL blueAlert = cloakIndicatorOnStatusLight && [PLAYER isCloaked];
2790 struct CachedInfo cached;
2791
2792 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2793
2794 x = useDefined(cached.x, STATUS_LIGHT_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2795 y = useDefined(cached.y, STATUS_LIGHT_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2797 siz.height = useDefined(cached.height, STATUS_LIGHT_HEIGHT);
2798 alpha *= cached.alpha;
2799
2800 GLfloat status_color[4] = { 0.25, 0.25, 0.25, 1.0};
2801 int alertCondition = [PLAYER alertCondition];
2802 GLfloat flash_alpha = 0.333 * (2.0f + sin((GLfloat)[UNIVERSE getTime] * 2.5f * alertCondition));
2803
2804 switch(alertCondition)
2805 {
2807 status_color[0] = red_color[0];
2808 status_color[1] = red_color[1];
2809 status_color[2] = blueAlert ? blue_color[2] : red_color[2];
2810 break;
2811
2813 status_color[0] = green_color[0];
2814 status_color[1] = green_color[1];
2815 status_color[2] = blueAlert ? blue_color[2] : green_color[2];
2816 break;
2817
2819 status_color[0] = yellow_color[0];
2820 status_color[1] = yellow_color[1];
2821 status_color[2] = blueAlert ? blue_color[2] : yellow_color[2];
2822 break;
2823
2824 default:
2826 break;
2827 }
2828 status_color[3] = flash_alpha;
2829 GLColorWithOverallAlpha(status_color, alpha);
2830 OOGLBEGIN(GL_POLYGON);
2831 hudDrawStatusIconAt(x, y, z1, siz);
2832 OOGLEND();
2833 OOGL(glColor4f(0.25, 0.25, 0.25, alpha));
2834 OOGLBEGIN(GL_LINE_LOOP);
2835 hudDrawStatusIconAt(x, y, z1, siz);
2836 OOGLEND();
2837}
2838
2839
2840- (void) drawDirectionCue:(NSDictionary *)info
2841{
2842 GLfloat alpha = overallAlpha;
2843 struct CachedInfo cached;
2844
2845 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2846
2847 alpha *= cached.alpha;
2848
2849 if ([UNIVERSE displayGUI]) return;
2850
2851 Entity *target = [PLAYER primaryTarget];
2852 if (target == nil) return;
2853
2854 // draw the direction cue
2855 OOMatrix rotMatrix;
2856
2857 rotMatrix = [PLAYER rotationMatrix];
2858
2859 if ([UNIVERSE viewDirection] != VIEW_GUI_DISPLAY)
2860 {
2861 const GLfloat innerSize = CROSSHAIR_SIZE;
2862 const GLfloat width = CROSSHAIR_SIZE * ONE_EIGHTH;
2863 const GLfloat outerSize = CROSSHAIR_SIZE * (1.0f + ONE_EIGHTH + ONE_EIGHTH);
2864 const float visMin = 0.994521895368273f; // cos(6 degrees)
2865 const float visMax = 0.984807753012208f; // cos(10 degrees)
2866
2867 // Transform the view
2868 Vector rpn = [PLAYER vectorTo:target];
2869 rpn = OOVectorMultiplyMatrix(rpn, rotMatrix);
2870 Vector drawPos = rpn;
2871 Vector forward = kZeroVector;
2872
2873 switch ([UNIVERSE viewDirection])
2874 {
2875 case VIEW_FORWARD:
2876 forward = kBasisZVector;
2877 break;
2878 case VIEW_AFT:
2879 drawPos.x = - drawPos.x;
2880 forward = vector_flip(kBasisZVector);
2881 break;
2882 case VIEW_PORT:
2883 drawPos.x = drawPos.z;
2884 forward = vector_flip(kBasisXVector);
2885 break;
2886 case VIEW_STARBOARD:
2887 drawPos.x = -drawPos.z;
2888 forward = kBasisXVector;
2889 break;
2890 case VIEW_CUSTOM:
2891 return;
2892
2893 default:
2894 break;
2895 }
2896
2897 float cosAngle = dot_product(vector_normal(rpn), forward);
2898 float visibility = 1.0f - ((visMax - cosAngle) * (1.0f / (visMax - visMin)));
2899 alpha *= OOClamp_0_1_f(visibility);
2900
2901 if (alpha > 0.0f)
2902 {
2903 NSUInteger cueColorIndex = [target isWormhole] ? OO_RETICLE_COLOR_WORMHOLE : OO_RETICLE_COLOR_TARGET;
2904 OOColor *directionCueColor = [_reticleColors objectAtIndex:cueColorIndex];
2905 GLfloat clearColorArray[4] = {[directionCueColor redComponent],
2906 [directionCueColor greenComponent],
2907 [directionCueColor blueComponent],
2908 0.0f};
2909 GLfloat directionCueColorArray[4] = {[directionCueColor redComponent],
2910 [directionCueColor greenComponent],
2911 [directionCueColor blueComponent],
2912 [directionCueColor alphaComponent]};
2913 drawPos.z = 0.0f; // flatten vector
2914 drawPos = vector_normal(drawPos);
2915 OOGLBEGIN(GL_LINE_STRIP);
2916 glColor4fv(clearColorArray);
2917 glVertex3f(drawPos.x * innerSize - drawPos.y * width, drawPos.y * innerSize + drawPos.x * width, z1);
2918 GLColorWithOverallAlpha(directionCueColorArray, alpha);
2919 glVertex3f(drawPos.x * outerSize, drawPos.y * outerSize, z1);
2920 glColor4fv(clearColorArray);
2921 glVertex3f(drawPos.x * innerSize + drawPos.y * width, drawPos.y * innerSize - drawPos.x * width, z1);
2922 OOGLEND();
2923 }
2924 }
2925}
2926
2927
2928- (void) drawClock:(NSDictionary *)info
2929{
2930 int x, y;
2931 NSSize siz;
2932 GLfloat itemColor[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
2933 struct CachedInfo cached;
2934
2935 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2936
2937 x = useDefined(cached.x, CLOCK_DISPLAY_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2938 y = useDefined(cached.y, CLOCK_DISPLAY_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2940 siz.height = useDefined(cached.height, CLOCK_DISPLAY_HEIGHT);
2941
2942 GetRGBAArrayFromInfo(info, itemColor);
2943 itemColor[3] *= overallAlpha;
2944
2945 OOGL(glColor4f(itemColor[0], itemColor[1], itemColor[2], itemColor[3]));
2946 OODrawString([PLAYER dial_clock], x, y, z1, siz);
2947}
2948
2949
2950- (void) drawPrimedEquipment:(NSDictionary *)info
2951{
2952 if ([PLAYER status] == STATUS_DOCKED)
2953 {
2954 // Can't activate equipment while docked
2955 return;
2956 }
2957
2958 GLfloat itemColor[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
2959 struct CachedInfo cached;
2960
2961 NSUInteger lines = [info oo_intForKey:@"n_bars" defaultValue:1];
2962 NSInteger pec = (NSInteger)[PLAYER primedEquipmentCount];
2963
2964 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
2965
2966 NSInteger x = useDefined(cached.x, PRIMED_DISPLAY_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
2967 NSInteger y = useDefined(cached.y, PRIMED_DISPLAY_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
2968
2969 NSSize size =
2970 {
2972 .height = useDefined(cached.height, PRIMED_DISPLAY_HEIGHT)
2973 };
2974
2975 if (pec == 0)
2976 {
2977 // Don't display if no primed equipment fitted
2978 return;
2979 }
2980
2981 GetRGBAArrayFromInfo(info, itemColor);
2982 itemColor[3] *= overallAlpha;
2983
2984 if (lines == 1)
2985 {
2986 OOGL(glColor4f(itemColor[0], itemColor[1], itemColor[2], itemColor[3]));
2987 NSString *equipmentName = [PLAYER primedEquipmentName:0];
2988 OODrawString(OOExpandKey(@"equipment-primed-hud", equipmentName), x, y, z1, size);
2989 }
2990 else
2991 {
2992 NSInteger negative = (lines - 1) / 2;
2993 NSInteger positive = lines / 2;
2994 for (NSInteger i = -negative; i <= positive; i++)
2995 {
2996 if (i >= -(pec) / 2 && i <= (pec + 1) / 2)
2997 {
2998 // don't display loops if we have more equipment than lines
2999 // instead compact the display towards its centre
3000 GLfloat alphaScale = 1.0/((i<0)?(1.0-i):(1.0+i));
3001 OOGL(glColor4f(itemColor[0], itemColor[1], itemColor[2], itemColor[3]*alphaScale));
3002 OODrawString([PLAYER primedEquipmentName:i], x, y, z1, size);
3003 }
3004 y -= size.height;
3005 }
3006 }
3007}
3008
3009
3010- (void) drawASCTarget:(NSDictionary *)info
3011{
3012 if (!([self checkPlayerInSystemFlight] && [PLAYER status] != STATUS_LAUNCHING)) // normal system
3013 {
3014 // Can't have compass target when docked, etc. (matches blip condition)
3015 return;
3016 }
3017
3018 GLfloat itemColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
3019 struct CachedInfo cached;
3020
3021 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
3022
3023 NSInteger x = useDefined(cached.x, ASCTARGET_DISPLAY_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
3024 NSInteger y = useDefined(cached.y, ASCTARGET_DISPLAY_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
3025
3026 NSSize size =
3027 {
3029 .height = useDefined(cached.height, ASCTARGET_DISPLAY_HEIGHT)
3030 };
3031
3032 GetRGBAArrayFromInfo(info, itemColor);
3033 itemColor[3] *= overallAlpha;
3034
3035 OOGL(glColor4f(itemColor[0], itemColor[1], itemColor[2], itemColor[3]));
3036 if ([info oo_intForKey:@"align"] == 1)
3037 {
3038 OODrawStringAligned([PLAYER compassTargetLabel], x, y, z1, size,YES);
3039 }
3040 else
3041 {
3042 OODrawStringAligned([PLAYER compassTargetLabel], x, y, z1, size,NO);
3043 }
3044
3045}
3046
3047
3048- (void) drawWeaponsOfflineText:(NSDictionary *)info
3049{
3050 OOViewID viewID = [UNIVERSE viewDirection];
3051 GLfloat textColor[4] = {0.0f, 1.0f, 0.0f, 1.0f};
3052
3053 if (viewID == VIEW_CUSTOM ||
3054 overallAlpha == 0.0f ||
3055 !([PLAYER status] == STATUS_IN_FLIGHT || [PLAYER status] == STATUS_WITCHSPACE_COUNTDOWN) ||
3056 [UNIVERSE displayGUI]
3057 )
3058 {
3059 // Don't draw weapons offline text
3060 return;
3061 }
3062
3063 if (![PLAYER weaponsOnline])
3064 {
3065 int x, y;
3066 NSSize siz;
3067 struct CachedInfo cached;
3068
3069 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
3070
3071 x = useDefined(cached.x, WEAPONSOFFLINETEXT_DISPLAY_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
3072 y = useDefined(cached.y, WEAPONSOFFLINETEXT_DISPLAY_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
3074 siz.height = useDefined(cached.height, WEAPONSOFFLINETEXT_HEIGHT);
3075
3076 GetRGBAArrayFromInfo(info, textColor);
3077 textColor[3] *= overallAlpha;
3078
3079 OOGL(glColor4f(textColor[0], textColor[1], textColor[2], textColor[3]));
3080 // TODO: some caching required...
3081 OODrawString(DESC(@"weapons-systems-offline"), x, y, z1, siz);
3082 }
3083}
3084
3085
3086- (void) drawFPSInfoCounter:(NSDictionary *)info
3087{
3088 if (![UNIVERSE displayFPS]) return;
3089
3090 int x, y;
3091 NSSize siz;
3092 struct CachedInfo cached;
3093 GLfloat textColor[4] = {0.0, 1.0, 0.0, 1.0};
3094
3095 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
3096
3097 x = useDefined(cached.x, FPSINFO_DISPLAY_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
3098 y = useDefined(cached.y, FPSINFO_DISPLAY_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
3100 siz.height = useDefined(cached.height, FPSINFO_DISPLAY_HEIGHT);
3101
3102 HPVector playerPos = [PLAYER position];
3103 NSString *positionInfo = [UNIVERSE expressPosition:playerPos inCoordinateSystem:@"pwm"];
3104 positionInfo = [NSString stringWithFormat:@"abs %.2f %.2f %.2f / %@", playerPos.x, playerPos.y, playerPos.z, positionInfo];
3105
3106 // We would normally set a variable alpha value here, but in this case we don't.
3107 // We prefer the FPS counter to be always visible - Nikos 20100405
3108 GetRGBAArrayFromInfo(info, textColor);
3109 OOGL(glColor4f(textColor[0], textColor[1], textColor[2], 1.0f));
3110 OODrawString([PLAYER dial_fpsinfo], x, y, z1, siz);
3111
3112#ifndef NDEBUG
3113 NSSize siz08 = NSMakeSize(0.8 * siz.width, 0.8 * siz.width);
3114 NSString *collDebugInfo = [NSString stringWithFormat:@"%@ - %@", [PLAYER dial_objinfo], [UNIVERSE collisionDescription]];
3115 OODrawString(collDebugInfo, x, y - siz.height, z1, siz);
3116
3117 OODrawString(positionInfo, x, y - 1.8 * siz.height, z1, siz08);
3118
3119 NSString *timeAccelerationFactorInfo = [NSString stringWithFormat:@"TAF: %@%.2f", DESC(@"multiplication-sign"), [UNIVERSE timeAccelerationFactor]];
3120 OODrawString(timeAccelerationFactorInfo, x, y - 3.2 * siz08.height, z1, siz08);
3121#endif
3122}
3123
3124
3125- (void) drawScoopStatus:(NSDictionary *)info
3126{
3127 int i, x, y;
3128 NSSize siz;
3129 GLfloat alpha;
3130 struct CachedInfo cached;
3131
3132 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
3133
3134 x = useDefined(cached.x, SCOOPSTATUS_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
3135 y = useDefined(cached.y, SCOOPSTATUS_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
3136 siz.width = useDefined(cached.width, SCOOPSTATUS_WIDTH);
3137 siz.height = useDefined(cached.height, SCOOPSTATUS_HEIGHT);
3138 // default alpha value different from all others, won't use cached.alpha
3139 alpha = [info oo_nonNegativeFloatForKey:ALPHA_KEY defaultValue:0.75f];
3140
3141 const GLfloat* s0_color = red_color;
3142 GLfloat s1c[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3143 GLfloat s2c[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3144 GLfloat s3c[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
3145 int scoop_status = [PLAYER dialFuelScoopStatus];
3146 GLfloat t = [UNIVERSE getTime];
3147 GLfloat a1 = alpha * 0.5f * (1.0f + sin(t * 8.0f));
3148 GLfloat a2 = alpha * 0.5f * (1.0f + sin(t * 8.0f - 1.0f));
3149 GLfloat a3 = alpha * 0.5f * (1.0f + sin(t * 8.0f - 2.0f));
3150
3151 switch (scoop_status)
3152 {
3154 return; // don't draw
3155
3157 s0_color = darkgreen_color;
3158 alpha *= 0.75;
3159 break;
3160
3162 case SCOOP_STATUS_OKAY:
3163 s0_color = green_color;
3164 break;
3165 }
3166
3167 for (i = 0; i < 3; i++)
3168 {
3169 s1c[i] = s0_color[i];
3170 s2c[i] = s0_color[i];
3171 s3c[i] = s0_color[i];
3172 }
3173 if (scoop_status == SCOOP_STATUS_FULL_HOLD)
3174 {
3175 s3c[0] = red_color[0];
3176 s3c[1] = red_color[1];
3177 s3c[2] = red_color[2];
3178 }
3179 if (scoop_status == SCOOP_STATUS_ACTIVE)
3180 {
3181 s1c[3] = alpha * a1;
3182 s2c[3] = alpha * a2;
3183 s3c[3] = alpha * a3;
3184 }
3185 else
3186 {
3187 s1c[3] = alpha;
3188 s2c[3] = alpha;
3189 s3c[3] = alpha;
3190 }
3191
3192 GLfloat w1 = siz.width / 8.0;
3193 GLfloat w2 = 2.0 * w1;
3194// GLfloat w3 = 3.0 * w1;
3195 GLfloat w4 = 4.0 * w1;
3196 GLfloat h1 = siz.height / 8.0;
3197 GLfloat h2 = 2.0 * h1;
3198 GLfloat h3 = 3.0 * h1;
3199 GLfloat h4 = 4.0 * h1;
3200
3201 OOGL(glDisable(GL_TEXTURE_2D));
3202 OOGLBEGIN(GL_QUADS);
3203 // section 1
3204 GLColorWithOverallAlpha(s1c, overallAlpha);
3205 glVertex3f(x, y + h1, z1); glVertex3f(x - w2, y + h2, z1); glVertex3f(x, y + h3, z1); glVertex3f(x + w2, y + h2, z1);
3206 // section 2
3207 GLColorWithOverallAlpha(s2c, overallAlpha);
3208 glVertex3f(x, y - h1, z1); glVertex3f(x - w4, y + h1, z1); glVertex3f(x - w4, y + h2, z1); glVertex3f(x, y, z1);
3209 glVertex3f(x, y - h1, z1); glVertex3f(x + w4, y + h1, z1); glVertex3f(x + w4, y + h2, z1); glVertex3f(x, y, z1);
3210 // section 3
3211 GLColorWithOverallAlpha(s3c, overallAlpha);
3212 glVertex3f(x, y - h4, z1); glVertex3f(x - w2, y - h2, z1); glVertex3f(x - w2, y - h1, z1); glVertex3f(x, y - h2, z1);
3213 glVertex3f(x, y - h4, z1); glVertex3f(x + w2, y - h2, z1); glVertex3f(x + w2, y - h1, z1); glVertex3f(x, y - h2, z1);
3214 OOGLEND();
3215}
3216
3217
3218- (void) drawStickSensitivityIndicator:(NSDictionary *)info
3219{
3220 GLfloat x, y;
3221 NSSize siz;
3222 GLfloat alpha = overallAlpha;
3223 BOOL mouse = [PLAYER isMouseControlOn];
3225 struct CachedInfo cached;
3226
3227 if (![stickHandler joystickCount])
3228 {
3229 return; // no need to draw if no joystick fitted
3230 }
3231
3232 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
3233
3234 x = useDefined(cached.x, STATUS_LIGHT_CENTRE_X) + [[UNIVERSE gameView] x_offset] * cached.x0;
3235 y = useDefined(cached.y, STATUS_LIGHT_CENTRE_Y) + [[UNIVERSE gameView] y_offset] * cached.y0;
3237 siz.height = useDefined(cached.height, STATUS_LIGHT_HEIGHT);
3238 alpha *= cached.alpha;
3239
3240 GLfloat div = [stickHandler getSensitivity];
3241
3242 GLColorWithOverallAlpha(black_color, alpha / 4);
3243 GLDrawFilledOval(x, y, z1, siz, 10);
3244
3245 GLColorWithOverallAlpha((div < 1.0 || mouse) ? lightgray_color : green_color, alpha);
3246 OOGL(GLScaledLineWidth(_crosshairWidth * lineWidth));
3247
3248 if (div >= 1.0)
3249 {
3250 if (!mouse)
3251 {
3252 NSSize siz8th = { siz.width / 8, siz.height / 8 };
3253 GLDrawFilledOval(x, y, z1, siz8th, 30);
3254
3255 if (div == 1.0) // normal mode
3256 GLColorWithOverallAlpha(lightgray_color, alpha);
3257 }
3258
3259 siz.width -= _crosshairWidth * lineWidth / 2;
3260 siz.height -= _crosshairWidth * lineWidth / 2;
3261 GLDrawOval(x, y, z1, siz, 10);
3262 }
3263 else if (div < 1.0) // insensitive mode (shouldn't happen)
3264 GLDrawFilledOval(x, y, z1, siz, 10);
3265
3266 OOGL(GLScaledLineWidth(lineWidth)); // reset
3267}
3268
3269
3270- (void) drawSurroundInternal:(NSDictionary *)info color:(const GLfloat[4])color
3271{
3272 NSInteger x, y;
3273 NSSize siz;
3274 GLfloat alpha = overallAlpha;
3275 struct CachedInfo cached;
3276
3277 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
3278
3279 if (cached.x == NOT_DEFINED || cached.y == NOT_DEFINED || cached.width == NOT_DEFINED || cached.height == NOT_DEFINED)
3280 {
3281 return;
3282 }
3283
3284 x = cached.x + [[UNIVERSE gameView] x_offset] * cached.x0;
3285 y = cached.y + [[UNIVERSE gameView] y_offset] * cached.y0;
3287 siz.height = useDefined(cached.height, WEAPONSOFFLINETEXT_HEIGHT);
3288 alpha *= cached.alpha;
3289
3290 // draw the surround
3291 GLColorWithOverallAlpha(color, alpha);
3292 hudDrawSurroundAt(x, y, z1, siz);
3293}
3294
3295
3296- (void) drawSurround:(NSDictionary *)info
3297{
3298 GLfloat itemColor[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
3299 id colorDesc = [info objectForKey:COLOR_KEY];
3300 if (colorDesc != nil)
3301 {
3302 OOColor *color = [OOColor colorWithDescription:colorDesc];
3303 if (color != nil)
3304 {
3305 itemColor[0] = [color redComponent];
3306 itemColor[1] = [color greenComponent];
3307 itemColor[2] = [color blueComponent];
3308 }
3309 }
3310
3311 [self drawSurroundInternal:info color:itemColor];
3312}
3313
3314
3315- (void) drawGreenSurround:(NSDictionary *)info
3316{
3317 [self drawSurroundInternal:info color:green_color];
3318}
3319
3320
3321- (void) drawYellowSurround:(NSDictionary *)info
3322{
3323 [self drawSurroundInternal:info color:yellow_color];
3324}
3325
3326
3327- (void) drawTrumbles:(NSDictionary *)info
3328{
3329 OOTrumble** trumbles = [PLAYER trumbleArray];
3330 NSUInteger i;
3331 for (i = [PLAYER trumbleCount]; i > 0; i--)
3332 {
3333 OOTrumble* trum = trumbles[i - 1];
3334 [trum drawTrumble: z1];
3335 }
3336}
3337
3338
3339- (void) drawMultiFunctionDisplay:(NSDictionary *)info withText:(NSString *)text asIndex:(NSUInteger)index
3340{
3341 PlayerEntity *player1 = PLAYER;
3342 struct CachedInfo cached;
3343 NSInteger i, x, y;
3344 NSSize siz, tmpsiz;
3345 if ([player1 guiScreen] != GUI_SCREEN_MAIN) // don't draw on text screens
3346 {
3347 return;
3348 }
3349 GLfloat alpha = [info oo_nonNegativeFloatForKey:ALPHA_KEY defaultValue:1.0f] * overallAlpha;
3350
3351 GLfloat mfd_color[4] = {0.0, 1.0, 0.0, 0.9*alpha};
3352 OOColor *mfdcol = [OOColor colorWithDescription:[info objectForKey:COLOR_KEY]];
3353 if (mfdcol != nil)
3354 {
3355 [mfdcol getRed:&mfd_color[0] green:&mfd_color[1] blue:&mfd_color[2] alpha:&mfd_color[3]];
3356 }
3357 if (index != [player1 activeMFD])
3358 {
3359 mfd_color[3] *= 0.75;
3360 }
3361 [self drawSurroundInternal:info color:mfd_color];
3362
3363 [(NSValue *)[sCurrentDrawItem objectAtIndex:WIDGET_CACHE] getValue:&cached];
3364 x = cached.x + [[UNIVERSE gameView] x_offset] * cached.x0;
3365 y = cached.y + [[UNIVERSE gameView] y_offset] * cached.y0;
3366
3367 siz.width = useDefined(cached.width / 15, MFD_TEXT_WIDTH);
3368 siz.height = useDefined(cached.height / 10, MFD_TEXT_HEIGHT);
3369
3370 GLfloat x0 = (GLfloat)(x - cached.width/2);
3371 GLfloat y0 = (GLfloat)(y + cached.height/2);
3372 GLfloat x1 = (GLfloat)(x + cached.width/2);
3373 GLfloat y1 = (GLfloat)(y - cached.height/2);
3374 GLColorWithOverallAlpha(mfd_color, alpha*0.3);
3375 OOGLBEGIN(GL_QUADS);
3376 glVertex3f(x0-2,y0+2,z1);
3377 glVertex3f(x0-2,y1-2,z1);
3378 glVertex3f(x1+2,y1-2,z1);
3379 glVertex3f(x1+2,y0+2,z1);
3380 OOGLEND();
3381
3382 NSString *line = nil;
3383 NSArray *lines = [text componentsSeparatedByString:@"\n"];
3384 // text at full opacity
3385 GLColorWithOverallAlpha(mfd_color, alpha);
3386 for (i = 0; i < 10 ; i++)
3387 {
3388 line = [lines oo_stringAtIndex:i defaultValue:nil];
3389 if (line != nil)
3390 {
3391 y0 -= siz.height;
3392 // all lines should be shorter than the size of the MFD
3393 GLfloat textwidth = OORectFromString(line, 0.0f, 0.0f, siz).size.width;
3394 if (textwidth <= cached.width)
3395 {
3396 OODrawString(line, x0, y0, z1, siz);
3397 }
3398 else
3399 {
3400 // compress it so it fits
3401 tmpsiz.height = siz.height;
3402 tmpsiz.width = siz.width * cached.width / textwidth;
3403 OODrawString(line, x0, y0, z1, tmpsiz);
3404 }
3405 }
3406 else
3407 {
3408 break;
3409 }
3410 }
3411}
3412
3413//---------------------------------------------------------------------//
3414
3415static void hudDrawIndicatorAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
3416{
3417 if (siz.width > siz.height)
3418 {
3419 GLfloat dial_oy = y - siz.height/2;
3420 GLfloat position = x + amount * siz.width / 2;
3421 OOGLBEGIN(GL_QUADS);
3422 glVertex3f(position, dial_oy, z);
3423 glVertex3f(position+2, y, z);
3424 glVertex3f(position, dial_oy+siz.height, z);
3425 glVertex3f(position-2, y, z);
3426 OOGLEND();
3427 }
3428 else
3429 {
3430 GLfloat dial_ox = x - siz.width/2;
3431 GLfloat position = y + amount * siz.height / 2;
3432 OOGLBEGIN(GL_QUADS);
3433 glVertex3f(dial_ox, position, z);
3434 glVertex3f(x, position+2, z);
3435 glVertex3f(dial_ox + siz.width, position, z);
3436 glVertex3f(x, position-2, z);
3437 OOGLEND();
3438 }
3439}
3440
3441
3442static void hudDrawMarkerAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
3443{
3444 if (siz.width > siz.height)
3445 {
3446 GLfloat dial_oy = y - siz.height/2;
3447 GLfloat position = x + amount * siz.width - siz.width/2;
3448 OOGLBEGIN(GL_QUADS);
3449 glVertex3f(position+1, dial_oy+1, z);
3450 glVertex3f(position+1, dial_oy+siz.height-1, z);
3451 glVertex3f(position-1, dial_oy+siz.height-1, z);
3452 glVertex3f(position-1, dial_oy+1, z);
3453 OOGLEND();
3454 }
3455 else
3456 {
3457 GLfloat dial_ox = x - siz.width/2;
3458 GLfloat position = y + amount * siz.height - siz.height/2;
3459 OOGLBEGIN(GL_QUADS);
3460 glVertex3f(dial_ox+1, position+1, z);
3461 glVertex3f(dial_ox + siz.width-1, position+1, z);
3462 glVertex3f(dial_ox + siz.width-1, position-1, z);
3463 glVertex3f(dial_ox+1, position-1, z);
3464 OOGLEND();
3465 }
3466}
3467
3468
3469static void hudDrawBarAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
3470{
3471 GLfloat dial_ox = x - siz.width/2;
3472 GLfloat dial_oy = y - siz.height/2;
3473 if (fabs(siz.width) > fabs(siz.height))
3474 {
3475 GLfloat position = dial_ox + amount * siz.width;
3476
3477 OOGLBEGIN(GL_QUADS);
3478 glVertex3f(dial_ox, dial_oy, z);
3479 glVertex3f(position, dial_oy, z);
3480 glVertex3f(position, dial_oy+siz.height, z);
3481 glVertex3f(dial_ox, dial_oy+siz.height, z);
3482 OOGLEND();
3483 }
3484 else
3485 {
3486 GLfloat position = dial_oy + amount * siz.height;
3487
3488 OOGLBEGIN(GL_QUADS);
3489 glVertex3f(dial_ox, dial_oy, z);
3490 glVertex3f(dial_ox, position, z);
3491 glVertex3f(dial_ox+siz.width, position, z);
3492 glVertex3f(dial_ox+siz.width, dial_oy, z);
3493 OOGLEND();
3494 }
3495}
3496
3497
3498static void hudDrawSurroundAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz)
3499{
3500 GLfloat dial_ox = x - siz.width/2;
3501 GLfloat dial_oy = y - siz.height/2;
3502
3503 OOGLBEGIN(GL_LINE_LOOP);
3504 glVertex3f(dial_ox-2, dial_oy-2, z);
3505 glVertex3f(dial_ox+siz.width+2, dial_oy-2, z);
3506 glVertex3f(dial_ox+siz.width+2, dial_oy+siz.height+2, z);
3507 glVertex3f(dial_ox-2, dial_oy+siz.height+2, z);
3508 OOGLEND();
3509}
3510
3511
3512static void hudDrawStatusIconAt(int x, int y, int z, NSSize siz)
3513{
3514 int ox = x - siz.width / 2.0;
3515 int oy = y - siz.height / 2.0;
3516 int w = siz.width / 4.0;
3517 int h = siz.height / 4.0;
3518
3519 glVertex3i(ox, oy + h, z);
3520 glVertex3i(ox, oy + 3 * h, z);
3521 glVertex3i(ox + w, oy + 4 * h, z);
3522 glVertex3i(ox + 3 * w, oy + 4 * h, z);
3523 glVertex3i(ox + 4 * w, oy + 3 * h, z);
3524 glVertex3i(ox + 4 * w, oy + h, z);
3525 glVertex3i(ox + 3 * w, oy, z);
3526 glVertex3i(ox + w, oy, z);
3527}
3528
3529
3530static void hudDrawReticleOnTarget(Entity *target, PlayerEntity *player1, GLfloat z1,
3531 GLfloat alpha, BOOL reticleTargetSensitive, NSMutableDictionary *propertiesReticleTargetSensitive,
3532 BOOL colourFromScannerColour, BOOL showText, NSDictionary *info, NSMutableArray *reticleColors)
3533{
3534 if (target == nil || player1 == nil)
3535 {
3536 return;
3537 }
3538 if ([player1 guiScreen] != GUI_SCREEN_MAIN) // don't draw on text screens
3539 {
3540 return;
3541 }
3542
3543 ShipEntity *target_ship = nil;
3544 NSString *legal_desc = nil;
3545
3546 GLfloat scale = [info oo_floatForKey:@"reticle_scale" defaultValue:ONE_SIXTYFOURTH];
3547
3548
3549 if ([target isShip])
3550 {
3551 target_ship = (ShipEntity *)target;
3552 legal_desc = [target_ship scanDescription];
3553 }
3554
3555 if ([target_ship isCloaked]) return;
3556
3557
3558 Vector p1;
3559
3560 // by definition close enough that single precision is fine
3561 p1 = HPVectorToVector(HPvector_subtract([target position], [player1 viewpointPosition]));
3562
3563 GLfloat rdist = magnitude(p1);
3564 GLfloat rsize = [target collisionRadius] / (2 * [[UNIVERSE gameView] fov:YES]); // FIXME integrate 2 into fov to remove magic number
3565
3566 if (rsize < rdist * scale)
3567 rsize = rdist * scale;
3568
3569 GLfloat rs0 = rsize;
3570 GLfloat rs2 = rsize * 0.50;
3571
3574
3575 // draw the reticle
3576 float range = sqrt(target->zero_distance) - target->collision_radius;
3577
3578 int flash = (int)([UNIVERSE getTime] * 4);
3579 flash &= 1;
3580
3581 // Draw reticle cyan for Wormholes
3582 if ([target isWormhole])
3583 {
3584 OOColor *wormholeReticleColor = [reticleColors objectAtIndex:OO_RETICLE_COLOR_WORMHOLE];
3585 GLfloat wormholeReticleColorArray[4] = {[wormholeReticleColor redComponent],
3586 [wormholeReticleColor greenComponent],
3587 [wormholeReticleColor blueComponent],
3588 [wormholeReticleColor alphaComponent]};
3589 GLColorWithOverallAlpha(wormholeReticleColorArray, alpha);
3590 }
3591 else
3592 {
3593 // Reticle sensitivity accuracy calculation
3594 BOOL isTargeted = NO;
3595 GLfloat probabilityAccuracy;
3596
3597 if (propertiesReticleTargetSensitive != nil)
3598 {
3599 // Only if target is within player's weapon range, we mind for reticle accuracy
3600 if (range < [player1 weaponRange])
3601 {
3602 // After MAX_ACCURACY_RANGE km start decreasing high accuracy probability by ACCURACY_PROBABILITY_DECREASE_FACTOR%
3603 if (range > MAX_ACCURACY_RANGE)
3604 {
3605 // Every one second re-evaluate accuracy
3606 if ([UNIVERSE getTime] > [propertiesReticleTargetSensitive oo_doubleForKey:@"timeLastAccuracyProbabilityCalculation"] + 1)
3607 {
3608 probabilityAccuracy = 1-(range-MAX_ACCURACY_RANGE)*ACCURACY_PROBABILITY_DECREASE_FACTOR;
3609 // Make sure probability does not go below a minimum
3610 probabilityAccuracy = probabilityAccuracy < MIN_PROBABILITY_ACCURACY ? MIN_PROBABILITY_ACCURACY : probabilityAccuracy;
3611 [propertiesReticleTargetSensitive setObject:[NSNumber numberWithBool:((randf() < probabilityAccuracy) ? YES : NO)] forKey:@"isAccurate"];
3612
3613 // Store the time the last accuracy probability has been performed
3614 [propertiesReticleTargetSensitive setObject:[NSNumber numberWithDouble:[UNIVERSE getTime]] forKey:@"timeLastAccuracyProbabilityCalculation"];
3615 }
3616 if ([propertiesReticleTargetSensitive oo_boolForKey:@"isAccurate"])
3617 {
3618 // high accuracy reticle
3619 isTargeted = ([UNIVERSE firstEntityTargetedByPlayerPrecisely] == target);
3620 }
3621 else
3622 {
3623 // low accuracy reticle
3624 isTargeted = ([UNIVERSE firstEntityTargetedByPlayer] == target);
3625 }
3626 }
3627 else
3628 {
3629 // high accuracy reticle
3630 isTargeted = ([UNIVERSE firstEntityTargetedByPlayerPrecisely] == target);
3631 }
3632 }
3633 }
3634
3635 // If reticle is target sensitive, draw target box in red
3636 // when target passes through laser hit-point(with decreasing accuracy)
3637 // and is within hit-range.
3638 //
3639 // NOTE: The following condition also considers (indirectly) the player's weapon range.
3640 // 'isTargeted' is initialised to FALSE. Only if target is within the player's weapon range,
3641 // it might change value. Therefore, it is not necessary to add '&& range < [player1 weaponRange]'
3642 // to the following condition.
3643 if (colourFromScannerColour)
3644 {
3645 if ([target isShip])
3646 {
3647 ShipEntity *ship = (ShipEntity *)target;
3648 BOOL isHostile = (([ship hasHostileTarget])&&([ship primaryTarget] == PLAYER));
3649 GLColorWithOverallAlpha([ship scannerDisplayColorForShip:PLAYER :isHostile :flash :[ship scannerDisplayColor1] :[ship scannerDisplayColor2] :[ship scannerDisplayColorHostile1] :[ship scannerDisplayColorHostile2]],alpha);
3650 }
3651 else if ([target isVisualEffect])
3652 {
3654 GLColorWithOverallAlpha([vis scannerDisplayColorForShip:flash :[vis scannerDisplayColor1] :[vis scannerDisplayColor2]],alpha);
3655 }
3656 else
3657 {
3658 GLColorWithOverallAlpha(green_color, alpha);
3659 }
3660 }
3661 else
3662 {
3663 OOColor *reticleDisplayColor = nil;
3664 if (reticleTargetSensitive && isTargeted)
3665 {
3666 reticleDisplayColor = [reticleColors objectAtIndex:OO_RETICLE_COLOR_TARGET_SENSITIVE];
3667 if (!reticleDisplayColor) reticleDisplayColor = [OOColor redColor];
3668 }
3669 else
3670 {
3671 reticleDisplayColor = [reticleColors objectAtIndex:OO_RETICLE_COLOR_TARGET];
3672 if (!reticleDisplayColor) reticleDisplayColor = [OOColor greenColor];
3673 }
3674 GLfloat reticleDisplayColorArray[4] = { [reticleDisplayColor redComponent],
3675 [reticleDisplayColor greenComponent],
3676 [reticleDisplayColor blueComponent],
3677 [reticleDisplayColor alphaComponent] };
3678 GLColorWithOverallAlpha(reticleDisplayColorArray, alpha);
3679 }
3680 }
3681 OOGLBEGIN(GL_LINES);
3682 glVertex2f(rs0,rs2); glVertex2f(rs0,rs0);
3683 glVertex2f(rs0,rs0); glVertex2f(rs2,rs0);
3684
3685 glVertex2f(rs0,-rs2); glVertex2f(rs0,-rs0);
3686 glVertex2f(rs0,-rs0); glVertex2f(rs2,-rs0);
3687
3688 glVertex2f(-rs0,rs2); glVertex2f(-rs0,rs0);
3689 glVertex2f(-rs0,rs0); glVertex2f(-rs2,rs0);
3690
3691 glVertex2f(-rs0,-rs2); glVertex2f(-rs0,-rs0);
3692 glVertex2f(-rs0,-rs0); glVertex2f(-rs2,-rs0);
3693 OOGLEND();
3694
3695 if (showText)
3696 {
3697 // add text for reticle here
3698 range *= 0.001f;
3699 if (range < 0.001f) range = 0.0f; // avoids the occasional -0.001 km distance.
3700 NSSize textsize = NSMakeSize(rdist * scale, rdist * scale);
3701 float line_height = rdist * scale;
3702 NSString* infoline = [NSString stringWithFormat:@"%0.3f km", range];
3703 if (legal_desc != nil) infoline = [NSString stringWithFormat:@"%@ (%@)", infoline, legal_desc];
3704 // no need to set colour here
3705 OODrawString([player1 dialTargetName], rs0, 0.5 * rs2, 0, textsize);
3706 OODrawString(infoline, rs0, 0.5 * rs2 - line_height, 0, textsize);
3707
3708 if ([target isWormhole])
3709 {
3710 // Note: No break statements in the following switch() since every case
3711 // falls through to the next. Cases arranged in reverse order.
3712 switch([(WormholeEntity *)target scanInfo])
3713 {
3714 case WH_SCANINFO_SHIP:
3715 // TOOD: Render anything on the HUD for this?
3717 // Rendered above in dialTargetName, so no need to do anything here
3718 // unless we want a separate line Destination: XXX ?
3720 {
3721 NSString *wormholeETA = [NSString stringWithFormat:DESC(@"wormhole-ETA-@"), ClockToString([(WormholeEntity *)target estimatedArrivalTime], NO)];
3722 OODrawString(wormholeETA, rs0, 0.5 * rs2 - 3 * line_height, 0, textsize);
3723 }
3725 {
3726 OOTimeDelta timeForCollapsing = [(WormholeEntity *)target expiryTime] - [player1 clockTimeAdjusted];
3727 int minutesToCollapse = floor (timeForCollapsing / 60.0);
3728 int secondsToCollapse = (int)timeForCollapsing % 60;
3729
3730 NSString *wormholeExpiringIn = [NSString stringWithFormat:DESC(@"wormhole-collapsing-in-mm:ss"), minutesToCollapse, secondsToCollapse];
3731 OODrawString(wormholeExpiringIn, rs0, 0.5 * rs2 - 2 * line_height, 0, textsize);
3732 }
3734 case WH_SCANINFO_NONE:
3735 break;
3736 }
3737 }
3738 }
3739
3741}
3742
3743
3744static void hudDrawWaypoint(OOWaypointEntity *waypoint, PlayerEntity *player1, GLfloat z1, GLfloat alpha, BOOL selected, GLfloat scale)
3745{
3746 if ([player1 guiScreen] != GUI_SCREEN_MAIN) // don't draw on text screens
3747 {
3748 return;
3749 }
3750
3751
3752 Vector p1 = HPVectorToVector(HPvector_subtract([waypoint position], [player1 viewpointPosition]));
3753
3756
3757 // either close enough that single precision is fine or far enough
3758 // away that precision is irrelevant
3759
3760 GLfloat rdist = magnitude(p1);
3761 GLfloat rsize = rdist * scale;
3762
3763 GLfloat rs0 = rsize;
3764 GLfloat rs2 = rsize * 0.50;
3765
3766 if (selected)
3767 {
3768 GLColorWithOverallAlpha(blue_color, alpha);
3769 }
3770 else
3771 {
3772 GLColorWithOverallAlpha(blue_color, alpha*0.25);
3773 }
3774
3775 OOGLBEGIN(GL_LINES);
3776 glVertex2f(rs0,rs2); glVertex2f(rs2,rs2);
3777 glVertex2f(rs2,rs0); glVertex2f(rs2,rs2);
3778
3779 glVertex2f(-rs0,rs2); glVertex2f(-rs2,rs2);
3780 glVertex2f(-rs2,rs0); glVertex2f(-rs2,rs2);
3781
3782 glVertex2f(-rs0,-rs2); glVertex2f(-rs2,-rs2);
3783 glVertex2f(-rs2,-rs0); glVertex2f(-rs2,-rs2);
3784
3785 glVertex2f(rs0,-rs2); glVertex2f(rs2,-rs2);
3786 glVertex2f(rs2,-rs0); glVertex2f(rs2,-rs2);
3787
3788// glVertex2f(0,-rs2); glVertex2f(0,rs2);
3789// glVertex2f(rs2,0); glVertex2f(-rs2,0);
3790 OOGLEND();
3791
3792 if (selected)
3793 {
3794 GLfloat range = HPdistance([player1 position],[waypoint position]) * 0.001f;
3795 if (range < 0.001f) range = 0.0f; // avoids the occasional -0.001 km distance.
3796 NSSize textsize = NSMakeSize(rdist * scale, rdist * scale);
3797 float line_height = rdist * scale;
3798 NSString* infoline = [NSString stringWithFormat:@"%0.3f km", range];
3799 OODrawString(infoline, rs0 * 0.5, -rs2 - line_height, 0, textsize);
3800 }
3801
3803}
3804
3805static void hudRotateViewpointForVirtualDepth(PlayerEntity * player1, Vector p1)
3806{
3807 Quaternion back_q = [player1 orientation];
3808 back_q.w = -back_q.w; // invert
3809 Vector v1 = vector_up_from_quaternion(back_q);
3810 NSSize viewSize = [[UNIVERSE gameView] viewSize];
3811 float aspect = viewSize.width / viewSize.height;
3812
3813 // The field of view transformation is really a scale operation on the view window.
3814 // We must unapply it through these transformations for them to be right.
3815 // We must also take into account the window aspect ratio.
3816 float ratio = 2 * [[UNIVERSE gameView] fov:YES]; // FIXME 2 is magic number; fov should integrate it
3817 if (3.0f * aspect >= 4.0f)
3818 {
3819 OOGLScaleModelView(make_vector(1/ratio, 1/ratio, 1.0f));
3820 }
3821 else
3822 {
3823 OOGLScaleModelView(make_vector((4.0f/3.0f)/(aspect*ratio), (4.0f/3.0f)/(aspect*ratio), 1.0f));
3824 }
3825
3826 // deal with view directions
3827 Vector view_dir, view_up = kBasisYVector;
3828 switch ([UNIVERSE viewDirection])
3829 {
3830 default:
3831 case VIEW_FORWARD:
3832 view_dir.x = 0.0; view_dir.y = 0.0; view_dir.z = 1.0;
3833 break;
3834
3835 case VIEW_AFT:
3836 view_dir.x = 0.0; view_dir.y = 0.0; view_dir.z = -1.0;
3837 quaternion_rotate_about_axis(&back_q, v1, M_PI);
3838 break;
3839
3840 case VIEW_PORT:
3841 view_dir.x = -1.0; view_dir.y = 0.0; view_dir.z = 0.0;
3842 quaternion_rotate_about_axis(&back_q, v1, 0.5 * M_PI);
3843 break;
3844
3845 case VIEW_STARBOARD:
3846 view_dir.x = 1.0; view_dir.y = 0.0; view_dir.z = 0.0;
3847 quaternion_rotate_about_axis(&back_q, v1, -0.5 * M_PI);
3848 break;
3849
3850 case VIEW_CUSTOM:
3851 view_dir = [player1 customViewForwardVector];
3852 view_up = [player1 customViewUpVector];
3853 back_q = quaternion_multiply([player1 customViewQuaternion], back_q);
3854 break;
3855 }
3856 OOGLLookAt(view_dir, kZeroVector, view_up);
3857
3858 // rotate the view
3859 OOGLMultModelView([player1 rotationMatrix]);
3860 // translate the view
3862 // rotate to face player1
3864
3865 // We come back now to the previous scale.
3866 OOGLScaleModelView(make_vector(ratio, ratio, 1.0f));
3867 // draw the waypoint
3868}
3869
3870
3871static void InitTextEngine(void)
3872{
3873 NSDictionary *fontSpec = nil;
3874 NSArray *widths = nil;
3875 NSString *texName = nil;
3876 NSUInteger i, count;
3877
3878 fontSpec = [ResourceManager dictionaryFromFilesNamed:@"oolite-font.plist"
3879 inFolder:@"Config"
3880 andMerge:NO];
3881
3882 texName = [fontSpec oo_stringForKey:@"texture" defaultValue:@"oolite-font.png"];
3884 inFolder:@"Textures"
3885 options:kFontTextureOptions
3886 anisotropy:0.0f
3887 lodBias:-0.75f];
3888 [sFontTexture retain];
3889
3890 sF6KernGovt = [fontSpec oo_floatForKey:@"f6KernGovernment" defaultValue:1.0];
3891 sF6KernTL = [fontSpec oo_floatForKey:@"f6KernTechLevel" defaultValue:2.0];
3892
3893 sEncodingCoverter = [[OOEncodingConverter alloc] initWithFontPList:fontSpec];
3894 widths = [fontSpec oo_arrayForKey:@"widths"];
3895 count = [widths count];
3896 if (count > 256) count = 256;
3897 for (i = 0; i != count; ++i)
3898 {
3899 sGlyphWidths[i] = [widths oo_floatAtIndex:i] * GLYPH_SCALE_FACTOR;
3900 }
3901}
3902
3903
3909
3910
3911static GLfloat drawCharacterQuad(uint8_t chr, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
3912{
3913 // 31 (narrow space) and 32 (space) are non-printing characters, so
3914 // don't print them, just return their width to move the pointer
3915 if (chr > 32 || chr < 31) {
3916 GLfloat texture_x = ONE_SIXTEENTH * (chr & 0x0f);
3917 GLfloat texture_y = ONE_SIXTEENTH * (chr >> 4);
3918 if (chr > 32) y += ONE_EIGHTH * siz.height; // Adjust for baseline offset change in 1.71 (needed to keep accented characters in box)
3919
3920 glTexCoord2f(texture_x, texture_y + ONE_SIXTEENTH);
3921 glVertex3f(x, y, z);
3922 glTexCoord2f(texture_x + ONE_SIXTEENTH, texture_y + ONE_SIXTEENTH);
3923 glVertex3f(x + siz.width, y, z);
3924 glTexCoord2f(texture_x + ONE_SIXTEENTH, texture_y);
3925 glVertex3f(x + siz.width, y + siz.height, z);
3926 glTexCoord2f(texture_x, texture_y);
3927 glVertex3f(x, y + siz.height, z);
3928 }
3929 return siz.width * sGlyphWidths[chr];
3930}
3931
3932
3933NSRect OORectFromString(NSString *text, GLfloat x, GLfloat y, NSSize siz)
3934{
3935 GLfloat w = 0;
3936 NSData *data = nil;
3937 const uint8_t *bytes = NULL;
3938 NSUInteger i, length;
3939
3940 data = [sEncodingCoverter convertString:text];
3941 bytes = [data bytes];
3942 length = [data length];
3943
3944 for (i = 0; i < length; i++)
3945 {
3946 w += siz.width * sGlyphWidths[bytes[i]];
3947 }
3948
3949 return NSMakeRect(x, y, w, siz.height);
3950}
3951
3952
3953CGFloat OOStringWidthInEm(NSString *text)
3954{
3955 return OORectFromString(text, 0, 0, NSMakeSize(1.0 / (GLYPH_SCALE_FACTOR * 8.0), 1.0)).size.width;
3956}
3957
3958
3959void drawHighlight(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat alpha)
3960{
3961 // Rounded corners, fading 'shadow' version
3962 OOGL(glColor4f(0.0f, 0.0f, 0.0f, alpha * 0.4f)); // dark translucent shadow
3963
3964 OOGLBEGIN(GL_POLYGON);
3965 // thin 'halo' around the 'solid' highlight
3966 glVertex3f(x + 1.0f , y + siz.height + 2.5f, z);
3967 glVertex3f(x + siz.width + 3.0f, y + siz.height + 2.5f, z);
3968 glVertex3f(x + siz.width + 4.5f, y + siz.height + 1.0f, z);
3969 glVertex3f(x + siz.width + 4.5f, y + 3.0f, z);
3970 glVertex3f(x + siz.width + 3.0f, y + 1.5f, z);
3971 glVertex3f(x + 1.0f, y + 1.5f, z);
3972 glVertex3f(x - 0.5f, y + 3.0f, z);
3973 glVertex3f(x - 0.5f, y + siz.height + 1.0f, z);
3974 OOGLEND();
3975
3976
3977 OOGLBEGIN(GL_POLYGON);
3978 glVertex3f(x + 1.0f, y + siz.height + 2.0f, z);
3979 glVertex3f(x + siz.width + 3.0f, y + siz.height + 2.0f, z);
3980 glVertex3f(x + siz.width + 4.0f, y + siz.height + 1.0f, z);
3981 glVertex3f(x + siz.width + 4.0f, y + 3.0f, z);
3982 glVertex3f(x + siz.width + 3.0f, y + 2.0f, z);
3983 glVertex3f(x + 1.0f, y + 2.0f, z);
3984 glVertex3f(x, y + 3.0f, z);
3985 glVertex3f(x, y + siz.height + 1.0f, z);
3986 OOGLEND();
3987}
3988
3989
3990void OODrawString(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
3991{
3992 OODrawStringAligned(text,x,y,z,siz,NO);
3993}
3994
3995
3996void OODrawStringAligned(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz, BOOL rightAlign)
3997{
3999 OODrawStringQuadsAligned(text,x,y,z,siz,rightAlign);
4001}
4002
4005
4006 OOGL(glEnable(GL_TEXTURE_2D));
4007 [sFontTexture apply];
4008 OOGLBEGIN(GL_QUADS);
4009
4010}
4011
4012void OODrawStringQuadsAligned(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz, BOOL rightAlign)
4013{
4014 GLfloat cx = x;
4015 NSInteger i, length;
4016 NSData *data = nil;
4017 const uint8_t *bytes = NULL;
4018
4019 data = [sEncodingCoverter convertString:text];
4020 length = [data length];
4021 bytes = [data bytes];
4022
4023 if (EXPECT_NOT(rightAlign))
4024 {
4025 cx -= OORectFromString(text, 0.0f, 0.0f, siz).size.width;
4026 }
4027
4028 for (i = 0; i < length; i++)
4029 {
4030 cx += drawCharacterQuad(bytes[i], cx, y, z, siz);
4031 }
4032}
4033
4035 OOGLEND();
4036
4038 OOGL(glDisable(GL_TEXTURE_2D));
4039
4041}
4042
4043
4044void OODrawHilightedString(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
4045{
4046 GLfloat color[4];
4047
4048 // get the physical dimensions of the string
4049 NSSize strsize = OORectFromString(text, 0.0f, 0.0f, siz).size;
4050 strsize.width += 0.5f;
4051
4053
4054 OOGL(glPushAttrib(GL_CURRENT_BIT)); // save the text colour
4055 OOGL(glGetFloatv(GL_CURRENT_COLOR, color)); // we need the original colour's alpha.
4056
4057 drawHighlight(x, y, z, strsize, color[3]);
4058
4059 OOGL(glPopAttrib()); //restore the colour
4060
4061 OODrawString(text, x, y, z, siz);
4062
4064}
4065
4066
4067void OODrawPlanetInfo(int gov, int eco, int tec, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
4068{
4069 GLfloat govcol[] = { 0.5, 0.0, 0.7,
4070 0.7, 0.5, 0.3,
4071 0.0, 1.0, 0.3,
4072 1.0, 0.8, 0.1,
4073 1.0, 0.0, 0.0,
4074 0.1, 0.5, 1.0,
4075 0.7, 0.7, 0.7,
4076 0.7, 1.0, 1.0};
4077
4078 GLfloat cx = x;
4079 int tl = tec + 1;
4080 GLfloat ce1 = 1.0f - 0.125f * eco;
4081
4083
4084 OOGL(glEnable(GL_TEXTURE_2D));
4085 [sFontTexture apply];
4086
4087 OOGLBEGIN(GL_QUADS);
4088 {
4089 [[UNIVERSE gui] setGLColorFromSetting:[NSString stringWithFormat:kGuiChartEconomyUColor, (unsigned long)eco]
4090 defaultValue:[OOColor colorWithRed:ce1 green:1.0f blue:0.0f alpha:1.0f]
4091 alpha:1.0];
4092
4093 // see OODrawHilightedPlanetInfo
4094 cx += drawCharacterQuad(23 - eco, cx, y, z, siz); // characters 16..23 are economy symbols
4095 [[UNIVERSE gui] setGLColorFromSetting:[NSString stringWithFormat:kGuiChartGovernmentUColor, (unsigned long)gov]
4096 defaultValue:[OOColor colorWithRed:govcol[gov*3] green:govcol[1+(gov*3)] blue:govcol[2+(gov*3)] alpha:1.0f]
4097 alpha:1.0];
4098
4099 cx += drawCharacterQuad(gov, cx, y, z, siz) - sF6KernGovt; // charcters 0..7 are government symbols
4100 [[UNIVERSE gui] setGLColorFromSetting:kGuiChartTechColor
4101 defaultValue:[OOColor colorWithRed:0.5 green:1.0f blue:1.0f alpha:1.0f]
4102 alpha:1.0];
4103
4104 if (tl > 9)
4105 {
4106 // display TL clamped between 1..16, this must be a '1'!
4107 cx += drawCharacterQuad(49, cx, y - 2, z, siz) - sF6KernTL;
4108 }
4109 cx += drawCharacterQuad(48 + (tl % 10), cx, y - 2.0f, z, siz);
4110 }
4111 OOGLEND();
4112
4113 (void)cx; // Suppress "value not used" analyzer issue.
4114
4116 OOGL(glDisable(GL_TEXTURE_2D));
4117
4119}
4120
4121
4122void OODrawHilightedPlanetInfo(int gov, int eco, int tec, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
4123{
4124 float color[4];
4125 int tl = tec + 1;
4126
4127 NSSize hisize;
4128
4129 // get the physical dimensions
4130 hisize.height = siz.height;
4131 hisize.width = 0.0f;
4132
4133 // see OODrawPlanetInfo
4134 hisize.width += siz.width * sGlyphWidths[23 - eco];
4135 hisize.width += siz.width * sGlyphWidths[gov] - 1.0;
4136 if (tl > 9) hisize.width += siz.width * sGlyphWidths[49] - 2.0;
4137 hisize.width += siz.width * sGlyphWidths[48 + (tl % 10)];
4138
4140
4141 OOGL(glPushAttrib(GL_CURRENT_BIT)); // save the text colour
4142 OOGL(glGetFloatv(GL_CURRENT_COLOR, color)); // we need the original colour's alpha.
4143
4144 drawHighlight(x, y - 2.0f, z, hisize, color[3]);
4145
4146 OOGL(glPopAttrib()); //restore the colour
4147
4148 OODrawPlanetInfo(gov, eco, tec, x, y, z, siz);
4149
4151}
4152
4153static void GLDrawNonlinearCascadeWeapon( GLfloat x, GLfloat y, GLfloat z, NSSize siz, Vector centre, GLfloat radius, GLfloat zoom, GLfloat alpha )
4154{
4155 Vector spacepos, scannerpos;
4156 GLfloat theta, phi;
4157 GLfloat z_factor = siz.height / siz.width; // approx 1/4
4158 GLfloat y_factor = 1.0 - sqrt(z_factor); // approx 1/2
4159 OOGLVector *points = malloc(sizeof(OOGLVector)*25);
4160 int i, j;
4161
4162 if (radius*radius > centre.y*centre.y)
4163 {
4164 GLfloat r0 = sqrt(radius*radius-centre.y*centre.y);
4165 OOGL(glColor4f(1.0, 0.5, 1.0, alpha));
4166 spacepos.y = 0;
4167 for (i = 0; i < 24; i++)
4168 {
4169 theta = i*2*M_PI/24;
4170 spacepos.x = centre.x + r0 * cos(theta);
4171 spacepos.z = centre.z + r0 * sin(theta);
4172 scannerpos = [HeadUpDisplay nonlinearScannerScale: spacepos Zoom: zoom Scale: 0.5*siz.width];
4173 points[i].x = x + scannerpos.x;
4174 points[i].y = y + scannerpos.z * z_factor + scannerpos.y * y_factor;
4175 points[i].z = z;
4176 }
4177 spacepos.x = centre.x + r0;
4178 spacepos.y = 0;
4179 spacepos.z = centre.z;
4180 scannerpos = [HeadUpDisplay nonlinearScannerScale: spacepos Zoom: zoom Scale: 0.5*siz.width];
4181 points[24].x = x + scannerpos.x;
4182 points[24].y = y + scannerpos.z * z_factor + scannerpos.y * y_factor;
4183 points[24].z = z;
4184 GLDrawPoints(points,25);
4185 }
4186 OOGL(glColor4f(0.5, 0.0, 1.0, 0.33333 * alpha));
4187 free(points);
4188 // Here, we draw a sphere distorted by the nonlinear function. We draw the sphere as a set of horizontal strips
4189 // The even indices of points are the points on the upper edge of the strip, while odd indices are points
4190 // on the bottom edge.
4191 points = malloc(sizeof(OOGLVector)*50);
4192 spacepos.x = centre.x;
4193 spacepos.y = centre.y + radius;
4194 spacepos.z = centre.z;
4195 scannerpos = [HeadUpDisplay nonlinearScannerScale: spacepos Zoom: zoom Scale: 0.5*siz.width];
4196 for (i = 0; i <= 24; i++)
4197 {
4198 points[2*i+1].x = x + scannerpos.x;
4199 points[2*i+1].y = y + scannerpos.y * y_factor + scannerpos.z * z_factor;
4200 points[2*i+1].z = z;
4201 }
4202 for (i = 1; i <= 24; i++)
4203 {
4204 theta = i*M_PI/24;
4205 for (j = 0; j <= 24; j++)
4206 {
4207 phi = j*M_PI/12;
4208 // copy point from bottom edge of previous strip into top edge position
4209 points[2*j] = points[2*j+1];
4210
4211 spacepos.x = centre.x + radius * sin(theta) * cos(phi);
4212 spacepos.y = centre.y + radius * cos(theta);
4213 spacepos.z = centre.z + radius * sin(theta) * sin(phi);
4214 scannerpos = [HeadUpDisplay nonlinearScannerScale: spacepos Zoom: zoom Scale: 0.5*siz.width];
4215 points[2*j+1].x = x + scannerpos.x;
4216 points[2*j+1].y = y + scannerpos.y * y_factor + scannerpos.z * z_factor;
4217 points[2*j+1].z = z;
4218 }
4219 GLDrawQuadStrip(points, 50);
4220 }
4221 free(points);
4222 return;
4223}
4224
4225static GLfloat nonlinearScannerFunc( GLfloat distance, GLfloat zoom, GLfloat scale )
4226{
4227 GLfloat x = fabs(distance / SCANNER_MAX_RANGE);
4228 if (x >= 1.0)
4229 return scale;
4230 if (zoom <= 1.0)
4231 return scale * x;
4232 GLfloat c = 1 / ( zoom - 1 );
4233 GLfloat b = c * ( c + 1 );
4234 GLfloat a = c + 1;
4235 return scale * ( a - b / ( x + c ) );
4236}
4237
4238
4239static void drawScannerGrid(GLfloat x, GLfloat y, GLfloat z, NSSize siz, int v_dir, GLfloat thickness, GLfloat zoom, BOOL nonlinear, BOOL minimalistic)
4240{
4242
4243 MyOpenGLView* gameView = [UNIVERSE gameView];
4244
4245 GLfloat w1, h1;
4246 GLfloat ww = 0.5 * siz.width;
4247 GLfloat hh = 0.5 * siz.height;
4248
4249 GLfloat km_scan;
4250 GLfloat hdiv;
4251 GLfloat wdiv;
4252 BOOL drawdiv = NO, drawdiv1 = NO, drawdiv5 = NO;
4253
4254 int i, ii;
4255
4256 OOGL(GLScaledLineWidth(2.0 * thickness));
4257 GLDrawOval(x, y, z, siz, 4);
4258 OOGL(GLScaledLineWidth(thickness)); // reset (thickness = lineWidth)
4259
4260 OOGLBEGIN(GL_LINES);
4261 if (!minimalistic)
4262 {
4263 glVertex3f(x, y - hh, z); glVertex3f(x, y + hh, z);
4264 glVertex3f(x - ww, y, z); glVertex3f(x + ww, y, z);
4265
4266 if (nonlinear)
4267 {
4268 if (nonlinearScannerFunc(4000.0, zoom, hh)-nonlinearScannerFunc(3000.0, zoom ,hh) > 2) drawdiv1 = YES;
4269 if (nonlinearScannerFunc(10000.0, zoom, hh)-nonlinearScannerFunc(5000.0, zoom, hh) > 2) drawdiv5 = YES;
4270 wdiv = ww/(0.001*SCANNER_MAX_RANGE);
4271 for (i = 1; 1000.0*i < SCANNER_MAX_RANGE; i++)
4272 {
4273 drawdiv = drawdiv1;
4274 w1 = wdiv;
4275 if (i % 10 == 0)
4276 {
4277 w1 = wdiv*4;
4278 drawdiv = YES;
4279 if (nonlinearScannerFunc((i+5)*1000,zoom,hh) - nonlinearScannerFunc(i*1000.0,zoom,hh)>2)
4280 {
4281 drawdiv5 = YES;
4282 }
4283 else
4284 {
4285 drawdiv5 = NO;
4286 }
4287 }
4288 else if (i % 5 == 0)
4289 {
4290 w1 = wdiv*2;
4291 drawdiv = drawdiv5;
4292 if (nonlinearScannerFunc((i+1)*1000,zoom,hh) - nonlinearScannerFunc(i*1000.0,zoom,hh)>2)
4293 {
4294 drawdiv1 = YES;
4295 }
4296 else
4297 {
4298 drawdiv1 = NO;
4299 }
4300 }
4301 if (drawdiv)
4302 {
4303 h1 = nonlinearScannerFunc(i*1000.0,zoom,hh);
4304 glVertex3f(x - w1, y + h1, z); glVertex3f(x + w1, y + h1, z);
4305 glVertex3f(x - w1, y - h1, z); glVertex3f(x + w1, y - h1, z);
4306 }
4307 }
4308 }
4309 else
4310 {
4311 km_scan = 0.001 * SCANNER_MAX_RANGE / zoom; // calculate kilometer divisions
4312 hdiv = 0.5 * siz.height / km_scan;
4313 wdiv = 0.25 * siz.width / km_scan;
4314 if (wdiv < 4.0)
4315 {
4316 wdiv *= 2.0;
4317 ii = 5;
4318 }
4319 else
4320 {
4321 ii = 1;
4322 }
4323
4324 for (i = ii; 2.0 * hdiv * i < siz.height; i += ii)
4325 {
4326 h1 = i * hdiv;
4327 w1 = wdiv;
4328 if (i % 5 == 0)
4329 w1 = w1 * 2.5;
4330 if (i % 10 == 0)
4331 w1 = w1 * 2.0;
4332 if (w1 > 3.5) // don't draw tiny marks
4333 {
4334 glVertex3f(x - w1, y + h1, z); glVertex3f(x + w1, y + h1, z);
4335 glVertex3f(x - w1, y - h1, z); glVertex3f(x + w1, y - h1, z);
4336 }
4337 }
4338 }
4339 }
4340
4341 double tanfov = [gameView fov:YES];
4342 GLfloat aspect = [gameView viewSize].width / [gameView viewSize].height;
4343 if (aspect < 4.0/3.0)
4344 {
4345 tanfov *= 0.75 * aspect;
4346 }
4347 double cosfov = 1.0/sqrt(1+tanfov*tanfov);
4348 double sinfov = tanfov * cosfov;
4349
4350 switch (v_dir)
4351 {
4352 case VIEW_BREAK_PATTERN:
4353 case VIEW_GUI_DISPLAY:
4354 case VIEW_FORWARD:
4355 case VIEW_NONE:
4356 glVertex3f(x, y, z); glVertex3f(x - ww * sinfov, y + hh * cosfov, z);
4357 glVertex3f(x, y, z); glVertex3f(x + ww * sinfov, y + hh * cosfov, z);
4358 break;
4359
4360 case VIEW_AFT:
4361 glVertex3f(x, y, z); glVertex3f(x - ww * sinfov, y - hh * cosfov, z);
4362 glVertex3f(x, y, z); glVertex3f(x + ww * sinfov, y - hh * cosfov, z);
4363 break;
4364
4365 case VIEW_PORT:
4366 glVertex3f(x, y, z); glVertex3f(x - ww * cosfov, y + hh * sinfov, z);
4367 glVertex3f(x, y, z); glVertex3f(x - ww * cosfov, y - hh * sinfov, z);
4368 break;
4369
4370 case VIEW_STARBOARD:
4371 glVertex3f(x, y, z); glVertex3f(x + ww * cosfov, y + hh * sinfov, z);
4372 glVertex3f(x, y, z); glVertex3f(x + ww * cosfov, y - hh * sinfov, z);
4373 break;
4374 }
4375 OOGLEND();
4376
4378}
4379
4380
4381static void DrawSpecialOval(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat step, GLfloat *color4v)
4382{
4383 GLfloat ww = 0.5 * siz.width;
4384 GLfloat hh = 0.5 * siz.height;
4385 GLfloat theta;
4386 GLfloat delta;
4387 GLfloat s;
4388
4389 delta = step * M_PI / 180.0f;
4390
4391 OOGLBEGIN(GL_LINE_LOOP);
4392 for (theta = 0.0f; theta < (2.0f * M_PI); theta += delta)
4393 {
4394 s = sin(theta);
4395 glColor4f(color4v[0], color4v[1], color4v[2], fabs(s * color4v[3]));
4396 glVertex3f(x + ww * s, y + hh * cos(theta), z);
4397 }
4398 OOGLEND();
4399}
4400
4401
4402- (void) setLineWidth:(GLfloat) value
4403{
4404 lineWidth = value;
4405}
4406
4407
4408- (GLfloat) lineWidth
4409{
4410 return lineWidth;
4411}
4412
4413@end
4414
4415
4416@implementation NSString (OODisplayEncoding)
4417
4418- (const char *) cStringUsingOoliteEncoding
4419{
4420 if (sEncodingCoverter == nil) InitTextEngine();
4421
4422 // Note: the data will be autoreleased, so the bytes behave as though they're autoreleased too.
4423 return [[self dataUsingEncoding:[sEncodingCoverter encoding] allowLossyConversion:YES] bytes];
4424}
4425
4426
4427- (const char *) cStringUsingOoliteEncodingAndRemapping
4428{
4429 if (sEncodingCoverter == nil) InitTextEngine();
4430
4431 // Note: the data will be autoreleased, so the bytes behave as though they're autoreleased too.
4432 return [[sEncodingCoverter convertString:self] bytes];
4433}
4434
4435@end
4436
4437
4438@implementation OOPolygonSprite (OOHUDBeaconIcon)
4439
4440- (void) oo_drawHUDBeaconIconAt:(NSPoint)where size:(NSSize)size alpha:(GLfloat)alpha z:(GLfloat)z
4441{
4442 GLfloat x = where.x - size.width;
4443 GLfloat y = where.y - 1.5 * size.height;
4444
4445 GLfloat ox = x - size.width * 0.5;
4446 GLfloat oy = y - size.height * 0.5;
4447 GLfloat width = size.width * (1.0f / 6.0f);
4448 GLfloat height = size.height * (1.0f / 6.0f);
4449
4451 OOGLTranslateModelView(make_vector(ox, oy, z));
4452 OOGLScaleModelView(make_vector(width, height, 1.0f));
4453 [self drawFilled];
4454 glColor4f(0.0, 0.0, 0.0, 0.5 * alpha);
4455 [self drawOutline];
4457}
4458
4459@end
4460
4461
4462@implementation NSString (OOHUDBeaconIcon)
4463
4464- (void) oo_drawHUDBeaconIconAt:(NSPoint)where size:(NSSize)size alpha:(GLfloat)alpha z:(GLfloat)z
4465{
4466 OODrawString(self, where.x - 2.5 * size.width, where.y - 3.0 * size.height, z, NSMakeSize(size.width * 2, size.height * 2));
4467}
4468
4469@end
4470
4471
4472static void SetGLColourFromInfo(NSDictionary *info, NSString *key, const GLfloat defaultColor[4], GLfloat alpha)
4473{
4474 id colorDesc = nil;
4475 OOColor *color = nil;
4476 colorDesc = [info objectForKey:key];
4477 if (colorDesc != nil)
4478 {
4479 color = [OOColor colorWithDescription:colorDesc];
4480 if (color != nil)
4481 {
4482 GLfloat ioColor[4];
4483 [color getRed:&ioColor[0] green:&ioColor[1] blue:&ioColor[2] alpha:&ioColor[3]];
4484 GLColorWithOverallAlpha(ioColor,alpha);
4485 return;
4486 }
4487 }
4488 GLColorWithOverallAlpha(defaultColor,alpha);
4489}
4490
4491
4492static void GetRGBAArrayFromInfo(NSDictionary *info, GLfloat ioColor[4])
4493{
4494 id colorDesc = nil;
4495 OOColor *color = nil;
4496
4497 // First, look for general colour specifier.
4498 colorDesc = [info objectForKey:RGB_COLOR_KEY];
4499 if (colorDesc != nil && ![info objectForKey:ALPHA_KEY])
4500 {
4501 color = [OOColor colorWithDescription:colorDesc];
4502 if (color != nil)
4503 {
4504 [color getRed:&ioColor[0] green:&ioColor[1] blue:&ioColor[2] alpha:&ioColor[3]];
4505 return;
4506 }
4507 }
4508
4509 // Failing that, look for rgb_color and alpha.
4510 colorDesc = [info oo_arrayForKey:RGB_COLOR_KEY];
4511 if (colorDesc != nil && [colorDesc count] == 3)
4512 {
4513 ioColor[0] = [colorDesc oo_nonNegativeFloatAtIndex:0];
4514 ioColor[1] = [colorDesc oo_nonNegativeFloatAtIndex:1];
4515 ioColor[2] = [colorDesc oo_nonNegativeFloatAtIndex:2];
4516 }
4517 ioColor[3] = [info oo_nonNegativeFloatForKey:ALPHA_KEY defaultValue:ioColor[3]];
4518}
#define SCANNER_MAX_RANGE
Definition Entity.h:51
#define SCANNER_MAX_RANGE2
Definition Entity.h:52
#define ZOOM_INDICATOR_HEIGHT
#define SELECTOR_KEY
#define ROW_HEIGHT_KEY
#define CABIN_TEMP_BAR_HEIGHT
#define AFT_SHIELD_BAR_HEIGHT
#define HEIGHT_KEY
#define FPSINFO_DISPLAY_Y
#define SCOOPSTATUS_HEIGHT
#define CABIN_TEMP_BAR_CENTRE_Y
#define FPSINFO_DISPLAY_WIDTH
#define SCANNER_WIDTH
#define MISSILE_ICON_WIDTH
#define ASCTARGET_DISPLAY_WIDTH
#define STATUS_LIGHT_CENTRE_X
#define ALTITUDE_BAR_CENTRE_X
#define MFD_TEXT_WIDTH
#define X_ORIGIN_KEY
#define SPEED_BAR_CENTRE_Y
#define SCANNER_CENTRE_Y
void OODrawStringAligned(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz, BOOL rightAlign)
#define Y_ORIGIN_KEY
#define WIDTH_KEY
#define ZOOM_INDICATOR_WIDTH
#define PITCH_BAR_CENTRE_Y
#define SCOOPSTATUS_CENTRE_X
#define ASCTARGET_DISPLAY_HEIGHT
#define ROLL_BAR_CENTRE_Y
#define WEAPON_TEMP_BAR_HEIGHT
#define AEGIS_CENTRE_Y
#define X_KEY
#define SCOOPSTATUS_WIDTH
#define ALTITUDE_BAR_WIDTH
#define SCANNER_ZOOM_LEVELS
#define CABIN_TEMP_BAR_WIDTH
#define CLOCK_DISPLAY_WIDTH
#define WEAPONSOFFLINETEXT_WIDTH
#define FORWARD_SHIELD_BAR_HEIGHT
#define WEAPON_TEMP_BAR_WIDTH
#define WITCHDEST_WIDTH
void OOHUDResetTextEngine(void)
#define WITCHDEST_HEIGHT
#define SPEED_BAR_WIDTH
#define FORWARD_SHIELD_BAR_WIDTH
void OODrawStringQuadsAligned(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz, BOOL rightAlign)
#define AFT_SHIELD_BAR_CENTRE_Y
#define FORWARD_SHIELD_BAR_CENTRE_Y
#define ROLL_BAR_WIDTH
#define CLOCK_DISPLAY_Y
#define PRIMED_DISPLAY_WIDTH
#define WEAPONSOFFLINETEXT_DISPLAY_X
#define WEAPONSOFFLINETEXT_HEIGHT
void OOStartDrawingStrings(void)
#define FPSINFO_DISPLAY_HEIGHT
#define TITLE_KEY
#define CABIN_TEMP_BAR_CENTRE_X
#define CUSTOM_DIAL_KEY
#define ROLL_BAR_HEIGHT
#define TEXT_KEY
#define MISSILES_DISPLAY_Y
#define FUEL_BAR_CENTRE_Y
#define AEGIS_CENTRE_X
#define FUEL_BAR_CENTRE_X
#define WEAPON_TEMP_BAR_CENTRE_X
#define ONE_EIGHTH
#define PRIMED_DISPLAY_X
NSRect OORectFromString(NSString *text, GLfloat x, GLfloat y, NSSize siz)
#define AEGIS_WIDTH
#define ZOOM_INDICATOR_CENTRE_X
#define AFT_SHIELD_BAR_WIDTH
#define CLOCK_DISPLAY_X
#define PITCH_BAR_CENTRE_X
#define ALTITUDE_BAR_HEIGHT
#define ACCURACY_PROBABILITY_DECREASE_FACTOR
#define COMPASS_CENTRE_Y
#define ASCTARGET_DISPLAY_X
#define ENERGY_GAUGE_CENTRE_X
#define FUEL_BAR_HEIGHT
#define SPEED_BAR_HEIGHT
#define MISSILES_DISPLAY_X
#define MIN_PROBABILITY_ACCURACY
#define WEAPONSOFFLINETEXT_DISPLAY_Y
#define FORWARD_SHIELD_BAR_CENTRE_X
#define ROLL_BAR_CENTRE_X
#define DIAL_REQUIRED_KEY
void OODrawString(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
#define WEAPON_TEMP_BAR_CENTRE_Y
#define AFT_SHIELD_BAR_CENTRE_X
void OODrawPlanetInfo(int gov, int eco, int tec, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
#define CLOCK_DISPLAY_HEIGHT
#define PRIMED_DISPLAY_HEIGHT
#define FPSINFO_DISPLAY_X
#define ENERGY_GAUGE_HEIGHT
#define BACKGROUND_RGBA_KEY
#define WITCHDEST_CENTRE_X
#define COMPASS_CENTRE_X
#define SCANNER_CENTRE_X
#define ENERGY_GAUGE_WIDTH
void OOStopDrawingStrings(void)
#define PRIMED_DISPLAY_Y
#define MAX_ACCURACY_RANGE
#define ALTITUDE_BAR_CENTRE_Y
#define SCANNER_SCALE
#define COMPASS_HALF_SIZE
#define WITCHDEST_CENTRE_Y
#define ASCTARGET_DISPLAY_Y
#define MISSILE_ICON_HEIGHT
#define AEGIS_HEIGHT
#define SCANNER_HEIGHT
#define PITCH_BAR_HEIGHT
#define STATUS_LIGHT_CENTRE_Y
#define ALPHA_KEY
#define STATUS_LIGHT_HEIGHT
#define SCOOPSTATUS_CENTRE_Y
#define Y_KEY
#define ENERGY_GAUGE_CENTRE_Y
#define FUEL_BAR_WIDTH
#define PITCH_BAR_WIDTH
@ OO_RETICLE_COLOR_TARGET
@ OO_RETICLE_COLOR_WORMHOLE
#define ZOOM_INDICATOR_CENTRE_Y
#define MFD_TEXT_HEIGHT
#define SPEED_BAR_CENTRE_X
static void hudRotateViewpointForVirtualDepth(PlayerEntity *player1, Vector p1)
static void hudDrawStatusIconAt(int x, int y, int z, NSSize siz)
#define SET_COLOR_CRITICAL(d)
static float sF6KernGovt
static void hudDrawWaypoint(OOWaypointEntity *waypoint, PlayerEntity *player1, GLfloat z1, GLfloat alpha, BOOL selected, GLfloat scale)
static const GLfloat redplus_color[4]
#define ONE_SIXTEENTH
#define SET_COLOR_LOW(d)
#define SET_COLOR_MEDIUM(d)
static NSString *const kDefaultMissileIconKey
static NSString *const kDefaultMineIconKey
static float sGlyphWidths[256]
static OOEncodingConverter * sEncodingCoverter
#define NOT_DEFINED
#define WIDGET_SELECTOR_NAME
static OOTexture * sFontTexture
static void SetGLColourFromInfo(NSDictionary *info, NSString *key, const GLfloat defaultColor[4], GLfloat alpha)
static void DrawSpecialOval(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat step, GLfloat *color4v)
static const GLfloat green_color[4]
static GLfloat nonlinearScannerFunc(GLfloat distance, GLfloat zoom, GLfloat scale)
static const GLfloat darkgreen_color[4]
static void hudDrawSurroundAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz)
static void GLDrawNonlinearCascadeWeapon(GLfloat x, GLfloat y, GLfloat z, NSSize siz, Vector centre, GLfloat radius, GLfloat zoom, GLfloat alpha)
static void hudDrawReticleOnTarget(Entity *target, PlayerEntity *player1, GLfloat z1, GLfloat alpha, BOOL reticleTargetSensitive, NSMutableDictionary *propertiesReticleTargetSensitive, BOOL colourFromScannerColour, BOOL showText, NSDictionary *info, NSMutableArray *reticleColors)
static NSArray * sCurrentDrawItem
static float sF6KernTL
static const GLfloat lightgray_color[4]
static BOOL _compassUpdated
static const GLfloat black_color[4]
#define SET_COLOR_HIGH(d)
static void hudDrawIndicatorAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
static const GLfloat blue_color[4]
static const GLfloat yellow_color[4]
#define SET_COLOR_SURROUND(d)
static void hudDrawMarkerAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
#define GLYPH_SCALE_FACTOR
#define SET_COLOR(d)
@ kFontTextureOptions
static const GLfloat red_color[4]
static void GetRGBAArrayFromInfo(NSDictionary *info, GLfloat ioColor[4])
static void drawScannerGrid(GLfloat x, GLfloat y, GLfloat z, NSSize siz, int v_dir, GLfloat thickness, GLfloat zoom, BOOL nonlinear, BOOL minimalistic)
OOINLINE float useDefined(float val, float validVal)
static void hudDrawBarAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
static const GLfloat kOutlineWidth
#define DESTROY(x)
Definition OOCocoa.h:75
#define EXPECT_NOT(x)
#define OOINLINE
#define OOLogERR(class, format,...)
Definition OOLogging.h:112
NSString *const kOOLogFileNotFound
Definition OOLogging.m:652
GLfloat OOScalar
Definition OOMaths.h:64
#define M_PI
Definition OOMaths.h:73
Vector OOVectorMultiplyMatrix(Vector v, OOMatrix m)
Definition OOMatrix.m:129
OOMatrix OOMatrixForQuaternionRotation(Quaternion orientation)
Definition OOMatrix.m:65
void OOGLLookAt(Vector eye, Vector center, Vector up)
void OOGLScaleModelView(Vector scale)
void OOGLPushModelView(void)
void OOGLTranslateModelView(Vector vector)
void OOGLMultModelView(OOMatrix matrix)
OOMatrix OOGLPopModelView(void)
#define OOGLBEGIN
Definition OOOpenGL.h:253
void GLDrawFilledOval(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat step)
Definition OOOpenGL.m:165
@ OPENGL_STATE_OVERLAY
Definition OOOpenGL.h:126
void GLDrawPoints(OOGLVector *points, int n)
Definition OOOpenGL.m:174
void GLDrawQuadStrip(OOGLVector *points, int n)
Definition OOOpenGL.m:203
#define OOVerifyOpenGLState()
Definition OOOpenGL.h:136
BOOL OOCheckOpenGLErrors(NSString *format,...)
Definition OOOpenGL.m:39
void GLScaledLineWidth(GLfloat width)
Definition OOOpenGL.m:218
void GLDrawOval(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat step)
Definition OOOpenGL.m:155
#define OOSetOpenGLState(STATE)
Definition OOOpenGL.h:135
#define OOGL(statement)
Definition OOOpenGL.h:251
#define OOGLEND
Definition OOOpenGL.h:254
unsigned count
return nil
Vector vector_up_from_quaternion(Quaternion quat)
void quaternion_rotate_about_axis(Quaternion *quat, Vector axis, OOScalar angle)
Quaternion quaternion_multiply(Quaternion q1, Quaternion q2)
float y
float x
#define OOExpandKey(key,...)
@ OO_SYSTEMCONCEALMENT_NONAME
@ kOOTextureNoShrink
Definition OOTexture.h:53
@ kOOTextureMinFilterMipMap
Definition OOTexture.h:48
@ kOOTextureAlphaMask
Definition OOTexture.h:60
@ kOOTextureMagFilterLinear
Definition OOTexture.h:51
@ AEGIS_IN_DOCKING_RANGE
Definition OOTypes.h:64
OOViewID
Definition OOTypes.h:43
double OOTimeDelta
Definition OOTypes.h:224
@ NO_TARGET
Definition OOTypes.h:194
const Vector kZeroVector
Definition OOVector.m:28
const Vector kBasisYVector
Definition OOVector.m:30
const Vector kBasisZVector
Definition OOVector.m:31
const Vector kBasisXVector
Definition OOVector.m:29
Vector OOVectorRandomRadial(OOScalar maxLength)
Definition OOVector.m:115
@ SCOOP_STATUS_FULL_HOLD
@ SCOOP_STATUS_NOT_INSTALLED
@ SCOOP_STATUS_ACTIVE
@ SCOOP_STATUS_OKAY
#define PLAYER
OOMissileStatus
@ MISSILE_STATUS_TARGET_LOCKED
@ MISSILE_STATUS_ARMED
@ MISSILE_STATUS_SAFE
#define PLAYER_TARGET_MEMORY_SIZE
OOAlertCondition
Definition ShipEntity.h:172
@ ALERT_CONDITION_GREEN
Definition ShipEntity.h:176
@ ALERT_CONDITION_RED
Definition ShipEntity.h:178
@ ALERT_CONDITION_YELLOW
Definition ShipEntity.h:177
@ ALERT_CONDITION_DOCKED
Definition ShipEntity.h:175
NSString * OOStringFromWeaponType(OOWeaponType weapon) CONST_FUNC
#define UNIVERSE
Definition Universe.h:842
#define DESC(key)
Definition Universe.h:848
@ OO_POSTFX_NONE
Definition Universe.h:90
#define CROSSHAIR_SIZE
Definition Universe.h:60
@ WH_SCANINFO_NONE
@ WH_SCANINFO_SCANNED
@ WH_SCANINFO_SHIP
@ WH_SCANINFO_ARRIVAL_TIME
@ WH_SCANINFO_DESTINATION
@ WH_SCANINFO_COLLAPSE_TIME
GLfloat collision_radius
Definition Entity.h:111
OOUniversalID universalID
Definition Entity.h:89
Quaternion orientation
Definition Entity.h:114
GLfloat zero_distance
Definition Entity.h:108
unsigned isShip
Definition Entity.h:91
GLfloat collisionRadius()
Definition Entity.m:906
OOScanClass scanClass
Definition Entity.h:106
unsigned isWormhole
Definition Entity.h:94
void setTextColor:(OOColor *color)
void resizeTo:characterHeight:title:(NSSize gui_size,[characterHeight] int csize,[title] NSString *gui_title)
void setMaxAlpha:(GLfloat an_alpha)
void setDrawPosition:(Vector vector)
void setCharacterSize:(NSSize character_size)
NSArray * getLastLines()
NSString * title
void setBackgroundColor:(OOColor *color)
void printLongText:align:color:fadeTime:key:addToArray:(NSString *str,[align] OOGUIAlignment alignment,[color] OOColor *text_color,[fadeTime] float text_fade,[key] NSString *text_key,[addToArray] NSMutableArray *text_array)
void setTextCommsColor:(OOColor *color)
void setAlpha:(GLfloat an_alpha)
void setCurrentRow:(OOGUIRow value)
unsigned rowHeight()
Vector nonlinearScannerScale:Zoom:Scale:(Vector V,[Zoom] GLfloat zoom,[Scale] double scale)
static void hudDrawIndicatorAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
static void hudDrawStatusIconAt(int x, int y, int z, NSSize siz)
void OOStopDrawingStrings()
void OODrawHilightedPlanetInfo(int gov, int eco, int tec, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
static void hudRotateViewpointForVirtualDepth(PlayerEntity *player1, Vector p1)
void OODrawStringQuadsAligned(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz, BOOL rightAlign)
static GLfloat nonlinearScannerFunc(GLfloat distance, GLfloat zoom, GLfloat scale)
static void hudDrawBarAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
static void hudDrawSurroundAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz)
NSRect OORectFromString(NSString *text, GLfloat x, GLfloat y, NSSize siz)
static void drawScannerGrid(GLfloat x, GLfloat y, GLfloat z, NSSize siz, int v_dir, GLfloat thickness, GLfloat zoom, BOOL nonlinear, BOOL minimalistic)
void OODrawStringAligned(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz, BOOL rightAlign)
void OOStartDrawingStrings()
static void GLDrawNonlinearCascadeWeapon(GLfloat x, GLfloat y, GLfloat z, NSSize siz, Vector centre, GLfloat radius, GLfloat zoom, GLfloat alpha)
void OODrawHilightedString(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
void drawHighlight(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat alpha)
static void hudDrawMarkerAt(GLfloat x, GLfloat y, GLfloat z, NSSize siz, GLfloat amount)
CGFloat OOStringWidthInEm(NSString *text)
static void hudDrawReticleOnTarget(Entity *target, PlayerEntity *player1, GLfloat z1, GLfloat alpha, BOOL reticleTargetSensitive, NSMutableDictionary *propertiesReticleTargetSensitive, BOOL colourFromScannerColour, BOOL showText, NSDictionary *info, NSMutableArray *reticleColors)
void OODrawString(NSString *text, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
static void hudDrawWaypoint(OOWaypointEntity *waypoint, PlayerEntity *player1, GLfloat z1, GLfloat alpha, BOOL selected, GLfloat scale)
void OODrawPlanetInfo(int gov, int eco, int tec, GLfloat x, GLfloat y, GLfloat z, NSSize siz)
float fov:(BOOL inFraction)
OOColor * cyanColor()
Definition OOColor.m:286
OOColor * colorWithRed:green:blue:alpha:(float red,[green] float green,[blue] float blue,[alpha] float alpha)
Definition OOColor.m:95
float alphaComponent()
Definition OOColor.m:486
OOColor * colorFromString:(NSString *colorFloatString)
Definition OOColor.m:214
float blueComponent()
Definition OOColor.m:362
OOColor * colorWithDescription:(id description)
Definition OOColor.m:127
OOColor * redColor()
Definition OOColor.m:268
OOColor * greenColor()
Definition OOColor.m:274
void getRed:green:blue:alpha:(float *red,[green] float *green,[blue] float *blue,[alpha] float *alpha)
Definition OOColor.m:368
OOColor * whiteColor()
Definition OOColor.m:256
float redComponent()
Definition OOColor.m:350
OOColor * yellowColor()
Definition OOColor.m:292
float greenComponent()
Definition OOColor.m:356
NSStringEncoding encoding()
NSData * convertString:(NSString *string)
void blitCentredToX:Y:Z:alpha:(float x,[Y] float y,[Z] float z,[alpha] float a)
void apply()
Definition OOTexture.m:269
NSSize dimensions()
Definition OOTexture.m:306
void applyNone()
Definition OOTexture.m:275
id textureWithName:inFolder:options:anisotropy:lodBias:(NSString *name,[inFolder] NSString *directory,[options] OOTextureFlags options,[anisotropy] GLfloat anisotropy,[lodBias] GLfloat lodBias)
Definition OOTexture.m:134
void drawTrumble:(double z)
Definition OOTrumble.m:371
NSMutableArray * targetMemory()
GLfloat dialMaxEnergy()
Vector customViewUpVector
Vector customViewForwardVector
double clockTimeAdjusted()
NSDictionary * whitelistDictionary()
NSDictionary * dictionaryFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)
Vector v_forward
Definition ShipEntity.h:200
OOColor * scannerDisplayColor2()
BoundingBox totalBoundingBox
Definition ShipEntity.h:213
Vector v_up
Definition ShipEntity.h:200
NSString * scanDescription()
OOColor * scannerDisplayColorHostile2()
OOColor * scannerDisplayColorHostile1()
BOOL hasHostileTarget()
void setMessageTime:(double value)
OOColor * scannerDisplayColor1()
Vector v_right
Definition ShipEntity.h:200
voidpf void uLong size
Definition ioapi.h:134
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
GLfloat y
Definition OOOpenGL.h:205
GLfloat x
Definition OOOpenGL.h:204
GLfloat z
Definition OOOpenGL.h:206