Clean up key mapping

FossilOrigin-Name: 31ef5be209e12c2b31695e15653e093d6bb96523a45513c06e3fbee1860935b2
This commit is contained in:
Jonathan Schleifer 2025-03-05 22:24:16 +00:00
parent cac7cebba0
commit d537e43f86
6 changed files with 94 additions and 66 deletions

View file

@ -9,7 +9,6 @@ VARP(minmillis, 0, 5, 1000);
@implementation Cube { @implementation Cube {
int _width, _height; int _width, _height;
OFIRI *_userDataIRI;
} }
+ (Cube *)sharedInstance + (Cube *)sharedInstance

View file

@ -77,9 +77,10 @@ newteam(OFString *name)
COMMANDN(team, newteam, ARG_1STR) COMMANDN(team, newteam, ARG_1STR)
void void
writeclientinfo(FILE *f) writeclientinfo(OFStream *stream)
{ {
fprintf(f, "name \"%s\"\nteam \"%s\"\n", player1->name, player1->team); [stream writeFormat:@"name \"%s\"\nteam \"%s\"\n", player1->name,
player1->team];
} }
void void

View file

@ -585,34 +585,47 @@ exec(OFString *cfgfile)
void void
writecfg() writecfg()
{ {
FILE *f = fopen("config.cfg", "w"); OFStream *stream;
if (!f) @try {
OFIRI *IRI = [Cube.sharedInstance.userDataIRI
IRIByAppendingPathComponent:@"config.cfg"];
stream = [[OFIRIHandler handlerForIRI:IRI] openItemAtIRI:IRI
mode:@"w"];
} @catch (id e) {
return; return;
fprintf(f, "// automatically written on exit, do not modify\n// delete " }
"this file to have defaults.cfg overwrite these "
"settings\n// modify settings in game, or put settings in " [stream writeString:
"autoexec.cfg to override anything\n\n"); @"// automatically written on exit, do not modify\n"
writeclientinfo(f); @"// delete this file to have defaults.cfg overwrite these "
fprintf(f, "\n"); @"settings\n"
@"// modify settings in game, or put settings in "
@"autoexec.cfg to override anything\n"
@"\n"];
writeclientinfo(stream);
[stream writeString:@"\n"];
[idents enumerateKeysAndObjectsUsingBlock:^( [idents enumerateKeysAndObjectsUsingBlock:^(
OFString *name, Ident *ident, bool *stop) { OFString *name, Ident *ident, bool *stop) {
if (ident.type == ID_VAR && ident.persist) { if (ident.type == ID_VAR && ident.persist) {
fprintf(f, "%s %d\n", ident.name.UTF8String, [stream
*ident.storage); writeFormat:@"%@ %d\n", ident.name, *ident.storage];
} }
}]; }];
fprintf(f, "\n"); [stream writeString:@"\n"];
writebinds(f);
fprintf(f, "\n"); writebinds(stream);
[stream writeString:@"\n"];
[idents enumerateKeysAndObjectsUsingBlock:^( [idents enumerateKeysAndObjectsUsingBlock:^(
OFString *name, Ident *ident, bool *stop) { OFString *name, Ident *ident, bool *stop) {
if (ident.type == ID_ALIAS && if (ident.type == ID_ALIAS &&
!strstr(ident.name.UTF8String, "nextmap_")) { ![ident.name hasPrefix:@"nextmap_"])
fprintf(f, "alias \"%s\" [%s]\n", ident.name.UTF8String, [stream writeFormat:@"alias \"%@\" [%@]\n", ident.name,
ident.action.UTF8String); ident.action];
}
}]; }];
fclose(f);
[stream close];
} }
COMMAND(writecfg, ARG_NONE) COMMAND(writecfg, ARG_NONE)

View file

