+
+ update_profiler_gui(guitext_profiler, g_fontengine,
+ run_data.profiler_current_page, run_data.profiler_max_page,
+ driver->getScreenSize().Height);
+
+ g_profiler->clear();
+ }
+
+ addProfilerGraphs(stats, draw_times, dtime);
+}
+
+
+void Game::addProfilerGraphs(const RunStats &stats,
+ const FpsControl &draw_times, f32 dtime)
+{
+ g_profiler->graphAdd("mainloop_other",
+ draw_times.busy_time / 1000.0f - stats.drawtime / 1000.0f);
+
+ if (draw_times.sleep_time != 0)
+ g_profiler->graphAdd("mainloop_sleep", draw_times.sleep_time / 1000.0f);
+ g_profiler->graphAdd("mainloop_dtime", dtime);
+
+ g_profiler->add("Elapsed time", dtime);
+ g_profiler->avg("FPS", 1. / dtime);
+}
+
+
+void Game::updateStats(RunStats *stats, const FpsControl &draw_times,
+ f32 dtime)
+{
+
+ f32 jitter;
+ Jitter *jp;
+
+ /* Time average and jitter calculation
+ */
+ jp = &stats->dtime_jitter;
+ jp->avg = jp->avg * 0.96 + dtime * 0.04;
+
+ jitter = dtime - jp->avg;
+
+ if (jitter > jp->max)
+ jp->max = jitter;
+
+ jp->counter += dtime;
+
+ if (jp->counter > 0.0) {
+ jp->counter -= 3.0;
+ jp->max_sample = jp->max;
+ jp->max_fraction = jp->max_sample / (jp->avg + 0.001);
+ jp->max = 0.0;
+ }
+
+ /* Busytime average and jitter calculation
+ */
+ jp = &stats->busy_time_jitter;
+ jp->avg = jp->avg + draw_times.busy_time * 0.02;
+
+ jitter = draw_times.busy_time - jp->avg;
+
+ if (jitter > jp->max)
+ jp->max = jitter;
+ if (jitter < jp->min)
+ jp->min = jitter;
+
+ jp->counter += dtime;
+
+ if (jp->counter > 0.0) {
+ jp->counter -= 3.0;
+ jp->max_sample = jp->max;
+ jp->min_sample = jp->min;
+ jp->max = 0.0;
+ jp->min = 0.0;
+ }
+}
+
+
+
+/****************************************************************************
+ Input handling
+ ****************************************************************************/
+
+void Game::processUserInput(VolatileRunFlags *flags,
+ GameRunData *interact_args, f32 dtime)
+{
+ // Reset input if window not active or some menu is active
+ if (device->isWindowActive() == false
+ || noMenuActive() == false
+ || guienv->hasFocus(gui_chat_console)) {
+ input->clear();
+ }
+
+ if (!guienv->hasFocus(gui_chat_console) && gui_chat_console->isOpen()) {
+ gui_chat_console->closeConsoleAtOnce();
+ }
+
+ // Input handler step() (used by the random input generator)
+ input->step(dtime);
+
+#ifdef HAVE_TOUCHSCREENGUI
+
+ if (g_touchscreengui) {
+ g_touchscreengui->step(dtime);
+ }
+
+#endif
+#ifdef __ANDROID__
+
+ if (current_formspec != 0)
+ current_formspec->getAndroidUIInput();
+
+#endif
+
+ // Increase timer for double tap of "keymap_jump"
+ if (m_cache_doubletap_jump && interact_args->jump_timer <= 0.2)
+ interact_args->jump_timer += dtime;
+
+ processKeyboardInput(
+ flags,
+ &interact_args->statustext_time,
+ &interact_args->jump_timer,
+ &interact_args->reset_jump_timer,
+ &interact_args->profiler_current_page,
+ interact_args->profiler_max_page);
+
+ processItemSelection(&interact_args->new_playeritem);
+}
+
+
+void Game::processKeyboardInput(VolatileRunFlags *flags,
+ float *statustext_time,
+ float *jump_timer,
+ bool *reset_jump_timer,
+ u32 *profiler_current_page,
+ u32 profiler_max_page)
+{
+
+ //TimeTaker tt("process kybd input", NULL, PRECISION_NANO);
+
+ if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DROP])) {
+ dropSelectedItem();
+ } 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(keycache.key[KeyCache::KEYMAP_ID_CHAT])) {
+ show_chat_menu(¤t_formspec, client, gamedef, texture_src, device,
+ client, "");
+ } 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(keycache.key[KeyCache::KEYMAP_ID_CONSOLE])) {
+ openConsole();
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FREEMOVE])) {
+ toggleFreeMove(statustext_time);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_JUMP])) {
+ toggleFreeMoveAlt(statustext_time, jump_timer);
+ *reset_jump_timer = true;
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_FASTMOVE])) {
+ toggleFast(statustext_time);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_NOCLIP])) {
+ toggleNoClip(statustext_time);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_SCREENSHOT])) {
+ client->makeScreenshot(device);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_HUD])) {
+ toggleHud(statustext_time, &flags->show_hud);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_CHAT])) {
+ toggleChat(statustext_time, &flags->show_chat);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_FORCE_FOG_OFF])) {
+ toggleFog(statustext_time, &flags->force_fog_off);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_UPDATE_CAMERA])) {
+ toggleUpdateCamera(statustext_time, &flags->disable_camera_update);
+ } 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(keycache.key[KeyCache::KEYMAP_ID_TOGGLE_PROFILER])) {
+ toggleProfiler(statustext_time, profiler_current_page, profiler_max_page);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_INCREASE_VIEWING_RANGE])) {
+ increaseViewRange(statustext_time);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DECREASE_VIEWING_RANGE])) {
+ decreaseViewRange(statustext_time);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_RANGESELECT])) {
+ toggleFullViewRange(statustext_time);
+ } else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_NEXT]))
+ quicktune->next();
+ else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_PREV]))
+ quicktune->prev();
+ else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_INC]))
+ quicktune->inc();
+ else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_QUICKTUNE_DEC]))
+ quicktune->dec();
+ else if (input->wasKeyDown(keycache.key[KeyCache::KEYMAP_ID_DEBUG_STACKS])) {
+ // Print debug stacks
+ dstream << "-----------------------------------------"
+ << std::endl;
+ dstream << DTIME << "Printing debug stacks:" << std::endl;
+ dstream << "-----------------------------------------"
+ << std::endl;
+ debug_stacks_print();
+ }
+
+ if (!input->isKeyDown(getKeySetting("keymap_jump")) && *reset_jump_timer) {
+ *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;
+ }
+}
+
+
+void Game::processItemSelection(u16 *new_playeritem)
+{
+ LocalPlayer *player = client->getEnv().getLocalPlayer();
+
+ /* Item selection using mouse wheel
+ */
+ *new_playeritem = client->getPlayerItem();
+
+ s32 wheel = input->getMouseWheel();
+ u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1,
+ player->hud_hotbar_itemcount - 1);
+
+ if (wheel < 0)
+ *new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0;
+ else if (wheel > 0)
+ *new_playeritem = *new_playeritem > 0 ? *new_playeritem - 1 : max_item;
+ // else wheel == 0
+
+
+ /* Item selection using keyboard
+ */
+ for (u16 i = 0; i < 10; i++) {
+ static const KeyPress *item_keys[10] = {
+ NumberKey + 1, NumberKey + 2, NumberKey + 3, NumberKey + 4,
+ NumberKey + 5, NumberKey + 6, NumberKey + 7, NumberKey + 8,
+ NumberKey + 9, NumberKey + 0,
+ };
+
+ if (input->wasKeyDown(*item_keys[i])) {
+ if (i < PLAYER_INVENTORY_SIZE && i < player->hud_hotbar_itemcount) {
+ *new_playeritem = i;
+ infostream << "Selected item: " << new_playeritem << std::endl;
+ }
+ break;