From 987e565eeb80f0fe2825267de728f8a1989a051d Mon Sep 17 00:00:00 2001 From: Craig Robbins Date: Mon, 10 Nov 2014 12:26:19 +1000 Subject: [PATCH] Create faster key cache for main game loop (client) --- src/game.cpp | 231 +++++++++++++++++++++++++++--------- src/guiKeyChangeMenu.cpp | 8 ++ src/mainmenumanager.h | 11 ++ src/quicktune_shortcutter.h | 5 + 4 files changed, 202 insertions(+), 53 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index fee45e31d..1396e9439 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1181,9 +1181,119 @@ static void updateChat(Client &client, f32 dtime, bool show_debug, } +/**************************************************************************** + Fast key cache for main game loop + ****************************************************************************/ + +/* This is faster than using getKeySetting with the tradeoff that functions + * using it must make sure that it's initialised before using it and there is + * no error handling (for example bounds checking). This is really intended for + * use only in the main running loop of the client (the_game()) where the faster + * (up to 10x faster) key lookup is an asset. Other parts of the codebase + * (e.g. formspecs) should continue using getKeySetting(). + */ +struct KeyCache { + + KeyCache() { populate(); } + + enum { + // Player movement + KEYMAP_ID_FORWARD, + KEYMAP_ID_BACKWARD, + KEYMAP_ID_LEFT, + KEYMAP_ID_RIGHT, + KEYMAP_ID_JUMP, + KEYMAP_ID_SPECIAL1, + KEYMAP_ID_SNEAK, + + // Other + KEYMAP_ID_DROP, + KEYMAP_ID_INVENTORY, + KEYMAP_ID_CHAT, + KEYMAP_ID_CMD, + KEYMAP_ID_CONSOLE, + KEYMAP_ID_FREEMOVE, + KEYMAP_ID_FASTMOVE, + KEYMAP_ID_NOCLIP, + KEYMAP_ID_SCREENSHOT, + KEYMAP_ID_TOGGLE_HUD, + KEYMAP_ID_TOGGLE_CHAT, + KEYMAP_ID_TOGGLE_FORCE_FOG_OFF, + KEYMAP_ID_TOGGLE_UPDATE_CAMERA, + KEYMAP_ID_TOGGLE_DEBUG, + KEYMAP_ID_TOGGLE_PROFILER, + KEYMAP_ID_CAMERA_MODE, + KEYMAP_ID_INCREASE_VIEWING_RANGE, + KEYMAP_ID_DECREASE_VIEWING_RANGE, + KEYMAP_ID_RANGESELECT, + + KEYMAP_ID_QUICKTUNE_NEXT, + KEYMAP_ID_QUICKTUNE_PREV, + KEYMAP_ID_QUICKTUNE_INC, + KEYMAP_ID_QUICKTUNE_DEC, + + KEYMAP_ID_DEBUG_STACKS, + + // Fake keycode for array size and internal checks + KEYMAP_INTERNAL_ENUM_COUNT + + + }; + + void populate(); + + KeyPress key[KEYMAP_INTERNAL_ENUM_COUNT]; +}; + +void KeyCache::populate() +{ + key[KEYMAP_ID_FORWARD] = getKeySetting("keymap_forward"); + key[KEYMAP_ID_BACKWARD] = getKeySetting("keymap_backward"); + key[KEYMAP_ID_LEFT] = getKeySetting("keymap_left"); + key[KEYMAP_ID_RIGHT] = getKeySetting("keymap_right"); + key[KEYMAP_ID_JUMP] = getKeySetting("keymap_jump"); + key[KEYMAP_ID_SPECIAL1] = getKeySetting("keymap_special1"); + key[KEYMAP_ID_SNEAK] = getKeySetting("keymap_sneak"); + + key[KEYMAP_ID_DROP] = getKeySetting("keymap_drop"); + key[KEYMAP_ID_INVENTORY] = getKeySetting("keymap_inventory"); + key[KEYMAP_ID_CHAT] = getKeySetting("keymap_chat"); + key[KEYMAP_ID_CMD] = getKeySetting("keymap_cmd"); + key[KEYMAP_ID_CONSOLE] = getKeySetting("keymap_console"); + key[KEYMAP_ID_FREEMOVE] = getKeySetting("keymap_freemove"); + key[KEYMAP_ID_FASTMOVE] = getKeySetting("keymap_fastmove"); + key[KEYMAP_ID_NOCLIP] = getKeySetting("keymap_noclip"); + key[KEYMAP_ID_SCREENSHOT] = getKeySetting("keymap_screenshot"); + key[KEYMAP_ID_TOGGLE_HUD] = getKeySetting("keymap_toggle_hud"); + key[KEYMAP_ID_TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat"); + key[KEYMAP_ID_TOGGLE_FORCE_FOG_OFF] + = getKeySetting("keymap_toggle_force_fog_off"); + key[KEYMAP_ID_TOGGLE_UPDATE_CAMERA] + = getKeySetting("keymap_toggle_update_camera"); + key[KEYMAP_ID_TOGGLE_DEBUG] + = getKeySetting("keymap_toggle_debug"); + key[KEYMAP_ID_TOGGLE_PROFILER] + = getKeySetting("keymap_toggle_profiler"); + key[KEYMAP_ID_CAMERA_MODE] + = getKeySetting("keymap_camera_mode"); + key[KEYMAP_ID_INCREASE_VIEWING_RANGE] + = getKeySetting("keymap_increase_viewing_range_min"); + key[KEYMAP_ID_DECREASE_VIEWING_RANGE] + = getKeySetting("keymap_decrease_viewing_range_min"); + key[KEYMAP_ID_RANGESELECT] + = getKeySetting("keymap_rangeselect"); + + key[KEYMAP_ID_QUICKTUNE_NEXT] = getKeySetting("keymap_quicktune_next"); + key[KEYMAP_ID_QUICKTUNE_PREV] = getKeySetting("keymap_quicktune_prev"); + key[KEYMAP_ID_QUICKTUNE_INC] = getKeySetting("keymap_quicktune_inc"); + key[KEYMAP_ID_QUICKTUNE_DEC] = getKeySetting("keymap_quicktune_dec"); + + key[KEYMAP_ID_DEBUG_STACKS] = getKeySetting("keymap_print_debug_stacks"); +} + /**************************************************************************** - THE GAME + ****************************************************************************/ const float object_hit_delay = 0.2; @@ -1264,6 +1374,10 @@ struct VolatileRunFlags { }; +/**************************************************************************** + THE GAME + ****************************************************************************/ + /* This is not intended to be a public class. If a public class becomes * desirable then it may be better to create another 'wrapper' class that * hides most of the stuff in this class (nothing in this class is required @@ -1458,6 +1572,8 @@ private: std::wstring infotext; std::wstring statustext; + + KeyCache keycache; }; Game::Game() : @@ -2186,6 +2302,11 @@ inline bool Game::handleCallbacks() g_gamecallback->keyconfig_requested = false; } + if (g_gamecallback->keyconfig_changed) { + keycache.populate(); // update the cache with new settings + g_gamecallback->keyconfig_changed = false; + } + return true; } @@ -2322,70 +2443,63 @@ void Game::processKeyboardInput(VolatileRunFlags *flags, u32 *profiler_current_page, u32 profiler_max_page) { - if (input->wasKeyDown(getKeySetting("keymap_drop"))) { + + //TimeTaker tt("process kybd input", NULL, PRECISION_NANO); + + if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DROP])) { dropSelectedItem(); - } else if (input->wasKeyDown(getKeySetting("keymap_inventory"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INVENTORY])) { openInventory(); } else if (input->wasKeyDown(EscapeKey) || input->wasKeyDown(CancelKey)) { show_pause_menu(¤t_formspec, client, gamedef, texture_src, device, simple_singleplayer_mode); - } else if (input->wasKeyDown(getKeySetting("keymap_chat"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CHAT])) { show_chat_menu(¤t_formspec, client, gamedef, texture_src, device, client, ""); - } else if (input->wasKeyDown(getKeySetting("keymap_cmd"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CMD])) { show_chat_menu(¤t_formspec, client, gamedef, texture_src, device, client, "/"); - } else if (input->wasKeyDown(getKeySetting("keymap_console"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CONSOLE])) { openConsole(); - } else if (input->wasKeyDown(getKeySetting("keymap_freemove"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FREEMOVE])) { toggleFreeMove(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_jump"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP])) { toggleFreeMoveAlt(statustext_time, jump_timer); *reset_jump_timer = true; - } else if (input->wasKeyDown(getKeySetting("keymap_fastmove"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FASTMOVE])) { toggleFast(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_noclip"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) { toggleNoClip(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_screenshot"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) { client->makeScreenshot(device); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_hud"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) { toggleHud(statustext_time, &flags->show_hud); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_chat"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_CHAT])) { toggleChat(statustext_time, &flags->show_chat); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_force_fog_off"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_FORCE_FOG_OFF])) { toggleFog(statustext_time, &flags->force_fog_off); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_update_camera"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_UPDATE_CAMERA])) { toggleUpdateCamera(statustext_time, &flags->disable_camera_update); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_debug"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_DEBUG])) { toggleDebug(statustext_time, &flags->show_debug, &flags->show_profiler_graph); - } else if (input->wasKeyDown(getKeySetting("keymap_toggle_profiler"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_PROFILER])) { toggleProfiler(statustext_time, profiler_current_page, profiler_max_page); - } else if (input->wasKeyDown(getKeySetting("keymap_increase_viewing_range_min"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INCREASE_VIEWING_RANGE])) { increaseViewRange(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_decrease_viewing_range_min"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DECREASE_VIEWING_RANGE])) { decreaseViewRange(statustext_time); - } else if (input->wasKeyDown(getKeySetting("keymap_rangeselect"))) { + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_RANGESELECT])) { toggleFullViewRange(statustext_time); - } - - // Handle QuicktuneShortcutter - if (input->wasKeyDown(getKeySetting("keymap_quicktune_next"))) + } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_NEXT])) quicktune->next(); - else if (input->wasKeyDown(getKeySetting("keymap_quicktune_prev"))) + else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_PREV])) quicktune->prev(); - else if (input->wasKeyDown(getKeySetting("keymap_quicktune_inc"))) + else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_INC])) quicktune->inc(); - else if (input->wasKeyDown(getKeySetting("keymap_quicktune_dec"))) + else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_DEC])) quicktune->dec(); - - std::string msg = quicktune->getMessage(); - if (msg != "") { - statustext = narrow_to_wide(msg); - *statustext_time = 0; - } - - // Print debug stacks - if (input->wasKeyDown(getKeySetting("keymap_print_debug_stacks"))) { + else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DEBUG_STACKS])) { + // Print debug stacks dstream << "-----------------------------------------" << std::endl; dstream << DTIME << "Printing debug stacks:" << std::endl; @@ -2398,6 +2512,14 @@ void Game::processKeyboardInput(VolatileRunFlags *flags, *reset_jump_timer = false; *jump_timer = 0.0; } + + //tt.stop(); + + if (quicktune->hasMessage()) { + std::string msg = quicktune->getMessage(); + statustext = narrow_to_wide(msg); + *statustext_time = 0; + } } @@ -2730,14 +2852,16 @@ void Game::updateCameraDirection(CameraOrientation *cam, void Game::updatePlayerControl(const CameraOrientation &cam) { + //TimeTaker tt("update player control", NULL, PRECISION_NANO); + PlayerControl control( - input->isKeyDown(getKeySetting("keymap_forward")), - input->isKeyDown(getKeySetting("keymap_backward")), - input->isKeyDown(getKeySetting("keymap_left")), - input->isKeyDown(getKeySetting("keymap_right")), - input->isKeyDown(getKeySetting("keymap_jump")), - input->isKeyDown(getKeySetting("keymap_special1")), - input->isKeyDown(getKeySetting("keymap_sneak")), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_FORWARD]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_BACKWARD]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_LEFT]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_RIGHT]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SPECIAL1]), + input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]), input->getLeftState(), input->getRightState(), cam.camera_pitch, @@ -2746,17 +2870,18 @@ void Game::updatePlayerControl(const CameraOrientation &cam) client->setPlayerControl(control); LocalPlayer *player = client->getEnv().getLocalPlayer(); player->keyPressed = - ( (u32)(input->isKeyDown(getKeySetting("keymap_forward")) & 0x1) << 0) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_backward")) & 0x1) << 1) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_left")) & 0x1) << 2) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_right")) & 0x1) << 3) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_jump")) & 0x1) << 4) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_special1")) & 0x1) << 5) | - ( (u32)(input->isKeyDown(getKeySetting("keymap_sneak")) & 0x1) << 6) | - ( (u32)(input->getLeftState() & 0x1) << 7) | - ( (u32)(input->getRightState() & 0x1) << 8 + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_FORWARD]) & 0x1) << 0) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_BACKWARD]) & 0x1) << 1) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_LEFT]) & 0x1) << 2) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_RIGHT]) & 0x1) << 3) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP]) & 0x1) << 4) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SPECIAL1]) & 0x1) << 5) | + ( (u32)(input->isKeyDown(keycache.key[KeyCache::KEYMAP_ID_SNEAK]) & 0x1) << 6) | + ( (u32)(input->getLeftState() & 0x1) << 7) | + ( (u32)(input->getRightState() & 0x1) << 8 ); + //tt.stop(); } @@ -3042,7 +3167,7 @@ void Game::updateCamera(VolatileRunFlags *flags, u32 busy_time, v3s16 old_camera_offset = camera->getOffset(); - if (input->wasKeyDown(getKeySetting("keymap_camera_mode"))) { + if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_CAMERA_MODE])) { camera->toggleCameraMode(); GenericCAO *playercao = player->getCAO(); diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp index 85222431e..8b0bb8278 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -32,8 +32,12 @@ #include "settings.h" #include +#include "mainmenumanager.h" // for g_gamecallback + #define KMaxButtonPerColumns 12 +extern MainGameCallback *g_gamecallback; + enum { GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR, @@ -234,7 +238,11 @@ bool GUIKeyChangeMenu::acceptInput() if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX) g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked()); } + clearKeyCache(); + + g_gamecallback->signalKeyConfigChange(); + return true; } diff --git a/src/mainmenumanager.h b/src/mainmenumanager.h index 56ba40129..db8aa9e19 100644 --- a/src/mainmenumanager.h +++ b/src/mainmenumanager.h @@ -35,6 +35,8 @@ public: virtual void disconnect() = 0; virtual void changePassword() = 0; virtual void changeVolume() = 0; + + virtual void signalKeyConfigChange() = 0; }; extern gui::IGUIEnvironment* guienv; @@ -127,6 +129,7 @@ public: changevolume_requested(false), keyconfig_requested(false), shutdown_requested(false), + keyconfig_changed(false), device(a_device) { } @@ -159,12 +162,20 @@ public: keyconfig_requested = true; } + virtual void signalKeyConfigChange() + { + keyconfig_changed = true; + } + bool disconnect_requested; bool changepassword_requested; bool changevolume_requested; bool keyconfig_requested; bool shutdown_requested; + + bool keyconfig_changed; + IrrlichtDevice *device; }; diff --git a/src/quicktune_shortcutter.h b/src/quicktune_shortcutter.h index 16bcc07e8..fe1463c93 100644 --- a/src/quicktune_shortcutter.h +++ b/src/quicktune_shortcutter.h @@ -29,6 +29,11 @@ private: u32 m_selected_i; std::string m_message; public: + bool hasMessage() + { + return m_message != ""; + } + std::string getMessage() { std::string s = m_message;