@ -93,38 +93,53 @@ renderconsole() // render buffer taking into account time & scrolling
// keymap is defined externally in keymap.cfg // keymap is defined externally in keymap.cfg
struct keym { @interface KeyMapping : OFObject
int code; @property (readonly) int code;
char *name; @property (readonly, nonatomic) OFString *name;
char *action; @property (copy, nonatomic) OFString *action;
} keyms[256];
int numkm = 0; - (instancetype)initWithCode:(int)code name:(OFString *)name;
@end
@implementation KeyMapping
- (instancetype)initWithCode:(int)code name:(OFString *)name
{
self = [super init];
_code = code;
_name = [name copy];
return self;
}
@end
static OFMutableArray<KeyMapping *> *keyMappings = nil;
void void
keymap(OFString *code, OFString *key, OFString *action) keymap(OFString *code, OFString *key, OFString *action)
{ {
@autoreleasepool { if (keyMappings == nil)
keyms[numkm].code = (int)code.longLongValue; keyMappings = [[OFMutableArray alloc] init];
keyms[numkm].name = newstring(key.UTF8String);
keyms[numkm++].action = newstringbuf(action.UTF8String); KeyMapping *mapping =
} [[KeyMapping alloc] initWithCode:(int)code.longLongValue name:key];
mapping.action = action;
[keyMappings addObject:mapping];
} }
COMMAND(keymap, ARG_3STR) COMMAND(keymap, ARG_3STR)
void void
bindkey(OFString *key_, OFString *action) bindkey(OFString *key, OFString *action)
{ {
@autoreleasepool { for (KeyMapping *mapping in keyMappings) {
std::unique_ptr<char> key(strdup(key_.UTF8String)); if ([mapping.name caseInsensitiveCompare:key] ==
for (char *x = key.get(); *x; x++) OFOrderedSame) {
*x = toupper(*x); mapping.action = action;
loopi(numkm) if (strcmp(keyms[i].name, key.get()) == 0)
{
strcpy_s(keyms[i].action, action.UTF8String);
return; return;
} }
conoutf(@"unknown key \"%s\"", key.get());
} }
conoutf(@"unknown key \"%@\"", key);
} }
COMMANDN(bind, bindkey, ARG_2STR) COMMANDN(bind, bindkey, ARG_2STR)
@ -244,33 +259,33 @@ keypress(int code, bool isdown, int cooked)
saycommand(NULL); saycommand(NULL);
}; };
}; };
} else if (!menukey(code, isdown)) // keystrokes go to menu } else if (!menukey(code, isdown)) {
{ // keystrokes go to menu
loopi(numkm) if (keyms[i].code ==
code) // keystrokes go to game, lookup in for (KeyMapping *mapping in keyMappings) {
// keymap and execute if (mapping.code == code) {
{ // keystrokes go to game, lookup in keymap and
// execute
string temp; string temp;
strcpy_s(temp, keyms[i].action); strcpy_s(temp, mapping.action.UTF8String);
execute(temp, isdown); execute(temp, isdown);
return; return;
}; }
}; }
}; }
}
char * char *
getcurcommand() getcurcommand()
{ {
return saycommandon ? commandbuf : NULL; return saycommandon ? commandbuf : NULL;
}; }
void void
writebinds(FILE *f) writebinds(OFStream *stream)
{ {
loopi(numkm) for (KeyMapping *mapping in keyMappings)
{ if (mapping.action.length > 0)
if (*keyms[i].action) [stream writeFormat:@"bind \"%@\" [%@]\n", mapping.name,
fprintf(f, "bind \"%s\" [%s]\n", keyms[i].name, mapping.action];
keyms[i].action); }
};
};

View file

@ -11,7 +11,7 @@
@interface Cube : OFObject <OFApplicationDelegate> @interface Cube : OFObject <OFApplicationDelegate>
@property (class, readonly, nonatomic) Cube *sharedInstance; @property (class, readonly, nonatomic) Cube *sharedInstance;
@property (readonly, nonatomic) SDL_Window *window; @property (readonly, nonatomic) SDL_Window *window;
@property (readonly, nonatomic) OFIRI *gameDataIRI; @property (readonly, nonatomic) OFIRI *gameDataIRI, *userDataIRI;
@property (nonatomic) bool repeatsKeys; @property (nonatomic) bool repeatsKeys;
@property (nonatomic) int framesInMap; @property (nonatomic) int framesInMap;
@end @end

View file

@ -21,7 +21,7 @@ extern void keypress(int code, bool isdown, int cooked);
extern void renderconsole(); extern void renderconsole();
extern void conoutf(OFConstantString *format, ...); extern void conoutf(OFConstantString *format, ...);
extern char *getcurcommand(); extern char *getcurcommand();
extern void writebinds(FILE *f); extern void writebinds(OFStream *stream);
// init // init
extern void enqueueInit(void (^init)(void)); extern void enqueueInit(void (^init)(void));
@ -83,7 +83,7 @@ extern void initclientnet();
extern bool netmapstart(); extern bool netmapstart();
extern int getclientnum(); extern int getclientnum();
extern void changemapserv(char *name, int mode); extern void changemapserv(char *name, int mode);
extern void writeclientinfo(FILE *f); extern void writeclientinfo(OFStream *stream);
// clientgame // clientgame
extern void mousemove(int dx, int dy); extern void mousemove(int dx, int dy);