From 062980d46538e4ce9da2a00e8d524fc44767f9e5 Mon Sep 17 00:00:00 2001 From: oxmox Date: Thu, 23 Feb 2023 22:00:24 +0100 Subject: [PATCH] implement input publishing and receiving Input publishing is currently toggled via Ctrl-A. This needs to be changed because pressing Ctrl makes doomguy attack. So every time input publishing is disabled the guy continues attacking. Use one of the unused F keys if there is one. --- src/doompanning.cc | 49 +++++++++++++++++-- .../linuxdoom-1.10/ib_video/ib_video_nng.c | 30 ++++++++++-- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/src/doompanning.cc b/src/doompanning.cc index 451c713..640cfe5 100644 --- a/src/doompanning.cc +++ b/src/doompanning.cc @@ -20,8 +20,8 @@ #include #include -#include "dp_common.h" #include "dp_util.hpp" +#include "doomlib.hpp" #if DoomBytesPerPixel == 3 // FIXME: don't use, it's buggy @@ -96,6 +96,8 @@ struct ControllerContext bool isMousePanning = false; bool isFullscreen = false; bool uiVisible = true; + bool publishInputsMode = false; + MsgInputs inputs; }; struct ControllerActions @@ -221,7 +223,7 @@ void check_on_dooms(ControllerContext &ctx) void do_networking(ControllerContext &ctx) { - // Set to true if we receive at least on DP_DS_Ready DoomState update. Then + // Set to true if we receive at least one DP_DS_Ready DoomState update. Then // a single DP_DC_RunDoom command is broadcast. bool sendRunDoom = false; @@ -390,6 +392,21 @@ void do_networking(ControllerContext &ctx) if ((res = nng_sendmsg(ctx.pub, msg, 0))) dp_nng_fatal("ctrl/sendmsg", res); } + + if (ctx.publishInputsMode && ctx.inputs.eventCount) + { + nng_msg *msg = nullptr; + int res = 0; + if ((res = nng_msg_alloc(&msg, sizeof(MsgInputs)))) + dp_nng_fatal("ctrl/nng_msg_alloc", res); + + auto dpmsg = DP_NNG_BODY_AS(msg, MsgInputs); + *dpmsg = ctx.inputs; + ctx.inputs.eventCount = 0; + + if ((res = nng_sendmsg(ctx.pub, msg, 0))) + dp_nng_fatal("ctrl/sendmsg", res); + } } void final_cleanup(ControllerContext &ctx) @@ -405,6 +422,13 @@ void final_cleanup(ControllerContext &ctx) } } +// Same as D_PostEvent from d_main.c +void post_doom_event(ControllerContext &ctx, const dp_doom_event_t &doom_event) +{ + ctx.inputs.events[ctx.inputs.eventCount] = doom_event; + ctx.inputs.eventCount = (ctx.inputs.eventCount+1) & (DoomMaxEvents-1); +} + void render_dooms(ControllerContext &ctx) { SDL_Rect destRect = { ctx.offsetX, ctx.offsetY, DoomScreenWidth, DoomScreenHeight }; @@ -493,6 +517,8 @@ ControllerActions run_ui(ControllerContext &ctx) { if (ImGui::BeginMenu("Menu")) { + ImGui::MenuItem("Send inputs to dooms", "Ctrl-A", &ctx.publishInputsMode, true); + ImGui::Separator(); ImGui::MenuItem("Quit", "Ctrl+Q", &ctx.quit, true); ImGui::EndMenu(); } @@ -568,6 +594,12 @@ int doom_controller_loop(ControllerContext &ctx) if (event.type == SDL_MOUSEWHEEL) mouseWheel += event.wheel.y; + + if (ctx.publishInputsMode) + { + if (auto doomEvent = doomevent_from_sdlevent(event)) + post_doom_event(ctx, *doomEvent); + } } // Process input events not consumed by ImGui @@ -577,6 +609,7 @@ int doom_controller_loop(ControllerContext &ctx) static const float ScaleStep = 0.01f; s32 PanStep = io.KeyCtrl ? 10 : 2; + // Ctrl-Q to quit if (io.KeyCtrl && ImGui::IsKeyDown(ImGuiKey_Q)) ctx.quit = true; @@ -600,7 +633,7 @@ int doom_controller_loop(ControllerContext &ctx) if (ImGui::IsKeyDown(ImGuiKey_G)) ctx.offsetX = ctx.offsetY = 0; - // fullscreen toggle + // Alt-Enter fullscreen toggle if (io.KeyAlt && ImGui::IsKeyPressed(ImGuiKey_Enter, false)) { u32 flag = (ctx.isFullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); @@ -608,16 +641,22 @@ int doom_controller_loop(ControllerContext &ctx) ctx.isFullscreen = !ctx.isFullscreen; } + // F10 to toggle ImGui visibility (skips the call to run_ui() if true) if (ImGui::IsKeyPressed(ImGuiKey_F10, false)) { ctx.uiVisible = !ctx.uiVisible; // FIXME: sadly this has issues: after toggling the ui off and // on again the mouse cursor is invisible. Even using // SDL_ShowCursor() unconditionally did not fix it. I suspect - // it's caused by some interaction between SLD and ImGui. + // it's caused by some interaction between SDL and ImGui. //if (SDL_SetRelativeMouseMode(ctx.uiVisible ? SDL_TRUE : SDL_FALSE) < 0) // log_warn("SDL_SetRelativeMouseMode: %s", SDL_GetError()); } + + // Ctrl-A to toggle sending input events to dooms. + if (io.KeyCtrl && ImGui::IsKeyPressed(ImGuiKey_A, false)) + ctx.publishInputsMode = !ctx.publishInputsMode; + } static ImVec2 panStartPos; @@ -734,6 +773,8 @@ int main(int argc, char *argv[]) ctx.sub = make_ctrl_sub(DoomUrlIpc); ctx.window = window; ctx.renderer = renderer; + ctx.inputs.head.msgType = DP_MT_Inputs; + ctx.inputs.eventCount = 0; log_add_callback(log_to_imgui, &ctx, LOG_DEBUG); diff --git a/src/dp_doom/linuxdoom-1.10/ib_video/ib_video_nng.c b/src/dp_doom/linuxdoom-1.10/ib_video/ib_video_nng.c index adc52aa..947fea3 100644 --- a/src/dp_doom/linuxdoom-1.10/ib_video/ib_video_nng.c +++ b/src/dp_doom/linuxdoom-1.10/ib_video/ib_video_nng.c @@ -42,6 +42,13 @@ #include #include #include +#include + +_Static_assert(sizeof(event_t) == sizeof(dp_doom_event_t), + "Size mismatch between dooms event_t and doompannings dp_doom_event_t. Packing?"); + +_Static_assert(MAXEVENTS == DoomMaxEvents, + "MAXEVENTS (from d_event.h) and DoomMaxEvents (from dp_common.h) are not equal!"); typedef struct DoomContext DoomContext; @@ -208,11 +215,6 @@ void IB_StartTic (void) event.data1 = xlatekey(sdl_event.key.keysym.sym); D_PostEvent(&event); */ - _Static_assert(sizeof(event_t) == sizeof(dp_doom_event_t), - "Size mismatch between dooms event_t and doompannings dp_doom_event_t. Packing?"); - event_t event; - static int button_state; - //SDL_Event sdl_event; } void IB_GetFramebuffer(unsigned char **pixels, size_t *pitch) @@ -227,14 +229,22 @@ void IB_FinishUpdate (void) assert(ctx->state == DP_DS_Running); + static const u64 MaxReceiveTime_ms = 10; + u64 tStart = SDL_GetTicks64(); + + while (true) { int res = 0; nng_msg *msg = NULL; + if (SDL_GetTicks64() - tStart >= MaxReceiveTime_ms) + break; + if ((res = dp_recv_new_msg_nonblock(ctx->sub, &msg))) { if (!dp_nng_is_timeout(res)) dp_nng_fatal("doom/recvmsg", res); + break; // timeout } else { @@ -254,6 +264,16 @@ void IB_FinishUpdate (void) MsgMcstCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgMcstCommand); cmd = msgCmd->cmd; } + else if (msgBase->msgType == DP_MT_Inputs) + { + MsgInputs *msgInputs = DP_NNG_BODY_AS(msg, MsgInputs); + for (unsigned eventIndex=0; eventIndexeventCount; ++eventIndex) + { + // Can do this cast. _Static_assert() at the top gives a bit + // of ensurance. + D_PostEvent((event_t *) msgInputs->events + eventIndex); + } + } nng_msg_free(msg);