// // SuperTuxKart - a fun racing game with go-kart // Copyright (C) 2013-2015 Lionel Fuentes // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 3 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "debug.hpp" #include "config/user_config.hpp" #include "font/bold_face.hpp" #include "font/digit_face.hpp" #include "font/font_manager.hpp" #include "font/regular_face.hpp" #include "graphics/camera_debug.hpp" #include "graphics/camera_fps.hpp" #include "karts/explosion_animation.hpp" #include "graphics/irr_driver.hpp" #include "graphics/light.hpp" #include "graphics/shaders.hpp" #include "items/powerup_manager.hpp" #include "items/attachment.hpp" #include "karts/abstract_kart.hpp" #include "karts/kart_properties.hpp" #include "karts/controller/controller.hpp" #include "modes/world.hpp" #include "physics/irr_debug_drawer.hpp" #include "physics/physics.hpp" #include "race/history.hpp" #include "main_loop.hpp" #include "replay/replay_recorder.hpp" #include "scriptengine/script_engine.hpp" #include "states_screens/dialogs/debug_slider.hpp" #include "states_screens/dialogs/general_text_field_dialog.hpp" #include "utils/constants.hpp" #include "utils/log.hpp" #include "utils/profiler.hpp" #include #include #include using namespace irr; using namespace gui; namespace Debug { /** This is to let mouse input events go through when the debug menu is * visible, otherwise GUI events would be blocked while in a race... */ static bool g_debug_menu_visible = false; // ----------------------------------------------------------------------------- // Commands for the debug menu enum DebugMenuCommand { //! graphics commands DEBUG_GRAPHICS_RELOAD_SHADERS, DEBUG_GRAPHICS_RESET, DEBUG_GRAPHICS_WIREFRAME, DEBUG_GRAPHICS_MIPMAP_VIZ, DEBUG_GRAPHICS_NORMALS_VIZ, DEBUG_GRAPHICS_SSAO_VIZ, DEBUG_GRAPHICS_RSM_VIZ, DEBUG_GRAPHICS_RH_VIZ, DEBUG_GRAPHICS_GI_VIZ, DEBUG_GRAPHICS_SHADOW_VIZ, DEBUG_GRAPHICS_LIGHT_VIZ, DEBUG_GRAPHICS_DISTORT_VIZ, DEBUG_GRAPHICS_BULLET_1, DEBUG_GRAPHICS_BULLET_2, DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ, DEBUG_PROFILER, DEBUG_PROFILER_GENERATE_REPORT, DEBUG_FONT_DUMP_GLYPH_PAGE, DEBUG_FONT_RELOAD, DEBUG_FPS, DEBUG_SAVE_REPLAY, DEBUG_SAVE_HISTORY, DEBUG_POWERUP_BOWLING, DEBUG_POWERUP_BUBBLEGUM, DEBUG_POWERUP_CAKE, DEBUG_POWERUP_PARACHUTE, DEBUG_POWERUP_PLUNGER, DEBUG_POWERUP_RUBBERBALL, DEBUG_POWERUP_SWATTER, DEBUG_POWERUP_SWITCH, DEBUG_POWERUP_ZIPPER, DEBUG_POWERUP_NITRO, DEBUG_ATTACHMENT_PARACHUTE, DEBUG_ATTACHMENT_BOMB, DEBUG_ATTACHMENT_ANVIL, DEBUG_ATTACHMENT_EXPLOSION, DEBUG_GUI_TOGGLE, DEBUG_GUI_HIDE_KARTS, DEBUG_GUI_CAM_FREE, DEBUG_GUI_CAM_TOP, DEBUG_GUI_CAM_WHEEL, DEBUG_GUI_CAM_BEHIND_KART, DEBUG_GUI_CAM_SIDE_OF_KART, DEBUG_GUI_CAM_NORMAL, DEBUG_GUI_CAM_SMOOTH, DEBUG_GUI_CAM_ATTACH, DEBUG_VIEW_KART_ONE, DEBUG_VIEW_KART_TWO, DEBUG_VIEW_KART_THREE, DEBUG_VIEW_KART_FOUR, DEBUG_VIEW_KART_FIVE, DEBUG_VIEW_KART_SIX, DEBUG_VIEW_KART_SEVEN, DEBUG_VIEW_KART_EIGHT, DEBUG_HIDE_KARTS, DEBUG_THROTTLE_FPS, DEBUG_VISUAL_VALUES, DEBUG_PRINT_START_POS, DEBUG_ADJUST_LIGHTS, DEBUG_SCRIPT_CONSOLE }; // DebugMenuCommand // ----------------------------------------------------------------------------- /** Add powerup selected from debug menu for all player karts */ void addPowerup(PowerupManager::PowerupType powerup) { World* world = World::getWorld(); if (!world) return; for(unsigned int i = 0; i < race_manager->getNumLocalPlayers(); i++) { AbstractKart* kart = world->getLocalPlayerKart(i); kart->setPowerup(powerup, 10000); } } // addPowerup // ---------------------------------------------------------------------------- void addAttachment(Attachment::AttachmentType type) { World* world = World::getWorld(); if (world == NULL) return; for (unsigned int i = 0; i < world->getNumKarts(); i++) { AbstractKart *kart = world->getKart(i); if (!kart->getController()->isLocalPlayerController()) continue; if (type == Attachment::ATTACH_ANVIL) { kart->getAttachment() ->set(type, kart->getKartProperties()->getAnvilDuration()); kart->adjustSpeed(kart->getKartProperties()->getAnvilSpeedFactor()); kart->updateWeight(); } else if (type == Attachment::ATTACH_PARACHUTE) { kart->getAttachment() ->set(type, kart->getKartProperties()->getParachuteDuration()); } else if (type == Attachment::ATTACH_BOMB) { kart->getAttachment() ->set(type, stk_config->m_bomb_time); } } } // addAttachment // ---------------------------------------------------------------------------- void changeCameraTarget(u32 num) { World* world = World::getWorld(); Camera *cam = Camera::getActiveCamera(); if (world == NULL || cam == NULL) return; if (num < (world->getNumKarts() + 1)) { AbstractKart* kart = world->getKart(num - 1); if (kart == NULL) return; cam->setMode(Camera::CM_NORMAL); cam->setKart(kart); } } // changeCameraTarget // ----------------------------------------------------------------------------- /** returns the light node with the lowest distance to the player kart (excluding * nitro emitters) */ LightNode* findNearestLight() { Camera* camera = Camera::getActiveCamera(); if (camera == NULL) { Log::error("[Debug Menu]", "No camera found."); return NULL; } core::vector3df cam_pos = camera->getCameraSceneNode()->getAbsolutePosition(); LightNode* nearest = 0; float nearest_dist = 1000000.0; // big enough for (unsigned int i = 0; i < irr_driver->getLights().size(); i++) { LightNode* light = irr_driver->getLights()[i]; // Avoid modifying the nitro emitter or another invisible light if (std::string(light->getName()).find("nitro emitter") == 0 || !light->isVisible()) continue; core::vector3df light_pos = light->getAbsolutePosition(); if ( cam_pos.getDistanceFrom(light_pos) < nearest_dist) { nearest = irr_driver->getLights()[i]; nearest_dist = cam_pos.getDistanceFrom(light_pos); } } return nearest; } // ---------------------------------------------------------------------------- bool handleContextMenuAction(s32 cmd_id) { World *world = World::getWorld(); Physics *physics = Physics::getInstance(); switch(cmd_id) { case DEBUG_GRAPHICS_RELOAD_SHADERS: #ifndef SERVER_ONLY Log::info("Debug", "Reloading shaders..."); ShaderFilesManager::getInstance()->clean(); ShaderBase::updateShaders(); #endif break; case DEBUG_GRAPHICS_RESET: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); break; case DEBUG_GRAPHICS_WIREFRAME: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleWireframe(); break; case DEBUG_GRAPHICS_MIPMAP_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleMipVisualization(); break; case DEBUG_GRAPHICS_NORMALS_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleNormals(); break; case DEBUG_GRAPHICS_SSAO_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleSSAOViz(); break; case DEBUG_GRAPHICS_RSM_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleRSM(); break; case DEBUG_GRAPHICS_RH_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleRH(); break; case DEBUG_GRAPHICS_GI_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleGI(); break; case DEBUG_GRAPHICS_SHADOW_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleShadowViz(); break; case DEBUG_GRAPHICS_LIGHT_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleLightViz(); break; case DEBUG_GRAPHICS_DISTORT_VIZ: if (physics) physics->setDebugMode(IrrDebugDrawer::DM_NONE); irr_driver->resetDebugModes(); irr_driver->toggleDistortViz(); break; case DEBUG_GRAPHICS_BULLET_1: irr_driver->resetDebugModes(); if (!world) return false; physics->setDebugMode(IrrDebugDrawer::DM_KARTS_PHYSICS); break; case DEBUG_GRAPHICS_BULLET_2: { irr_driver->resetDebugModes(); Physics *physics = Physics::getInstance(); if (!physics) return false; physics->setDebugMode(IrrDebugDrawer::DM_NO_KARTS_GRAPHICS); break; } case DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ: irr_driver->resetDebugModes(); irr_driver->toggleBoundingBoxesViz(); break; case DEBUG_PROFILER: UserConfigParams::m_profiler_enabled = !UserConfigParams::m_profiler_enabled; break; case DEBUG_PROFILER_GENERATE_REPORT: profiler.setCaptureReport(!profiler.getCaptureReport()); break; case DEBUG_THROTTLE_FPS: main_loop->setThrottleFPS(false); break; case DEBUG_FONT_DUMP_GLYPH_PAGE: font_manager->getFont()->dumpGlyphPage("bold"); font_manager->getFont()->dumpGlyphPage("digit"); font_manager->getFont()->dumpGlyphPage("regular"); case DEBUG_FONT_RELOAD: font_manager->getFont()->reset(); font_manager->getFont()->reset(); font_manager->getFont()->reset(); break; case DEBUG_FPS: UserConfigParams::m_display_fps = !UserConfigParams::m_display_fps; break; case DEBUG_SAVE_REPLAY: ReplayRecorder::get()->save(); break; case DEBUG_SAVE_HISTORY: history->Save(); break; case DEBUG_POWERUP_BOWLING: addPowerup(PowerupManager::POWERUP_BOWLING); break; case DEBUG_POWERUP_BUBBLEGUM: addPowerup(PowerupManager::POWERUP_BUBBLEGUM); break; case DEBUG_POWERUP_CAKE: addPowerup(PowerupManager::POWERUP_CAKE); break; case DEBUG_POWERUP_PARACHUTE: addPowerup(PowerupManager::POWERUP_PARACHUTE); break; case DEBUG_POWERUP_PLUNGER: addPowerup(PowerupManager::POWERUP_PLUNGER); break; case DEBUG_POWERUP_RUBBERBALL: addPowerup(PowerupManager::POWERUP_RUBBERBALL); break; case DEBUG_POWERUP_SWATTER: addPowerup(PowerupManager::POWERUP_SWATTER); break; case DEBUG_POWERUP_SWITCH: addPowerup(PowerupManager::POWERUP_SWITCH); break; case DEBUG_POWERUP_ZIPPER: addPowerup(PowerupManager::POWERUP_ZIPPER); break; case DEBUG_POWERUP_NITRO: { if (!world) return false; const unsigned int num_local_players = race_manager->getNumLocalPlayers(); for (unsigned int i = 0; i < num_local_players; i++) { AbstractKart* kart = world->getLocalPlayerKart(i); kart->setEnergy(100.0f); } break; } case DEBUG_ATTACHMENT_ANVIL: addAttachment(Attachment::ATTACH_ANVIL); break; case DEBUG_ATTACHMENT_BOMB: addAttachment(Attachment::ATTACH_BOMB); break; case DEBUG_ATTACHMENT_PARACHUTE: addAttachment(Attachment::ATTACH_PARACHUTE); break; case DEBUG_ATTACHMENT_EXPLOSION: for (unsigned int i = 0; i < race_manager->getNumLocalPlayers(); i++) { AbstractKart* kart = world->getLocalPlayerKart(i); ExplosionAnimation::create(kart, kart->getXYZ(), true); } break; case DEBUG_GUI_TOGGLE: { if (!world) return false; RaceGUIBase* gui = world->getRaceGUI(); if (gui != NULL) gui->m_enabled = !gui->m_enabled; break; } case DEBUG_GUI_HIDE_KARTS: if (!world) return false; for (unsigned int n = 0; ngetNumKarts(); n++) { AbstractKart* kart = world->getKart(n); if (kart->getController()->isPlayerController()) kart->getNode()->setVisible(false); } break; case DEBUG_GUI_CAM_TOP: CameraDebug::setDebugType(CameraDebug::CM_DEBUG_TOP_OF_KART); Camera::changeCamera(0, Camera::CM_TYPE_DEBUG); irr_driver->getDevice()->getCursorControl()->setVisible(true); break; case DEBUG_GUI_CAM_WHEEL: CameraDebug::setDebugType(CameraDebug::CM_DEBUG_GROUND); Camera::changeCamera(0, Camera::CM_TYPE_DEBUG); irr_driver->getDevice()->getCursorControl()->setVisible(true); break; case DEBUG_GUI_CAM_BEHIND_KART: CameraDebug::setDebugType(CameraDebug::CM_DEBUG_BEHIND_KART); Camera::changeCamera(0, Camera::CM_TYPE_DEBUG); irr_driver->getDevice()->getCursorControl()->setVisible(true); break; case DEBUG_GUI_CAM_SIDE_OF_KART: CameraDebug::setDebugType(CameraDebug::CM_DEBUG_SIDE_OF_KART); Camera::changeCamera(0, Camera::CM_TYPE_DEBUG); irr_driver->getDevice()->getCursorControl()->setVisible(true); break; case DEBUG_GUI_CAM_FREE: { Camera *camera = Camera::getActiveCamera(); Camera::changeCamera(camera->getIndex(), Camera::CM_TYPE_FPS); irr_driver->getDevice()->getCursorControl()->setVisible(false); // Reset camera rotation CameraFPS *cam = dynamic_cast(Camera::getActiveCamera()); if(cam) { cam->setDirection(vector3df(0, 0, 1)); cam->setUpVector(vector3df(0, 1, 0)); } break; } case DEBUG_GUI_CAM_NORMAL: { Camera *camera = Camera::getActiveCamera(); Camera::changeCamera(camera->getIndex(), Camera::CM_TYPE_NORMAL); irr_driver->getDevice()->getCursorControl()->setVisible(true); break; } case DEBUG_GUI_CAM_SMOOTH: { CameraFPS *cam = dynamic_cast(Camera::getActiveCamera()); if(cam) { cam->setSmoothMovement(!cam->getSmoothMovement()); } break; } case DEBUG_GUI_CAM_ATTACH: { CameraFPS *cam = dynamic_cast(Camera::getActiveCamera()); if(cam) { cam->setAttachedFpsCam(!cam->getAttachedFpsCam()); } break; } case DEBUG_VIEW_KART_ONE: changeCameraTarget(1); break; case DEBUG_VIEW_KART_TWO: changeCameraTarget(2); break; case DEBUG_VIEW_KART_THREE: changeCameraTarget(3); break; case DEBUG_VIEW_KART_FOUR: changeCameraTarget(4); break; case DEBUG_VIEW_KART_FIVE: changeCameraTarget(5); break; case DEBUG_VIEW_KART_SIX: changeCameraTarget(6); break; case DEBUG_VIEW_KART_SEVEN: changeCameraTarget(7); break; case DEBUG_VIEW_KART_EIGHT: changeCameraTarget(8); break; case DEBUG_PRINT_START_POS: if (!world) return false; for (unsigned int i = 0; igetNumKarts(); i++) { AbstractKart *kart = world->getKart(i); Log::warn(kart->getIdent().c_str(), "", i, kart->getXYZ().getX(), kart->getXYZ().getY(), kart->getXYZ().getZ(), kart->getHeading()*RAD_TO_DEGREE ); } break; case DEBUG_VISUAL_VALUES: { #if !defined(__APPLE__) DebugSliderDialog *dsd = new DebugSliderDialog(); dsd->setSliderHook("red_slider", 0, 255, [](){ return int(irr_driver->getAmbientLight().r * 255.f); }, [](int v){ video::SColorf ambient = irr_driver->getAmbientLight(); ambient.setColorComponentValue(0, v / 255.f); irr_driver->setAmbientLight(ambient); } ); dsd->setSliderHook("green_slider", 0, 255, [](){ return int(irr_driver->getAmbientLight().g * 255.f); }, [](int v){ video::SColorf ambient = irr_driver->getAmbientLight(); ambient.setColorComponentValue(1, v / 255.f); irr_driver->setAmbientLight(ambient); } ); dsd->setSliderHook("blue_slider", 0, 255, [](){ return int(irr_driver->getAmbientLight().b * 255.f); }, [](int v){ video::SColorf ambient = irr_driver->getAmbientLight(); ambient.setColorComponentValue(2, v / 255.f); irr_driver->setAmbientLight(ambient); } ); dsd->setSliderHook("ssao_radius", 0, 100, [](){ return int(irr_driver->getSSAORadius() * 10.f); }, [](int v){irr_driver->setSSAORadius(v / 10.f); } ); dsd->setSliderHook("ssao_k", 0, 100, [](){ return int(irr_driver->getSSAOK() * 10.f); }, [](int v){irr_driver->setSSAOK(v / 10.f); } ); dsd->setSliderHook("ssao_sigma", 0, 100, [](){ return int(irr_driver->getSSAOSigma() * 10.f); }, [](int v){irr_driver->setSSAOSigma(v / 10.f); } ); #endif } break; case DEBUG_ADJUST_LIGHTS: { #if !defined(__APPLE__) // Some sliders use multipliers because the spinner widget // only supports integers DebugSliderDialog *dsd = new DebugSliderDialog(); dsd->changeLabel("Red", "Red (x10)"); dsd->setSliderHook("red_slider", 0, 100, []() { return int(findNearestLight()->getColor().X * 100); }, [](int intensity) { LightNode* nearest = findNearestLight(); core::vector3df color = nearest->getColor(); nearest->setColor(intensity / 100.0f, color.Y, color.Z); } ); dsd->changeLabel("Green", "Green (x10)"); dsd->setSliderHook("green_slider", 0, 100, []() { return int(findNearestLight()->getColor().Y * 100); }, [](int intensity) { LightNode* nearest = findNearestLight(); core::vector3df color = nearest->getColor(); nearest->setColor(color.X, intensity / 100.0f, color.Z); } ); dsd->changeLabel("Blue", "Blue (x10)"); dsd->setSliderHook("blue_slider", 0, 100, []() { return int(findNearestLight()->getColor().Z * 100); }, [](int intensity) { LightNode* nearest = findNearestLight(); core::vector3df color = nearest->getColor(); nearest->setColor(color.X, color.Y, intensity / 100.0f); } ); dsd->changeLabel("SSAO radius", "energy (x10)"); dsd->setSliderHook("ssao_radius", 0, 100, []() { return int(findNearestLight()->getEnergy() * 10); }, [](int v){ findNearestLight()->setEnergy(v / 10.0f); } ); dsd->changeLabel("SSAO k", "radius"); dsd->setSliderHook("ssao_k", 0, 100, []() { return int(findNearestLight()->getRadius()); }, [](int v){ findNearestLight()->setRadius(float(v)); } ); dsd->changeLabel("SSAO Sigma", "[None]"); #endif break; } case DEBUG_SCRIPT_CONSOLE: new GeneralTextFieldDialog(L"Run Script", [=] (const irr::core::stringw& text) { Scripting::ScriptEngine::getInstance() ->evalScript(StringUtils::wideToUtf8(text)); }); break; } // switch return false; } // ----------------------------------------------------------------------------- /** Debug menu handling */ bool onEvent(const SEvent &event) { // Only activated in artist debug mode if(!UserConfigParams::m_artist_debug_mode) return true; // keep handling the events if(event.EventType == EET_MOUSE_INPUT_EVENT) { // Create the menu (only one menu at a time) if(event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN && !g_debug_menu_visible) { irr_driver->getDevice()->getCursorControl()->setVisible(true); // root menu gui::IGUIEnvironment* guienv = irr_driver->getGUI(); core::rect r(100, 50, 150, 500); IGUIContextMenu* mnu = guienv->addContextMenu(r, NULL); int graphicsMenuIndex = mnu->addItem(L"Graphics >",-1,true,true); // graphics menu IGUIContextMenu* sub = mnu->getSubMenu(graphicsMenuIndex); sub->addItem(L"Reload shaders", DEBUG_GRAPHICS_RELOAD_SHADERS ); sub->addItem(L"Wireframe", DEBUG_GRAPHICS_WIREFRAME ); sub->addItem(L"Mipmap viz", DEBUG_GRAPHICS_MIPMAP_VIZ ); sub->addItem(L"Normals viz", DEBUG_GRAPHICS_NORMALS_VIZ ); sub->addItem(L"SSAO viz", DEBUG_GRAPHICS_SSAO_VIZ ); sub->addItem(L"RSM viz", DEBUG_GRAPHICS_RSM_VIZ); sub->addItem(L"RH viz", DEBUG_GRAPHICS_RH_VIZ); sub->addItem(L"GI viz", DEBUG_GRAPHICS_GI_VIZ); sub->addItem(L"Shadow viz", DEBUG_GRAPHICS_SHADOW_VIZ ); sub->addItem(L"Light viz", DEBUG_GRAPHICS_LIGHT_VIZ ); sub->addItem(L"Distort viz", DEBUG_GRAPHICS_DISTORT_VIZ ); sub->addItem(L"Physics debug", DEBUG_GRAPHICS_BULLET_1); sub->addItem(L"Physics debug (no kart)", DEBUG_GRAPHICS_BULLET_2); sub->addItem(L"Bounding Boxes viz", DEBUG_GRAPHICS_BOUNDING_BOXES_VIZ); sub->addItem(L"Reset debug views", DEBUG_GRAPHICS_RESET ); mnu->addItem(L"Items >",-1,true,true); sub = mnu->getSubMenu(1); sub->addItem(L"Basketball", DEBUG_POWERUP_RUBBERBALL ); sub->addItem(L"Bowling", DEBUG_POWERUP_BOWLING ); sub->addItem(L"Bubblegum", DEBUG_POWERUP_BUBBLEGUM ); sub->addItem(L"Cake", DEBUG_POWERUP_CAKE ); sub->addItem(L"Parachute", DEBUG_POWERUP_PARACHUTE ); sub->addItem(L"Plunger", DEBUG_POWERUP_PLUNGER ); sub->addItem(L"Swatter", DEBUG_POWERUP_SWATTER ); sub->addItem(L"Switch", DEBUG_POWERUP_SWITCH ); sub->addItem(L"Zipper", DEBUG_POWERUP_ZIPPER ); sub->addItem(L"Nitro", DEBUG_POWERUP_NITRO ); mnu->addItem(L"Attachments >",-1,true, true); sub = mnu->getSubMenu(2); sub->addItem(L"Bomb", DEBUG_ATTACHMENT_BOMB); sub->addItem(L"Anvil", DEBUG_ATTACHMENT_ANVIL); sub->addItem(L"Parachute", DEBUG_ATTACHMENT_PARACHUTE); sub->addItem(L"Explosion", DEBUG_ATTACHMENT_EXPLOSION); mnu->addItem(L"GUI >",-1,true, true); sub = mnu->getSubMenu(3); sub->addItem(L"Toggle GUI", DEBUG_GUI_TOGGLE); sub->addItem(L"Hide karts", DEBUG_GUI_HIDE_KARTS); sub->addItem(L"Top view", DEBUG_GUI_CAM_TOP); sub->addItem(L"Behind wheel view", DEBUG_GUI_CAM_WHEEL); sub->addItem(L"Behind kart view", DEBUG_GUI_CAM_BEHIND_KART); sub->addItem(L"Side of kart view", DEBUG_GUI_CAM_SIDE_OF_KART); sub->addItem(L"First person view (Ctrl + F1)", DEBUG_GUI_CAM_FREE); sub->addItem(L"Normal view (Ctrl + F2)", DEBUG_GUI_CAM_NORMAL); sub->addItem(L"Toggle smooth camera", DEBUG_GUI_CAM_SMOOTH); sub->addItem(L"Attach fps camera to kart", DEBUG_GUI_CAM_ATTACH); mnu->addItem(L"Change camera target >",-1,true, true); sub = mnu->getSubMenu(4); sub->addItem(L"To kart one", DEBUG_VIEW_KART_ONE); sub->addItem(L"To kart two", DEBUG_VIEW_KART_TWO); sub->addItem(L"To kart three", DEBUG_VIEW_KART_THREE); sub->addItem(L"To kart four", DEBUG_VIEW_KART_FOUR); sub->addItem(L"To kart five", DEBUG_VIEW_KART_FIVE); sub->addItem(L"To kart six", DEBUG_VIEW_KART_SIX); sub->addItem(L"To kart seven", DEBUG_VIEW_KART_SEVEN); sub->addItem(L"To kart eight", DEBUG_VIEW_KART_EIGHT); mnu->addItem(L"Font >",-1,true, true); sub = mnu->getSubMenu(5); sub->addItem(L"Dump glyph pages of fonts", DEBUG_FONT_DUMP_GLYPH_PAGE); sub->addItem(L"Reload all fonts", DEBUG_FONT_RELOAD); mnu->addItem(L"Adjust values", DEBUG_VISUAL_VALUES); mnu->addItem(L"Profiler", DEBUG_PROFILER); if (UserConfigParams::m_profiler_enabled) mnu->addItem(L"Toggle capture profiler report", DEBUG_PROFILER_GENERATE_REPORT); mnu->addItem(L"Do not limit FPS", DEBUG_THROTTLE_FPS); mnu->addItem(L"Toggle FPS", DEBUG_FPS); mnu->addItem(L"Save replay", DEBUG_SAVE_REPLAY); mnu->addItem(L"Save history", DEBUG_SAVE_HISTORY); mnu->addItem(L"Print position", DEBUG_PRINT_START_POS); mnu->addItem(L"Adjust Lights", DEBUG_ADJUST_LIGHTS); mnu->addItem(L"Scripting console", DEBUG_SCRIPT_CONSOLE); g_debug_menu_visible = true; irr_driver->showPointer(); } // Let Irrlicht handle the event while the menu is visible. // Otherwise in a race the GUI events won't be generated if(g_debug_menu_visible) return false; } if (event.EventType == EET_GUI_EVENT) { if (event.GUIEvent.Caller != NULL && event.GUIEvent.Caller->getType() == EGUIET_CONTEXT_MENU ) { IGUIContextMenu *menu = (IGUIContextMenu*)event.GUIEvent.Caller; s32 cmdID = menu->getItemCommandId(menu->getSelectedItem()); if (event.GUIEvent.EventType == EGET_ELEMENT_CLOSED) { g_debug_menu_visible = false; } else if (event.GUIEvent.EventType == gui::EGET_MENU_ITEM_SELECTED) { return handleContextMenuAction(cmdID); } return false; } } return true; // continue event handling } // onEvent // ---------------------------------------------------------------------------- bool handleStaticAction(int key) { if (key == KEY_F1) { handleContextMenuAction(DEBUG_GUI_CAM_FREE); } else if (key == KEY_F2) { handleContextMenuAction(DEBUG_GUI_CAM_NORMAL); } // TODO: create more keyboard shortcuts return false; } // ---------------------------------------------------------------------------- /** Returns if the debug menu is visible. */ bool isOpen() { return g_debug_menu_visible; } // isOpen } // namespace Debug