Merge pull request #1825 from Zeno-/control_key_cache

Create faster key cache for main game loop (client)
This commit is contained in:
Zeno- 2014-11-10 19:12:25 +10:00
commit a1e9732407
4 changed files with 202 additions and 53 deletions

@ -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(&current_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(&current_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(&current_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;
}
else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DEBUG_STACKS])) {
// Print debug stacks
if (input->wasKeyDown(getKeySetting("keymap_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->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();

@ -32,8 +32,12 @@
#include "settings.h"
#include <algorithm>
#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;
}

@ -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;
};

@ -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;