Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
PlayerEntityStickMapper.m
Go to the documentation of this file.
1/*
2
3PlayerEntityStickMapper.m
4
5Oolite
6Copyright (C) 2004-2019 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
28#import "OOJoystickManager.h"
29#import "OOTexture.h"
31#import "HeadUpDisplay.h"
32
33@interface PlayerEntity (StickMapperInternal)
34
35- (void) resetStickFunctions;
36- (void) checkCustomEquipButtons:(NSDictionary *)stickFn ignore:(int)idx;
37- (void) removeFunction:(int)selFunctionIdx;
38- (NSArray *)stickFunctionList;
39- (void)displayFunctionList:(GuiDisplayGen *)gui
40 skip:(NSUInteger) skip;
41- (NSString *)describeStickDict:(NSDictionary *)stickDict;
42- (NSString *)hwToString:(int)hwFlags;
43
44@end
45
46
47@implementation PlayerEntity (StickMapper)
48
49- (void) resetStickFunctions
50{
51 [stickFunctions release];
52 stickFunctions = nil;
53}
54
55
56- (void) setGuiToStickMapperScreen:(unsigned)skip
57{
58 [self setGuiToStickMapperScreen: skip resetCurrentRow: NO];
59}
60
61- (void) setGuiToStickMapperScreen:(unsigned)skip resetCurrentRow: (BOOL) resetCurrentRow
62{
63 GuiDisplayGen *gui = [UNIVERSE gui];
65 NSArray *stickList = [stickHandler listSticks];
66 unsigned stickCount = [stickList count];
67 unsigned i;
68
69 OOGUITabStop tabStop[GUI_MAX_COLUMNS];
70 tabStop[0] = 10;
71 tabStop[1] = 290;
72 tabStop[2] = 400;
73 [gui setTabStops:tabStop];
74
75 gui_screen = GUI_SCREEN_STICKMAPPER;
76 [gui clear];
77 [gui setTitle:[NSString stringWithFormat:@"Configure Joysticks"]];
78
79 for(i=0; i < stickCount; i++)
80 {
81 NSString *stickNameForThisRow = [NSString stringWithFormat: @"Stick %d %@", i+1, [stickList objectAtIndex: i]];
82 // for more than 2 sticks, the stick name rows are populated by more than one name if needed
83 NSString *stickNameAdditional = nil;
84 if (stickCount > 2 && OOStringWidthInEm(stickNameForThisRow) > 18.0)
85 {
86 // string is too long, truncate it until its length gets below threshold
87 do {
88 stickNameForThisRow = [[stickNameForThisRow substringToIndex:[stickNameForThisRow length] - 5]
89 stringByAppendingString:@"..."];
90 } while (OOStringWidthInEm(stickNameForThisRow) > 18.0);
91 }
92 unsigned j = i + 2;
93 if (j < stickCount)
94 {
95 stickNameAdditional = [NSString stringWithFormat: @"Stick %d %@", j+1, [stickList objectAtIndex: j]];
96 if (OOStringWidthInEm(stickNameAdditional) > 11.0)
97 {
98 // string is too long, truncate it until its length gets below threshold
99 do {
100 stickNameAdditional = [[stickNameAdditional substringToIndex:[stickNameAdditional length] - 5]
101 stringByAppendingString:@"..."];
102 } while (OOStringWidthInEm(stickNameAdditional) > 11.0);
103 }
104 }
105 [gui setArray:[NSArray arrayWithObjects:
106 stickNameForThisRow,
107 @"", // skip one column
108 stickNameAdditional,
109 nil]
110 forRow:i + GUI_ROW_STICKNAME];
111 }
112
113 [gui setArray: [NSArray arrayWithObjects: DESC(@"stickmapper-profile"), nil] forRow: GUI_ROW_STICKPROFILE];
114 [gui setKey: GUI_KEY_OK forRow: GUI_ROW_STICKPROFILE];
115 [self displayFunctionList:gui skip:skip];
116
117 [gui setArray:[NSArray arrayWithObject:@"Select a function and press Enter to modify or 'u' to unset."]
118 forRow:GUI_ROW_INSTRUCT];
119
120 [gui setText:@"Space to return to previous screen." forRow:GUI_ROW_INSTRUCT+1 align:GUI_ALIGN_CENTER];
121
122 if (resetCurrentRow)
123 {
124 [gui setSelectedRow: GUI_ROW_STICKPROFILE];
125 }
126 [[UNIVERSE gameView] suppressKeysUntilKeyUp];
127 [gui setForegroundTextureKey:[self status] == STATUS_DOCKED ? @"docked_overlay" : @"paused_overlay"];
128 [gui setBackgroundTextureKey:@"settings"];
129}
130
131
132- (void) stickMapperInputHandler:(GuiDisplayGen *)gui
133 view:(MyOpenGLView *)gameView
134{
136
137 // Don't do anything if the user is supposed to be selecting
138 // a function - other than look for Escape.
139 if(waitingForStickCallback)
140 {
141 if([gameView isDown: 27])
142 {
143 [stickHandler clearCallback];
144 [gui setArray: [NSArray arrayWithObjects:
145 @"Function setting aborted.", nil]
146 forRow: GUI_ROW_INSTRUCT];
147 waitingForStickCallback=NO;
148 }
149
150 // Break out now.
151 return;
152 }
153
154 [self handleGUIUpDownArrowKeys];
155
156 if ([gui selectedRow] == GUI_ROW_STICKPROFILE && [gameView isDown: 13])
157 {
158 [self setGuiToStickProfileScreen: gui];
159 return;
160 }
161
162 NSString* key = [gui keyForRow: [gui selectedRow]];
163 if ([key hasPrefix:@"Index:"])
164 selFunctionIdx=[[[key componentsSeparatedByString:@":"] objectAtIndex: 1] intValue];
165 else
166 selFunctionIdx=-1;
167
168 if([gameView isDown: 13])
169 {
170 if ([key hasPrefix:@"More:"])
171 {
172 int from_function = [[[key componentsSeparatedByString:@":"] objectAtIndex: 1] intValue];
173 if (from_function < 0) from_function = 0;
174
175 [self setGuiToStickMapperScreen:from_function];
176 if ([[UNIVERSE gui] selectedRow] < 0)
177 [[UNIVERSE gui] setSelectedRow: GUI_ROW_FUNCSTART];
178 if (from_function == 0)
179 [[UNIVERSE gui] setSelectedRow: GUI_ROW_FUNCSTART + MAX_ROWS_FUNCTIONS - 1];
180 return;
181 }
182
183 NSDictionary *entry=[stickFunctions objectAtIndex: selFunctionIdx];
184 int hw=[(NSNumber *)[entry objectForKey: KEY_ALLOWABLE] intValue];
185 [stickHandler setCallback: @selector(updateFunction:)
186 object: self
187 hardware: hw];
188
189 // Print instructions
190 NSString *instructions;
191 switch(hw)
192 {
193 case HW_AXIS:
194 instructions = @"Fully deflect the axis you want to use for this function. Esc aborts.";
195 break;
196 case HW_BUTTON:
197 instructions = @"Press the button you want to use for this function. Esc aborts.";
198 break;
199 default:
200 instructions = @"Press the button or deflect the axis you want to use for this function.";
201 }
202 [gui setArray: [NSArray arrayWithObjects: instructions, nil] forRow: GUI_ROW_INSTRUCT];
203 waitingForStickCallback=YES;
204 }
205
206 if([gameView isDown: 'u'])
207 {
208 if (selFunctionIdx >= 0) [self removeFunction: selFunctionIdx];
209 }
210}
211
212
213// Callback function, called by JoystickHandler when the callback
214// is set. The dictionary contains the thing that was pressed/moved.
215- (void) updateFunction: (NSDictionary *)hwDict
216{
218 waitingForStickCallback = NO;
219
220 // Right time and the right place?
221 if(gui_screen != GUI_SCREEN_STICKMAPPER)
222 {
223 OOLog(@"joystick.configure.error", @"%s called when not on stick mapper screen.", __PRETTY_FUNCTION__);
224 return;
225 }
226
227 // What moved?
228 int function;
229 NSDictionary *entry = [stickFunctions objectAtIndex:selFunctionIdx];
230 if([hwDict oo_boolForKey:STICK_ISAXIS])
231 {
232 function=[entry oo_intForKey: KEY_AXISFN];
233 if (function == AXIS_THRUST)
234 {
235 [stickHandler unsetButtonFunction:BUTTON_INCTHRUST];
236 [stickHandler unsetButtonFunction:BUTTON_DECTHRUST];
237 }
238#if OO_FOV_INFLIGHT_CONTROL_ENABLED
239 if (function == AXIS_FIELD_OF_VIEW)
240 {
241 [stickHandler unsetButtonFunction:BUTTON_INC_FIELD_OF_VIEW];
242 [stickHandler unsetButtonFunction:BUTTON_DEC_FIELD_OF_VIEW];
243 }
244#endif
245 if (function == AXIS_VIEWX)
246 {
247 [stickHandler unsetButtonFunction:BUTTON_VIEWPORT];
248 [stickHandler unsetButtonFunction:BUTTON_VIEWSTARBOARD];
249 }
250 if (function == AXIS_VIEWY)
251 {
252 [stickHandler unsetButtonFunction:BUTTON_VIEWFORWARD];
253 [stickHandler unsetButtonFunction:BUTTON_VIEWAFT];
254 }
255 }
256 else
257 {
258 function = [entry oo_intForKey:KEY_BUTTONFN];
259 if (function == BUTTON_INCTHRUST || function == BUTTON_DECTHRUST)
260 {
261 [stickHandler unsetAxisFunction:AXIS_THRUST];
262 }
263#if OO_FOV_INFLIGHT_CONTROL_ENABLED
264 if (function == BUTTON_INC_FIELD_OF_VIEW || function == BUTTON_DEC_FIELD_OF_VIEW)
265 {
266 [stickHandler unsetAxisFunction:AXIS_FIELD_OF_VIEW];
267 }
268#endif
269 if (function == BUTTON_VIEWPORT || function == BUTTON_VIEWSTARBOARD)
270 {
271 [stickHandler unsetAxisFunction:AXIS_VIEWX];
272 }
273 if (function == BUTTON_VIEWFORWARD || function == BUTTON_VIEWAFT)
274 {
275 [stickHandler unsetAxisFunction:AXIS_VIEWY];
276 }
277 }
278 // special case for OXP equipment buttons
279 if (function >= 10000)
280 {
281 NSString *key = CUSTOMEQUIP_BUTTONACTIVATE;
282 function -= 10000;
283 if (function >= 10000)
284 {
285 function -= 10000;
287 }
288 [[customEquipActivation objectAtIndex:function] setObject:hwDict forKey:key];
289 [self checkCustomEquipButtons:hwDict ignore:function];
290
291 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
292 [defaults setObject:customEquipActivation forKey:KEYCONFIG_CUSTOMEQUIP];
293 }
294 else
295 {
296 [stickHandler setFunction:function withDict:hwDict];
297 [self checkCustomEquipButtons:hwDict ignore:-1];
298 [stickHandler saveStickSettings];
299 }
300
301 // Update the GUI (this will refresh the function list).
302 unsigned skip;
303 if (selFunctionIdx < MAX_ROWS_FUNCTIONS - 1)
304 {
305 skip = 0;
306 }
307 else
308 {
309 skip = ((selFunctionIdx - 1) / (MAX_ROWS_FUNCTIONS - 2)) * (MAX_ROWS_FUNCTIONS - 2) + 1;
310 }
311
312 [self setGuiToStickMapperScreen:skip];
313}
314
315
316- (void) checkCustomEquipButtons:(NSDictionary *)stickFn ignore:(int)idx
317{
318 int i;
319 for (i = 0; i < [customEquipActivation count]; i++)
320 {
321 if (i != idx) {
322 NSDictionary *bf = [[customEquipActivation objectAtIndex:i] objectForKey:CUSTOMEQUIP_BUTTONACTIVATE];
323 if ([bf oo_integerForKey:STICK_NUMBER] == [stickFn oo_integerForKey:STICK_NUMBER] &&
324 [bf oo_integerForKey:STICK_AXBUT] == [stickFn oo_integerForKey:STICK_AXBUT])
325 {
326 [[customEquipActivation objectAtIndex:i] removeObjectForKey:CUSTOMEQUIP_BUTTONACTIVATE];
327 }
328 bf = [[customEquipActivation objectAtIndex:i] objectForKey:CUSTOMEQUIP_BUTTONMODE];
329 if ([bf oo_integerForKey:STICK_NUMBER] == [stickFn oo_integerForKey:STICK_NUMBER] &&
330 [bf oo_integerForKey:STICK_AXBUT] == [stickFn oo_integerForKey:STICK_AXBUT])
331 {
332 [[customEquipActivation objectAtIndex:i] removeObjectForKey:CUSTOMEQUIP_BUTTONMODE];
333 }
334 }
335 }
336}
337
338
339- (void) removeFunction:(int)idx
340{
342 NSDictionary *entry = [stickFunctions objectAtIndex:idx];
343 NSNumber *butfunc = [entry objectForKey:KEY_BUTTONFN];
344 NSNumber *axfunc = [entry objectForKey:KEY_AXISFN];
345 BOOL custom = NO;
346 selFunctionIdx = idx;
347
348 // Some things can have either axis or buttons - make sure we clear
349 // both!
350 if(butfunc)
351 {
352 // special case for OXP equipment buttons
353 if ([butfunc intValue] >= 10000)
354 {
355 int bf = [butfunc intValue];
356 custom = YES;
357 NSString *key = CUSTOMEQUIP_BUTTONACTIVATE;
358 bf -= 10000;
359 if (bf >= 10000)
360 {
361 bf -= 10000;
363 }
364 [[customEquipActivation objectAtIndex:bf] removeObjectForKey:key];
365 }
366 else
367 {
368 [stickHandler unsetButtonFunction:[butfunc intValue]];
369 }
370 }
371 if(axfunc)
372 {
373 [stickHandler unsetAxisFunction:[axfunc intValue]];
374 }
375 if (!custom)
376 {
377 [stickHandler saveStickSettings];
378 }
379 else
380 {
381 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
382 [defaults setObject:customEquipActivation forKey:KEYCONFIG_CUSTOMEQUIP];
383 }
384
385 unsigned skip;
386 if (selFunctionIdx < MAX_ROWS_FUNCTIONS - 1)
387 skip = 0;
388 else
389 skip = ((selFunctionIdx - 1) / (MAX_ROWS_FUNCTIONS - 2)) * (MAX_ROWS_FUNCTIONS - 2) + 1;
390 [self setGuiToStickMapperScreen: skip];
391}
392
393
394- (void) displayFunctionList:(GuiDisplayGen *)gui
395 skip:(NSUInteger)skip
396{
398
399 [gui setColor:[OOColor greenColor] forRow: GUI_ROW_HEADING];
400 [gui setArray:[NSArray arrayWithObjects:
401 @"Function", @"Assigned to", @"Type", nil]
402 forRow:GUI_ROW_HEADING];
403
404 if(!stickFunctions)
405 {
406 stickFunctions = [[self stickFunctionList] retain];
407 }
408 NSDictionary *assignedAxes = [stickHandler axisFunctions];
409 NSDictionary *assignedButs = [stickHandler buttonFunctions];
410
411 NSUInteger i, n_functions = [stickFunctions count];
412 NSInteger n_rows, start_row, previous = 0;
413
414 if (skip >= n_functions)
415 skip = n_functions - 1;
416
417 if (n_functions < MAX_ROWS_FUNCTIONS)
418 {
419 skip = 0;
420 previous = 0;
421 n_rows = MAX_ROWS_FUNCTIONS;
422 start_row = GUI_ROW_FUNCSTART;
423 }
424 else
425 {
426 n_rows = MAX_ROWS_FUNCTIONS - 1;
427 start_row = GUI_ROW_FUNCSTART;
428 if (skip > 0)
429 {
430 n_rows -= 1;
431 start_row += 1;
432 if (skip > MAX_ROWS_FUNCTIONS)
433 previous = skip - (MAX_ROWS_FUNCTIONS - 2);
434 else
435 previous = 0;
436 }
437 }
438
439 if (n_functions > 0)
440 {
441 if (skip > 0)
442 {
443 [gui setColor:[OOColor greenColor] forRow:GUI_ROW_FUNCSTART];
444 [gui setArray:[NSArray arrayWithObjects:DESC(@"gui-back"), @" <-- ", nil] forRow:GUI_ROW_FUNCSTART];
445 [gui setKey:[NSString stringWithFormat:@"More:%ld", previous] forRow:GUI_ROW_FUNCSTART];
446 }
447
448 for(i=0; i < (n_functions - skip) && (int)i < n_rows; i++)
449 {
450 NSDictionary *entry = [stickFunctions objectAtIndex: i + skip];
451 if ([entry objectForKey:KEY_HEADER]) {
452 NSString *header = [entry objectForKey:KEY_HEADER];
453 [gui setArray:[NSArray arrayWithObjects:header, @"", @"", nil] forRow:i + start_row];
454 [gui setColor:[OOColor cyanColor] forRow:i + start_row];
455 }
456 else
457 {
458 NSString *allowedThings;
459 NSString *assignment;
460 NSString *axFuncKey = [entry oo_stringForKey:KEY_AXISFN];
461 NSString *butFuncKey = [entry oo_stringForKey:KEY_BUTTONFN];
462 int allowable = [entry oo_intForKey:KEY_ALLOWABLE];
463 switch(allowable)
464 {
465 case HW_AXIS:
466 allowedThings=@"Axis";
467 assignment=[self describeStickDict:
468 [assignedAxes objectForKey: axFuncKey]];
469 break;
470 case HW_BUTTON:
471 allowedThings=@"Button";
472 int bf = [butFuncKey integerValue];
473 if (bf < 10000)
474 {
475 assignment=[self describeStickDict:
476 [assignedButs objectForKey: butFuncKey]];
477 }
478 else
479 {
480 NSString *key = CUSTOMEQUIP_BUTTONACTIVATE;
481 bf -= 10000;
482 if (bf >= 10000)
483 {
484 bf -= 10000;
486 }
487 assignment=[self describeStickDict:
488 [[customEquipActivation objectAtIndex:bf] objectForKey:key]];
489 }
490 break;
491 default:
492 allowedThings=@"Axis/Button";
493
494 // axis has priority
495 assignment=[self describeStickDict:
496 [assignedAxes objectForKey: axFuncKey]];
497 if(!assignment)
498 assignment=[self describeStickDict:
499 [assignedButs objectForKey: butFuncKey]];
500 }
501
502 // Find out what's assigned for this function currently.
503 if (assignment == nil)
504 {
505 assignment = @" - ";
506 }
507
508 [gui setArray: [NSArray arrayWithObjects:
509 [entry objectForKey: KEY_GUIDESC], assignment, allowedThings, nil]
510 forRow: i + start_row];
511 //[gui setKey: GUI_KEY_OK forRow: i + start_row];
512 [gui setKey: [NSString stringWithFormat: @"Index:%ld", i + skip] forRow: i + start_row];
513 }
514 }
515 if (i < n_functions - skip)
516 {
517 [gui setColor: [OOColor greenColor] forRow: start_row + i];
518 [gui setArray: [NSArray arrayWithObjects: DESC(@"gui-more"), @" --> ", nil] forRow: start_row + i];
519 [gui setKey: [NSString stringWithFormat: @"More:%ld", n_rows + skip] forRow: start_row + i];
520 i++;
521 }
522
523 [gui setSelectableRange: NSMakeRange(GUI_ROW_STICKPROFILE, i + start_row - GUI_ROW_STICKPROFILE)];
524 }
525
526}
527
528
529- (NSString *) describeStickDict: (NSDictionary *)stickDict
530{
531 NSString *desc=nil;
532 if(stickDict)
533 {
534 int thingNumber=[(NSNumber *)[stickDict objectForKey: STICK_AXBUT]
535 intValue];
536 int stickNumber=[(NSNumber *)[stickDict objectForKey: STICK_NUMBER]
537 intValue];
538 // Button or axis?
539 if([(NSNumber *)[stickDict objectForKey: STICK_ISAXIS] boolValue])
540 {
541 desc=[NSString stringWithFormat: @"Stick %d axis %d",
542 stickNumber+1, thingNumber+1];
543 }
544 else if(thingNumber >= MAX_REAL_BUTTONS)
545 {
546 static const char dir[][6] = { "up", "right", "down", "left" };
547 desc=[NSString stringWithFormat: @"Stick %d hat %d %s",
548 stickNumber+1, (thingNumber - MAX_REAL_BUTTONS) / 4 + 1,
549 dir[thingNumber & 3]];
550 }
551 else
552 {
553 desc=[NSString stringWithFormat: @"Stick %d button %d",
554 stickNumber+1, thingNumber+1];
555 }
556 }
557 return desc;
558}
559
560
561- (NSString *)hwToString: (int)hwFlags
562{
563 NSString *hwString;
564 switch(hwFlags)
565 {
566 case HW_AXIS:
567 hwString = @"axis";
568 break;
569 case HW_BUTTON:
570 hwString = @"button";
571 break;
572 default:
573 hwString = @"axis/button";
574 }
575 return hwString;
576}
577
578
579// TODO: This data could be put into a plist (i18n or just modifiable by
580// the user). It is otherwise an ugly method, but it'll do for testing.
581- (NSArray *)stickFunctionList
582{
583 NSMutableArray *funcList = [NSMutableArray array];
584
585 // propulsion
586 [funcList addObject:[self makeStickGuiDictHeader:DESC(@"stickmapper-header-propulsion")]];
587 [funcList addObject:
588 [self makeStickGuiDict:DESC(@"stickmapper-roll")
589 allowable:HW_AXIS
590 axisfn:AXIS_ROLL
591 butfn:STICK_NOFUNCTION]];
592 [funcList addObject:
593 [self makeStickGuiDict:DESC(@"stickmapper-pitch")
594 allowable:HW_AXIS
595 axisfn:AXIS_PITCH
596 butfn:STICK_NOFUNCTION]];
597 [funcList addObject:
598 [self makeStickGuiDict:DESC(@"stickmapper-yaw")
599 allowable:HW_AXIS
600 axisfn:AXIS_YAW
601 butfn:STICK_NOFUNCTION]];
602 [funcList addObject:
603 [self makeStickGuiDict:DESC(@"stickmapper-increase-thrust")
604 allowable:HW_AXIS|HW_BUTTON
605 axisfn:AXIS_THRUST
606 butfn:BUTTON_INCTHRUST]];
607 [funcList addObject:
608 [self makeStickGuiDict:DESC(@"stickmapper-decrease-thrust")
609 allowable:HW_AXIS|HW_BUTTON
610 axisfn:AXIS_THRUST
611 butfn:BUTTON_DECTHRUST]];
612 [funcList addObject:
613 [self makeStickGuiDict:DESC(@"stickmapper-fuel-injection")
614 allowable:HW_BUTTON
615 axisfn:STICK_NOFUNCTION
616 butfn:BUTTON_FUELINJECT]];
617 [funcList addObject:
618 [self makeStickGuiDict:DESC(@"stickmapper-hyperspeed")
619 allowable:HW_BUTTON
620 axisfn:STICK_NOFUNCTION
621 butfn:BUTTON_HYPERSPEED]];
622 [funcList addObject:
623 [self makeStickGuiDict:DESC(@"stickmapper-hyperdrive")
624 allowable:HW_BUTTON
625 axisfn:STICK_NOFUNCTION
626 butfn:BUTTON_HYPERDRIVE]];
627 [funcList addObject:
628 [self makeStickGuiDict:DESC(@"stickmapper-gal-hyperdrive")
629 allowable:HW_BUTTON
630 axisfn:STICK_NOFUNCTION
631 butfn:BUTTON_GALACTICDRIVE]];
632
633 [funcList addObject:
634 [self makeStickGuiDict:DESC(@"stickmapper-roll/pitch-precision-toggle")
635 allowable:HW_BUTTON
636 axisfn:STICK_NOFUNCTION
637 butfn:BUTTON_PRECISION]];
638
639 // navigation
640 [funcList addObject:[self makeStickGuiDictHeader:DESC(@"stickmapper-header-navigation")]];
641 [funcList addObject:
642 [self makeStickGuiDict:DESC(@"stickmapper-compass-mode-next")
643 allowable:HW_BUTTON
644 axisfn:STICK_NOFUNCTION
645 butfn:BUTTON_COMPASSMODE]];
646 [funcList addObject:
647 [self makeStickGuiDict:DESC(@"stickmapper-compass-mode-prev")
648 allowable:HW_BUTTON
649 axisfn:STICK_NOFUNCTION
650 butfn:BUTTON_COMPASSMODE_PREV]];
651 [funcList addObject:
652 [self makeStickGuiDict:DESC(@"stickmapper-scanner-zoom")
653 allowable:HW_BUTTON
654 axisfn:STICK_NOFUNCTION
655 butfn:BUTTON_SCANNERZOOM]];
656 [funcList addObject:
657 [self makeStickGuiDict:DESC(@"stickmapper-scanner-unzoom")
658 allowable:HW_BUTTON
659 axisfn:STICK_NOFUNCTION
660 butfn:BUTTON_SCANNERUNZOOM]];
661 [funcList addObject:
662 [self makeStickGuiDict:DESC(@"stickmapper-view-forward")
663 allowable:HW_AXIS|HW_BUTTON
664 axisfn:AXIS_VIEWY
665 butfn:BUTTON_VIEWFORWARD]];
666 [funcList addObject:
667 [self makeStickGuiDict:DESC(@"stickmapper-view-aft")
668 allowable:HW_AXIS|HW_BUTTON
669 axisfn:AXIS_VIEWY
670 butfn:BUTTON_VIEWAFT]];
671 [funcList addObject:
672 [self makeStickGuiDict:DESC(@"stickmapper-view-port")
673 allowable:HW_AXIS|HW_BUTTON
674 axisfn:AXIS_VIEWX
675 butfn:BUTTON_VIEWPORT]];
676 [funcList addObject:
677 [self makeStickGuiDict:DESC(@"stickmapper-view-starboard")
678 allowable:HW_AXIS|HW_BUTTON
679 axisfn:AXIS_VIEWX
680 butfn:BUTTON_VIEWSTARBOARD]];
681 [funcList addObject:
682 [self makeStickGuiDict:DESC(@"stickmapper-ext-view-cycle")
683 allowable:HW_BUTTON
684 axisfn:STICK_NOFUNCTION
685 butfn:BUTTON_EXTVIEWCYCLE]];
686 [funcList addObject:
687 [self makeStickGuiDict:DESC(@"stickmapper-toggle-ID")
688 allowable:HW_BUTTON
689 axisfn:STICK_NOFUNCTION
690 butfn:BUTTON_ID]];
691 [funcList addObject:
692 [self makeStickGuiDict:DESC(@"stickmapper-docking-clearance")
693 allowable:HW_BUTTON
694 axisfn:STICK_NOFUNCTION
695 butfn:BUTTON_DOCKINGCLEARANCE]];
696 [funcList addObject:
697 [self makeStickGuiDict:DESC(@"stickmapper-dockcpu")
698 allowable:HW_BUTTON
699 axisfn:STICK_NOFUNCTION
700 butfn:BUTTON_DOCKCPU]];
701 [funcList addObject:
702 [self makeStickGuiDict:DESC(@"stickmapper-dockcpufast")
703 allowable:HW_BUTTON
704 axisfn:STICK_NOFUNCTION
705 butfn:BUTTON_DOCKCPUFAST]];
706 [funcList addObject:
707 [self makeStickGuiDict:DESC(@"stickmapper-docking-music")
708 allowable:HW_BUTTON
709 axisfn:STICK_NOFUNCTION
710 butfn:BUTTON_DOCKINGMUSIC]];
711
712 // offensive
713 [funcList addObject:[self makeStickGuiDictHeader:DESC(@"stickmapper-header-offensive")]];
714 [funcList addObject:
715 [self makeStickGuiDict:DESC(@"stickmapper-weapons-online-toggle")
716 allowable:HW_BUTTON
717 axisfn:STICK_NOFUNCTION
718 butfn:BUTTON_WEAPONSONLINETOGGLE]];
719 [funcList addObject:
720 [self makeStickGuiDict:DESC(@"stickmapper-primary-weapon")
721 allowable:HW_BUTTON
722 axisfn:STICK_NOFUNCTION
723 butfn:BUTTON_FIRE]];
724 [funcList addObject:
725 [self makeStickGuiDict:DESC(@"stickmapper-secondary-weapon")
726 allowable:HW_BUTTON
727 axisfn:STICK_NOFUNCTION
728 butfn:BUTTON_LAUNCHMISSILE]];
729 [funcList addObject:
730 [self makeStickGuiDict:DESC(@"stickmapper-arm-secondary")
731 allowable:HW_BUTTON
732 axisfn:STICK_NOFUNCTION
733 butfn:BUTTON_ARMMISSILE]];
734 [funcList addObject:
735 [self makeStickGuiDict:DESC(@"stickmapper-disarm-secondary")
736 allowable:HW_BUTTON
737 axisfn:STICK_NOFUNCTION
738 butfn:BUTTON_UNARM]];
739 [funcList addObject:
740 [self makeStickGuiDict:DESC(@"stickmapper-target-nearest-incoming-missile")
741 allowable:HW_BUTTON
742 axisfn:STICK_NOFUNCTION
743 butfn:BUTTON_TARGETINCOMINGMISSILE]];
744 [funcList addObject:
745 [self makeStickGuiDict:DESC(@"stickmapper-cycle-secondary")
746 allowable:HW_BUTTON
747 axisfn:STICK_NOFUNCTION
748 butfn:BUTTON_CYCLEMISSILE]];
749 [funcList addObject:
750 [self makeStickGuiDict:DESC(@"stickmapper-next-target")
751 allowable:HW_BUTTON
752 axisfn:STICK_NOFUNCTION
753 butfn:BUTTON_NEXTTARGET]];
754 [funcList addObject:
755 [self makeStickGuiDict:DESC(@"stickmapper-previous-target")
756 allowable:HW_BUTTON
757 axisfn:STICK_NOFUNCTION
758 butfn:BUTTON_PREVTARGET]];
759
760 // defensive
761 [funcList addObject:[self makeStickGuiDictHeader:DESC(@"stickmapper-header-defensive")]];
762 [funcList addObject:
763 [self makeStickGuiDict:DESC(@"stickmapper-ECM")
764 allowable:HW_BUTTON
765 axisfn:STICK_NOFUNCTION
766 butfn:BUTTON_ECM]];
767 [funcList addObject:
768 [self makeStickGuiDict:DESC(@"stickmapper-jettison")
769 allowable:HW_BUTTON
770 axisfn:STICK_NOFUNCTION
771 butfn:BUTTON_JETTISON]];
772 [funcList addObject:
773 [self makeStickGuiDict:DESC(@"stickmapper-rotate-cargo")
774 allowable:HW_BUTTON
775 axisfn:STICK_NOFUNCTION
776 butfn:BUTTON_ROTATECARGO]];
777 [funcList addObject:
778 [self makeStickGuiDict:DESC(@"stickmapper-escape-pod")
779 allowable:HW_BUTTON
780 axisfn:STICK_NOFUNCTION
781 butfn:BUTTON_ESCAPE]];
782
783 // oxp special equip
784 [funcList addObject:[self makeStickGuiDictHeader:DESC(@"stickmapper-header-special-equip")]];
785 [funcList addObject:
786 [self makeStickGuiDict:DESC(@"stickmapper-mfd-select-next")
787 allowable:HW_BUTTON
788 axisfn:STICK_NOFUNCTION
789 butfn:BUTTON_MFDSELECTNEXT]];
790 [funcList addObject:
791 [self makeStickGuiDict:DESC(@"stickmapper-mfd-select-prev")
792 allowable:HW_BUTTON
793 axisfn:STICK_NOFUNCTION
794 butfn:BUTTON_MFDSELECTPREV]];
795 [funcList addObject:
796 [self makeStickGuiDict:DESC(@"stickmapper-mfd-cycle-next")
797 allowable:HW_BUTTON
798 axisfn:STICK_NOFUNCTION
799 butfn:BUTTON_MFDCYCLENEXT]];
800 [funcList addObject:
801 [self makeStickGuiDict:DESC(@"stickmapper-mfd-cycle-prev")
802 allowable:HW_BUTTON
803 axisfn:STICK_NOFUNCTION
804 butfn:BUTTON_MFDCYCLEPREV]];
805 [funcList addObject:
806 [self makeStickGuiDict:DESC(@"stickmapper-prime-equipment")
807 allowable:HW_BUTTON
808 axisfn:STICK_NOFUNCTION
809 butfn:BUTTON_PRIMEEQUIPMENT]];
810 [funcList addObject:
811 [self makeStickGuiDict:DESC(@"stickmapper-prime-prev-equipment")
812 allowable:HW_BUTTON
813 axisfn:STICK_NOFUNCTION
814 butfn:BUTTON_PRIMEEQUIPMENT]];
815 [funcList addObject:
816 [self makeStickGuiDict:DESC(@"stickmapper-activate-equipment")
817 allowable:HW_BUTTON
818 axisfn:STICK_NOFUNCTION
819 butfn:BUTTON_ACTIVATEEQUIPMENT]];
820 [funcList addObject:
821 [self makeStickGuiDict:DESC(@"stickmapper-mode-equipment")
822 allowable:HW_BUTTON
823 axisfn:STICK_NOFUNCTION
824 butfn:BUTTON_MODEEQUIPMENT]];
825 [funcList addObject:
826 [self makeStickGuiDict:DESC(@"stickmapper-fastactivate-a")
827 allowable:HW_BUTTON
828 axisfn:STICK_NOFUNCTION
829 butfn:BUTTON_CLOAK]];
830 [funcList addObject:
831 [self makeStickGuiDict:DESC(@"stickmapper-fastactivate-b")
832 allowable:HW_BUTTON
833 axisfn:STICK_NOFUNCTION
834 butfn:BUTTON_ENERGYBOMB]];
835
836 // misc
837 [funcList addObject:[self makeStickGuiDictHeader:DESC(@"stickmapper-header-misc")]];
838 [funcList addObject:
839 [self makeStickGuiDict:DESC(@"stickmapper-snapshot")
840 allowable:HW_BUTTON
841 axisfn:STICK_NOFUNCTION
842 butfn:BUTTON_SNAPSHOT]];
843 [funcList addObject:
844 [self makeStickGuiDict:DESC(@"stickmapper-pause")
845 allowable:HW_BUTTON
846 axisfn:STICK_NOFUNCTION
847 butfn:BUTTON_PAUSE]];
848 [funcList addObject:
849 [self makeStickGuiDict:DESC(@"stickmapper-toggle-hud")
850 allowable:HW_BUTTON
851 axisfn:STICK_NOFUNCTION
852 butfn:BUTTON_TOGGLEHUD]];
853 [funcList addObject:
854 [self makeStickGuiDict:DESC(@"stickmapper-comms-log")
855 allowable:HW_BUTTON
856 axisfn:STICK_NOFUNCTION
857 butfn:BUTTON_COMMSLOG]];
858#if OO_FOV_INFLIGHT_CONTROL_ENABLED
859 [funcList addObject:
860 [self makeStickGuiDict:DESC(@"stickmapper-increase-field-of-view")
861 allowable:HW_AXIS|HW_BUTTON
862 axisfn:AXIS_FIELD_OF_VIEW
863 butfn:BUTTON_INC_FIELD_OF_VIEW]];
864 [funcList addObject:
865 [self makeStickGuiDict:DESC(@"stickmapper-decrease-field-of-view")
866 allowable:HW_AXIS|HW_BUTTON
867 axisfn:AXIS_FIELD_OF_VIEW
868 butfn:BUTTON_DEC_FIELD_OF_VIEW]];
869#endif
870 if ([customEquipActivation count] > 0) {
871 [funcList addObject:[self makeStickGuiDictHeader:DESC(@"stickmapper-header-oxp-equip")]];
872 int i;
873 for (i = 0; i < [customEquipActivation count]; i++)
874 {
875 [funcList addObject:
876 [self makeStickGuiDict:[NSString stringWithFormat: @"Activate '%@'", [[customEquipActivation objectAtIndex:i] oo_stringForKey:CUSTOMEQUIP_EQUIPNAME]]
877 allowable:HW_BUTTON
878 axisfn:STICK_NOFUNCTION
879 butfn:(i+10000)]];
880 [funcList addObject:
881 [self makeStickGuiDict:[NSString stringWithFormat: @"Mode '%@'", [[customEquipActivation objectAtIndex:i] oo_stringForKey:CUSTOMEQUIP_EQUIPNAME]]
882 allowable:HW_BUTTON
883 axisfn:STICK_NOFUNCTION
884 butfn:(i+20000)]];
885 }
886
887 }
888 return funcList;
889}
890
891
892
893- (NSDictionary *)makeStickGuiDict:(NSString *)what
894 allowable:(int)allowable
895 axisfn:(int)axisfn
896 butfn:(int)butfn
897{
898 NSMutableDictionary *guiDict = [NSMutableDictionary dictionary];
899
900 if ([what length] > 50) what = [[what substringToIndex:28] stringByAppendingString:@"..."];
901 [guiDict setObject: what forKey: KEY_GUIDESC];
902 [guiDict setObject: [NSNumber numberWithInt: allowable]
903 forKey: KEY_ALLOWABLE];
904 if(axisfn >= 0)
905 [guiDict setObject: [NSNumber numberWithInt: axisfn]
906 forKey: KEY_AXISFN];
907 if(butfn >= 0)
908 [guiDict setObject: [NSNumber numberWithInt: butfn]
909 forKey: KEY_BUTTONFN];
910 return guiDict;
911}
912
913- (NSDictionary *)makeStickGuiDictHeader:(NSString *)header
914{
915 NSMutableDictionary *guiDict = [NSMutableDictionary dictionary];
916 [guiDict setObject:header forKey:KEY_HEADER];
917 [guiDict setObject:@"" forKey:KEY_ALLOWABLE];
918 [guiDict setObject:@"" forKey:KEY_AXISFN];
919 [guiDict setObject:@"" forKey:KEY_BUTTONFN];
920 return guiDict;
921}
922
923@end
924
NSInteger OOGUITabStop
CGFloat OOStringWidthInEm(NSString *text)
#define STICK_ISAXIS
@ BUTTON_VIEWSTARBOARD
@ BUTTON_VIEWAFT
@ BUTTON_VIEWPORT
@ BUTTON_VIEWFORWARD
@ BUTTON_INCTHRUST
@ BUTTON_DECTHRUST
@ AXIS_VIEWX
@ AXIS_THRUST
@ AXIS_VIEWY
#define MAX_REAL_BUTTONS
#define HW_BUTTON
#define HW_AXIS
#define STICK_NUMBER
#define STICK_AXBUT
#define OOLog(class, format,...)
Definition OOLogging.h:88
unsigned count
return nil
#define KEY_HEADER
#define GUI_ROW_STICKPROFILE
#define KEY_AXISFN
#define KEY_BUTTONFN
#define MAX_ROWS_FUNCTIONS
#define GUI_ROW_FUNCSTART
#define CUSTOMEQUIP_BUTTONACTIVATE
#define CUSTOMEQUIP_BUTTONMODE
#define UNIVERSE
Definition Universe.h:840
BOOL setBackgroundTextureKey:(NSString *key)
BOOL setSelectedRow:(OOGUIRow row)
BOOL setForegroundTextureKey:(NSString *key)
void setText:forRow:align:(NSString *str,[forRow] OOGUIRow row,[align] OOGUIAlignment alignment)
OOGUIRow selectedRow
void setSelectableRange:(NSRange range)
void setColor:forRow:(OOColor *color,[forRow] OOGUIRow row)
void setTitle:(NSString *str)
void setTabStops:(OOGUITabSettings stops)
NSString * keyForRow:(OOGUIRow row)
void setArray:forRow:(NSArray *arr,[forRow] OOGUIRow row)
void setKey:forRow:(NSString *str,[forRow] OOGUIRow row)
OOColor * cyanColor()
Definition OOColor.m:286
OOColor * greenColor()
Definition OOColor.m:274
NSDictionary * buttonFunctions()
void unsetButtonFunction:(int function)
void setFunction:withDict:(int function,[withDict] NSDictionary *stickFn)
NSDictionary * axisFunctions()
void unsetAxisFunction:(int function)
void setCallback:object:hardware:(SEL selector,[object] id obj,[hardware] char hwflags)
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque