Browse Source

Use SDL events directly

Removes redundant miniwin events and queue, using SDL events directly instead.

Demo migrated using this script: https://gist.github.com/glebm/8a73b04f695de96f344cc2e35151e03e
pull/5182/head
Gleb Mazovetskiy 4 years ago committed by Anders Jenbo
parent
commit
ba34bafb3f
  1. 9
      Source/debug.cpp
  2. 177
      Source/diablo.cpp
  3. 2
      Source/diablo.h
  4. 188
      Source/engine/demomode.cpp
  5. 6
      Source/engine/demomode.h
  6. 43
      Source/init.cpp
  7. 2
      Source/init.h
  8. 35
      Source/interfac.cpp
  9. 33
      Source/interfac.h
  10. 180
      Source/miniwin/misc_msg.cpp
  11. 41
      Source/miniwin/misc_msg.h
  12. 16
      Source/movie.cpp
  13. 12
      Source/player.cpp
  14. 1
      Source/utils/display.cpp
  15. BIN
      test/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo

9
Source/debug.cpp

@ -116,14 +116,15 @@ void PrintDebugMonster(const Monster &monster)
void ProcessMessages()
{
tagMSG msg;
while (FetchMessage(&msg)) {
if (msg.message == DVL_WM_QUIT) {
SDL_Event event;
uint16_t modState;
while (FetchMessage(&event, &modState)) {
if (event.type == SDL_QUIT) {
gbRunGameResult = false;
gbRunGame = false;
break;
}
PushMessage(&msg);
HandleMessage(event, modState);
}
}

177
Source/diablo.cpp

@ -594,110 +594,79 @@ void PressKey(SDL_Keycode vkey, uint16_t modState)
}
}
void GetMousePos(uint32_t lParam)
void GameEventHandler(const SDL_Event &event, uint16_t modState)
{
MousePosition = { (std::int16_t)(lParam & 0xffff), (std::int16_t)((lParam >> 16) & 0xffff) };
}
void GameEventHandler(uint32_t uMsg, uint32_t wParam, uint16_t lParam)
{
switch (uMsg) {
case DVL_WM_KEYDOWN:
PressKey(static_cast<SDL_Keycode>(wParam), lParam);
switch (event.type) {
case SDL_KEYDOWN:
PressKey(event.key.keysym.sym, modState);
return;
case DVL_WM_KEYUP:
ReleaseKey(static_cast<SDL_Keycode>(wParam));
case SDL_KEYUP:
ReleaseKey(event.key.keysym.sym);
return;
case DVL_WM_MOUSEMOVE:
GetMousePos(wParam);
case SDL_MOUSEMOTION:
MousePosition = { event.motion.x, event.motion.y };
gmenu_on_mouse_move();
return;
case DVL_WM_LBUTTONDOWN:
GetMousePos(wParam);
case SDL_MOUSEBUTTONDOWN:
MousePosition = { event.button.x, event.button.y };
if (sgbMouseDown == CLICK_NONE) {
sgbMouseDown = CLICK_LEFT;
LeftMouseDown(lParam);
switch (event.button.button) {
case SDL_BUTTON_LEFT:
sgbMouseDown = CLICK_LEFT;
LeftMouseDown(modState);
break;
case SDL_BUTTON_RIGHT:
sgbMouseDown = CLICK_RIGHT;
RightMouseDown((modState & KMOD_SHIFT) != 0);
break;
default:
sgOptions.Keymapper.KeyPressed(event.button.button | KeymapperMouseButtonMask);
break;
}
}
return;
case DVL_WM_LBUTTONUP:
GetMousePos(wParam);
if (sgbMouseDown == CLICK_LEFT) {
case SDL_MOUSEBUTTONUP:
MousePosition = { event.button.x, event.button.y };
if (sgbMouseDown == CLICK_LEFT && event.button.button == SDL_BUTTON_LEFT) {
LastMouseButtonAction = MouseActionType::None;
sgbMouseDown = CLICK_NONE;
LeftMouseUp(lParam);
}
return;
case DVL_WM_RBUTTONDOWN:
GetMousePos(wParam);
if (sgbMouseDown == CLICK_NONE) {
sgbMouseDown = CLICK_RIGHT;
RightMouseDown((lParam & KMOD_SHIFT) != 0);
LeftMouseUp(modState);
} else if (sgbMouseDown == CLICK_RIGHT && event.button.button == SDL_BUTTON_RIGHT) {
LastMouseButtonAction = MouseActionType::None;
sgbMouseDown = CLICK_NONE;
} else {
sgOptions.Keymapper.KeyReleased(event.button.button | KeymapperMouseButtonMask);
}
return;
case DVL_WM_RBUTTONUP:
GetMousePos(wParam);
if (sgbMouseDown == CLICK_RIGHT) {
default:
if (IsCustomEvent(event.type)) {
if (gbIsMultiplayer)
pfile_write_hero();
nthread_ignore_mutex(true);
PaletteFadeOut(8);
sound_stop();
LastMouseButtonAction = MouseActionType::None;
sgbMouseDown = CLICK_NONE;
ShowProgress(GetCustomEvent(event.type));
force_redraw = 255;
DrawAndBlit();
LoadPWaterPalette();
if (gbRunGame)
PaletteFadeIn(8);
nthread_ignore_mutex(false);
gbGameLoopStartup = true;
return;
}
return;
case DVL_WM_MBUTTONDOWN:
sgOptions.Keymapper.KeyPressed(SDL_BUTTON_MIDDLE | KeymapperMouseButtonMask);
return;
case DVL_WM_MBUTTONUP:
sgOptions.Keymapper.KeyReleased(SDL_BUTTON_MIDDLE | KeymapperMouseButtonMask);
return;
case DVL_WM_X1BUTTONDOWN:
sgOptions.Keymapper.KeyPressed(SDL_BUTTON_X1 | KeymapperMouseButtonMask);
return;
case DVL_WM_X1BUTTONUP:
sgOptions.Keymapper.KeyReleased(SDL_BUTTON_X1 | KeymapperMouseButtonMask);
return;
case DVL_WM_X2BUTTONDOWN:
sgOptions.Keymapper.KeyPressed(SDL_BUTTON_X2 | KeymapperMouseButtonMask);
return;
case DVL_WM_X2BUTTONUP:
sgOptions.Keymapper.KeyReleased(SDL_BUTTON_X2 | KeymapperMouseButtonMask);
return;
case DVL_WM_CAPTURECHANGED:
sgbMouseDown = CLICK_NONE;
LastMouseButtonAction = MouseActionType::None;
MainWndProc(event);
break;
case WM_DIABNEXTLVL:
case WM_DIABPREVLVL:
case WM_DIABRTNLVL:
case WM_DIABSETLVL:
case WM_DIABWARPLVL:
case WM_DIABTOWNWARP:
case WM_DIABTWARPUP:
case WM_DIABRETOWN:
if (gbIsMultiplayer)
pfile_write_hero();
nthread_ignore_mutex(true);
PaletteFadeOut(8);
sound_stop();
LastMouseButtonAction = MouseActionType::None;
sgbMouseDown = CLICK_NONE;
ShowProgress((interface_mode)uMsg);
force_redraw = 255;
DrawAndBlit();
LoadPWaterPalette();
if (gbRunGame)
PaletteFadeIn(8);
nthread_ignore_mutex(false);
gbGameLoopStartup = true;
return;
}
MainWndProc(uMsg);
}
void RunGameLoop(interface_mode uMsg)
{
demo::NotifyGameLoopStart();
tagMSG msg;
nthread_ignore_mutex(true);
StartGame(uMsg);
assert(HeadlessMode || ghMainWnd);
@ -730,13 +699,15 @@ void RunGameLoop(interface_mode uMsg)
}
#endif
while (FetchMessage(&msg)) {
if (msg.message == DVL_WM_QUIT) {
SDL_Event event;
uint16_t modState;
while (FetchMessage(&event, &modState)) {
if (event.type == SDL_QUIT) {
gbRunGameResult = false;
gbRunGame = false;
break;
}
PushMessage(&msg);
HandleMessage(event, modState);
}
if (!gbRunGame)
break;
@ -2015,41 +1986,31 @@ bool PressEscKey()
return rv;
}
void DisableInputEventHandler(uint32_t uMsg, uint32_t wParam, uint16_t /*lParam*/)
void DisableInputEventHandler(const SDL_Event &event, uint16_t modState)
{
switch (uMsg) {
case DVL_WM_KEYDOWN:
case DVL_WM_KEYUP:
return;
case DVL_WM_MOUSEMOVE:
GetMousePos(wParam);
switch (event.type) {
case SDL_MOUSEMOTION:
MousePosition = { event.motion.x, event.motion.y };
return;
case DVL_WM_LBUTTONDOWN:
case SDL_MOUSEBUTTONDOWN:
if (sgbMouseDown != CLICK_NONE)
return;
sgbMouseDown = CLICK_LEFT;
return;
case DVL_WM_LBUTTONUP:
if (sgbMouseDown != CLICK_LEFT)
switch (event.button.button) {
case SDL_BUTTON_LEFT:
sgbMouseDown = CLICK_LEFT;
return;
sgbMouseDown = CLICK_NONE;
return;
case DVL_WM_RBUTTONDOWN:
if (sgbMouseDown != CLICK_NONE)
case SDL_BUTTON_RIGHT:
sgbMouseDown = CLICK_RIGHT;
return;
sgbMouseDown = CLICK_RIGHT;
return;
case DVL_WM_RBUTTONUP:
if (sgbMouseDown != CLICK_RIGHT)
default:
return;
sgbMouseDown = CLICK_NONE;
return;
case DVL_WM_CAPTURECHANGED:
}
case SDL_MOUSEBUTTONUP:
sgbMouseDown = CLICK_NONE;
return;
}
MainWndProc(uMsg);
MainWndProc(event);
}
void LoadGameLevel(bool firstflag, lvl_entry lvldir)

2
Source/diablo.h

@ -93,7 +93,7 @@ bool diablo_is_focused();
void diablo_focus_pause();
void diablo_focus_unpause();
bool PressEscKey();
void DisableInputEventHandler(uint32_t uMsg, uint32_t wParam, uint16_t lParam);
void DisableInputEventHandler(const SDL_Event &event, uint16_t modState);
void LoadGameLevel(bool firstflag, lvl_entry lvldir);
/**

188
Source/engine/demomode.cpp

@ -25,12 +25,39 @@ enum class DemoMsgType {
Message = 2,
};
struct MouseMotionEventData {
uint16_t x;
uint16_t y;
};
struct MouseButtonEventData {
uint8_t button;
uint16_t x;
uint16_t y;
uint16_t mod;
};
struct MouseWheelEventData {
int32_t x;
int32_t y;
uint16_t mod;
};
struct KeyEventData {
SDL_Keycode sym;
SDL_Keymod mod;
};
struct DemoMsg {
DemoMsgType type;
uint32_t message;
uint32_t wParam;
uint16_t lParam;
float progressToNextGameTick;
SDL_EventType eventType;
union {
MouseMotionEventData motion;
MouseButtonEventData button;
MouseWheelEventData wheel;
KeyEventData key;
};
};
int DemoNumber = -1;
@ -48,11 +75,6 @@ int StartTime = 0;
uint16_t DemoGraphicsWidth = 640;
uint16_t DemoGraphicsHeight = 480;
void PumpDemoMessage(DemoMsgType demoMsgType, uint32_t message, uint32_t wParam, uint16_t lParam, float progressToNextGameTick)
{
Demo_Message_Queue.push_back(DemoMsg { demoMsgType, message, wParam, lParam, progressToNextGameTick });
}
bool LoadDemoMessages(int i)
{
std::ifstream demofile;
@ -78,14 +100,45 @@ bool LoadDemoMessages(int i)
switch (type) {
case DemoMsgType::Message: {
const uint32_t message = ReadLE32(demofile);
const uint32_t wParam = ReadLE32(demofile);
const uint16_t lParam = ReadLE16(demofile);
PumpDemoMessage(type, message, wParam, lParam, progressToNextGameTick);
const auto eventType = static_cast<SDL_EventType>(ReadLE32(demofile));
DemoMsg msg { type, progressToNextGameTick, eventType, {} };
switch (eventType) {
case SDL_MOUSEMOTION:
msg.motion.x = ReadLE16(demofile);
msg.motion.y = ReadLE16(demofile);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
msg.button.button = ReadByte(demofile);
msg.button.x = ReadLE16(demofile);
msg.button.y = ReadLE16(demofile);
msg.button.mod = ReadLE16(demofile);
break;
#ifndef USE_SDL1
case SDL_MOUSEWHEEL:
msg.wheel.x = ReadLE32<int32_t>(demofile);
msg.wheel.y = ReadLE32<int32_t>(demofile);
msg.wheel.mod = ReadLE16(demofile);
break;
#endif
case SDL_KEYDOWN:
case SDL_KEYUP:
msg.key.sym = static_cast<SDL_Keycode>(ReadLE32(demofile));
msg.key.mod = static_cast<SDL_Keymod>(ReadLE16(demofile));
break;
case SDL_QUIT:
break;
default:
if (eventType < SDL_USEREVENT) {
app_fatal(StrCat("Unknown event ", static_cast<uint32_t>(eventType)));
}
break;
}
Demo_Message_Queue.push_back(msg);
break;
}
default:
PumpDemoMessage(type, 0, 0, 0, progressToNextGameTick);
Demo_Message_Queue.push_back(DemoMsg { type, progressToNextGameTick, static_cast<SDL_EventType>(0), {} });
break;
}
}
@ -97,6 +150,13 @@ bool LoadDemoMessages(int i)
return true;
}
void RecordEventHeader(const SDL_Event &event)
{
WriteLE32(DemoRecording, static_cast<uint32_t>(DemoMsgType::Message));
WriteLEFloat(DemoRecording, gfProgressToNextGameTick);
WriteLE32(DemoRecording, event.type);
}
} // namespace
namespace demo {
@ -180,19 +240,16 @@ bool GetRunGameLoop(bool &drawGame, bool &processInput)
return dmsg.type == DemoMsgType::GameTick;
}
bool FetchMessage(tagMSG *lpMsg)
bool FetchMessage(SDL_Event *event, uint16_t *modState)
{
SDL_Event e;
if (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) {
lpMsg->message = DVL_WM_QUIT;
lpMsg->wParam = 0;
lpMsg->lParam = 0;
*event = e;
return true;
}
if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE) {
Demo_Message_Queue.clear();
ClearMessageQueue();
DemoNumber = -1;
Timedemo = false;
last_tick = SDL_GetTicks();
@ -212,19 +269,45 @@ bool FetchMessage(tagMSG *lpMsg)
if (!Demo_Message_Queue.empty()) {
const DemoMsg dmsg = Demo_Message_Queue.front();
if (dmsg.type == DemoMsgType::Message) {
lpMsg->message = dmsg.message;
lpMsg->wParam = dmsg.wParam;
lpMsg->lParam = dmsg.lParam;
event->type = dmsg.eventType;
switch (dmsg.eventType) {
case SDL_MOUSEMOTION:
event->motion.x = dmsg.motion.x;
event->motion.y = dmsg.motion.y;
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
event->button.button = dmsg.button.button;
event->button.state = dmsg.eventType == SDL_MOUSEBUTTONDOWN ? SDL_PRESSED : SDL_RELEASED;
event->button.x = dmsg.button.x;
event->button.y = dmsg.button.y;
*modState = dmsg.button.mod;
break;
#ifndef USE_SDL1
case SDL_MOUSEWHEEL:
event->wheel.x = dmsg.wheel.x;
event->wheel.y = dmsg.wheel.y;
*modState = dmsg.wheel.mod;
break;
#endif
case SDL_KEYDOWN:
case SDL_KEYUP:
event->key.state = dmsg.eventType == SDL_KEYDOWN ? SDL_PRESSED : SDL_RELEASED;
event->key.keysym.sym = dmsg.key.sym;
event->key.keysym.mod = dmsg.key.mod;
break;
default:
if (dmsg.eventType >= SDL_USEREVENT) {
event->type = CustomEventToSdlEvent(static_cast<interface_mode>(dmsg.eventType - SDL_USEREVENT));
}
break;
}
gfProgressToNextGameTick = dmsg.progressToNextGameTick;
Demo_Message_Queue.pop_front();
return true;
}
}
lpMsg->message = 0;
lpMsg->wParam = 0;
lpMsg->lParam = 0;
return false;
}
@ -234,15 +317,58 @@ void RecordGameLoopResult(bool runGameLoop)
WriteLEFloat(DemoRecording, gfProgressToNextGameTick);
}
void RecordMessage(tagMSG *lpMsg)
void RecordMessage(const SDL_Event &event, uint16_t modState)
{
if (!gbRunGame || !DemoRecording.is_open())
return;
WriteLE32(DemoRecording, static_cast<uint32_t>(DemoMsgType::Message));
WriteLEFloat(DemoRecording, gfProgressToNextGameTick);
WriteLE32(DemoRecording, lpMsg->message);
WriteLE32(DemoRecording, lpMsg->wParam);
WriteLE16(DemoRecording, lpMsg->lParam);
switch (event.type) {
case SDL_MOUSEMOTION:
RecordEventHeader(event);
WriteLE16(DemoRecording, event.motion.x);
WriteLE16(DemoRecording, event.motion.y);
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
RecordEventHeader(event);
WriteByte(DemoRecording, event.button.button);
WriteLE16(DemoRecording, event.button.x);
WriteLE16(DemoRecording, event.button.y);
WriteLE16(DemoRecording, modState);
break;
#ifndef USE_SDL1
case SDL_MOUSEWHEEL:
RecordEventHeader(event);
WriteLE32(DemoRecording, event.wheel.x);
WriteLE32(DemoRecording, event.wheel.y);
WriteLE16(DemoRecording, modState);
break;
#endif
case SDL_KEYDOWN:
case SDL_KEYUP:
RecordEventHeader(event);
WriteLE32(DemoRecording, static_cast<uint32_t>(event.key.keysym.sym));
WriteLE16(DemoRecording, static_cast<uint16_t>(event.key.keysym.mod));
break;
#ifndef USE_SDL1
case SDL_WINDOWEVENT:
if (event.window.type == SDL_WINDOWEVENT_CLOSE) {
SDL_Event quitEvent;
quitEvent.type = SDL_QUIT;
RecordEventHeader(quitEvent);
}
break;
#endif
case SDL_QUIT:
RecordEventHeader(event);
break;
default:
if (IsCustomEvent(event.type)) {
SDL_Event stableCustomEvent;
stableCustomEvent.type = SDL_USEREVENT + static_cast<uint32_t>(GetCustomEvent(event.type));
RecordEventHeader(stableCustomEvent);
}
break;
}
}
void NotifyGameLoopStart()

6
Source/engine/demomode.h

@ -5,6 +5,8 @@
*/
#pragma once
#include <SDL.h>
#include "miniwin/misc_msg.h"
namespace devilution {
@ -19,9 +21,9 @@ bool IsRunning();
bool IsRecording();
bool GetRunGameLoop(bool &drawGame, bool &processInput);
bool FetchMessage(tagMSG *lpMsg);
bool FetchMessage(SDL_Event *event, uint16_t *modState);
void RecordGameLoopResult(bool runGameLoop);
void RecordMessage(tagMSG *lpMsg);
void RecordMessage(const SDL_Event &event, uint16_t modState);
void NotifyGameLoopStart();
void NotifyGameLoopEnd();

43
Source/init.cpp

@ -229,15 +229,50 @@ void init_create_window()
#endif
}
void MainWndProc(uint32_t msg)
void MainWndProc(const SDL_Event &event)
{
switch (msg) {
case DVL_WM_PAINT:
#ifndef USE_SDL1
if (event.type != SDL_WINDOWEVENT)
return;
switch (event.window.event) {
case SDL_WINDOWEVENT_HIDDEN:
gbActive = false;
break;
case SDL_WINDOWEVENT_SHOWN:
gbActive = false;
force_redraw = 255;
break;
case SDL_WINDOWEVENT_EXPOSED:
force_redraw = 255;
break;
case SDL_WINDOWEVENT_LEAVE:
sgbMouseDown = CLICK_NONE;
LastMouseButtonAction = MouseActionType::None;
force_redraw = 255;
break;
case DVL_WM_QUERYENDSESSION:
case SDL_WINDOWEVENT_CLOSE:
diablo_quit(0);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
diablo_focus_pause();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
diablo_focus_unpause();
break;
default:
LogVerbose("Unhandled SDL_WINDOWEVENT event: ", event.window.event);
break;
}
#else
if (event.type != SDL_ACTIVEEVENT)
return;
if ((event.active.state & SDL_APPINPUTFOCUS) != 0) {
if (event.active.gain == 0)
diablo_focus_pause();
else
diablo_focus_unpause();
}
#endif
}
EventHandler SetEventHandler(EventHandler eventHandler)

2
Source/init.h

@ -34,7 +34,7 @@ void LoadCoreArchives();
void LoadLanguageArchive();
void LoadGameArchives();
void init_create_window();
void MainWndProc(uint32_t Msg);
void MainWndProc(const SDL_Event &event);
EventHandler SetEventHandler(EventHandler NewProc);
} // namespace devilution

35
Source/interfac.cpp

@ -44,6 +44,9 @@ const int BarPos[3][2] = { { 53, 37 }, { 53, 421 }, { 53, 37 } };
OptionalOwnedClxSpriteList ArtCutsceneWidescreen;
uint32_t CustomEventsBegin = SDL_USEREVENT;
constexpr uint32_t NumCustomEvents = WM_LAST - WM_FIRST + 1;
Cutscenes PickCutscene(interface_mode uMsg)
{
switch (uMsg) {
@ -204,13 +207,35 @@ void DrawCutsceneForeground()
} // namespace
void interface_msg_pump()
void RegisterCustomEvents()
{
#ifndef USE_SDL1
CustomEventsBegin = SDL_RegisterEvents(NumCustomEvents);
#endif
}
bool IsCustomEvent(uint32_t eventType)
{
return eventType >= CustomEventsBegin && eventType < CustomEventsBegin + NumCustomEvents;
}
interface_mode GetCustomEvent(uint32_t eventType)
{
tagMSG msg;
return static_cast<interface_mode>(eventType - CustomEventsBegin);
}
while (FetchMessage(&msg)) {
if (msg.message != DVL_WM_QUIT) {
PushMessage(&msg);
uint32_t CustomEventToSdlEvent(interface_mode eventType)
{
return CustomEventsBegin + eventType;
}
void interface_msg_pump()
{
SDL_Event event;
uint16_t modState;
while (FetchMessage(&event, &modState)) {
if (event.type != SDL_QUIT) {
HandleMessage(event, modState);
}
}
}

33
Source/interfac.h

@ -11,24 +11,33 @@
namespace devilution {
/**
* @brief Custom events.
*/
enum interface_mode : uint16_t {
// clang-format off
WM_DIABNEXTLVL = 0x402, // WM_USER+2
WM_DIABPREVLVL = 0x403,
WM_DIABRTNLVL = 0x404,
WM_DIABSETLVL = 0x405,
WM_DIABWARPLVL = 0x406,
WM_DIABTOWNWARP = 0x407,
WM_DIABTWARPUP = 0x408,
WM_DIABRETOWN = 0x409,
WM_DIABNEWGAME = 0x40A,
WM_DIABLOADGAME = 0x40B,
// clang-format on
WM_DIABNEXTLVL = 0,
WM_DIABPREVLVL,
WM_DIABRTNLVL,
WM_DIABSETLVL,
WM_DIABWARPLVL,
WM_DIABTOWNWARP,
WM_DIABTWARPUP,
WM_DIABRETOWN,
WM_DIABNEWGAME,
WM_DIABLOADGAME,
WM_FIRST = WM_DIABNEXTLVL,
WM_LAST = WM_DIABLOADGAME,
};
void RegisterCustomEvents();
bool IsCustomEvent(uint32_t eventType);
interface_mode GetCustomEvent(uint32_t eventType);
uint32_t CustomEventToSdlEvent(interface_mode eventType);
enum Cutscenes : uint8_t {
CutStart,
CutTown,

180
Source/miniwin/misc_msg.cpp

@ -47,8 +47,6 @@
namespace devilution {
static std::deque<tagMSG> message_queue;
void SetMouseButtonEvent(SDL_Event &event, uint32_t type, uint8_t button, Point position)
{
event.type = type;
@ -97,11 +95,6 @@ void FocusOnCharInfo()
namespace {
uint32_t PositionForMouse(int16_t x, int16_t y)
{
return (static_cast<uint16_t>(y) << 16) | static_cast<uint16_t>(x);
}
bool FalseAvail(const char *name, int value)
{
LogVerbose("Unhandled SDL event: {} {}", name, value);
@ -217,26 +210,19 @@ void ProcessGamepadEvents(GameAction &action)
} // namespace
bool FetchMessage_Real(tagMSG *lpMsg)
bool FetchMessage_Real(SDL_Event *event, uint16_t *modState)
{
#ifdef __SWITCH__
HandleDocking();
#endif
if (!message_queue.empty()) {
*lpMsg = message_queue.front();
message_queue.pop_front();
return true;
}
SDL_Event e;
if (PollEvent(&e) == 0) {
return false;
}
lpMsg->message = 0;
lpMsg->wParam = 0;
lpMsg->lParam = 0;
event->type = static_cast<SDL_EventType>(0);
*modState = SDL_GetModState();
#ifdef __vita__
HandleTouchEvent(&e, MousePosition);
@ -244,8 +230,8 @@ bool FetchMessage_Real(tagMSG *lpMsg)
HandleTouchEvent(e);
#endif
if (e.type == SDL_QUIT) {
lpMsg->message = DVL_WM_QUIT;
if (e.type == SDL_QUIT || IsCustomEvent(e.type)) {
*event = e;
return true;
}
@ -292,21 +278,18 @@ bool FetchMessage_Real(tagMSG *lpMsg)
if (GetGameAction(e, ctrlEvent, &action)) {
if (movie_playing) {
if (action.type != GameActionType_NONE) {
lpMsg->message = DVL_WM_KEYDOWN;
event->type = SDL_KEYDOWN;
if (action.type == GameActionType_SEND_KEY)
lpMsg->wParam = action.send_key.vk_code;
event->key.keysym.sym = static_cast<SDL_Keycode>(action.send_key.vk_code);
}
} else if (action.type == GameActionType_SEND_KEY) {
if ((action.send_key.vk_code & KeymapperMouseButtonMask) != 0) {
const unsigned button = action.send_key.vk_code & ~KeymapperMouseButtonMask;
lpMsg->message = action.send_key.up
? (button == SDL_BUTTON_LEFT ? DVL_WM_LBUTTONUP : DVL_WM_RBUTTONUP)
: (button == SDL_BUTTON_RIGHT ? DVL_WM_LBUTTONDOWN : DVL_WM_RBUTTONDOWN);
lpMsg->wParam = (static_cast<int16_t>(MousePosition.y) << 16) | static_cast<int16_t>(MousePosition.x);
lpMsg->lParam = 0;
SetMouseButtonEvent(*event, action.send_key.up ? SDL_MOUSEBUTTONUP : SDL_MOUSEBUTTONDOWN, static_cast<uint8_t>(button), MousePosition);
} else {
lpMsg->message = action.send_key.up ? DVL_WM_KEYUP : DVL_WM_KEYDOWN;
lpMsg->wParam = action.send_key.vk_code;
event->type = action.send_key.up ? SDL_KEYUP : SDL_KEYDOWN;
event->key.state = action.send_key.up ? SDL_PRESSED : SDL_RELEASED;
event->key.keysym.sym = static_cast<SDL_Keycode>(action.send_key.vk_code);
}
} else {
ProcessGamepadEvents(action);
@ -318,9 +301,6 @@ bool FetchMessage_Real(tagMSG *lpMsg)
return true;
switch (e.type) {
case SDL_QUIT:
lpMsg->message = DVL_WM_QUIT;
break;
case SDL_KEYDOWN:
case SDL_KEYUP: {
#ifdef USE_SDL1
@ -340,72 +320,31 @@ bool FetchMessage_Real(tagMSG *lpMsg)
remap_keyboard_key(&key);
if (key == -1)
return FalseAvail(e.type == SDL_KEYDOWN ? "SDL_KEYDOWN" : "SDL_KEYUP", e.key.keysym.sym);
lpMsg->message = e.type == SDL_KEYDOWN ? DVL_WM_KEYDOWN : DVL_WM_KEYUP;
lpMsg->wParam = static_cast<uint32_t>(key);
lpMsg->lParam = e.key.keysym.mod;
event->type = e.type;
event->key.state = e.key.state;
event->key.keysym.sym = key;
event->key.keysym.mod = e.key.keysym.mod;
} break;
case SDL_MOUSEMOTION:
lpMsg->message = DVL_WM_MOUSEMOVE;
lpMsg->wParam = PositionForMouse(e.motion.x, e.motion.y);
lpMsg->lParam = SDL_GetModState();
*event = e;
if (ControlMode == ControlTypes::KeyboardAndMouse && invflag)
InvalidateInventorySlot();
break;
case SDL_MOUSEBUTTONDOWN: {
lpMsg->wParam = PositionForMouse(e.button.x, e.button.y);
lpMsg->lParam = SDL_GetModState();
const int button = e.button.button;
switch (button) {
case SDL_BUTTON_LEFT:
lpMsg->message = DVL_WM_LBUTTONDOWN;
break;
case SDL_BUTTON_RIGHT:
lpMsg->message = DVL_WM_RBUTTONDOWN;
break;
case SDL_BUTTON_MIDDLE:
lpMsg->message = DVL_WM_MBUTTONDOWN;
break;
case SDL_BUTTON_X1:
lpMsg->message = DVL_WM_X1BUTTONDOWN;
break;
case SDL_BUTTON_X2:
lpMsg->message = DVL_WM_X2BUTTONDOWN;
break;
}
} break;
case SDL_MOUSEBUTTONUP: {
lpMsg->wParam = PositionForMouse(e.button.x, e.button.y);
lpMsg->lParam = SDL_GetModState();
const int button = e.button.button;
switch (button) {
case SDL_BUTTON_LEFT:
lpMsg->message = DVL_WM_LBUTTONUP;
break;
case SDL_BUTTON_RIGHT:
lpMsg->message = DVL_WM_RBUTTONUP;
break;
case SDL_BUTTON_MIDDLE:
lpMsg->message = DVL_WM_MBUTTONUP;
break;
case SDL_BUTTON_X1:
lpMsg->message = DVL_WM_X1BUTTONUP;
break;
case SDL_BUTTON_X2:
lpMsg->message = DVL_WM_X2BUTTONUP;
break;
}
} break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
*event = e;
break;
#ifndef USE_SDL1
case SDL_MOUSEWHEEL:
lpMsg->message = DVL_WM_KEYDOWN;
event->type = SDL_KEYDOWN;
if (e.wheel.y > 0) {
lpMsg->wParam = (SDL_GetModState() & KMOD_CTRL) != 0 ? SDLK_KP_PLUS : SDLK_UP;
event->key.keysym.sym = (SDL_GetModState() & KMOD_CTRL) != 0 ? SDLK_KP_PLUS : SDLK_UP;
} else if (e.wheel.y < 0) {
lpMsg->wParam = (SDL_GetModState() & KMOD_CTRL) != 0 ? SDLK_KP_MINUS : SDLK_DOWN;
event->key.keysym.sym = (SDL_GetModState() & KMOD_CTRL) != 0 ? SDLK_KP_MINUS : SDLK_DOWN;
} else if (e.wheel.x > 0) {
lpMsg->wParam = SDLK_LEFT;
event->key.keysym.sym = SDLK_LEFT;
} else if (e.wheel.x < 0) {
lpMsg->wParam = SDLK_RIGHT;
event->key.keysym.sym = SDLK_RIGHT;
}
break;
#if SDL_VERSION_ATLEAST(2, 0, 4)
@ -435,56 +374,11 @@ bool FetchMessage_Real(tagMSG *lpMsg)
}
return FalseAvail("SDL_TEXTINPUT", e.text.windowID);
case SDL_WINDOWEVENT:
switch (e.window.event) {
case SDL_WINDOWEVENT_SHOWN:
gbActive = true;
lpMsg->message = DVL_WM_PAINT;
break;
case SDL_WINDOWEVENT_HIDDEN:
gbActive = false;
break;
case SDL_WINDOWEVENT_EXPOSED:
lpMsg->message = DVL_WM_PAINT;
break;
case SDL_WINDOWEVENT_LEAVE:
lpMsg->message = DVL_WM_CAPTURECHANGED;
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
ReinitializeHardwareCursor();
break;
case SDL_WINDOWEVENT_MOVED:
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_MINIMIZED:
case SDL_WINDOWEVENT_MAXIMIZED:
case SDL_WINDOWEVENT_RESTORED:
#if SDL_VERSION_ATLEAST(2, 0, 5)
case SDL_WINDOWEVENT_TAKE_FOCUS:
#endif
break;
case SDL_WINDOWEVENT_CLOSE:
lpMsg->message = DVL_WM_QUERYENDSESSION;
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
diablo_focus_pause();
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
diablo_focus_unpause();
break;
default:
return FalseAvail("SDL_WINDOWEVENT", e.window.event);
}
*event = e;
break;
#else
case SDL_ACTIVEEVENT:
if ((e.active.state & SDL_APPINPUTFOCUS) != 0) {
if (e.active.gain == 0)
diablo_focus_pause();
else
diablo_focus_unpause();
}
*event = e;
break;
#endif
default:
@ -493,31 +387,21 @@ bool FetchMessage_Real(tagMSG *lpMsg)
return true;
}
bool FetchMessage(tagMSG *lpMsg)
bool FetchMessage(SDL_Event *event, uint16_t *modState)
{
bool available = demo::IsRunning() ? demo::FetchMessage(lpMsg) : FetchMessage_Real(lpMsg);
const bool available = demo::IsRunning() ? demo::FetchMessage(event, modState) : FetchMessage_Real(event, modState);
if (available && demo::IsRecording())
demo::RecordMessage(lpMsg);
demo::RecordMessage(*event, *modState);
return available;
}
void PushMessage(const tagMSG *lpMsg)
void HandleMessage(const SDL_Event &event, uint16_t modState)
{
assert(CurrentEventHandler != nullptr);
CurrentEventHandler(lpMsg->message, lpMsg->wParam, lpMsg->lParam);
}
void PostMessage(uint32_t type, uint32_t wParam, uint16_t lParam)
{
message_queue.push_back({ type, wParam, lParam });
}
void ClearMessageQueue()
{
message_queue.clear();
CurrentEventHandler(event, modState);
}
} // namespace devilution

41
Source/miniwin/misc_msg.h

@ -16,47 +16,14 @@
namespace devilution {
struct tagMSG {
uint32_t message;
uint32_t wParam;
uint16_t lParam;
};
typedef void (*EventHandler)(uint32_t, uint32_t, uint16_t);
using EventHandler = void (*)(const SDL_Event &event, uint16_t modState);
void SetCursorPos(Point position);
void FocusOnCharInfo();
void SetMouseButtonEvent(SDL_Event &event, uint32_t type, uint8_t button, Point position);
bool FetchMessage(tagMSG *lpMsg);
void PushMessage(const tagMSG *lpMsg);
void PostMessage(uint32_t type, uint32_t wParam, uint16_t lParam);
void ClearMessageQueue();
//
// Events
//
#define DVL_WM_QUIT 0x0012
#define DVL_WM_MOUSEMOVE 0x0200
#define DVL_WM_LBUTTONDOWN 0x0201
#define DVL_WM_LBUTTONUP 0x0202
#define DVL_WM_RBUTTONDOWN 0x0204
#define DVL_WM_RBUTTONUP 0x0205
#define DVL_WM_MBUTTONDOWN 0x0206
#define DVL_WM_MBUTTONUP 0x0207
#define DVL_WM_X1BUTTONDOWN 0x0208
#define DVL_WM_X1BUTTONUP 0x0209
#define DVL_WM_X2BUTTONDOWN 0x020A
#define DVL_WM_X2BUTTONUP 0x020B
#define DVL_WM_KEYDOWN 0x0100
#define DVL_WM_KEYUP 0x0101
#define DVL_WM_CAPTURECHANGED 0x0215
#define DVL_WM_PAINT 0x000F
#define DVL_WM_QUERYENDSESSION 0x0011
bool FetchMessage(SDL_Event *event, uint16_t *modState);
void HandleMessage(const SDL_Event &event, uint16_t modState);
} // namespace devilution

16
Source/movie.cpp

@ -37,17 +37,17 @@ void play_movie(const char *pszMovie, bool userCanClose)
}
if (SVidPlayBegin(pszMovie, loop_movie ? 0x100C0808 : 0x10280808)) {
tagMSG msg;
SDL_Event event;
uint16_t modState;
while (movie_playing) {
while (movie_playing && FetchMessage(&msg)) {
switch (msg.message) {
case DVL_WM_KEYDOWN:
case DVL_WM_LBUTTONUP:
case DVL_WM_RBUTTONUP:
if (userCanClose || (msg.message == DVL_WM_KEYDOWN && msg.wParam == SDLK_ESCAPE))
while (movie_playing && FetchMessage(&event, &modState)) {
switch (event.type) {
case SDL_KEYDOWN:
case SDL_MOUSEBUTTONUP:
if (userCanClose || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))
movie_playing = false;
break;
case DVL_WM_QUIT:
case SDL_QUIT:
SVidPlayEnd();
diablo_quit(0);
}

12
Source/player.cpp

@ -3191,7 +3191,9 @@ StartNewLvl(Player &player, interface_mode fom, int lvl)
if (&player == MyPlayer) {
player._pmode = PM_NEWLVL;
player._pInvincible = true;
PostMessage(fom, 0, 0);
SDL_Event event;
event.type = CustomEventToSdlEvent(fom);
SDL_PushEvent(&event);
if (gbIsMultiplayer) {
NetSendCmdParam2(true, CMD_NEWLVL, fom, lvl);
}
@ -3215,7 +3217,9 @@ void RestartTownLvl(Player &player)
if (&player == MyPlayer) {
player._pmode = PM_NEWLVL;
player._pInvincible = true;
PostMessage(WM_DIABRETOWN, 0, 0);
SDL_Event event;
event.type = CustomEventToSdlEvent(WM_DIABRETOWN);
SDL_PushEvent(&event);
}
}
@ -3238,7 +3242,9 @@ void StartWarpLvl(Player &player, int pidx)
SetCurrentPortal(pidx);
player._pmode = PM_NEWLVL;
player._pInvincible = true;
PostMessage(WM_DIABWARPLVL, 0, 0);
SDL_Event event;
event.type = CustomEventToSdlEvent(WM_DIABWARPLVL);
SDL_PushEvent(&event);
}
}

1
Source/utils/display.cpp

@ -275,6 +275,7 @@ bool SpawnWindow(const char *lpWindowName)
if (SDL_Init(initFlags) <= -1) {
ErrSdl();
}
RegisterCustomEvents();
#ifndef USE_SDL1
if (sgOptions.Controller.szMapping[0] != '\0') {

BIN
test/fixtures/timedemo/WarriorLevel1to2/demo_0.dmo vendored

Binary file not shown.
Loading…
Cancel
Save