1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-10-04 16:17:17 +02:00

Use ImGui for debug menu

This commit is contained in:
Daniel Evans 2019-05-22 22:55:03 +01:00
parent 4202297e0e
commit baeffe6c8f
2 changed files with 151 additions and 171 deletions

View File

@ -17,10 +17,7 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
constexpr float kDebugEntryHeight = 14.f; #include <imgui.h>
constexpr float kDebugEntryHeightMissions = 12.f;
constexpr int kDebugFont = 2;
const glm::vec2 kDebugMenuOffset = glm::vec2(10.f, 50.f);
static void jumpCharacter(RWGame* game, CharacterObject* player, static void jumpCharacter(RWGame* game, CharacterObject* player,
const glm::vec3& target, bool ground = true) { const glm::vec3& target, bool ground = true) {
@ -38,126 +35,133 @@ static void jumpCharacter(RWGame* game, CharacterObject* player,
} }
} }
Menu DebugState::createDebugMenu() { void DebugState::drawDebugMenu() {
CharacterObject* player = nullptr; CharacterObject* player = nullptr;
if (game->getWorld()->getPlayer()) { if (game->getWorld()->getPlayer()) {
player = game->getWorld()->getPlayer()->getCharacter(); player = game->getWorld()->getPlayer()->getCharacter();
} }
Menu menu{ ImGui::Begin("Debug Tools");
{{"Jump to Debug Camera",
[=] { if (player && ImGui::BeginMenu("Game")) {
jumpCharacter(game, player, if (ImGui::MenuItem("Set Super Jump")) {
_debugCam.position + player->setJumpSpeed(20.f);
_debugCam.rotation * glm::vec3(3.f, 0.f, 0.f), }
false); if (ImGui::MenuItem("Set Normal Jump")) {
}}, player->setJumpSpeed(CharacterObject::DefaultJumpSpeed);
{"-Map", [=] { setNextMenu(createMapMenu()); }}, }
{"-Vehicles", [=] { setNextMenu(createVehicleMenu()); }},
{"-AI", [=] { setNextMenu(createAIMenu()); }}, if (ImGui::MenuItem("Full Health")) {
{"-Weapons", [=] { setNextMenu(createWeaponMenu()); }}, player->getCurrentState().health = 100.f;
{"-Weather", [=] { setNextMenu(createWeatherMenu()); }}, }
{"-Missions", [=] { setNextMenu(createMissionsMenu()); }}, if (ImGui::MenuItem("Full Armour")) {
{"Set Super Jump", [=] { player->setJumpSpeed(20.f); }}, player->getCurrentState().armour = 100.f;
{"Set Normal Jump", }
[=] { player->setJumpSpeed(CharacterObject::DefaultJumpSpeed); }},
{"Full Health", [=] { player->getCurrentState().health = 100.f; }},
{"Full Armour", [=] { player->getCurrentState().armour = 100.f; }},
{"Cull Here",
[=] { game->getRenderer().setCullOverride(true, _debugCam); }}},
kDebugMenuOffset,
kDebugFont,
kDebugEntryHeight};
// Optional block if the player is in a vehicle // Optional block if the player is in a vehicle
auto cv = player->getCurrentVehicle(); if (auto cv = player->getCurrentVehicle(); cv) {
if (cv) { if (ImGui::MenuItem("Flip Vehicle")) {
menu.lambda("Flip vehicle", [=] { cv->setRotation(
cv->setRotation(cv->getRotation() * cv->getRotation() *
glm::quat(glm::vec3(0.f, glm::pi<float>(), 0.f))); glm::quat(glm::vec3(0.f, glm::pi<float>(), 0.f)));
}); }
} }
return menu; if (ImGui::MenuItem("Cull Here")) {
game->getRenderer().setCullOverride(true, _debugCam);
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Map")) {
drawMapMenu();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Vehicle")) {
drawVehicleMenu();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("AI")) {
drawAIMenu();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Weapons")) {
drawWeaponMenu();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Weather")) {
drawWeatherMenu();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Missions")) {
drawMissionsMenu();
ImGui::EndMenu();
}
ImGui::End();
} }
Menu DebugState::createMapMenu() { void DebugState::drawMapMenu() {
CharacterObject* player = nullptr; CharacterObject* player = nullptr;
if (game->getWorld()->getPlayer()) { if (game->getWorld()->getPlayer()) {
player = game->getWorld()->getPlayer()->getCharacter(); player = game->getWorld()->getPlayer()->getCharacter();
} }
Menu menu{ if (ImGui::MenuItem("Jump to Debug Camera")) {
{{"Back", [=] { setNextMenu(createDebugMenu()); }}, jumpCharacter(
{"Jump to Docks", game, player,
[=] { _debugCam.position + _debugCam.rotation * glm::vec3(3.f, 0.f, 0.f),
jumpCharacter(game, player, glm::vec3(1390.f, -837.f, 100.f)); false);
}}, }
{"Jump to Garage",
[=] { jumpCharacter(game, player, glm::vec3(270.f, -605.f, 40.f)); }}, const std::vector<std::tuple<const char*, glm::vec3>> kInterestingPlaces{
{"Jump to Airport", {"Docks", {1390.f, -837.f, 100.f}},
[=] { {"Garage", {270.f, -605.f, 40.f}},
jumpCharacter(game, player, glm::vec3(-950.f, -980.f, 12.f)); {"Airport", {-950.f, -980.f, 12.f}},
}}, {"Hideout", {875.0, -309.0, 100.0}},
{"Jump to Hideout", {"Luigi's", {902.75, -425.56, 100.0}},
[=] { {"Hospital", {1123.77, -569.15, 100.0}},
jumpCharacter(game, player, glm::vec3(875.0, -309.0, 100.0)); };
}},
{"Jump to Luigi's", for (const auto& [name, pos] : kInterestingPlaces) {
[=] { if (ImGui::MenuItem((std::string("Jump to ") + name).c_str())) {
jumpCharacter(game, player, glm::vec3(902.75, -425.56, 100.0)); jumpCharacter(game, player, pos);
}}, }
{"Jump to Hospital", }
[=] {
jumpCharacter(game, player, glm::vec3(1123.77, -569.15, 100.0)); if (ImGui::MenuItem("Unsolid Garage Doors")) {
}},
{"Unsolid garage doors",
[=] {
static constexpr std::array<char const*, 33> garageDoorModels{ static constexpr std::array<char const*, 33> garageDoorModels{
{"8ballsuburbandoor", "amcogaragedoor", {"8ballsuburbandoor", "amcogaragedoor", "bankjobdoor",
"bankjobdoor", "bombdoor", "bombdoor", "crushercrush", "crushertop",
"crushercrush", "crushertop", "door2_garage", "door3_garage", "door4_garage",
"door2_garage", "door3_garage", "door_bombshop", "door_col_compnd_01", "door_col_compnd_02",
"door4_garage", "door_bombshop", "door_col_compnd_03", "door_col_compnd_04", "door_col_compnd_05",
"door_col_compnd_01", "door_col_compnd_02", "door_jmsgrage", "door_sfehousegrge", "double_garage_dr",
"door_col_compnd_03", "door_col_compnd_04", "impex_door", "impexpsubgrgdoor", "ind_plyrwoor",
"door_col_compnd_05", "door_jmsgrage", "ind_slidedoor", "jamesgrge_kb", "leveldoor2",
"door_sfehousegrge", "double_garage_dr", "oddjgaragdoor", "plysve_gragedoor", "SalvGarage",
"impex_door", "impexpsubgrgdoor", "shedgaragedoor", "Sub_sprayshopdoor", "towergaragedoor1",
"ind_plyrwoor", "ind_slidedoor", "towergaragedoor2", "towergaragedoor3", "vheistlocdoor"}};
"jamesgrge_kb", "leveldoor2",
"oddjgaragdoor", "plysve_gragedoor",
"SalvGarage", "shedgaragedoor",
"Sub_sprayshopdoor", "towergaragedoor1",
"towergaragedoor2", "towergaragedoor3",
"vheistlocdoor"}};
auto gw = game->getWorld(); auto gw = game->getWorld();
for (auto& [id, instancePtr] : gw->instancePool.objects) { for (auto& [id, instancePtr] : gw->instancePool.objects) {
auto obj = static_cast<InstanceObject*>(instancePtr.get()); auto obj = static_cast<InstanceObject*>(instancePtr.get());
if (std::find(garageDoorModels.begin(), if (std::find(garageDoorModels.begin(), garageDoorModels.end(),
garageDoorModels.end(),
obj->getModelInfo<BaseModelInfo>()->name) != obj->getModelInfo<BaseModelInfo>()->name) !=
garageDoorModels.end()) { garageDoorModels.end()) {
obj->setSolid(false); obj->setSolid(false);
} }
} }
}}}, }
kDebugMenuOffset,
kDebugFont,
kDebugEntryHeight};
return menu;
} }
Menu DebugState::createVehicleMenu() { void DebugState::drawVehicleMenu() {
Menu menu{
{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
kDebugMenuOffset,
kDebugFont,
kDebugEntryHeight,
};
static constexpr std::array<std::tuple<char const*, unsigned int>, 19> static constexpr std::array<std::tuple<char const*, unsigned int>, 19>
kVehicleTypes{{{"Landstalker", 90}, kVehicleTypes{{{"Landstalker", 90},
{"Taxi", 110}, {"Taxi", 110},
@ -180,18 +184,13 @@ Menu DebugState::createVehicleMenu() {
{"Infernus", 101}}}; {"Infernus", 101}}};
for (const auto& [name, id] : kVehicleTypes) { for (const auto& [name, id] : kVehicleTypes) {
menu.lambda(name, [this, id = id] { spawnVehicle(id); }); if (ImGui::MenuItem(name)) {
spawnVehicle(id);
}
} }
return menu;
} }
Menu DebugState::createAIMenu() { void DebugState::drawAIMenu() {
Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
kDebugMenuOffset,
kDebugFont,
kDebugEntryHeight};
static constexpr std::array<std::tuple<char const*, unsigned int>, 6> static constexpr std::array<std::tuple<char const*, unsigned int>, 6>
kPedTypes{{ kPedTypes{{
{"Triad", 12}, {"Triad", 12},
@ -203,10 +202,12 @@ Menu DebugState::createAIMenu() {
}}; }};
for (const auto& [name, id] : kPedTypes) { for (const auto& [name, id] : kPedTypes) {
menu.lambda(name, [this, id = id] { spawnFollower(id); }); if (ImGui::MenuItem(name)) {
spawnFollower(id);
}
} }
menu.lambda("Kill All Peds", [=] { if (ImGui::MenuItem("Kill All Peds")) {
for (auto& [id, pedestrianPtr] : for (auto& [id, pedestrianPtr] :
game->getWorld()->pedestrianPool.objects) { game->getWorld()->pedestrianPool.objects) {
if (pedestrianPtr->getLifetime() == GameObject::PlayerLifetime) { if (pedestrianPtr->getLifetime() == GameObject::PlayerLifetime) {
@ -220,47 +221,31 @@ Menu DebugState::createAIMenu() {
0.f 0.f
}); });
} }
}); }
return menu;
} }
Menu DebugState::createWeaponMenu() { void DebugState::drawWeaponMenu() {
Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
kDebugMenuOffset,
kDebugFont,
kDebugEntryHeight};
for (int i = 1; i < kMaxInventorySlots; ++i) { for (int i = 1; i < kMaxInventorySlots; ++i) {
auto& name = getWorld()->data->weaponData[i].name; auto& name = getWorld()->data->weaponData[i].name;
menu.lambda(name, [=] { giveItem(i); }); if (ImGui::MenuItem(name.c_str())) {
giveItem(i);
}
} }
return menu;
} }
Menu DebugState::createWeatherMenu() { void DebugState::drawWeatherMenu() {
Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}}, static constexpr std::array<char const*, 4> w{
kDebugMenuOffset, {"Sunny", "Cloudy", "Rainy", "Foggy"}};
kDebugFont,
kDebugEntryHeight};
static constexpr std::array<char const*, 4> w{{"Sunny", "Cloudy", "Rainy", "Foggy"}};
for (std::size_t i = 0; i < w.size(); ++i) { for (std::size_t i = 0; i < w.size(); ++i) {
menu.lambda(w[i], if (ImGui::MenuItem(w[i])) {
[=] { game->getWorld()->state->basic.nextWeather = static_cast<std::uint16_t>(i); }); game->getWorld()->state->basic.nextWeather =
static_cast<std::uint16_t>(i);
}
} }
return menu;
} }
Menu DebugState::createMissionsMenu() { void DebugState::drawMissionsMenu() {
Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
kDebugMenuOffset,
kDebugFont,
kDebugEntryHeightMissions};
static constexpr std::array<char const*, 80> w{{ static constexpr std::array<char const*, 80> w{{
"Intro Movie", "Intro Movie",
"Hospital Info Scene", "Hospital Info Scene",
@ -345,7 +330,7 @@ Menu DebugState::createMissionsMenu() {
}}; }};
for (std::size_t i = 0; i < w.size(); ++i) { for (std::size_t i = 0; i < w.size(); ++i) {
menu.lambda(w[i], [=] { if (ImGui::MenuItem(w[i])) {
ScriptMachine* vm = game->getScriptVM(); ScriptMachine* vm = game->getScriptVM();
if (vm) { if (vm) {
@ -367,16 +352,12 @@ Menu DebugState::createMissionsMenu() {
vm->startThread(offsets[i], true); vm->startThread(offsets[i], true);
} }
});
} }
}
return menu;
} }
DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd) DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd)
: State(game), _invertedY(game->getConfig().invertY()) { : State(game), _invertedY(game->getConfig().invertY()) {
this->setNextMenu(createDebugMenu());
_debugCam.position = vp; _debugCam.position = vp;
_debugCam.rotation = vd; _debugCam.rotation = vd;
} }
@ -400,19 +381,18 @@ void DebugState::tick(float dt) {
} }
void DebugState::draw(GameRenderer& r) { void DebugState::draw(GameRenderer& r) {
// Draw useful information like camera position. ImGui::SetNextWindowPos({20.f, 20.f});
std::stringstream ss; ImGui::Begin("Debug Info", nullptr,
ss << "Camera Position: " << glm::to_string(_debugCam.position) << "\n"; ImGuiWindowFlags_NoDecoration |
auto zone = getWorld()->data->findZoneAt(_debugCam.position); ImGuiWindowFlags_NoSavedSettings |
ss << (zone ? zone->name : "No Zone") << "\n"; ImGuiWindowFlags_NoInputs);
TextRenderer::TextInfo ti; ImGui::Text("Camera: %s", glm::to_string(_debugCam.position).c_str());
ti.font = FONT_ARIAL; auto zone = getWorld()->data->findZoneAt(_debugCam.position);
ti.text = GameStringUtil::fromString(ss.str(), ti.font); ImGui::Text("Zone: %s", zone ? zone->name.c_str() : "No Zone");
ti.screenPosition = glm::vec2(10.f, 10.f); ImGui::End();
ti.size = 15.f;
ti.baseColour = glm::u8vec3(255); drawDebugMenu();
r.text.renderText(ti);
State::draw(r); State::draw(r);
} }

View File

@ -18,13 +18,13 @@ class DebugState final : public State {
bool _sonicMode = false; bool _sonicMode = false;
bool _invertedY; bool _invertedY;
Menu createDebugMenu(); void drawDebugMenu();
Menu createMapMenu(); void drawMapMenu();
Menu createVehicleMenu(); void drawVehicleMenu();
Menu createAIMenu(); void drawAIMenu();
Menu createWeaponMenu(); void drawWeaponMenu();
Menu createWeatherMenu(); void drawWeatherMenu();
Menu createMissionsMenu(); void drawMissionsMenu();
public: public:
DebugState(RWGame* game, const glm::vec3& vp = {}, DebugState(RWGame* game, const glm::vec3& vp = {},