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 <unistd.h>
#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);

View file

@ -42,6 +42,13 @@
#include <nng/protocol/pubsub0/sub.h>
#include <dp_common.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;
@ -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; 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);