Line data Source code
1 0 : /*
2 :
3 : GuiDisplayGen.m
4 :
5 : Oolite
6 : Copyright (C) 2004-2013 Giles C Williams and contributors
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License
10 : as published by the Free Software Foundation; either version 2
11 : of the License, or (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 : MA 02110-1301, USA.
22 :
23 : */
24 :
25 : #import "GuiDisplayGen.h"
26 : #import "Universe.h"
27 : #import "GameController.h"
28 : #import "PlayerEntity.h"
29 : #import "PlayerEntityControls.h"
30 : #import "OOTextureSprite.h"
31 : #import "ResourceManager.h"
32 : #import "OOSound.h"
33 : #import "OOStringExpander.h"
34 : #import "OOStringParsing.h"
35 : #import "HeadUpDisplay.h"
36 : #import "OOCollectionExtractors.h"
37 : #import "OOTexture.h"
38 : #import "OOJavaScriptEngine.h"
39 : #import "PlayerEntityStickProfile.h"
40 : #import "OOSystemDescriptionManager.h"
41 :
42 0 : OOINLINE BOOL RowInRange(OOGUIRow row, NSRange range)
43 : {
44 : return ((int)range.location <= row && row < (int)(range.location + range.length));
45 : }
46 :
47 : @interface GuiDisplayGen (Internal)
48 :
49 0 : - (void) drawGLDisplay:(GLfloat)x :(GLfloat)y :(GLfloat)z :(GLfloat) alpha;
50 :
51 0 : - (void) drawCrossHairsWithSize:(GLfloat) size x:(GLfloat)x y:(GLfloat)y z:(GLfloat)z;
52 0 : - (void) drawStarChart:(GLfloat)x :(GLfloat)y :(GLfloat)z :(GLfloat) alpha :(BOOL) compact;
53 0 : - (void) drawSystemMarkers:(NSArray *)marker atX:(GLfloat)x andY:(GLfloat)y andZ:(GLfloat)z withAlpha:(GLfloat)alpha andScale:(GLfloat)scale;
54 0 : - (void) drawSystemMarker:(NSDictionary *)marker atX:(GLfloat)x andY:(GLfloat)y andZ:(GLfloat)z withAlpha:(GLfloat)alpha andScale:(GLfloat)scale;
55 :
56 1 : - (void) drawEquipmentList:(NSArray *)eqptList z:(GLfloat)z;
57 0 : - (void) drawAdvancedNavArrayAtX:(float)x y:(float)y z:(float)z alpha:(float)alpha usingRoute:(NSDictionary *) route optimizedBy:(OORouteType) optimizeBy zoom: (OOScalar) zoom;
58 :
59 : @end
60 :
61 :
62 : @implementation GuiDisplayGen
63 :
64 0 : static BOOL _refreshStarChart = NO;
65 :
66 : - (id) init
67 : {
68 : if ((self = [super init]))
69 : {
70 : size_in_pixels = NSMakeSize(MAIN_GUI_PIXEL_WIDTH, MAIN_GUI_PIXEL_HEIGHT);
71 : n_columns = GUI_DEFAULT_COLUMNS;
72 : n_rows = GUI_DEFAULT_ROWS;
73 : pixel_row_center = size_in_pixels.width / 2;
74 : pixel_row_height = MAIN_GUI_ROW_HEIGHT;
75 : pixel_row_start = MAIN_GUI_PIXEL_ROW_START; // first position down the page...
76 : max_alpha = 1.0;
77 :
78 : pixel_text_size = NSMakeSize(0.9f * pixel_row_height, pixel_row_height); // main gui has 18x20 characters
79 :
80 : pixel_title_size = NSMakeSize(pixel_row_height * 1.75f, pixel_row_height * 1.5f);
81 :
82 : int stops[6] = {0, 192, 256, 320, 384, 448};
83 : unsigned i;
84 :
85 : rowRange = NSMakeRange(0,n_rows);
86 :
87 : rowText = [[NSMutableArray alloc] initWithCapacity:n_rows]; // alloc retains
88 : rowKey = [[NSMutableArray alloc] initWithCapacity:n_rows]; // alloc retains
89 : rowColor = [[NSMutableArray alloc] initWithCapacity:n_rows]; // alloc retains
90 :
91 : for (i = 0; i < n_rows; i++)
92 : {
93 : [rowText addObject:@"."];
94 : [rowKey addObject:[NSString stringWithFormat:@"%d",i]];
95 : [rowColor addObject:[OOColor yellowColor]];
96 : rowPosition[i].x = 0.0f;
97 : rowPosition[i].y = size_in_pixels.height - (pixel_row_start + i * pixel_row_height);
98 : rowAlignment[i] = GUI_ALIGN_LEFT;
99 : }
100 :
101 : for (i = 0; i < n_columns; i++)
102 : {
103 : tabStops[i] = stops[i];
104 : }
105 :
106 : title = @"";
107 :
108 : textColor = [[OOColor yellowColor] retain];
109 :
110 : drawPosition = make_vector(0.0f, 0.0f, 640.0f);
111 :
112 : backgroundSpecial = GUI_BACKGROUND_SPECIAL_NONE;
113 :
114 : guiUserSettings = [[ResourceManager dictionaryFromFilesNamed:@"gui-settings.plist" inFolder:@"Config" andMerge:YES] retain];
115 : }
116 : return self;
117 : }
118 :
119 :
120 : - (id) initWithPixelSize:(NSSize)gui_size
121 : columns:(int)gui_cols
122 : rows:(int)gui_rows
123 : rowHeight:(int)gui_row_height
124 : rowStart:(int)gui_row_start
125 : title:(NSString*)gui_title
126 : {
127 : self = [super init];
128 :
129 : size_in_pixels = gui_size;
130 : n_columns = gui_cols;
131 : n_rows = gui_rows;
132 : pixel_row_center = size_in_pixels.width / 2;
133 : pixel_row_height = gui_row_height;
134 : pixel_row_start = gui_row_start; // first position down the page...
135 : max_alpha = 1.0;
136 :
137 : pixel_text_size = NSMakeSize(pixel_row_height, pixel_row_height);
138 :
139 : pixel_title_size = NSMakeSize(pixel_row_height * 1.75f, pixel_row_height * 1.5f);
140 :
141 : unsigned i;
142 :
143 : rowRange = NSMakeRange(0,n_rows);
144 :
145 : rowText = [[NSMutableArray alloc] initWithCapacity:n_rows]; // alloc retains
146 : rowKey = [[NSMutableArray alloc] initWithCapacity:n_rows]; // alloc retains
147 : rowColor = [[NSMutableArray alloc] initWithCapacity:n_rows]; // alloc retains
148 :
149 : for (i = 0; i < n_rows; i++)
150 : {
151 : [rowText addObject:@""];
152 : [rowKey addObject:@""];
153 : [rowColor addObject:[OOColor greenColor]];
154 : rowPosition[i].x = 0.0f;
155 : rowPosition[i].y = size_in_pixels.height - (pixel_row_start + i * pixel_row_height);
156 : rowAlignment[i] = GUI_ALIGN_LEFT;
157 : }
158 :
159 : title = [gui_title retain];
160 :
161 : textColor = [[OOColor yellowColor] retain];
162 :
163 : return self;
164 : }
165 :
166 :
167 : - (void) dealloc
168 : {
169 : [backgroundSprite release];
170 : [foregroundSprite release];
171 : [backgroundColor release];
172 : [textColor release];
173 : [title release];
174 : [rowText release];
175 : [rowKey release];
176 : [rowColor release];
177 : [guiUserSettings release];
178 :
179 : [super dealloc];
180 : }
181 :
182 :
183 : - (void) resizeWithPixelSize:(NSSize)gui_size
184 : columns:(int)gui_cols
185 : rows:(int)gui_rows
186 : rowHeight:(int)gui_row_height
187 : rowStart:(int)gui_row_start
188 : title:(NSString*) gui_title
189 : {
190 : [self clear];
191 : //
192 : size_in_pixels = gui_size;
193 : n_columns = gui_cols;
194 : n_rows = gui_rows;
195 : pixel_row_center = size_in_pixels.width / 2;
196 : pixel_row_height = gui_row_height;
197 : pixel_row_start = gui_row_start; // first position down the page...
198 :
199 : pixel_text_size = NSMakeSize(pixel_row_height, pixel_row_height);
200 : pixel_title_size = NSMakeSize(pixel_row_height * 1.75f, pixel_row_height * 1.5f);
201 :
202 : rowRange = NSMakeRange(0,n_rows);
203 : [self clear];
204 : //
205 : [self setTitle: gui_title];
206 : }
207 :
208 :
209 : - (void) resizeTo:(NSSize)gui_size
210 : characterHeight:(int)csize
211 : title:(NSString*)gui_title
212 : {
213 : [self clear];
214 : //
215 : size_in_pixels = gui_size;
216 : n_columns = gui_size.width / csize;
217 : n_rows = (int)gui_size.height / csize;
218 :
219 : [self setTitle: gui_title];
220 :
221 : pixel_row_center = gui_size.width / 2;
222 : pixel_row_height = csize;
223 : currentRow = n_rows - 1; // first position down the page...
224 :
225 : if (title != nil)
226 : pixel_row_start = 2.75f * csize + 0.5f * (gui_size.height - n_rows * csize);
227 : else
228 : pixel_row_start = csize + 0.5f * (gui_size.height - n_rows * csize);
229 :
230 : [rowText removeAllObjects];
231 : [rowKey removeAllObjects];
232 : [rowColor removeAllObjects];
233 :
234 : unsigned i;
235 : for (i = 0; i < n_rows; i++)
236 : {
237 : [rowText addObject:@""];
238 : [rowKey addObject:@""];
239 : [rowColor addObject:[OOColor greenColor]];
240 : rowPosition[i].x = 0.0f;
241 : rowPosition[i].y = size_in_pixels.height - (pixel_row_start + i * pixel_row_height);
242 : rowAlignment[i] = GUI_ALIGN_LEFT;
243 : }
244 :
245 : pixel_text_size = NSMakeSize(csize, csize);
246 : pixel_title_size = NSMakeSize(csize * 1.75f, csize * 1.5f);
247 :
248 : OOLog(@"gui.reset", @"gui %@ reset to rows:%d columns:%d start:%d", self, n_rows, n_columns, pixel_row_start);
249 :
250 : rowRange = NSMakeRange(0,n_rows);
251 : [self clear];
252 : }
253 :
254 :
255 : - (NSSize)size
256 : {
257 : return size_in_pixels;
258 : }
259 :
260 :
261 : - (unsigned)columns
262 : {
263 : return n_columns;
264 : }
265 :
266 :
267 : - (unsigned)rows
268 : {
269 : return n_rows;
270 : }
271 :
272 :
273 : - (unsigned)rowHeight
274 : {
275 : return pixel_row_height;
276 : }
277 :
278 :
279 : - (int)rowStart
280 : {
281 : return pixel_row_start;
282 : }
283 :
284 :
285 : - (NSString *)title
286 : {
287 : return title;
288 : }
289 :
290 :
291 : - (void) setTitle:(NSString *)str
292 : {
293 : if (str != title)
294 : {
295 : [title release];
296 : if ([str length] == 0) str = nil;
297 : title = [str copy];
298 : }
299 : }
300 :
301 :
302 : - (void) setDrawPosition:(Vector) vector
303 : {
304 : drawPosition = vector;
305 : }
306 :
307 :
308 : - (Vector) drawPosition
309 : {
310 : return drawPosition;
311 : }
312 :
313 :
314 : - (NSDictionary *) userSettings
315 : {
316 : return guiUserSettings;
317 : }
318 :
319 :
320 : - (void) fadeOutFromTime:(OOTimeAbsolute) now_time overDuration:(OOTimeDelta) duration
321 : {
322 : if (fade_alpha <= 0.0f)
323 : {
324 : return;
325 : }
326 : if (duration == 0.0)
327 : fade_sign = -1000.0f;
328 : else
329 : fade_sign = (float)(-fade_alpha / duration);
330 : }
331 :
332 :
333 : - (void) stopFadeOuts
334 : {
335 : fade_sign = 0.0f;
336 : }
337 :
338 :
339 : - (GLfloat) alpha
340 : {
341 : return fade_alpha;
342 : }
343 :
344 :
345 : - (void) setAlpha:(GLfloat) an_alpha
346 : {
347 : fade_alpha = an_alpha * max_alpha;
348 : }
349 :
350 :
351 : - (void) setMaxAlpha:(GLfloat) an_alpha
352 : {
353 : max_alpha = an_alpha;
354 : }
355 :
356 :
357 : - (void) setBackgroundColor:(OOColor*) color
358 : {
359 : [backgroundColor release];
360 : backgroundColor = [color retain];
361 : }
362 :
363 :
364 : - (OOColor *) textColor
365 : {
366 : return textColor;
367 : }
368 :
369 :
370 : // default text colour for rows
371 : - (void) setTextColor:(OOColor*) color
372 : {
373 : [textColor release];
374 : if (color == nil) color = [[OOColor yellowColor] retain];
375 : textColor = [color retain];
376 : }
377 :
378 :
379 : - (OOColor *) textCommsColor
380 : {
381 : return textCommsColor;
382 : }
383 :
384 :
385 : - (void) setTextCommsColor:(OOColor*) color
386 : {
387 : [textCommsColor release];
388 : if (color == nil) color = [[OOColor yellowColor] retain];
389 : textCommsColor = [color retain];
390 : }
391 :
392 :
393 : - (OOColor *) colorFromSetting:(NSString *)setting defaultValue:(OOColor *)def
394 : {
395 :
396 : OOColor *col = nil;
397 : if (setting != nil) {
398 : col = [OOColor colorWithDescription:[guiUserSettings objectForKey:setting]];
399 : }
400 : if (col == nil) {
401 : if (def != nil) {
402 : col = def;
403 : // def = nil => use default_text_color
404 : } else {
405 : col = textColor;
406 : }
407 : }
408 : return [[col copy] autorelease];
409 : }
410 :
411 :
412 : - (void) setGLColorFromSetting:(NSString *)setting defaultValue:(OOColor *)def alpha:(GLfloat)alpha
413 : {
414 : GLfloat r,g,b,a;
415 : OOColor *col = [self colorFromSetting:setting defaultValue:def];
416 : [col getRed:&r green:&g blue:&b alpha:&a];
417 :
418 : OOGL(glColor4f(r, g, b, a*alpha));
419 : }
420 :
421 :
422 : - (void) setGuiColorSettingFromKey:(NSString *)key color:(OOColor *)col
423 : {
424 : NSMutableDictionary *guiCopy = [guiUserSettings mutableCopy];
425 : if (col == nil)
426 : {
427 : [guiCopy removeObjectForKey:key];
428 : }
429 : else
430 : {
431 : [guiCopy setObject:col forKey:key];
432 : }
433 : [guiUserSettings release];
434 : guiUserSettings = [guiCopy copy];
435 : [guiCopy release];
436 : }
437 :
438 :
439 : - (void) setCharacterSize:(NSSize) character_size
440 : {
441 : pixel_text_size = character_size;
442 : }
443 :
444 :
445 : - (void)setShowAdvancedNavArray:(BOOL)inFlag
446 : {
447 : showAdvancedNavArray = inFlag;
448 : }
449 :
450 :
451 : - (void) setColor:(OOColor *) color forRow:(OOGUIRow)row
452 : {
453 : if (RowInRange(row, rowRange))
454 : [rowColor replaceObjectAtIndex:row withObject:color];
455 : }
456 :
457 :
458 : - (id) objectForRow:(OOGUIRow)row
459 : {
460 : if (RowInRange(row, rowRange))
461 : return [rowText objectAtIndex:row];
462 : else
463 : return NULL;
464 : }
465 :
466 :
467 : - (OOGUIRow) rowForKey:(NSString*)key
468 : {
469 : for (unsigned i=0;i<[rowKey count];i++)
470 : {
471 : if ([key isEqualToString:[rowKey objectAtIndex:i]])
472 : {
473 : return (OOGUIRow)i;
474 : }
475 : }
476 : return -1;
477 : }
478 :
479 :
480 : - (NSString*) keyForRow:(OOGUIRow)row
481 : {
482 : if (RowInRange(row, rowRange))
483 : return [rowKey objectAtIndex:row];
484 : else
485 : return NULL;
486 : }
487 :
488 :
489 : - (OOGUIRow) selectedRow
490 : {
491 : if (RowInRange(selectedRow, selectableRange))
492 : return selectedRow;
493 : else
494 : return -1;
495 : }
496 :
497 :
498 : - (BOOL) setSelectedRow:(OOGUIRow)row
499 : {
500 : if ((row == selectedRow) && RowInRange(row, selectableRange))
501 : {
502 : return YES;
503 : }
504 : if (RowInRange(row, selectableRange))
505 : {
506 : if (![[rowKey objectAtIndex:row] isEqual:GUI_KEY_SKIP])
507 : {
508 : selectedRow = row;
509 : [self reportSelectedRow:row];
510 : return YES;
511 : }
512 : }
513 : return NO;
514 : }
515 :
516 :
517 : - (BOOL) setNextRow:(int) direction
518 : {
519 : OOGUIRow row = selectedRow + direction;
520 : while (RowInRange(row, selectableRange))
521 : {
522 : if (![[rowKey objectAtIndex:row] isEqual:GUI_KEY_SKIP])
523 : {
524 : selectedRow = row;
525 : [self reportSelectedRow:row];
526 : return YES;
527 : }
528 : row += direction;
529 : }
530 : return NO;
531 : }
532 :
533 :
534 : - (BOOL) setFirstSelectableRow
535 : {
536 : NSUInteger row = selectableRange.location;
537 : while (RowInRange(row, selectableRange))
538 : {
539 : if (![[rowKey objectAtIndex:row] isEqual:GUI_KEY_SKIP])
540 : {
541 : selectedRow = row;
542 : [self reportSelectedRow:row];
543 : return YES;
544 : }
545 : row++;
546 : }
547 : selectedRow = -1;
548 : return NO;
549 : }
550 :
551 :
552 : - (BOOL) setLastSelectableRow
553 : {
554 : NSUInteger row = selectableRange.location + selectableRange.length - 1;
555 : while (RowInRange(row, selectableRange))
556 : {
557 : if (![[rowKey objectAtIndex:row] isEqual:GUI_KEY_SKIP])
558 : {
559 : selectedRow = row;
560 : [self reportSelectedRow:row];
561 : return YES;
562 : }
563 : row--;
564 : }
565 : selectedRow = -1;
566 : return NO;
567 : }
568 :
569 :
570 : - (void) reportSelectedRow:(int) row
571 : {
572 : [PLAYER doScriptEvent:OOJSID("guiSelectedRowChanged") withArguments:[NSArray arrayWithObjects:[self keyForRow:row], [NSNumber numberWithInt:row], [self selectedRowText], nil]];
573 : }
574 :
575 :
576 : - (void) setNoSelectedRow
577 : {
578 : selectedRow = -1;
579 : }
580 :
581 :
582 : - (NSString *) selectedRowText
583 : {
584 : if ([[rowText objectAtIndex:selectedRow] isKindOfClass:[NSString class]])
585 : return (NSString *)[rowText objectAtIndex:selectedRow];
586 : if ([[rowText objectAtIndex:selectedRow] isKindOfClass:[NSArray class]])
587 : return (NSString *)[[rowText objectAtIndex:selectedRow] objectAtIndex:0];
588 : return NULL;
589 : }
590 :
591 :
592 : - (NSString *) selectedRowKey
593 : {
594 : if ((selectedRow < 0)||((unsigned)selectedRow > [rowKey count]))
595 : return nil;
596 : else
597 : return (NSString *)[rowKey objectAtIndex:selectedRow];
598 : }
599 :
600 :
601 : - (void) setShowTextCursor:(BOOL) yesno
602 : {
603 : showTextCursor = yesno;
604 : }
605 :
606 :
607 : - (void) setCurrentRow:(OOGUIRow) value
608 : {
609 : if ((value < 0)||((unsigned)value >= n_rows))
610 : {
611 : showTextCursor = NO;
612 : currentRow = -1;
613 : }
614 : else
615 : {
616 : currentRow = value;
617 : }
618 : }
619 :
620 :
621 : - (NSRange) selectableRange
622 : {
623 : return selectableRange;
624 : }
625 :
626 :
627 : - (void) setSelectableRange:(NSRange) range
628 : {
629 : selectableRange = range;
630 : }
631 :
632 :
633 : - (void) setTabStops:(OOGUITabSettings)stops
634 : {
635 : if (stops != NULL) memmove(tabStops, stops, sizeof tabStops);
636 : }
637 :
638 : - (void) overrideTabs:(OOGUITabSettings)stops from:(NSString *)setting length:(NSUInteger)len
639 : {
640 : NSArray *override = [guiUserSettings oo_arrayForKey:setting defaultValue:nil];
641 : NSUInteger i;
642 : if (stops != NULL && override != nil)
643 : {
644 : if (len > GUI_MAX_COLUMNS)
645 : {
646 : len = GUI_MAX_COLUMNS;
647 : }
648 : for (i=0;i<len;i++)
649 : {
650 : stops[i] = [override oo_unsignedIntegerAtIndex:i defaultValue:stops[i]];
651 : }
652 : }
653 : }
654 :
655 :
656 : - (void) clear
657 : {
658 : [self clearAndKeepBackground:NO];
659 : }
660 :
661 :
662 : - (void) clearAndKeepBackground:(BOOL)keepBackground
663 : {
664 : unsigned i;
665 : [self setTitle: nil];
666 : for (i = 0; i < n_rows; i++)
667 : {
668 : [self setText:@"" forRow:i align:GUI_ALIGN_LEFT];
669 : [self setColor:textColor forRow:i];
670 : //
671 : [self setKey:GUI_KEY_SKIP forRow:i];
672 : //
673 : rowFadeTime[i] = 0.0f;
674 : }
675 : [self setShowTextCursor:NO];
676 : [self setSelectableRange:NSMakeRange(0,0)];
677 : if (!keepBackground) [self clearBackground];
678 : }
679 :
680 :
681 : - (void) setKey:(NSString *)str forRow:(OOGUIRow)row
682 : {
683 : if (RowInRange(row, rowRange))
684 : [rowKey replaceObjectAtIndex:row withObject:str];
685 : }
686 :
687 :
688 : - (void) setText:(NSString *)str forRow:(OOGUIRow)row
689 : {
690 : if (RowInRange(row, rowRange))
691 : {
692 : [rowText replaceObjectAtIndex:row withObject:str];
693 : }
694 : }
695 :
696 :
697 : - (void) setText:(NSString *)str forRow:(OOGUIRow)row align:(OOGUIAlignment)alignment
698 : {
699 : if (str != nil && RowInRange(row, rowRange))
700 : {
701 : [rowText replaceObjectAtIndex:row withObject:str];
702 : rowAlignment[row] = alignment;
703 : }
704 : }
705 :
706 :
707 : - (OOGUIRow) addLongText:(NSString *)str
708 : startingAtRow:(OOGUIRow)row
709 : align:(OOGUIAlignment)alignment
710 : {
711 :
712 : if ([str rangeOfString:@"\n"].location != NSNotFound)
713 : {
714 : NSArray *lines = [str componentsSeparatedByString:@"\n"];
715 : unsigned i;
716 : for (i = 0; i < [lines count]; i++)
717 : {
718 : row = [self addLongText:[lines oo_stringAtIndex:i] startingAtRow:row align:alignment];
719 : }
720 : return row;
721 : }
722 :
723 : NSSize chSize = pixel_text_size;
724 : NSSize strsize = OORectFromString(str, 0.0f, 0.0f, chSize).size;
725 : if (strsize.width < size_in_pixels.width)
726 : {
727 : [self setText:str forRow:row align:alignment];
728 : return row + 1;
729 : }
730 : else
731 : {
732 : NSMutableArray *words = ScanTokensFromString(str);
733 : NSMutableString *string1 = [NSMutableString stringWithCapacity:256];
734 : NSMutableString *string2 = [NSMutableString stringWithCapacity:256];
735 : strsize.width = 0.0f;
736 : while ((strsize.width < size_in_pixels.width)&&([words count] > 0))
737 : {
738 : [string1 appendString:(NSString *)[words objectAtIndex:0]];
739 : [string1 appendString:@" "];
740 : [words removeObjectAtIndex:0];
741 : strsize = OORectFromString(string1, 0.0f, 0.0f, chSize).size;
742 : if ([words count] > 0)
743 : strsize.width += OORectFromString((NSString *)[words objectAtIndex:0], 0.0f, 0.0f, chSize).size.width;
744 : }
745 : [string2 appendString:[words componentsJoinedByString:@" "]];
746 : [self setText:string1 forRow:row align:alignment];
747 : return [self addLongText:string2 startingAtRow:row+1 align:alignment];
748 : }
749 : }
750 :
751 :
752 : - (NSString *) reflowTextForMFD:(NSString *)input
753 : {
754 : NSMutableString *output = [[NSMutableString alloc] initWithCapacity:512];
755 : NSArray *lines = [input componentsSeparatedByString:@"\n"];
756 : NSSize chSize = pixel_text_size;
757 : NSUInteger limit = chSize.width * 15;
758 : NSString *line = nil;
759 : foreach (line, lines)
760 : {
761 : NSMutableArray *words = ScanTokensFromString(line);
762 : NSMutableString *accum = [NSMutableString stringWithCapacity:64];
763 : if ([words count] > 0)
764 : {
765 : while ([words count] > 1)
766 : {
767 : [accum appendString:[words oo_stringAtIndex:0]];
768 : [accum appendString:@" "];
769 : if (OORectFromString(accum, 0.0f, 0.0f,chSize).size.width + OORectFromString([words oo_stringAtIndex:1], 0.0f, 0.0f,chSize).size.width > limit)
770 : {
771 : // can't fit next word on this line
772 : [output appendString:[accum stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
773 : [output appendString:@"\n"];
774 : [accum setString:@""];
775 : }
776 : [words removeObjectAtIndex:0];
777 : }
778 : [output appendString:accum];
779 : [output appendString:[words oo_stringAtIndex:0]];
780 : }
781 : [output appendString:@"\n"];
782 : }
783 :
784 : return [output autorelease];
785 : }
786 :
787 :
788 : - (void) leaveLastLine
789 : {
790 : unsigned i;
791 : for (i=0; i < n_rows-1; i++)
792 : {
793 : [rowText replaceObjectAtIndex:i withObject:@""];
794 : [rowColor replaceObjectAtIndex:i withObject:textColor];
795 : [rowKey replaceObjectAtIndex:i withObject:@""];
796 : rowAlignment[i] = GUI_ALIGN_LEFT;
797 : rowFadeTime[i] = 0.0f;
798 : }
799 : rowFadeTime[i] = 0.4f; // fade the last line...
800 : }
801 :
802 :
803 : - (NSArray *) getLastLines // text, colour, fade time - text, colour, fade time
804 : {
805 : if (n_rows <1) return nil;
806 :
807 : // we have at least 1 row!
808 :
809 : unsigned i = n_rows-1;
810 : OORGBAComponents col = [(OOColor *)[rowColor objectAtIndex:i] rgbaComponents];
811 :
812 : if (i>0)
813 : {
814 : // we have at least 2 rows!
815 : OORGBAComponents col0 = [(OOColor *)[rowColor objectAtIndex:i-1] rgbaComponents];
816 : return [NSArray arrayWithObjects:[rowText oo_stringAtIndex:i-1],
817 : [NSString stringWithFormat:@"%.3g %.3g %.3g %.3g", col0.r, col0.g, col0.b, col0.a],
818 : [NSNumber numberWithFloat:rowFadeTime[i-1]],
819 : [rowText oo_stringAtIndex:i],
820 : [NSString stringWithFormat:@"%.3g %.3g %.3g %.3g", col.r, col.g, col.b, col.a],
821 : [NSNumber numberWithFloat:rowFadeTime[i]], nil];
822 : }
823 : else
824 : {
825 : return [NSArray arrayWithObjects:[rowText oo_stringAtIndex:i],
826 : [NSString stringWithFormat:@"%.3g %.3g %.3g %.3g", col.r, col.g, col.b, col.a],
827 : [NSNumber numberWithFloat:rowFadeTime[i]], nil];
828 : }
829 : }
830 :
831 :
832 : - (void) printLongText:(NSString *)str
833 : align:(OOGUIAlignment) alignment
834 : color:(OOColor *)text_color
835 : fadeTime:(float)text_fade
836 : key:(NSString *)text_key
837 : addToArray:(NSMutableArray *)text_array
838 : {
839 : // print a multi-line message
840 : //
841 : if ([str rangeOfString:@"\n"].location != NSNotFound)
842 : {
843 : NSArray *lines = [str componentsSeparatedByString:@"\n"];
844 : unsigned i;
845 : for (i = 0; i < [lines count]; i++)
846 : [self printLongText:[lines oo_stringAtIndex:i] align:alignment color:text_color fadeTime:text_fade key:text_key addToArray:text_array];
847 : return;
848 : }
849 :
850 : OOGUIRow row = currentRow;
851 : if (row == (OOGUIRow)n_rows - 1)
852 : [self scrollUp:1];
853 : NSSize chSize = pixel_text_size;
854 : NSSize strsize = OORectFromString(str, 0.0f, 0.0f, chSize).size;
855 : if (strsize.width < size_in_pixels.width)
856 : {
857 : [self setText:str forRow:row align:alignment];
858 : if (text_color)
859 : [self setColor:text_color forRow:row];
860 : if (text_key)
861 : [self setKey:text_key forRow:row];
862 : rowFadeTime[row] = text_fade;
863 : if (currentRow < (OOGUIRow)n_rows - 1)
864 : currentRow++;
865 : if (text_array)
866 : [text_array addObject:str];
867 : }
868 : else
869 : {
870 : NSMutableArray *words = ScanTokensFromString(str);
871 : NSMutableString *string1 = [NSMutableString stringWithCapacity:256];
872 : NSMutableString *string2 = [NSMutableString stringWithCapacity:256];
873 : strsize.width = 0.0f;
874 : while ((strsize.width < size_in_pixels.width)&&([words count] > 0))
875 : {
876 : [string1 appendString:(NSString *)[words objectAtIndex:0]];
877 : [string1 appendString:@" "];
878 : [words removeObjectAtIndex:0];
879 : strsize = OORectFromString(string1, 0.0f, 0.0f, chSize).size;
880 : if ([words count] > 0)
881 : strsize.width += OORectFromString([words oo_stringAtIndex:0], 0.0f, 0.0f, chSize).size.width;
882 : }
883 :
884 : [self setText:string1 forRow:row align:alignment];
885 :
886 : [string2 appendString:[words componentsJoinedByString:@" "]];
887 : if (text_color)
888 : [self setColor:text_color forRow:row];
889 : if (text_key)
890 : [self setKey:text_key forRow:row];
891 : if (text_array)
892 : [text_array addObject:string1];
893 : rowFadeTime[row] = text_fade;
894 : [self printLongText:string2 align:alignment color:text_color fadeTime:text_fade key:text_key addToArray:text_array];
895 : }
896 : }
897 :
898 :
899 : - (void) printLineNoScroll:(NSString *)str
900 : align:(OOGUIAlignment)alignment
901 : color:(OOColor *)text_color
902 : fadeTime:(float)text_fade
903 : key:(NSString *)text_key
904 : addToArray:(NSMutableArray *)text_array
905 : {
906 : [self setText:str forRow:currentRow align:alignment];
907 : if (text_color)
908 : [self setColor:text_color forRow:currentRow];
909 : if (text_key)
910 : [self setKey:text_key forRow:currentRow];
911 : if (text_array)
912 : [text_array addObject:str];
913 : rowFadeTime[currentRow] = text_fade;
914 : }
915 :
916 :
917 : - (void) setArray:(NSArray *)arr forRow:(OOGUIRow)row
918 : {
919 : if (RowInRange(row, rowRange))
920 : [rowText replaceObjectAtIndex:row withObject:arr];
921 : }
922 :
923 :
924 : - (void) insertItemsFromArray:(NSArray *)items
925 : withKeys:(NSArray *)item_keys
926 : intoRow:(OOGUIRow)row
927 : color:(OOColor *)text_color
928 : {
929 : if (!items)
930 : return;
931 : if([items count] == 0)
932 : return;
933 :
934 : NSUInteger n_items = [items count];
935 : if ((item_keys)&&([item_keys count] != n_items))
936 : {
937 : // throw exception
938 : [NSException raise:@"ArrayLengthMismatchException"
939 : format:@"The NSArray sent as 'item_keys' to insertItemsFromArray::: must contain the same number of objects as the NSArray 'items'"];
940 : }
941 :
942 : unsigned i;
943 : for (i = n_rows; i >= row + n_items ; i--)
944 : {
945 : [self setKey:[self keyForRow:i - n_items] forRow:i];
946 : id old_row_info = [self objectForRow:i - n_items];
947 : if ([old_row_info isKindOfClass:[NSArray class]])
948 : [self setArray:old_row_info forRow:i];
949 : if ([old_row_info isKindOfClass:[NSString class]])
950 : [self setText:(NSString *)old_row_info forRow:i];
951 : }
952 : for (i = 0; i < n_items; i++)
953 : {
954 : id new_row_info = [items objectAtIndex:i];
955 : if (text_color)
956 : [self setColor:text_color forRow: row + i];
957 : else
958 : [self setColor:textColor forRow: row + i];
959 : if ([new_row_info isKindOfClass:[NSArray class]])
960 : [self setArray:new_row_info forRow: row + i];
961 : if ([new_row_info isKindOfClass:[NSString class]])
962 : [self setText:(NSString *)new_row_info forRow: row + i];
963 : if (item_keys)
964 : [self setKey:[item_keys objectAtIndex:i] forRow: row + i];
965 : else
966 : [self setKey:@"" forRow: row + i];
967 : }
968 : }
969 :
970 :
971 : - (void) scrollUp:(int) how_much
972 : {
973 : unsigned i;
974 : for (i = 0; i + how_much < n_rows; i++)
975 : {
976 : [rowText replaceObjectAtIndex:i withObject:[rowText objectAtIndex: i + how_much]];
977 : [rowColor replaceObjectAtIndex:i withObject:[rowColor objectAtIndex: i + how_much]];
978 : [rowKey replaceObjectAtIndex:i withObject:[rowKey objectAtIndex: i + how_much]];
979 : rowAlignment[i] = rowAlignment[i + how_much];
980 : rowFadeTime[i] = rowFadeTime[i + how_much];
981 : }
982 : for (; i < n_rows; i++)
983 : {
984 : [rowText replaceObjectAtIndex:i withObject:@""];
985 : [rowColor replaceObjectAtIndex:i withObject:textColor];
986 : [rowKey replaceObjectAtIndex:i withObject:@""];
987 : rowAlignment[i] = GUI_ALIGN_LEFT;
988 : rowFadeTime[i] = 0.0f;
989 : }
990 : }
991 :
992 :
993 : - (void) clearBackground
994 : {
995 : [self setBackgroundTextureDescriptor:nil];
996 : [self setForegroundTextureDescriptor:nil];
997 : }
998 :
999 :
1000 0 : static OOTexture *TextureForGUITexture(NSDictionary *descriptor)
1001 : {
1002 : /*
1003 : GUI textures like backgrounds, foregrounds etc. are not processed in any way after loading. However, they are
1004 : subject to tone nmapping and gamma correction at the end of the render pass. So we need to declare them as
1005 : SRGBA textures here so that OpenGL will automatically convert them to linear space upon loading and the
1006 : subsequent tone mapping and gamma correction shader operations will not result in heavy distortion of their
1007 : colors.
1008 :
1009 : Also, remember that if no shaders are in use (as in lower detail levels), then we don't need to declare anything.
1010 : */
1011 : uint32_t srgbaOption = 0UL;
1012 : if ([UNIVERSE useShaders]) srgbaOption = kOOTextureSRGBA;
1013 : return [OOTexture textureWithName:[descriptor oo_stringForKey:@"name"]
1014 : inFolder:@"Images"
1015 : options:kOOTextureDefaultOptions | kOOTextureNoShrink | srgbaOption
1016 : anisotropy:kOOTextureDefaultAnisotropy
1017 : lodBias:kOOTextureDefaultLODBias];
1018 : }
1019 :
1020 :
1021 : /*
1022 : Load a texture sprite given a descriptor. The caller owns a reference to
1023 : the result.
1024 : */
1025 0 : static OOTextureSprite *NewTextureSpriteWithDescriptor(NSDictionary *descriptor)
1026 : {
1027 : OOTexture *texture = nil;
1028 : NSSize size;
1029 :
1030 : texture = TextureForGUITexture(descriptor);
1031 : if (texture == nil) return nil;
1032 :
1033 : double specifiedWidth = [descriptor oo_doubleForKey:@"width" defaultValue:-INFINITY];
1034 : double specifiedHeight = [descriptor oo_doubleForKey:@"height" defaultValue:-INFINITY];
1035 : BOOL haveWidth = isfinite(specifiedWidth);
1036 : BOOL haveHeight = isfinite(specifiedHeight);
1037 :
1038 : if (haveWidth && haveHeight)
1039 : {
1040 : // Both specified, use directly without calling -originalDimensions (which may block).
1041 : size.width = specifiedWidth;
1042 : size.height = specifiedHeight;
1043 : }
1044 : else
1045 : {
1046 : NSSize originalDimensions = [texture originalDimensions];
1047 :
1048 : if (haveWidth)
1049 : {
1050 : // Width specified, but not height; preserve aspect ratio.
1051 : CGFloat ratio = originalDimensions.height / originalDimensions.width;
1052 : size.width = specifiedWidth;
1053 : size.height = ratio * size.width;
1054 : }
1055 : else if (haveHeight)
1056 : {
1057 : // Height specified, but not width; preserve aspect ratio.
1058 : CGFloat ratio = originalDimensions.width / originalDimensions.height;
1059 : size.height = specifiedHeight;
1060 : size.width = ratio * size.height;
1061 : }
1062 : else
1063 : {
1064 : // Neither specified; use backwards-compatible behaviour.
1065 : size = originalDimensions;
1066 : }
1067 : }
1068 :
1069 : return [[OOTextureSprite alloc] initWithTexture:texture size:size];
1070 : }
1071 :
1072 :
1073 : - (void) setBackgroundTextureSpecial:(OOGUIBackgroundSpecial)spec withBackground:(BOOL)withBackground
1074 : {
1075 : if (withBackground)
1076 : {
1077 : NSDictionary *bgDescriptor = nil;
1078 : OOGalaxyID galaxy_number = [PLAYER galaxyNumber];
1079 :
1080 : switch (spec)
1081 : {
1082 : case GUI_BACKGROUND_SPECIAL_CUSTOM:
1083 : case GUI_BACKGROUND_SPECIAL_CUSTOM_ANA_SHORTEST:
1084 : case GUI_BACKGROUND_SPECIAL_CUSTOM_ANA_QUICKEST:
1085 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:@"custom_chart_mission"];
1086 : if (bgDescriptor == nil)
1087 : {
1088 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:@"short_range_chart_mission"];
1089 : if (bgDescriptor == nil)
1090 : {
1091 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:@"short_range_chart"];
1092 : }
1093 : }
1094 : break;
1095 : case GUI_BACKGROUND_SPECIAL_SHORT:
1096 : case GUI_BACKGROUND_SPECIAL_SHORT_ANA_SHORTEST:
1097 : case GUI_BACKGROUND_SPECIAL_SHORT_ANA_QUICKEST:
1098 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:@"short_range_chart_mission"];
1099 : if (bgDescriptor == nil)
1100 : {
1101 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:@"short_range_chart"];
1102 : }
1103 : break;
1104 : case GUI_BACKGROUND_SPECIAL_LONG:
1105 : case GUI_BACKGROUND_SPECIAL_LONG_ANA_SHORTEST:
1106 : case GUI_BACKGROUND_SPECIAL_LONG_ANA_QUICKEST:
1107 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:[NSString stringWithFormat:@"long_range_chart%d_mission", galaxy_number+1]];
1108 : if (bgDescriptor == nil)
1109 : {
1110 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:@"long_range_chart_mission"];
1111 : if (bgDescriptor == nil)
1112 : {
1113 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:[NSString stringWithFormat:@"long_range_chart%d", galaxy_number+1]];
1114 : if (bgDescriptor == nil)
1115 : {
1116 : bgDescriptor = [UNIVERSE screenTextureDescriptorForKey:@"long_range_chart"];
1117 :
1118 : }
1119 : }
1120 : }
1121 : break;
1122 : case GUI_BACKGROUND_SPECIAL_NONE:
1123 : break;
1124 : }
1125 : if (bgDescriptor != nil)
1126 : {
1127 : [self setBackgroundTextureDescriptor:bgDescriptor];
1128 : }
1129 : }
1130 : backgroundSpecial = spec;
1131 : [self refreshStarChart];
1132 : }
1133 :
1134 :
1135 : - (BOOL) setBackgroundTextureDescriptor:(NSDictionary *)descriptor
1136 : {
1137 : [backgroundSprite autorelease];
1138 : backgroundSpecial = GUI_BACKGROUND_SPECIAL_NONE; // reset
1139 : backgroundSprite = NewTextureSpriteWithDescriptor(descriptor);
1140 : return backgroundSprite != nil;
1141 : }
1142 :
1143 :
1144 : - (BOOL) setForegroundTextureDescriptor:(NSDictionary *)descriptor
1145 : {
1146 : [foregroundSprite autorelease];
1147 : foregroundSprite = NewTextureSpriteWithDescriptor(descriptor);
1148 : return foregroundSprite != nil;
1149 : }
1150 :
1151 :
1152 : - (BOOL) setBackgroundTextureKey:(NSString *)key
1153 : {
1154 : return [self setBackgroundTextureDescriptor:[UNIVERSE screenTextureDescriptorForKey:key]];
1155 : }
1156 :
1157 :
1158 : - (BOOL) setForegroundTextureKey:(NSString *)key
1159 : {
1160 : return [self setForegroundTextureDescriptor:[UNIVERSE screenTextureDescriptorForKey:key]];
1161 : }
1162 :
1163 :
1164 : - (BOOL) preloadGUITexture:(NSDictionary *)descriptor
1165 : {
1166 : return TextureForGUITexture(descriptor) != nil;
1167 : }
1168 :
1169 :
1170 : - (NSDictionary *) textureDescriptorFromJSValue:(jsval)value
1171 : inContext:(JSContext *)context
1172 : callerDescription:(NSString *)callerDescription
1173 : {
1174 : OOJS_PROFILE_ENTER
1175 :
1176 : NSDictionary *result = nil;
1177 :
1178 : if (JSVAL_IS_OBJECT(value))
1179 : {
1180 : // Null may be used to indicate no texture.
1181 : if (JSVAL_IS_NULL(value)) return [NSDictionary dictionary];
1182 :
1183 : JSObject *objValue = JSVAL_TO_OBJECT(value);
1184 :
1185 : if (OOJSGetClass(context, objValue) != [[OOJavaScriptEngine sharedEngine] stringClass])
1186 : {
1187 : result = OOJSDictionaryFromJSObject(context, objValue);
1188 : }
1189 : }
1190 :
1191 : if (result == nil)
1192 : {
1193 : NSString *name = OOStringFromJSValue(context, value);
1194 :
1195 : if (name != nil)
1196 : {
1197 : result = [NSDictionary dictionaryWithObject:name forKey:@"name"];
1198 : if ([name length] == 0) return result; // Explicit empty string may be used to indicate no texture.
1199 : }
1200 : }
1201 :
1202 : // Start loading the texture, and return nil if it doesn't exist.
1203 : if (result != nil && ![self preloadGUITexture:result])
1204 : {
1205 : OOJSReportWarning(context, @"%@: texture \"%@\" could not be found.", callerDescription, [result oo_stringForKey:@"name"]);
1206 : result = nil;
1207 : }
1208 :
1209 : return result;
1210 :
1211 : OOJS_PROFILE_EXIT
1212 : }
1213 :
1214 :
1215 : - (void) setStatusPage:(NSInteger)pageNum
1216 : {
1217 : if (pageNum == 0 || (pageNum < 0 && ((NSUInteger)-pageNum) >= statusPage))
1218 : {
1219 : statusPage = 1;
1220 : }
1221 : else
1222 : {
1223 : statusPage += pageNum;
1224 : }
1225 : }
1226 :
1227 :
1228 : - (NSUInteger) statusPage
1229 : {
1230 : return statusPage;
1231 : }
1232 :
1233 :
1234 1 : - (void) drawEquipmentList:(NSArray *)eqptList z:(GLfloat)z
1235 : {
1236 : if ([eqptList count] == 0) return;
1237 :
1238 : OOGUIRow firstRow = STATUS_EQUIPMENT_FIRST_ROW;
1239 : NSUInteger maxRows = STATUS_EQUIPMENT_MAX_ROWS;
1240 : if ([[PLAYER hud] allowBigGui])
1241 : {
1242 : maxRows += STATUS_EQUIPMENT_BIGGUI_EXTRA_ROWS;
1243 : }
1244 : NSUInteger itemsPerColumn = maxRows;
1245 :
1246 :
1247 : NSInteger firstY = 40; // firstRow =10 :-> 40 - firstRow=11 -> 24 etc...
1248 : NSUInteger eqptCount = [eqptList count];
1249 : NSUInteger pageCount = 1;
1250 : NSUInteger i;
1251 : NSInteger start;
1252 : NSArray *info = nil;
1253 : NSString *name = nil;
1254 : BOOL damaged;
1255 :
1256 : // Paging calculations. Assuming 10 lines we get - one page:20 items per page (ipp)
1257 : // two pages: 18 ipp - three+ pages: 1st & last 18pp, middle pages 16ipp
1258 :
1259 : i = itemsPerColumn * 2 + 2;
1260 : if (eqptCount > i) // don't fit in one page?
1261 : {
1262 : [[UNIVERSE gameController] setMouseInteractionModeForUIWithMouseInteraction:YES];
1263 :
1264 : i = itemsPerColumn * 4; // total items in the first and last pages
1265 : itemsPerColumn--; // for all the middle pages.
1266 : if (eqptCount <= i) // two pages
1267 : {
1268 : pageCount++;
1269 : if (statusPage == 1)
1270 : {
1271 : start = 0;
1272 : }
1273 : else
1274 : {
1275 : statusPage = 2;
1276 : start = i/statusPage; // for the for loop
1277 : }
1278 : }
1279 : else // three or more
1280 : {
1281 : pageCount = ceil((float)(eqptCount-i)/(itemsPerColumn*2)) + 2;
1282 : statusPage = (NSInteger)OOClampInteger(statusPage, 1, pageCount);
1283 : start = (statusPage == 1) ? 0 : (statusPage-1) * itemsPerColumn * 2 + 2;
1284 : }
1285 : }
1286 : else
1287 : {
1288 : statusPage = pageCount; // one page
1289 : start = 0;
1290 : // if we have mouse interaction active, it means that we had more than one
1291 : // pages earlier, but only one now, as e.g. in the case of a hud that wss
1292 : // subsequently hidden, resulting in the equip list fitting in one page,
1293 : // so we need to deactivate it
1294 : if (OOMouseInteractionModeIsUIScreen([[UNIVERSE gameController] mouseInteractionMode]))
1295 : {
1296 : // clear the gui-more and gui-back key rows first
1297 : [self setText:@"" forRow:firstRow];
1298 : [self setKey:GUI_KEY_SKIP forRow:firstRow];
1299 : [self setText:@"" forRow:firstRow + STATUS_EQUIPMENT_MAX_ROWS];
1300 : [self setKey:GUI_KEY_SKIP forRow:firstRow + STATUS_EQUIPMENT_MAX_ROWS];
1301 : [self setSelectableRange:NSMakeRange(0,0)];
1302 :
1303 : [[UNIVERSE gameController] setMouseInteractionModeForUIWithMouseInteraction:NO];
1304 : }
1305 : }
1306 :
1307 : if (statusPage > 1)
1308 : {
1309 : [self setColor:[self colorFromSetting:kGuiStatusEquipmentScrollColor defaultValue:[OOColor greenColor]] forRow:firstRow];
1310 : [self setArray:[NSArray arrayWithObjects:DESC(@"gui-back"), @"", @" <-- ",nil] forRow:firstRow];
1311 : [self setKey:GUI_KEY_OK forRow:firstRow];
1312 : firstY -= 16; // start 1 row down!
1313 : if (statusPage == pageCount)
1314 : {
1315 : [self setSelectableRange:NSMakeRange(firstRow, 1)];
1316 : [self setSelectedRow:firstRow];
1317 : }
1318 : }
1319 : if (statusPage < pageCount)
1320 : {
1321 : [self setColor:[self colorFromSetting:kGuiStatusEquipmentScrollColor defaultValue:[OOColor greenColor]] forRow:firstRow + maxRows];
1322 : [self setArray:[NSArray arrayWithObjects:DESC(@"gui-more"), @"", @" --> ",nil] forRow:firstRow + maxRows];
1323 : [self setKey:GUI_KEY_OK forRow:firstRow + maxRows];
1324 : if (statusPage == 1)
1325 : {
1326 : [self setSelectableRange:NSMakeRange(firstRow + maxRows, 1)];
1327 : [self setSelectedRow:firstRow + maxRows];
1328 : }
1329 : }
1330 : if (statusPage > 1 && statusPage < pageCount)
1331 : {
1332 : [self setSelectableRange:NSMakeRange(firstRow, MIN(firstRow + maxRows, GUI_DEFAULT_ROWS - firstRow))];
1333 : // default selected row to 'More -->' if we are looking at one of the middle pages
1334 : if ([self selectedRow] == -1) [self setSelectedRow:firstRow + maxRows];
1335 : }
1336 :
1337 : if (statusPage == 1 || statusPage == pageCount) itemsPerColumn++;
1338 : eqptCount = (NSInteger)OOClampInteger(eqptCount, 1, start + itemsPerColumn * 2);
1339 : for (i = start; i < eqptCount; i++)
1340 : {
1341 : info = [eqptList oo_arrayAtIndex:i];
1342 : name = [info oo_stringAtIndex:0];
1343 : if([name length] > 42) name = [[name substringToIndex:40] stringByAppendingString:@"..."];
1344 :
1345 : damaged = ![info oo_boolAtIndex:1];
1346 : if (damaged)
1347 : {
1348 : // Damaged items show up orange.
1349 : [self setGLColorFromSetting:@"status_equipment_damaged_color" defaultValue:[OOColor orangeColor] alpha:1.0];
1350 : }
1351 : else /// add color selection here
1352 : {
1353 : OOColor *dispCol = [info oo_objectAtIndex:2];
1354 : // Normal items in default colour
1355 : [self setGLColorFromSetting:@"status_equipment_ok_color" defaultValue:dispCol alpha:1.0];
1356 : }
1357 :
1358 : if (i - start < itemsPerColumn)
1359 : {
1360 : OODrawString(name, -220, firstY - 16 * (NSInteger)(i - start), z, NSMakeSize(15, 15));
1361 : }
1362 : else
1363 : {
1364 : OODrawString(name, 50, firstY - 16 * (NSInteger)(i - itemsPerColumn - start), z, NSMakeSize(15, 15));
1365 : }
1366 : }
1367 : }
1368 :
1369 :
1370 : - (void) drawGUIBackground
1371 : {
1372 : GLfloat x = drawPosition.x;
1373 : GLfloat y = drawPosition.y;
1374 : GLfloat z = [[UNIVERSE gameView] display_z];
1375 :
1376 : if (backgroundSprite!=nil)
1377 : {
1378 : [backgroundSprite blitBackgroundCentredToX:x Y:y Z:z alpha:1.0f];
1379 : }
1380 :
1381 : }
1382 :
1383 :
1384 : - (void) refreshStarChart
1385 : {
1386 : _refreshStarChart = YES;
1387 : }
1388 :
1389 :
1390 : - (int) drawGUI:(GLfloat) alpha drawCursor:(BOOL) drawCursor
1391 : {
1392 : GLfloat x = drawPosition.x;
1393 : GLfloat y = drawPosition.y;
1394 : GLfloat z = [[UNIVERSE gameView] display_z];
1395 :
1396 : if (alpha > 0.05f)
1397 : {
1398 : PlayerEntity* player = PLAYER;
1399 :
1400 : [self drawGLDisplay:x - 0.5f * size_in_pixels.width :y - 0.5f * size_in_pixels.height :z :alpha];
1401 :
1402 : if (self == [UNIVERSE gui])
1403 : {
1404 : if ([player guiScreen] == GUI_SCREEN_SHORT_RANGE_CHART || [player guiScreen] == GUI_SCREEN_LONG_RANGE_CHART ||
1405 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_SHORT ||
1406 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_SHORT_ANA_QUICKEST ||
1407 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_SHORT_ANA_SHORTEST ||
1408 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_CUSTOM ||
1409 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_CUSTOM_ANA_QUICKEST ||
1410 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_CUSTOM_ANA_SHORTEST)
1411 : {
1412 : [self drawStarChart:x - 0.5f * size_in_pixels.width :y - 0.5f * size_in_pixels.height :z :alpha :NO];
1413 : }
1414 : if (backgroundSpecial == GUI_BACKGROUND_SPECIAL_LONG ||
1415 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_LONG_ANA_QUICKEST ||
1416 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_LONG_ANA_SHORTEST)
1417 : {
1418 : [self drawStarChart:x - 0.5f * size_in_pixels.width :y - 0.5f * size_in_pixels.height :z :alpha :YES];
1419 : }
1420 : if ([player guiScreen] == GUI_SCREEN_STATUS)
1421 : {
1422 : [self drawEquipmentList:[player equipmentList] z:z];
1423 : }
1424 : if ([player guiScreen] == GUI_SCREEN_STICKPROFILE)
1425 : {
1426 : [player stickProfileGraphAxisProfile: alpha screenAt: make_vector(x,y,z) screenSize: size_in_pixels];
1427 : }
1428 : }
1429 :
1430 : if (fade_sign)
1431 : {
1432 : fade_alpha += (float)(fade_sign * [UNIVERSE getTimeDelta]);
1433 : if (fade_alpha < 0.05f) // done fading out
1434 : {
1435 : fade_alpha = 0.0f;
1436 : fade_sign = 0.0f;
1437 : }
1438 : if (fade_alpha >= max_alpha) // done fading in
1439 : {
1440 : fade_alpha = max_alpha;
1441 : fade_sign = 0.0f;
1442 : }
1443 : }
1444 : }
1445 :
1446 : int cursor_row = 0;
1447 :
1448 : if (drawCursor)
1449 : {
1450 : NSPoint vjpos = [[UNIVERSE gameView] virtualJoystickPosition];
1451 : double cursor_x = size_in_pixels.width * vjpos.x;
1452 : if (cursor_x < -size_in_pixels.width * 0.5) cursor_x = -size_in_pixels.width * 0.5f;
1453 : if (cursor_x > size_in_pixels.width * 0.5) cursor_x = size_in_pixels.width * 0.5f;
1454 : double cursor_y = -size_in_pixels.height * vjpos.y;
1455 : if (cursor_y < -size_in_pixels.height * 0.5) cursor_y = -size_in_pixels.height * 0.5f;
1456 : if (cursor_y > size_in_pixels.height * 0.5) cursor_y = size_in_pixels.height * 0.5f;
1457 :
1458 : cursor_row = 1 + (float)floor((0.5f * size_in_pixels.height - pixel_row_start - cursor_y) / pixel_row_height);
1459 :
1460 : GLfloat h1 = 3.0f;
1461 : GLfloat h3 = 9.0f;
1462 : OOGL(glColor4f(0.6f, 0.6f, 1.0f, 1.0f)); // original value of (0.2f, 0.2f, 1.0f, 0.5f) too dark - Nikos 20130616
1463 : OOGL(GLScaledLineWidth(2.0f));
1464 :
1465 : cursor_x += x;
1466 : cursor_y += y;
1467 : [[UNIVERSE gameView] setVirtualJoystick:cursor_x/size_in_pixels.width :-cursor_y/size_in_pixels.height];
1468 :
1469 : OOGLBEGIN(GL_LINES);
1470 : glVertex3f((float)cursor_x - h1, (float)cursor_y, z); glVertex3f((float)cursor_x - h3, (float)cursor_y, z);
1471 : glVertex3f((float)cursor_x + h1, (float)cursor_y, z); glVertex3f((float)cursor_x + h3, (float)cursor_y, z);
1472 : glVertex3f((float)cursor_x, (float)cursor_y - h1, z); glVertex3f((float)cursor_x, (float)cursor_y - h3, z);
1473 : glVertex3f((float)cursor_x, (float)cursor_y + h1, z); glVertex3f((float)cursor_x, (float)cursor_y + h3, z);
1474 : OOGLEND();
1475 : OOGL(GLScaledLineWidth(1.0f));
1476 :
1477 : }
1478 :
1479 : return cursor_row;
1480 : }
1481 :
1482 :
1483 0 : - (void) drawGLDisplay:(GLfloat)x :(GLfloat)y :(GLfloat)z :(GLfloat) alpha
1484 : {
1485 : NSSize strsize;
1486 : unsigned i;
1487 : OOTimeDelta delta_t = [UNIVERSE getTimeDelta];
1488 : NSSize characterSize = pixel_text_size;
1489 : NSSize titleCharacterSize = pixel_title_size;
1490 : float backgroundAlpha = self == [UNIVERSE messageGUI] && ![UNIVERSE permanentMessageLog] ? 0.0f : alpha;
1491 : float row_alpha[n_rows];
1492 :
1493 : // calculate fade out time and alpha for each row. Do it before
1494 : // applying a potential background because we need the maximum alpha
1495 : // of all rows to be the alpha applied to the background color
1496 : for (i = 0; i < n_rows; i++)
1497 : {
1498 : row_alpha[i] = alpha;
1499 :
1500 : if(![UNIVERSE autoMessageLogBg] && [PLAYER guiScreen] == GUI_SCREEN_MAIN) backgroundAlpha = alpha;
1501 :
1502 : if (rowFadeTime[i] > 0.0f && ![UNIVERSE permanentMessageLog])
1503 : {
1504 : rowFadeTime[i] -= (float)delta_t;
1505 : if (rowFadeTime[i] <= 0.0f)
1506 : {
1507 : [rowText replaceObjectAtIndex:i withObject:@""];
1508 : rowFadeTime[i] = 0.0f;
1509 : continue;
1510 : }
1511 : if ((rowFadeTime[i] > 0.0f)&&(rowFadeTime[i] < 1.0))
1512 : {
1513 : row_alpha[i] *= rowFadeTime[i];
1514 : if (backgroundAlpha < row_alpha[i]) backgroundAlpha = row_alpha[i];
1515 : }
1516 : else
1517 : {
1518 : backgroundAlpha = alpha;
1519 : }
1520 : }
1521 : }
1522 :
1523 : // do backdrop
1524 : // don't draw it if docked, unless message_gui is permanent
1525 : // don't draw it on the intro screens
1526 : if (backgroundColor)
1527 : {
1528 : int playerStatus = [PLAYER status];
1529 : if (playerStatus != STATUS_START_GAME && playerStatus != STATUS_DEAD)
1530 : {
1531 : OOGL(glColor4f([backgroundColor redComponent], [backgroundColor greenComponent], [backgroundColor blueComponent], backgroundAlpha * [backgroundColor alphaComponent]));
1532 : OOGLBEGIN(GL_QUADS);
1533 : glVertex3f(x + 0.0f, y + 0.0f, z);
1534 : glVertex3f(x + size_in_pixels.width, y + 0.0f, z);
1535 : glVertex3f(x + size_in_pixels.width, y + size_in_pixels.height, z);
1536 : glVertex3f(x + 0.0f, y + size_in_pixels.height, z);
1537 : OOGLEND();
1538 : }
1539 : }
1540 :
1541 : // show the 'foreground', aka overlay!
1542 :
1543 : if (foregroundSprite != nil)
1544 : {
1545 : [foregroundSprite blitCentredToX:x + 0.5f * size_in_pixels.width Y:y + 0.5f * size_in_pixels.height Z:z alpha:alpha];
1546 : }
1547 :
1548 : if (!RowInRange(selectedRow, selectableRange))
1549 : selectedRow = -1; // out of Range;
1550 :
1551 : ////
1552 : // drawing operations here
1553 :
1554 : if (title != nil)
1555 : {
1556 : //
1557 : // draw the title
1558 : //
1559 : strsize = OORectFromString(title, 0.0f, 0.0f, titleCharacterSize).size;
1560 : [self setGLColorFromSetting:kGuiScreenTitleColor defaultValue:[OOColor redColor] alpha:alpha];
1561 :
1562 : OODrawString(title, x + pixel_row_center - strsize.width/2.0, y + size_in_pixels.height - pixel_title_size.height, z, titleCharacterSize);
1563 :
1564 : // draw a horizontal divider
1565 : //
1566 : [self setGLColorFromSetting:kGuiScreenDividerColor defaultValue:[OOColor colorWithWhite:0.75 alpha:1.0] alpha:alpha];
1567 :
1568 : OOGLBEGIN(GL_QUADS);
1569 : glVertex3f(x + 0, y + size_in_pixels.height - pixel_title_size.height + 4, z);
1570 : glVertex3f(x + size_in_pixels.width, y + size_in_pixels.height - pixel_title_size.height + 4, z);
1571 : glVertex3f(x + size_in_pixels.width, y + size_in_pixels.height - pixel_title_size.height + 2, z);
1572 : glVertex3f(x + 0, y + size_in_pixels.height - pixel_title_size.height + 2, z);
1573 : OOGLEND();
1574 : }
1575 :
1576 : // draw each row of text
1577 : //
1578 : OOStartDrawingStrings();
1579 : for (i = 0; i < n_rows; i++)
1580 : {
1581 : OOColor* row_color = (OOColor *)[rowColor objectAtIndex:i];
1582 : glColor4f([row_color redComponent], [row_color greenComponent], [row_color blueComponent], row_alpha[i]);
1583 :
1584 : if ([[rowText objectAtIndex:i] isKindOfClass:[NSString class]])
1585 : {
1586 : NSString* text = (NSString *)[rowText objectAtIndex:i];
1587 : if (![text isEqual:@""])
1588 : {
1589 : strsize = OORectFromString(text, 0.0f, 0.0f, characterSize).size;
1590 : switch (rowAlignment[i])
1591 : {
1592 : case GUI_ALIGN_LEFT :
1593 : rowPosition[i].x = 0.0f;
1594 : break;
1595 : case GUI_ALIGN_RIGHT :
1596 : rowPosition[i].x = size_in_pixels.width - strsize.width;
1597 : break;
1598 : case GUI_ALIGN_CENTER :
1599 : rowPosition[i].x = (size_in_pixels.width - strsize.width)/2.0f;
1600 : break;
1601 : }
1602 : if (i == (unsigned)selectedRow)
1603 : {
1604 : NSRect block = OORectFromString(text, x + rowPosition[i].x + 2, y + rowPosition[i].y + 2, characterSize);
1605 : OOStopDrawingStrings();
1606 : [self setGLColorFromSetting:kGuiSelectedRowBackgroundColor defaultValue:[OOColor redColor] alpha:alpha];
1607 : OOGLBEGIN(GL_QUADS);
1608 : glVertex3f(block.origin.x, block.origin.y, z);
1609 : glVertex3f(block.origin.x + block.size.width, block.origin.y, z);
1610 : glVertex3f(block.origin.x + block.size.width, block.origin.y + block.size.height, z);
1611 : glVertex3f(block.origin.x, block.origin.y + block.size.height, z);
1612 : OOGLEND();
1613 : [self setGLColorFromSetting:kGuiSelectedRowColor defaultValue:[OOColor blackColor] alpha:alpha];
1614 : OOStartDrawingStrings();
1615 : }
1616 : OODrawStringQuadsAligned(text, x + rowPosition[i].x, y + rowPosition[i].y, z, characterSize, NO);
1617 :
1618 : // draw cursor at end of current Row
1619 : //
1620 : if ((showTextCursor)&&(i == (unsigned)currentRow))
1621 : {
1622 : NSRect tr = OORectFromString(text, 0.0f, 0.0f, characterSize);
1623 : NSPoint cu = NSMakePoint(x + rowPosition[i].x + tr.size.width + 0.2f * characterSize.width, y + rowPosition[i].y);
1624 : tr.origin = cu;
1625 : tr.size.width = 0.5f * characterSize.width;
1626 : GLfloat g_alpha = 0.5f * (1.0f + (float)sin(6 * [UNIVERSE getTime]));
1627 : OOStopDrawingStrings();
1628 : [self setGLColorFromSetting:kGuiTextInputCursorColor defaultValue:[OOColor redColor] alpha:row_alpha[i]*g_alpha];
1629 : OOGLBEGIN(GL_QUADS);
1630 : glVertex3f(tr.origin.x, tr.origin.y, z);
1631 : glVertex3f(tr.origin.x + tr.size.width, tr.origin.y, z);
1632 : glVertex3f(tr.origin.x + tr.size.width, tr.origin.y + tr.size.height, z);
1633 : glVertex3f(tr.origin.x, tr.origin.y + tr.size.height, z);
1634 : OOGLEND();
1635 : OOStartDrawingStrings();
1636 : }
1637 : }
1638 : }
1639 : if ([[rowText objectAtIndex:i] isKindOfClass:[NSArray class]])
1640 : {
1641 : NSArray *array = [rowText oo_arrayAtIndex:i];
1642 : NSUInteger j, max_columns = MIN([array count], n_columns);
1643 : BOOL isLeftAligned;
1644 :
1645 : for (j = 0; j < max_columns; j++)
1646 : {
1647 : NSString* text = [array oo_stringAtIndex:j];
1648 : if ([text length] != 0)
1649 : {
1650 : isLeftAligned = tabStops[j] >= 0;
1651 : rowPosition[i].x = labs(tabStops[j]);
1652 :
1653 : // we don't want to highlight leading space(s) or narrow spaces (\037s)
1654 : NSString *hilitedText = [text stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" \037"]];
1655 : NSRange txtRange = [text rangeOfString:hilitedText];
1656 : unsigned leadingSpaces = 0;
1657 :
1658 : if (EXPECT_NOT(txtRange.location == NSNotFound))
1659 : {
1660 : // This never happens!
1661 : hilitedText = text;
1662 : }
1663 : else if (txtRange.location > 0)
1664 : {
1665 : // padded string!
1666 : NSRange padRange;
1667 : padRange.location = 0;
1668 : padRange.length = txtRange.location;
1669 : NSRect charBlock = OORectFromString([text substringWithRange:padRange], 0, 0, characterSize);
1670 : leadingSpaces = (unsigned)charBlock.size.width;
1671 :
1672 : /* // if we're displaying commodity-quantity-none, let's try and be pixel perfect!
1673 : NSString *qtyNone = DESC(@"commodity-quantity-none");
1674 : txtRange = [hilitedText rangeOfString:qtyNone];
1675 :
1676 : if (txtRange.location == 0) // bingo!
1677 : {
1678 : rowPosition[i].x += OORectFromString(@"0", 0, 0, characterSize).size.width - OORectFromString(qtyNone, 0, 0, characterSize).size.width;
1679 : } */
1680 : }
1681 :
1682 : // baseline text rect, needed for correct highlight positioning.
1683 : NSRect block = OORectFromString(text, x + rowPosition[i].x + 2, y + rowPosition[i].y + 2, characterSize);
1684 :
1685 : if(!isLeftAligned)
1686 : {
1687 : rowPosition[i].x -= block.size.width + 3;
1688 : }
1689 : block = OORectFromString(hilitedText, x + rowPosition[i].x + 1 + leadingSpaces, y + rowPosition[i].y + 2, characterSize);
1690 : block.size.width += 3;
1691 :
1692 :
1693 : if (i == (unsigned)selectedRow)
1694 : {
1695 : OOStopDrawingStrings();
1696 : [self setGLColorFromSetting:kGuiSelectedRowBackgroundColor defaultValue:[OOColor redColor] alpha:alpha];
1697 : OOGLBEGIN(GL_QUADS);
1698 : glVertex3f(block.origin.x, block.origin.y, z);
1699 : glVertex3f(block.origin.x + block.size.width, block.origin.y, z);
1700 : glVertex3f(block.origin.x + block.size.width, block.origin.y + block.size.height, z);
1701 : glVertex3f(block.origin.x, block.origin.y + block.size.height, z);
1702 : OOGLEND();
1703 : [self setGLColorFromSetting:kGuiSelectedRowColor defaultValue:[OOColor blackColor] alpha:alpha];
1704 : OOStartDrawingStrings();
1705 : }
1706 : OODrawStringQuadsAligned(text, x + rowPosition[i].x, y + rowPosition[i].y, z, characterSize,NO);
1707 : }
1708 : }
1709 : }
1710 : }
1711 : OOStopDrawingStrings();
1712 : [OOTexture applyNone];
1713 : }
1714 :
1715 :
1716 0 : - (void) drawCrossHairsWithSize:(GLfloat) size x:(GLfloat)x y:(GLfloat)y z:(GLfloat)z
1717 : {
1718 : OOGLBEGIN(GL_QUADS);
1719 : glVertex3f(x - 1, y - size, z);
1720 : glVertex3f(x + 1, y - size, z);
1721 : glVertex3f(x + 1, y + size, z);
1722 : glVertex3f(x - 1, y + size, z);
1723 : glVertex3f(x - size, y - 1, z);
1724 : glVertex3f(x + size, y - 1, z);
1725 : glVertex3f(x + size, y + 1, z);
1726 : glVertex3f(x - size, y + 1, z);
1727 : OOGLEND();
1728 : }
1729 :
1730 :
1731 : - (void) setStarChartTitle
1732 : {
1733 : PlayerEntity *player = PLAYER;
1734 : OOGalaxyID galaxy_number = [player galaxyNumber];
1735 : NSInteger system_id = [UNIVERSE findSystemNumberAtCoords:[player cursor_coordinates] withGalaxy:[player galaxyNumber] includingHidden:NO];
1736 :
1737 : NSString *location_key = [NSString stringWithFormat:@"long-range-chart-title-%d-%ld", galaxy_number, (long)system_id];
1738 : if ([[UNIVERSE descriptions] valueForKey:location_key] == nil)
1739 : {
1740 : NSString *gal_key = [NSString stringWithFormat:@"long-range-chart-title-%d", galaxy_number];
1741 : if ([[UNIVERSE descriptions] valueForKey:gal_key] == nil)
1742 : {
1743 : [self setTitle:[NSString stringWithFormat:DESC(@"long-range-chart-title-d"), galaxy_number+1]];
1744 : }
1745 : else
1746 : {
1747 : [self setTitle:[UNIVERSE descriptionForKey:gal_key]];
1748 : }
1749 : }
1750 : else
1751 : {
1752 : [self setTitle:[UNIVERSE descriptionForKey:location_key]];
1753 : }
1754 : }
1755 :
1756 :
1757 0 : - (void) drawStarChart:(GLfloat)x :(GLfloat)y :(GLfloat)z :(GLfloat) alpha :(BOOL)compact
1758 : {
1759 : PlayerEntity* player = PLAYER;
1760 :
1761 : if (!player)
1762 : return;
1763 :
1764 : OOSystemDescriptionManager *systemManager = [UNIVERSE systemManager];
1765 :
1766 : OOScalar zoom = [player chart_zoom];
1767 : NSPoint chart_centre_coordinates = [player adjusted_chart_centre];
1768 : NSPoint galaxy_coordinates = [player galaxy_coordinates];
1769 : NSPoint cursor_coordinates = [player cursor_coordinates];
1770 : NSPoint info_system_coordinates = [[UNIVERSE systemManager] getCoordinatesForSystem: [player infoSystemID] inGalaxy: [player galaxyNumber]];
1771 : OOLongRangeChartMode chart_mode = [player longRangeChartMode];
1772 : OOGalaxyID galaxy_id = [player galaxyNumber];
1773 : GLfloat r = 1.0, g = 1.0, b = 1.0;
1774 : BOOL noNova;
1775 : NSPoint cu;
1776 : NSUInteger systemParameter;
1777 :
1778 : double fuel = 35.0 * [player dialFuel];
1779 :
1780 : double hcenter = size_in_pixels.width/2.0;
1781 : double hscale = size_in_pixels.width / (CHART_WIDTH_AT_MAX_ZOOM*zoom);
1782 : double vscale = -size_in_pixels.height / (2*CHART_HEIGHT_AT_MAX_ZOOM*zoom);
1783 : double vcenter = CHART_SCREEN_VERTICAL_CENTRE;
1784 : double hoffset = hcenter - chart_centre_coordinates.x*hscale;
1785 : double voffset = size_in_pixels.height - vcenter - chart_centre_coordinates.y*vscale;
1786 :
1787 : if (compact)
1788 : {
1789 : hscale = size_in_pixels.width / 256.0;
1790 : vscale = -1.0 * size_in_pixels.height / 512.0;
1791 : hoffset = 0.0f;
1792 : voffset = size_in_pixels.height - pixel_title_size.height - 5;
1793 : vcenter = CHART_SCREEN_VERTICAL_CENTRE_COMPACT;
1794 : chart_centre_coordinates.x = 128.0;
1795 : chart_centre_coordinates.y = 128.0;
1796 : zoom = CHART_MAX_ZOOM;
1797 : }
1798 :
1799 : int i;
1800 : double d, distance = 0.0, time = 0.0;
1801 : int jumps = 0;
1802 : NSPoint star;
1803 : OOScalar pixelRatio;
1804 : NSRect clipRect;
1805 :
1806 : OORouteType advancedNavArrayMode = [player ANAMode];
1807 : BOOL routeExists = NO;
1808 :
1809 : NSInteger concealment[256];
1810 : for (i=0;i<256;i++) {
1811 : NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:galaxy_id];
1812 : concealment[i] = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
1813 : }
1814 :
1815 : BOOL *systemsFound = [UNIVERSE systemsFound];
1816 : NSSize viewSize = [[UNIVERSE gameView] backingViewSize];
1817 : double aspect_ratio = viewSize.width / viewSize.height;
1818 :
1819 : // default colours - match those in HeadUpDisplay:OODrawPlanetInfo
1820 : GLfloat govcol[] = { 0.5, 0.0, 0.7,
1821 : 0.7, 0.5, 0.3,
1822 : 0.0, 1.0, 0.3,
1823 : 1.0, 0.8, 0.1,
1824 : 1.0, 0.0, 0.0,
1825 : 0.1, 0.5, 1.0,
1826 : 0.7, 0.7, 0.7,
1827 : 0.7, 1.0, 1.0};
1828 :
1829 : if (aspect_ratio > 4.0/3.0)
1830 : {
1831 : pixelRatio = viewSize.height / 480.0;
1832 : }
1833 : else
1834 : {
1835 : pixelRatio = viewSize.width / 640.0;
1836 : }
1837 :
1838 : NSInteger textRow = compact ? GUI_ROW_CHART_SYSTEM_COMPACT : GUI_ROW_CHART_SYSTEM;
1839 :
1840 : clipRect = NSMakeRect((viewSize.width - size_in_pixels.width*pixelRatio)/2.0,
1841 : (viewSize.height + size_in_pixels.height*pixelRatio)/2.0 - (pixel_title_size.height + 15 + (textRow-2)*MAIN_GUI_ROW_HEIGHT) * pixelRatio,
1842 : size_in_pixels.width * pixelRatio,
1843 : (textRow-1) * MAIN_GUI_ROW_HEIGHT * pixelRatio);
1844 :
1845 : OOSystemID target = [PLAYER targetSystemID];
1846 : double dx, dy;
1847 :
1848 : // get a list of systems marked as contract destinations
1849 : NSDictionary* markedDestinations = [player markedDestinations];
1850 :
1851 : // get present location
1852 : cu = NSMakePoint((float)(hscale*galaxy_coordinates.x+hoffset),(float)(vscale*galaxy_coordinates.y+voffset));
1853 :
1854 : // enable draw clipping; limit drawing area within the chart area
1855 : OOGL(glEnable(GL_SCISSOR_TEST));
1856 : OOGL(glScissor(clipRect.origin.x, clipRect.origin.y, clipRect.size.width, clipRect.size.height));
1857 :
1858 : // Cache nearby systems so that [UNIVERSE generateSystemData:] does not get called on every frame
1859 : // Caching code submitted by Y A J, 20091022
1860 :
1861 : static OOGalaxyID saved_galaxy_id;
1862 : static struct saved_system
1863 : {
1864 : OOSystemID sysid;
1865 : int tec, eco, gov;
1866 : NSString* p_name;
1867 : BOOL nova;
1868 : } nearby_systems[ 256 ];
1869 : static int num_nearby_systems = 0;
1870 :
1871 : if ( _refreshStarChart || galaxy_id != saved_galaxy_id)
1872 : {
1873 : // saved systems are stale; recompute
1874 : _refreshStarChart = NO;
1875 : for (i = 0; i < num_nearby_systems; i++)
1876 : [nearby_systems[ i ].p_name release];
1877 :
1878 : num_nearby_systems = 0;
1879 : for (i = 0; i < 256; i++)
1880 : {
1881 :
1882 : NSDictionary* sys_info = [UNIVERSE generateSystemData:i];
1883 : if (EXPECT_NOT([sys_info oo_boolForKey:@"sun_gone_nova"]))
1884 : {
1885 : nearby_systems[ num_nearby_systems ].gov = -1; // Flag up nova systems!
1886 : }
1887 : else
1888 : {
1889 : nearby_systems[ num_nearby_systems ].tec = [sys_info oo_intForKey:KEY_TECHLEVEL];
1890 : nearby_systems[ num_nearby_systems ].eco = [sys_info oo_intForKey:KEY_ECONOMY];
1891 : nearby_systems[ num_nearby_systems ].gov = [sys_info oo_intForKey:KEY_GOVERNMENT];
1892 : }
1893 : nearby_systems[ num_nearby_systems ].sysid = i;
1894 : nearby_systems[ num_nearby_systems ].p_name = [[sys_info oo_stringForKey:KEY_NAME] retain];
1895 : nearby_systems[ num_nearby_systems ].nova = [[UNIVERSE generateSystemData:i] oo_boolForKey:@"sun_gone_nova"];
1896 : num_nearby_systems++;
1897 : }
1898 : saved_galaxy_id = [player galaxyNumber];
1899 : }
1900 :
1901 : static OOSystemID savedPlanetNumber = 0;
1902 : static OOSystemID savedDestNumber = 0;
1903 : static OORouteType savedArrayMode = OPTIMIZED_BY_NONE;
1904 : static NSDictionary *routeInfo = nil;
1905 :
1906 : /* May override current mode for mission screens */
1907 : if (backgroundSpecial == GUI_BACKGROUND_SPECIAL_LONG_ANA_SHORTEST ||
1908 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_SHORT_ANA_SHORTEST ||
1909 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_CUSTOM_ANA_SHORTEST)
1910 : {
1911 : advancedNavArrayMode = OPTIMIZED_BY_JUMPS;
1912 : }
1913 : else if (backgroundSpecial == GUI_BACKGROUND_SPECIAL_LONG_ANA_QUICKEST ||
1914 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_SHORT_ANA_QUICKEST ||
1915 : backgroundSpecial == GUI_BACKGROUND_SPECIAL_CUSTOM_ANA_QUICKEST)
1916 : {
1917 : advancedNavArrayMode = OPTIMIZED_BY_TIME;
1918 : }
1919 :
1920 : if (advancedNavArrayMode != OPTIMIZED_BY_NONE && [player hasEquipmentItemProviding:@"EQ_ADVANCED_NAVIGATIONAL_ARRAY"])
1921 : {
1922 : OOSystemID planetNumber = [PLAYER systemID];
1923 : OOSystemID destNumber = [PLAYER targetSystemID];
1924 : if (routeInfo == nil || planetNumber != savedPlanetNumber || destNumber != savedDestNumber || advancedNavArrayMode != savedArrayMode)
1925 : {
1926 : [routeInfo release];
1927 : routeInfo = [[UNIVERSE routeFromSystem:planetNumber toSystem:destNumber optimizedBy:advancedNavArrayMode] retain];
1928 : savedPlanetNumber = planetNumber;
1929 : savedDestNumber = destNumber;
1930 : savedArrayMode = advancedNavArrayMode;
1931 : }
1932 : target = destNumber;
1933 :
1934 : // if the ANA has been activated and we are in string input mode (i.e. planet search),
1935 : // get out of it so that distance and time data can be displayed
1936 : //if ([[[UNIVERSE gameView] typedString] length] > 0) [player clearPlanetSearchString];
1937 :
1938 : if (routeInfo) routeExists = YES;
1939 :
1940 : [self drawAdvancedNavArrayAtX:x+hoffset y:y+voffset z:z alpha:alpha usingRoute: (planetNumber != destNumber ? (id)routeInfo : nil) optimizedBy:advancedNavArrayMode zoom: zoom];
1941 :
1942 : if (routeExists)
1943 : {
1944 : distance = [routeInfo oo_doubleForKey:@"distance"];
1945 : time = [routeInfo oo_doubleForKey:@"time"];
1946 : jumps = [routeInfo oo_intForKey:@"jumps"];
1947 :
1948 : if (distance == 0.0 && planetNumber != destNumber)
1949 : {
1950 : // zero-distance double fix
1951 : distance = 0.1;
1952 : time = 0.01;
1953 : }
1954 : }
1955 : }
1956 : else
1957 : {
1958 : [self drawAdvancedNavArrayAtX:x+hoffset y:y+voffset z:z alpha:alpha usingRoute:nil optimizedBy:OPTIMIZED_BY_NONE zoom: zoom];
1959 : }
1960 : if (!routeExists)
1961 : {
1962 : NSPoint targetCoordinates = [systemManager getCoordinatesForSystem:target inGalaxy:galaxy_id];
1963 :
1964 : distance = distanceBetweenPlanetPositions(targetCoordinates.x,targetCoordinates.y,galaxy_coordinates.x,galaxy_coordinates.y);
1965 : if (distance == 0.0)
1966 : {
1967 : if (target != [PLAYER systemID])
1968 : {
1969 : // looking at the other half of a zero-distance double
1970 : // distance is treated as 0.1 LY
1971 : distance = 0.1;
1972 : }
1973 : }
1974 : if ([player hasHyperspaceMotor] && distance <= [player fuel]/10.0)
1975 : {
1976 : time = distance * distance;
1977 : }
1978 : else
1979 : {
1980 : time = 0.0;
1981 : }
1982 : }
1983 :
1984 : if ([player hasHyperspaceMotor])
1985 : {
1986 : // draw fuel range circle
1987 : OOGL(GLScaledLineWidth(2.0f));
1988 : [self setGLColorFromSetting:kGuiChartRangeColor defaultValue:[OOColor greenColor] alpha:alpha];
1989 :
1990 : GLDrawOval(x + cu.x, y + cu.y, z, NSMakeSize((float)(fuel*hscale), 2*(float)(fuel*vscale)), 5);
1991 : }
1992 :
1993 :
1994 : // draw crosshairs over current location
1995 : //
1996 : [self setGLColorFromSetting:kGuiChartCrosshairColor defaultValue:[OOColor greenColor] alpha:alpha];
1997 :
1998 : [self drawCrossHairsWithSize:12/zoom+2 x:x + cu.x y:y + cu.y z:z];
1999 :
2000 :
2001 : // draw crosshairs over cursor
2002 : //
2003 : [self setGLColorFromSetting:kGuiChartCursorColor defaultValue:[OOColor redColor] alpha:alpha];
2004 : cu = NSMakePoint((float)(hscale*cursor_coordinates.x+hoffset),(float)(vscale*cursor_coordinates.y+voffset));
2005 : [self drawCrossHairsWithSize:7/zoom+2 x:x + cu.x y:y + cu.y z:z];
2006 :
2007 : // draw marks and stars
2008 : //
2009 : OOGL(GLScaledLineWidth(1.5f));
2010 : OOGL(glColor4f(1.0f, 1.0f, 0.75f, alpha)); // pale yellow
2011 :
2012 : for (i = 0; i < num_nearby_systems; i++)
2013 : {
2014 : NSPoint sys_coordinates = [systemManager getCoordinatesForSystem:i inGalaxy:galaxy_id];
2015 :
2016 : dx = fabs(chart_centre_coordinates.x - sys_coordinates.x);
2017 : dy = fabs(chart_centre_coordinates.y - sys_coordinates.y);
2018 :
2019 : if ((dx > zoom*(CHART_WIDTH_AT_MAX_ZOOM/2.0 + CHART_CLIP_BORDER))||(dy > zoom*(CHART_HEIGHT_AT_MAX_ZOOM + CHART_CLIP_BORDER)))
2020 : continue;
2021 :
2022 :
2023 : if (concealment[i] >= OO_SYSTEMCONCEALMENT_NOTHING) {
2024 : // system is not known
2025 : continue;
2026 : }
2027 :
2028 : NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:galaxy_id];
2029 : float blob_factor = [guiUserSettings oo_floatForKey:kGuiChartCircleScale defaultValue:0.0017];
2030 : float blob_size = (1.0f + blob_factor * [systemInfo oo_floatForKey:@"radius"])/zoom;
2031 : if (blob_size < 0.5) blob_size = 0.5;
2032 :
2033 : star.x = (float)(sys_coordinates.x * hscale + hoffset);
2034 : star.y = (float)(sys_coordinates.y * vscale + voffset);
2035 :
2036 : noNova = !nearby_systems[i].nova;
2037 : NSAssert1(chart_mode <= OOLRC_MODE_TECHLEVEL, @"Long range chart mode %i out of range", (int)chart_mode);
2038 :
2039 : NSArray *markers = [markedDestinations objectForKey:[NSNumber numberWithInt:i]];
2040 : if (markers != nil) // is marked
2041 : {
2042 : GLfloat base_size = 0.5f * blob_size + 2.5f;
2043 : [self drawSystemMarkers:markers atX:x+star.x andY:y+star.y andZ:z withAlpha:alpha andScale:base_size];
2044 : }
2045 :
2046 : if (concealment[i] >= OO_SYSTEMCONCEALMENT_NODATA) {
2047 : // no system data available
2048 : r = g = b = 0.7;
2049 : OOGL(glColor4f(r, g, b, alpha));
2050 : } else {
2051 : switch (chart_mode)
2052 : {
2053 : case OOLRC_MODE_ECONOMY:
2054 : if (EXPECT(noNova))
2055 : {
2056 : systemParameter = nearby_systems[i].eco;
2057 : GLfloat ce1 = 1.0f - 0.125f * systemParameter;
2058 : [self setGLColorFromSetting:[NSString stringWithFormat:kGuiChartEconomyUColor, (unsigned long)systemParameter]
2059 : defaultValue:[OOColor colorWithRed:ce1 green:1.0f blue:0.0f alpha:1.0f]
2060 : alpha:1.0];
2061 : }
2062 : else
2063 : {
2064 : r = g = b = 0.3;
2065 : OOGL(glColor4f(r, g, b, alpha));
2066 : }
2067 : break;
2068 : case OOLRC_MODE_GOVERNMENT:
2069 : if (EXPECT(noNova))
2070 : {
2071 : systemParameter = nearby_systems[i].gov;
2072 : [self setGLColorFromSetting:[NSString stringWithFormat:kGuiChartGovernmentUColor, (unsigned long)systemParameter]
2073 : defaultValue:[OOColor colorWithRed:govcol[systemParameter*3] green:govcol[1+(systemParameter*3)] blue:govcol[2+(systemParameter*3)] alpha:1.0f]
2074 : alpha:1.0];
2075 : }
2076 : else
2077 : {
2078 : r = g = b = 0.3;
2079 : OOGL(glColor4f(r, g, b, alpha));
2080 : }
2081 : break;
2082 : case OOLRC_MODE_TECHLEVEL:
2083 : if (EXPECT(noNova))
2084 : {
2085 : systemParameter = nearby_systems[i].tec;
2086 : r = 0.6;
2087 : g = b = 0.20 + (0.05 * (GLfloat)systemParameter);
2088 : }
2089 : else
2090 : {
2091 : r = g = b = 0.3;
2092 : }
2093 : OOGL(glColor4f(r, g, b, alpha));
2094 : break;
2095 : case OOLRC_MODE_UNKNOWN:
2096 : case OOLRC_MODE_SUNCOLOR:
2097 : if (EXPECT(noNova))
2098 : {
2099 : r = g = b = 1.0;
2100 : OOColor *sunColor = [OOColor colorWithDescription:[[UNIVERSE systemManager] getProperty:@"sun_color" forSystem:i inGalaxy:galaxy_id]];
2101 : if (sunColor != nil) {
2102 : [sunColor getRed:&r green:&g blue:&b alpha:&alpha];
2103 : alpha = 1.0; // reset
2104 : }
2105 : }
2106 : else
2107 : {
2108 : r = 1.0;
2109 : g = 0.2;
2110 : b = 0.0;
2111 : }
2112 : OOGL(glColor4f(r, g, b, alpha));
2113 : break;
2114 : }
2115 : }
2116 :
2117 : GLDrawFilledOval(x + star.x, y + star.y, z, NSMakeSize(blob_size,blob_size), 15);
2118 : }
2119 :
2120 : // draw found stars and captions
2121 : //
2122 : GLfloat systemNameScale = [guiUserSettings oo_floatForKey:kGuiChartLabelScale defaultValue:1.0];
2123 :
2124 : OOGL(GLScaledLineWidth(1.5f));
2125 : [self setGLColorFromSetting:kGuiChartMatchBoxColor defaultValue:[OOColor greenColor] alpha:alpha];
2126 :
2127 : int n_matches = 0, foundIndex = -1;
2128 :
2129 : for (i = 0; i < 256; i++) if (systemsFound[i])
2130 : {
2131 : if(foundSystem == n_matches) foundIndex = i;
2132 : n_matches++;
2133 : }
2134 :
2135 : if (n_matches == 0)
2136 : {
2137 : foundSystem = 0;
2138 : }
2139 : else if (backgroundSpecial == GUI_BACKGROUND_SPECIAL_LONG_ANA_SHORTEST || backgroundSpecial == GUI_BACKGROUND_SPECIAL_LONG_ANA_QUICKEST || backgroundSpecial == GUI_BACKGROUND_SPECIAL_LONG)
2140 : {
2141 : // do nothing at this stage
2142 : }
2143 : else
2144 : {
2145 : for (i = 0; i < 256; i++)
2146 : {
2147 : if (concealment[i] >= OO_SYSTEMCONCEALMENT_NONAME)
2148 : {
2149 : continue;
2150 : }
2151 :
2152 : BOOL mark = systemsFound[i];
2153 : float marker_size = 8.0/zoom;
2154 : NSPoint sys_coordinates = [systemManager getCoordinatesForSystem:i inGalaxy:galaxy_id];
2155 :
2156 : dx = fabs(chart_centre_coordinates.x - sys_coordinates.x);
2157 : dy = fabs(chart_centre_coordinates.y - sys_coordinates.y);
2158 :
2159 : if (mark && (dx <= zoom*(CHART_WIDTH_AT_MAX_ZOOM/2.0+CHART_CLIP_BORDER))&&(dy <= zoom*(CHART_HEIGHT_AT_MAX_ZOOM+CHART_CLIP_BORDER)))
2160 : {
2161 : star.x = (float)(sys_coordinates.x * hscale + hoffset);
2162 : star.y = (float)(sys_coordinates.y * vscale + voffset);
2163 : OOGLBEGIN(GL_LINE_LOOP);
2164 : glVertex3f(x + star.x - marker_size, y + star.y - marker_size, z);
2165 : glVertex3f(x + star.x + marker_size, y + star.y - marker_size, z);
2166 : glVertex3f(x + star.x + marker_size, y + star.y + marker_size, z);
2167 : glVertex3f(x + star.x - marker_size, y + star.y + marker_size, z);
2168 : OOGLEND();
2169 : if (i == foundIndex || n_matches == 1)
2170 : {
2171 : if (n_matches == 1) foundSystem = 0;
2172 : if (zoom > CHART_ZOOM_SHOW_LABELS && advancedNavArrayMode == OPTIMIZED_BY_NONE)
2173 : {
2174 : [self setGLColorFromSetting:kGuiChartMatchLabelColor defaultValue:[OOColor cyanColor] alpha:alpha];
2175 : OODrawString([UNIVERSE systemNameIndex:i] , x + star.x + 2.0, y + star.y - 10.0f, z, NSMakeSize(10*systemNameScale,10*systemNameScale));
2176 : [self setGLColorFromSetting:kGuiChartMatchBoxColor defaultValue:[OOColor greenColor] alpha:alpha];
2177 : }
2178 : }
2179 : else if (zoom > CHART_ZOOM_SHOW_LABELS)
2180 : {
2181 : OODrawString([UNIVERSE systemNameIndex:i] , x + star.x + 2.0, y + star.y - 10.0f, z, NSMakeSize(10*systemNameScale,10*systemNameScale));
2182 : }
2183 : }
2184 : }
2185 : }
2186 :
2187 : // draw names
2188 : //
2189 : // OOGL(glColor4f(1.0f, 1.0f, 0.0f, alpha)); // yellow
2190 :
2191 : int targetIdx = -1;
2192 : struct saved_system *sys;
2193 : NSSize chSize = NSMakeSize(pixel_row_height*systemNameScale/zoom,pixel_row_height*systemNameScale/zoom);
2194 :
2195 : double jumpRange = MAX_JUMP_RANGE * [PLAYER dialFuel];
2196 : for (i = 0; i < num_nearby_systems; i++)
2197 : {
2198 : if (concealment[i] >= OO_SYSTEMCONCEALMENT_NONAME)
2199 : {
2200 : continue;
2201 : }
2202 :
2203 : sys = nearby_systems + i;
2204 : NSPoint sys_coordinates = [systemManager getCoordinatesForSystem:sys->sysid inGalaxy:galaxy_id];
2205 :
2206 : dx = fabs(chart_centre_coordinates.x - sys_coordinates.x);
2207 : dy = fabs(chart_centre_coordinates.y - sys_coordinates.y);
2208 :
2209 : if ((dx > zoom*(CHART_WIDTH_AT_MAX_ZOOM/2.0+CHART_CLIP_BORDER))||(dy > zoom*(CHART_HEIGHT_AT_MAX_ZOOM+CHART_CLIP_BORDER)))
2210 : continue;
2211 : star.x = (float)(sys_coordinates.x * hscale + hoffset);
2212 : star.y = (float)(sys_coordinates.y * vscale + voffset);
2213 : if (sys->sysid == target) // not overlapping twin? (example: Divees & Tezabi in galaxy 5)
2214 : {
2215 : targetIdx = i; // we have a winner!
2216 : }
2217 :
2218 :
2219 :
2220 : if (zoom < CHART_ZOOM_SHOW_LABELS)
2221 : {
2222 : if (![player showInfoFlag]) // System's name
2223 : {
2224 :
2225 : d = distanceBetweenPlanetPositions(galaxy_coordinates.x, galaxy_coordinates.y, sys_coordinates.x, sys_coordinates.y);
2226 : if (d <= jumpRange)
2227 : {
2228 : [self setGLColorFromSetting:kGuiChartLabelReachableColor defaultValue:[OOColor yellowColor] alpha:alpha];
2229 : }
2230 : else
2231 : {
2232 : [self setGLColorFromSetting:kGuiChartLabelColor defaultValue:[OOColor yellowColor] alpha:alpha];
2233 :
2234 : }
2235 :
2236 : OODrawString(sys->p_name, x + star.x + 2.0, y + star.y, z, chSize);
2237 : }
2238 : else if (EXPECT(sys->gov >= 0)) // Not a nova? Show the info.
2239 : {
2240 : if (concealment[i] >= OO_SYSTEMCONCEALMENT_NODATA)
2241 : {
2242 : [self setGLColorFromSetting:kGuiChartLabelColor defaultValue:[OOColor yellowColor] alpha:alpha];
2243 : OODrawHilightedString(@"???", x + star.x + 2.0, y + star.y, z, chSize);
2244 : }
2245 : else
2246 : {
2247 : OODrawPlanetInfo(sys->gov, sys->eco, sys->tec, x + star.x + 2.0, y + star.y + 2.0, z, chSize);
2248 : }
2249 : }
2250 : }
2251 : }
2252 :
2253 : // highlight the name of the currently selected system
2254 : // (needed to get things right in closely-overlapping systems)
2255 : if( targetIdx != -1 && zoom <= CHART_ZOOM_SHOW_LABELS)
2256 : {
2257 : if (concealment[targetIdx] < OO_SYSTEMCONCEALMENT_NONAME)
2258 : {
2259 : sys = nearby_systems + targetIdx;
2260 : NSPoint sys_coordinates = [systemManager getCoordinatesForSystem:sys->sysid inGalaxy:galaxy_id];
2261 :
2262 : star.x = (float)(sys_coordinates.x * hscale + hoffset);
2263 : star.y = (float)(sys_coordinates.y * vscale + voffset);
2264 :
2265 : if (![player showInfoFlag])
2266 : {
2267 : d = distanceBetweenPlanetPositions(galaxy_coordinates.x, galaxy_coordinates.y, sys_coordinates.x, sys_coordinates.y);
2268 : if (d <= jumpRange)
2269 : {
2270 : [self setGLColorFromSetting:kGuiChartLabelReachableColor defaultValue:[OOColor yellowColor] alpha:alpha];
2271 : }
2272 : else
2273 : {
2274 : [self setGLColorFromSetting:kGuiChartLabelColor defaultValue:[OOColor yellowColor] alpha:alpha];
2275 :
2276 : }
2277 :
2278 : OODrawHilightedString(sys->p_name, x + star.x + 2.0, y + star.y, z, chSize);
2279 : }
2280 : else if (sys->gov >= 0) // Not a nova? Show the info.
2281 : {
2282 : if (concealment[targetIdx] >= OO_SYSTEMCONCEALMENT_NODATA)
2283 : {
2284 : [self setGLColorFromSetting:kGuiChartLabelColor defaultValue:[OOColor yellowColor] alpha:alpha];
2285 : OODrawHilightedString(@"???", x + star.x + 2.0, y + star.y, z, chSize);
2286 : }
2287 : else
2288 : {
2289 : OODrawHilightedPlanetInfo(sys->gov, sys->eco, sys->tec, x + star.x + 2.0, y + star.y + 2.0, z, chSize);
2290 : }
2291 : }
2292 : }
2293 : }
2294 :
2295 : OOGUITabSettings tab_stops;
2296 : tab_stops[0] = 0;
2297 : tab_stops[1] = 96;
2298 : tab_stops[2] = 288;
2299 : [self overrideTabs:tab_stops from:kGuiChartTraveltimeTabs length:3];
2300 : [self setTabStops:tab_stops];
2301 : NSString *targetName = [[UNIVERSE getSystemName:target] retain];
2302 :
2303 : // distance-f & est-travel-time-f are identical between short & long range charts in standard Oolite, however can be alterered separately via OXPs
2304 : NSString *travelDistLine = @"";
2305 : if (distance > 0)
2306 : {
2307 : travelDistLine = OOExpandKey(@"long-range-chart-distance", distance);
2308 : }
2309 : NSString *travelTimeLine = @"";
2310 : if (time > 0)
2311 : {
2312 : travelTimeLine = OOExpandKey(@"long-range-chart-est-travel-time", time);
2313 : }
2314 :
2315 : if(concealment[target] < OO_SYSTEMCONCEALMENT_NONAME)
2316 : {
2317 : [self setArray:[NSArray arrayWithObjects:targetName, travelDistLine,travelTimeLine,nil] forRow:textRow];
2318 : }
2319 : else
2320 : {
2321 : [self setArray:[NSArray arrayWithObjects:@"", travelDistLine,travelTimeLine,nil] forRow:textRow];
2322 : }
2323 : if ([PLAYER guiScreen] == GUI_SCREEN_SHORT_RANGE_CHART)
2324 : {
2325 : if (jumps > 0)
2326 : {
2327 : [self setArray:[NSArray arrayWithObjects: @"", OOExpandKey(@"short-range-chart-jumps", jumps), nil] forRow: textRow + 1];
2328 : }
2329 : else
2330 : {
2331 : [self setArray:[NSArray array] forRow: textRow + 1];
2332 : }
2333 : }
2334 : [targetName release];
2335 :
2336 : // draw planet info circle
2337 : OOGL(GLScaledLineWidth(2.0f));
2338 : [self setGLColorFromSetting: kGuiChartInfoMarkerColor defaultValue:[OOColor blueColor] alpha:alpha];
2339 : cu = NSMakePoint((float)(hscale*info_system_coordinates.x+hoffset),(float)(vscale*info_system_coordinates.y+voffset));
2340 : GLDrawOval(x + cu.x, y + cu.y, z, NSMakeSize(6.0f/zoom+2.0f, 6.0f/zoom+2.0f), 5);
2341 :
2342 : // disable draw clipping
2343 : OOGL(glDisable(GL_SCISSOR_TEST));
2344 :
2345 : // Draw bottom divider
2346 : [self setGLColorFromSetting:kGuiScreenDividerColor defaultValue:[OOColor colorWithWhite:0.75 alpha:1.0] alpha:alpha];
2347 : OOGLBEGIN(GL_QUADS);
2348 : glVertex3f(x + 0, (float)(y + size_in_pixels.height - (textRow-1)*MAIN_GUI_ROW_HEIGHT - pixel_title_size.height), z);
2349 : glVertex3f(x + size_in_pixels.width, (GLfloat)(y + size_in_pixels.height - (textRow-1)*MAIN_GUI_ROW_HEIGHT - pixel_title_size.height), z);
2350 : glVertex3f(x + size_in_pixels.width, (GLfloat)(y + size_in_pixels.height - (textRow-1)*MAIN_GUI_ROW_HEIGHT - pixel_title_size.height - 2), z);
2351 : glVertex3f(x + 0, (GLfloat)(y + size_in_pixels.height - (textRow-1)*MAIN_GUI_ROW_HEIGHT - pixel_title_size.height - 2), z);
2352 : OOGLEND();
2353 : }
2354 :
2355 :
2356 0 : - (void) drawSystemMarkers:(NSArray *)markers atX:(GLfloat)x andY:(GLfloat)y andZ:(GLfloat)z withAlpha:(GLfloat)alpha andScale:(GLfloat)scale
2357 : {
2358 : NSEnumerator *mEnum;
2359 : NSDictionary *marker;
2360 : for (mEnum = [markers objectEnumerator]; (marker = [mEnum nextObject]); )
2361 : {
2362 : [self drawSystemMarker:marker atX:x andY:y andZ:z withAlpha:alpha andScale:scale];
2363 : }
2364 : }
2365 :
2366 :
2367 0 : - (void) drawSystemMarker:(NSDictionary *)marker atX:(GLfloat)x andY:(GLfloat)y andZ:(GLfloat)z withAlpha:(GLfloat)alpha andScale:(GLfloat)scale
2368 : {
2369 : NSString *colorDesc = [marker oo_stringForKey:@"markerColor" defaultValue:@"redColor"];
2370 : OORGBAComponents color = [[OOColor colorWithDescription:colorDesc] rgbaComponents];
2371 :
2372 : OOGL(glColor4f(color.r, color.g, color.b, alpha)); // red
2373 : GLfloat mark_size = [marker oo_floatForKey:@"markerScale" defaultValue:1.0];
2374 : if (mark_size > 2.0)
2375 : {
2376 : mark_size = 2.0;
2377 : }
2378 : else if (mark_size < 0.5)
2379 : {
2380 : mark_size = 0.5;
2381 : }
2382 : mark_size *= scale;
2383 :
2384 : NSString *shape = [marker oo_stringForKey:@"markerShape" defaultValue:@"MARKER_X"];
2385 :
2386 : OOGLBEGIN(GL_LINES);
2387 : if ([shape isEqualToString:@"MARKER_X"])
2388 : {
2389 : glVertex3f(x - mark_size, y - mark_size, z);
2390 : glVertex3f(x + mark_size, y + mark_size, z);
2391 : glVertex3f(x - mark_size, y + mark_size, z);
2392 : glVertex3f(x + mark_size, y - mark_size, z);
2393 : }
2394 : else if ([shape isEqualToString:@"MARKER_PLUS"])
2395 : {
2396 : mark_size *= 1.4; // match volumes
2397 : glVertex3f(x, y - mark_size, z);
2398 : glVertex3f(x, y + mark_size, z);
2399 : glVertex3f(x - mark_size, y, z);
2400 : glVertex3f(x + mark_size, y, z);
2401 : }
2402 : else if ([shape isEqualToString:@"MARKER_SQUARE"])
2403 : {
2404 : glVertex3f(x - mark_size, y - mark_size, z);
2405 : glVertex3f(x - mark_size, y + mark_size, z);
2406 : glVertex3f(x - mark_size, y + mark_size, z);
2407 : glVertex3f(x + mark_size, y + mark_size, z);
2408 : glVertex3f(x + mark_size, y + mark_size, z);
2409 : glVertex3f(x + mark_size, y - mark_size, z);
2410 : glVertex3f(x + mark_size, y - mark_size, z);
2411 : glVertex3f(x - mark_size, y - mark_size, z);
2412 : }
2413 : else if ([shape isEqualToString:@"MARKER_DIAMOND"])
2414 : {
2415 : mark_size *= 1.4; // match volumes
2416 : glVertex3f(x, y - mark_size, z);
2417 : glVertex3f(x - mark_size, y, z);
2418 : glVertex3f(x - mark_size, y, z);
2419 : glVertex3f(x, y + mark_size, z);
2420 : glVertex3f(x, y + mark_size, z);
2421 : glVertex3f(x + mark_size, y, z);
2422 : glVertex3f(x + mark_size, y, z);
2423 : glVertex3f(x, y - mark_size, z);
2424 : }
2425 : OOGLEND();
2426 : }
2427 :
2428 :
2429 : - (OOSystemID) targetNextFoundSystem:(int)direction // +1 , 0 , -1
2430 : {
2431 : OOSystemID sys = [PLAYER targetSystemID];
2432 : if ([PLAYER guiScreen] != GUI_SCREEN_SHORT_RANGE_CHART && [PLAYER guiScreen] != GUI_SCREEN_LONG_RANGE_CHART) return sys;
2433 :
2434 : BOOL *systemsFound = [UNIVERSE systemsFound];
2435 : unsigned i, first = 0, last = 0, count = 0;
2436 : int systemIndex = foundSystem + direction;
2437 :
2438 : if (direction == 0) systemIndex = 0;
2439 :
2440 : for (i = 0; i <= kOOMaximumSystemID; i++)
2441 : {
2442 : if (systemsFound[i])
2443 : {
2444 : if (count == 0)
2445 : {
2446 : first = last = i;
2447 : }
2448 : else
2449 : {
2450 : last = i;
2451 : }
2452 : if (systemIndex == (int)count)
2453 : {
2454 : sys = i;
2455 : }
2456 : count++;
2457 : }
2458 : }
2459 :
2460 : if (count == 0) return sys; // empty systemFound list.
2461 :
2462 : // loop back if needed.
2463 : if (systemIndex < 0)
2464 : {
2465 : systemIndex = count - 1;
2466 : sys = last;
2467 : }
2468 : if (systemIndex >= (int)count)
2469 : {
2470 : systemIndex = 0;
2471 : sys = first;
2472 : }
2473 :
2474 : foundSystem = systemIndex;
2475 : return sys;
2476 : }
2477 :
2478 :
2479 : // Advanced Navigation Array -- galactic chart route mapping - contributed by Nikos Barkas (another_commander).
2480 0 : - (void) drawAdvancedNavArrayAtX:(float)x y:(float)y z:(float)z alpha:(float)alpha usingRoute:(NSDictionary *) routeInfo optimizedBy:(OORouteType) optimizeBy zoom: (OOScalar) zoom
2481 : {
2482 : GLfloat lr,lg,lb,la,lr2,lg2,lb2,la2;
2483 : double hscale = size_in_pixels.width / (CHART_WIDTH_AT_MAX_ZOOM*zoom);
2484 : double vscale = -1.0 * size_in_pixels.height / (2*CHART_HEIGHT_AT_MAX_ZOOM*zoom);
2485 : NSPoint star = NSZeroPoint,
2486 : star2 = NSZeroPoint,
2487 : starabs = NSZeroPoint,
2488 : star2abs = NSZeroPoint;
2489 : OOSystemDescriptionManager *systemManager = [UNIVERSE systemManager];
2490 : OOGalaxyID g = [PLAYER galaxyNumber];
2491 : OOSystemID planetNumber = [PLAYER systemID];
2492 :
2493 : OOColor *defaultConnectionColor = [self colorFromSetting:kGuiChartConnectionColor defaultValue:[OOColor colorWithWhite:0.25 alpha:1.0]];
2494 : OOColor *currentJumpColorStart = [self colorFromSetting:kGuiChartCurrentJumpStartColor defaultValue:[OOColor colorWithWhite:0.25 alpha:0.0]];
2495 : OOColor *currentJumpColorEnd = [self colorFromSetting:kGuiChartCurrentJumpEndColor defaultValue:[OOColor colorWithWhite:0.25 alpha:0.0]];
2496 :
2497 : OOColor *thisConnectionColor = nil;
2498 : OOColor *thatConnectionColor = nil;
2499 :
2500 : float jumpRange = MAX_JUMP_RANGE * ((optimizeBy == OPTIMIZED_BY_NONE) ? [PLAYER dialFuel] : 1.0);
2501 :
2502 : NSInteger concealment[256];
2503 : for (NSUInteger i=0;i<256;i++) {
2504 : NSDictionary *systemInfo = [systemManager getPropertiesForSystem:i inGalaxy:g];
2505 : concealment[i] = [systemInfo oo_intForKey:@"concealment" defaultValue:OO_SYSTEMCONCEALMENT_NONE];
2506 : }
2507 :
2508 :
2509 : OOGLBEGIN(GL_LINES);
2510 : for (OOSystemID i = 0; i < 256; i++)
2511 : {
2512 :
2513 : if (concealment[i] >= OO_SYSTEMCONCEALMENT_NOTHING) {
2514 : // system is not known
2515 : continue;
2516 : }
2517 :
2518 : /* Concealment */
2519 : if (optimizeBy == OPTIMIZED_BY_NONE && i != planetNumber)
2520 : {
2521 : continue;
2522 : }
2523 :
2524 : starabs = [systemManager getCoordinatesForSystem:i inGalaxy:g];
2525 :
2526 : star.x = (float)(starabs.x * hscale);
2527 : star.y = (float)(starabs.y * vscale);
2528 :
2529 : // if in non-route mode, we're always starting from i, so need
2530 : // to do <i here too.
2531 : OOSystemID loopstart = (optimizeBy == OPTIMIZED_BY_NONE) ? 0 : (i+1);
2532 :
2533 : for (OOSystemID j = loopstart; j < 256; j++)
2534 : {
2535 : if (i == j)
2536 : {
2537 : continue; // for OPTIMIZED_BY_NONE case
2538 : }
2539 :
2540 : if (concealment[j] >= OO_SYSTEMCONCEALMENT_NOTHING) {
2541 : // system is not known
2542 : continue;
2543 : }
2544 :
2545 : star2abs = [systemManager getCoordinatesForSystem:j inGalaxy:g];
2546 : double d = distanceBetweenPlanetPositions(starabs.x, starabs.y, star2abs.x, star2abs.y);
2547 :
2548 : if (d <= jumpRange) // another_commander - Default to 7.0 LY.
2549 : {
2550 : star2.x = (float)(star2abs.x * hscale);
2551 : star2.y = (float)(star2abs.y * vscale);
2552 : if (optimizeBy == OPTIMIZED_BY_NONE)
2553 : {
2554 : [currentJumpColorStart getRed:&lr green:&lg blue:&lb alpha:&la];
2555 : [currentJumpColorEnd getRed:&lr2 green:&lg2 blue:&lb2 alpha:&la2];
2556 : OOGL(glColor4f(lr, lg, lb, la*alpha));
2557 : glVertex3f(x+star.x, y+star.y, z);
2558 :
2559 : float frac = (d/jumpRange);
2560 : OOGL(glColor4f(
2561 : OOLerp(lr,lr2,frac),
2562 : OOLerp(lg,lg2,frac),
2563 : OOLerp(lb,lb2,frac),
2564 : OOLerp(la,la2,frac)
2565 : ));
2566 : glVertex3f(x+star2.x, y+star2.y, z);
2567 :
2568 : }
2569 : else
2570 : {
2571 : thisConnectionColor = [OOColor colorWithDescription:[systemManager getProperty:@"link_color" forSystemKey:[NSString stringWithFormat:@"interstellar: %d %ld %ld", g, (long)i, (long)j]]];
2572 :
2573 : if (thisConnectionColor == nil)
2574 : {
2575 : thisConnectionColor = defaultConnectionColor;
2576 : }
2577 : [thisConnectionColor getRed:&lr green:&lg blue:&lb alpha:&la];
2578 : OOGL(glColor4f(lr, lg, lb, la*alpha));
2579 :
2580 : glVertex3f(x+star.x, y+star.y, z);
2581 :
2582 : // and the other colour for the other end
2583 : thatConnectionColor = [OOColor colorWithDescription:[systemManager getProperty:@"link_color" forSystemKey:[NSString stringWithFormat:@"interstellar: %d %ld %ld", g, (long)j, (long)i]]];
2584 :
2585 : if (thatConnectionColor == nil)
2586 : {
2587 : thatConnectionColor = thisConnectionColor;
2588 : }
2589 : [thatConnectionColor getRed:&lr green:&lg blue:&lb alpha:&la];
2590 : OOGL(glColor4f(lr, lg, lb, la*alpha));
2591 :
2592 : glVertex3f(x+star2.x, y+star2.y, z);
2593 : }
2594 : }
2595 : }
2596 : }
2597 : OOGLEND();
2598 :
2599 : if (optimizeBy == OPTIMIZED_BY_NONE)
2600 : {
2601 : return;
2602 : }
2603 :
2604 : if (routeInfo)
2605 : {
2606 : NSUInteger i, route_hops = [[routeInfo oo_arrayForKey:@"route"] count] - 1;
2607 :
2608 : if (optimizeBy == OPTIMIZED_BY_JUMPS)
2609 : {
2610 : // route optimised by distance
2611 : [self setGLColorFromSetting:kGuiChartRouteShortColor defaultValue:[OOColor yellowColor] alpha:alpha];
2612 : }
2613 : else
2614 : {
2615 : // route optimised by time
2616 : [self setGLColorFromSetting:kGuiChartRouteQuickColor defaultValue:[OOColor cyanColor] alpha:alpha];
2617 : }
2618 : OOSystemID loc;
2619 : for (i = 0; i < route_hops; i++)
2620 : {
2621 : loc = [[routeInfo objectForKey:@"route"] oo_intAtIndex:i];
2622 : starabs = [systemManager getCoordinatesForSystem:loc inGalaxy:g];
2623 : star2abs = [systemManager getCoordinatesForSystem:[[routeInfo objectForKey:@"route"] oo_intAtIndex:i+1] inGalaxy:g];
2624 :
2625 : star.x = (float)(starabs.x * hscale);
2626 : star.y = (float)(starabs.y * vscale);
2627 :
2628 : star2.x = (float)(star2abs.x * hscale);
2629 : star2.y = (float)(star2abs.y * vscale);
2630 :
2631 :
2632 : OOGLBEGIN(GL_LINES);
2633 : glVertex3f(x+star.x, y+star.y, z);
2634 : glVertex3f(x+star2.x, y+star2.y, z);
2635 : OOGLEND();
2636 :
2637 : // Label the route, if not already labelled
2638 : if (zoom > CHART_ZOOM_SHOW_LABELS && concealment[loc] < OO_SYSTEMCONCEALMENT_NONAME)
2639 : {
2640 : OODrawString([UNIVERSE systemNameIndex:loc], x + star.x + 2.0, y + star.y, z, NSMakeSize(8,8));
2641 : }
2642 : }
2643 : // Label the destination, which was not included in the above loop.
2644 : if (zoom > CHART_ZOOM_SHOW_LABELS)
2645 : {
2646 : loc = [[routeInfo objectForKey:@"route"] oo_intAtIndex:i];
2647 : if(concealment[loc] < OO_SYSTEMCONCEALMENT_NONAME)
2648 : {
2649 : OODrawString([UNIVERSE systemNameIndex:loc], x + star2.x + 2.0, y + star2.y, z, NSMakeSize(10,10));
2650 : }
2651 : }
2652 : }
2653 : }
2654 :
2655 : @end
|