Joystick Event Injection
NickWebHA

Hey, all.

I am toying with Allegro 5.0.x with which I am using several gamepads (joysticks, according to the API). I have all that working great (got my game loop checking events, ect).

For debug builds, which I work on while, say, on the bus, I do not have a gamepad with me. In the past to alleviate this issue I have created a thin "conversation layer" that maps keyboard inputs to gamepad buttons. The solution has worked wonders for my convenience but I can not seem to figure out how to implement it with Allegro.

Is there a way to inject custom events into the joystick queue? Going through the documentation I have tried playing with al_set_event_source_data() (line looks like al_set_event_source_data(al_get_joystick_event_source(), 1)) but can not figure it out. On top of that looking through the source I see intptr_t is just an int pointer of a specific size but with no indication as to what that should be pointing to?

This would only be for debugs builds. A handful of #define's remove it from release builds.

I searched both Google and the forums but can not seem to find an answer. Any help-- or alternative suggestions-- would be welcomed.

Edit 2015.03.25-01
Wait, intptr_t is not a pointer. Name threw me.

Edgar Reynaldo

Well, you can use al_init_user_event_source and al_emit_user_event to emit an event with a type value of 1024 or greater. But you can't actually emit a standard allegro event and I'm not quite sure what the reasoning for this is. It would be nice to be able to simulate events.

Then when you get a joystick event you emit a user event to match it. Then only take action on the user joystick events. That way you can emit one yourself, or forward one from the joystick event.

Thomas Fjellstrom

But you can't actually emit a standard allegro event and I'm not quite sure what the reasoning for this is.

As you state, it would be nice to simulate events.

NickWebHA

Been a long time since I have been a part of this community. I need to figure out where I can submit such a request... for another day.

Thanks, guys. I was considering the user-defined events but they seemed a bit too round-about. However if that is the answer then that is the answer.

Ben Delacob

If it's for testing purposes, you could use a virtual joystick. The operating system reports to applications about a controller that only exists digitally. The virtual joystick is fed whatever input necessary through library functions.

For Windows, vJoy looks like a good option to create the virtual joystick. ppJoy can work but is a little bit of a pain to set up for Vista onward. If you don't want to feed the input from your program with library functions, you can feed with a control script program like AutoHotkey, FreePIE, or GlovePIE.

I know there's a nice program for Macs. And don't know about other OSes.

NickWebHA

That is a great idea! Since I control the development machine and am not interested in keyboard controls in the release builds-- read: distributed builds-- a virtual joystick would work perfectly.

Why did I not think of that? I blame the democrats.

Edit 2015.03.26-01
... and now to find one for Linux. Everything I am coming across is gamepad to keyboard, not the other way around. "antimicro is a graphical program used to map keyboard keys and mouse controls to a gamepad" my ass!

Chris Katko
NickWebHA said:

Is there a way to inject custom events into the joystick queue? Going through the documentation I have tried playing with al_set_event_source_data() (line looks like al_set_event_source_data(al_get_joystick_event_source(), 1)) but can not figure it out. On top of that looking through the source I see intptr_t is just an int pointer of a specific size but with no indication as to what that should be pointing to?

If you're doing custom mapping, inject your conversion layer inbetween your game and the allegro routines, not the allegro routines and the OS.

Instead of using some form of "is_allegro_joystick_pressed()" in your logic routines you do "is_control_pressed()" and let your code do the linking between whether Allegro has a joystick, mouse, or keyboard present. Your game shouldn't know whats behind is_control_pressed() at all.

Mark Oates

AutoHotKey is really powerful.

And 2, being able to emit allegro events of any type would be very useful.

Edgar Reynaldo

I think all that needs to be done is to remove this ASSERT and then I believe you should be able to emit regular allegro events using al_emit_user_event.

evtsrc.c#SelectExpand
215/* Function: al_emit_user_event 216 */ 217bool al_emit_user_event(ALLEGRO_EVENT_SOURCE *src, 218 ALLEGRO_EVENT *event, void (*dtor)(ALLEGRO_USER_EVENT *)) 219{ 220 size_t num_queues; 221 bool rc; 222 223 ASSERT(src); 224 ASSERT(event);
225 ASSERT(ALLEGRO_EVENT_TYPE_IS_USER(event->any.type));
226 227 if (dtor) { 228 ALLEGRO_USER_EVENT_DESCRIPTOR *descr = al_malloc(sizeof(*descr)); 229 descr->refcount = 0; 230 descr->dtor = dtor; 231 event->user.__internal__descr = descr; 232 } 233 else { 234 event->user.__internal__descr = NULL; 235 } 236 237 _al_event_source_lock(src); 238 { 239 ALLEGRO_EVENT_SOURCE_REAL *rsrc = (ALLEGRO_EVENT_SOURCE_REAL *)src; 240 241 num_queues = _al_vector_size(&rsrc->queues); 242 if (num_queues > 0) {
243 event->user.timestamp = al_get_time();
244 _al_event_source_emit_event(src, event); 245 rc = true; 246 } 247 else { 248 rc = false; 249 } 250 } 251 _al_event_source_unlock(src); 252 253 if (dtor && !rc) { 254 dtor(&event->user); 255 al_free(event->user.__internal__descr); 256 } 257 258 return rc; 259}

The other highlighted line should probably be changed to event->any.timestamp = al_get_time(); to make it more suitable for any event in general.

The actual nitty gritty function that allegro uses behind the scenes is _al_event_source_emit_event, which needs to have the event source locked first, and which uses _al_event_queue_push_event internally.

SiegeLord

I'm not 100% clear on the implications, but I think being able to emit core events would be great. Another related thing is that it would be great to create event constructor functions (like al_emit_key_event or whatnot). It'd make the internals somewhat cleaner (pretty much every backend has a version of these constructor functions).

Chris Katko
SiegeLord said:

I'm not 100% clear on the implications, but I think being able to emit core events would be great.

I agree. I was initially hesitant, but the more I think about it the more I like it. I already do plenty of sending XEvents in XLib in the same vein.

Thread #615220. Printed from Allegro.cc