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.
This commit is contained in:
oxmox 2023-02-23 22:00:24 +01:00
parent e2830e3d68
commit 062980d465
2 changed files with 70 additions and 9 deletions

View file

@ -20,8 +20,8 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include "dp_common.h"
#include "dp_util.hpp" #include "dp_util.hpp"
#include "doomlib.hpp"
#if DoomBytesPerPixel == 3 #if DoomBytesPerPixel == 3
// FIXME: don't use, it's buggy // FIXME: don't use, it's buggy
@ -96,6 +96,8 @@ struct ControllerContext
bool isMousePanning = false; bool isMousePanning = false;
bool isFullscreen = false; bool isFullscreen = false;
bool uiVisible = true; bool uiVisible = true;
bool publishInputsMode = false;
MsgInputs inputs;
}; };
struct ControllerActions struct ControllerActions
@ -221,7 +223,7 @@ void check_on_dooms(ControllerContext &ctx)
void do_networking(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. // a single DP_DC_RunDoom command is broadcast.
bool sendRunDoom = false; bool sendRunDoom = false;
@ -390,6 +392,21 @@ void do_networking(ControllerContext &ctx)
if ((res = nng_sendmsg(ctx.pub, msg, 0))) if ((res = nng_sendmsg(ctx.pub, msg, 0)))
dp_nng_fatal("ctrl/sendmsg", res); 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) 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) void render_dooms(ControllerContext &ctx)
{ {
SDL_Rect destRect = { ctx.offsetX, ctx.offsetY, DoomScreenWidth, DoomScreenHeight }; SDL_Rect destRect = { ctx.offsetX, ctx.offsetY, DoomScreenWidth, DoomScreenHeight };
@ -493,6 +517,8 @@ ControllerActions run_ui(ControllerContext &ctx)
{ {
if (ImGui::BeginMenu("Menu")) 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::MenuItem("Quit", "Ctrl+Q", &ctx.quit, true);
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -568,6 +594,12 @@ int doom_controller_loop(ControllerContext &ctx)
if (event.type == SDL_MOUSEWHEEL) if (event.type == SDL_MOUSEWHEEL)
mouseWheel += event.wheel.y; 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 // Process input events not consumed by ImGui
@ -577,6 +609,7 @@ int doom_controller_loop(ControllerContext &ctx)
static const float ScaleStep = 0.01f; static const float ScaleStep = 0.01f;
s32 PanStep = io.KeyCtrl ? 10 : 2; s32 PanStep = io.KeyCtrl ? 10 : 2;
// Ctrl-Q to quit
if (io.KeyCtrl && ImGui::IsKeyDown(ImGuiKey_Q)) if (io.KeyCtrl && ImGui::IsKeyDown(ImGuiKey_Q))
ctx.quit = true; ctx.quit = true;
@ -600,7 +633,7 @@ int doom_controller_loop(ControllerContext &ctx)
if (ImGui::IsKeyDown(ImGuiKey_G)) if (ImGui::IsKeyDown(ImGuiKey_G))
ctx.offsetX = ctx.offsetY = 0; ctx.offsetX = ctx.offsetY = 0;
// fullscreen toggle // Alt-Enter fullscreen toggle
if (io.KeyAlt && ImGui::IsKeyPressed(ImGuiKey_Enter, false)) if (io.KeyAlt && ImGui::IsKeyPressed(ImGuiKey_Enter, false))
{ {
u32 flag = (ctx.isFullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP); u32 flag = (ctx.isFullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
@ -608,16 +641,22 @@ int doom_controller_loop(ControllerContext &ctx)
ctx.isFullscreen = !ctx.isFullscreen; ctx.isFullscreen = !ctx.isFullscreen;
} }
// F10 to toggle ImGui visibility (skips the call to run_ui() if true)
if (ImGui::IsKeyPressed(ImGuiKey_F10, false)) if (ImGui::IsKeyPressed(ImGuiKey_F10, false))
{ {
ctx.uiVisible = !ctx.uiVisible; ctx.uiVisible = !ctx.uiVisible;
// FIXME: sadly this has issues: after toggling the ui off and // FIXME: sadly this has issues: after toggling the ui off and
// on again the mouse cursor is invisible. Even using // on again the mouse cursor is invisible. Even using
// SDL_ShowCursor() unconditionally did not fix it. I suspect // 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) //if (SDL_SetRelativeMouseMode(ctx.uiVisible ? SDL_TRUE : SDL_FALSE) < 0)
// log_warn("SDL_SetRelativeMouseMode: %s", SDL_GetError()); // 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; static ImVec2 panStartPos;
@ -734,6 +773,8 @@ int main(int argc, char *argv[])
ctx.sub = make_ctrl_sub(DoomUrlIpc); ctx.sub = make_ctrl_sub(DoomUrlIpc);
ctx.window = window; ctx.window = window;
ctx.renderer = renderer; ctx.renderer = renderer;
ctx.inputs.head.msgType = DP_MT_Inputs;
ctx.inputs.eventCount = 0;
log_add_callback(log_to_imgui, &ctx, LOG_DEBUG); log_add_callback(log_to_imgui, &ctx, LOG_DEBUG);

View file

@ -42,6 +42,13 @@
#include <nng/protocol/pubsub0/sub.h> #include <nng/protocol/pubsub0/sub.h>
#include <dp_common.h> #include <dp_common.h>
#include <unistd.h> #include <unistd.h>
#include <SDL.h>
_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; typedef struct DoomContext DoomContext;
@ -208,11 +215,6 @@ void IB_StartTic (void)
event.data1 = xlatekey(sdl_event.key.keysym.sym); event.data1 = xlatekey(sdl_event.key.keysym.sym);
D_PostEvent(&event); 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) void IB_GetFramebuffer(unsigned char **pixels, size_t *pitch)
@ -227,14 +229,22 @@ void IB_FinishUpdate (void)
assert(ctx->state == DP_DS_Running); assert(ctx->state == DP_DS_Running);
static const u64 MaxReceiveTime_ms = 10;
u64 tStart = SDL_GetTicks64();
while (true)
{ {
int res = 0; int res = 0;
nng_msg *msg = NULL; nng_msg *msg = NULL;
if (SDL_GetTicks64() - tStart >= MaxReceiveTime_ms)
break;
if ((res = dp_recv_new_msg_nonblock(ctx->sub, &msg))) if ((res = dp_recv_new_msg_nonblock(ctx->sub, &msg)))
{ {
if (!dp_nng_is_timeout(res)) if (!dp_nng_is_timeout(res))
dp_nng_fatal("doom/recvmsg", res); dp_nng_fatal("doom/recvmsg", res);
break; // timeout
} }
else else
{ {
@ -254,6 +264,16 @@ void IB_FinishUpdate (void)
MsgMcstCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgMcstCommand); MsgMcstCommand *msgCmd = DP_NNG_BODY_AS(msg, MsgMcstCommand);
cmd = msgCmd->cmd; cmd = msgCmd->cmd;
} }
else if (msgBase->msgType == DP_MT_Inputs)
{
MsgInputs *msgInputs = DP_NNG_BODY_AS(msg, MsgInputs);
for (unsigned eventIndex=0; eventIndex<msgInputs->eventCount; ++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); nng_msg_free(msg);