mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-24 19:32:55 +01:00
Use ImGui for debug menu
This commit is contained in:
parent
4202297e0e
commit
baeffe6c8f
@ -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",
|
|
||||||
[=] {
|
|
||||||
jumpCharacter(game, player,
|
|
||||||
_debugCam.position +
|
|
||||||
_debugCam.rotation * glm::vec3(3.f, 0.f, 0.f),
|
|
||||||
false);
|
|
||||||
}},
|
|
||||||
{"-Map", [=] { setNextMenu(createMapMenu()); }},
|
|
||||||
{"-Vehicles", [=] { setNextMenu(createVehicleMenu()); }},
|
|
||||||
{"-AI", [=] { setNextMenu(createAIMenu()); }},
|
|
||||||
{"-Weapons", [=] { setNextMenu(createWeaponMenu()); }},
|
|
||||||
{"-Weather", [=] { setNextMenu(createWeatherMenu()); }},
|
|
||||||
{"-Missions", [=] { setNextMenu(createMissionsMenu()); }},
|
|
||||||
{"Set Super Jump", [=] { player->setJumpSpeed(20.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
|
if (player && ImGui::BeginMenu("Game")) {
|
||||||
auto cv = player->getCurrentVehicle();
|
if (ImGui::MenuItem("Set Super Jump")) {
|
||||||
if (cv) {
|
player->setJumpSpeed(20.f);
|
||||||
menu.lambda("Flip vehicle", [=] {
|
}
|
||||||
cv->setRotation(cv->getRotation() *
|
if (ImGui::MenuItem("Set Normal Jump")) {
|
||||||
glm::quat(glm::vec3(0.f, glm::pi<float>(), 0.f)));
|
player->setJumpSpeed(CharacterObject::DefaultJumpSpeed);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("Full Health")) {
|
||||||
|
player->getCurrentState().health = 100.f;
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Full Armour")) {
|
||||||
|
player->getCurrentState().armour = 100.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional block if the player is in a vehicle
|
||||||
|
if (auto cv = player->getCurrentVehicle(); cv) {
|
||||||
|
if (ImGui::MenuItem("Flip Vehicle")) {
|
||||||
|
cv->setRotation(
|
||||||
|
cv->getRotation() *
|
||||||
|
glm::quat(glm::vec3(0.f, glm::pi<float>(), 0.f)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("Cull Here")) {
|
||||||
|
game->getRenderer().setCullOverride(true, _debugCam);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
return menu;
|
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)); }},
|
|
||||||
{"Jump to Airport",
|
|
||||||
[=] {
|
|
||||||
jumpCharacter(game, player, glm::vec3(-950.f, -980.f, 12.f));
|
|
||||||
}},
|
|
||||||
{"Jump to Hideout",
|
|
||||||
[=] {
|
|
||||||
jumpCharacter(game, player, glm::vec3(875.0, -309.0, 100.0));
|
|
||||||
}},
|
|
||||||
{"Jump to Luigi's",
|
|
||||||
[=] {
|
|
||||||
jumpCharacter(game, player, glm::vec3(902.75, -425.56, 100.0));
|
|
||||||
}},
|
|
||||||
{"Jump to Hospital",
|
|
||||||
[=] {
|
|
||||||
jumpCharacter(game, player, glm::vec3(1123.77, -569.15, 100.0));
|
|
||||||
}},
|
|
||||||
{"Unsolid garage doors",
|
|
||||||
[=] {
|
|
||||||
static constexpr std::array<char const*, 33> garageDoorModels{
|
|
||||||
{"8ballsuburbandoor", "amcogaragedoor",
|
|
||||||
"bankjobdoor", "bombdoor",
|
|
||||||
"crushercrush", "crushertop",
|
|
||||||
"door2_garage", "door3_garage",
|
|
||||||
"door4_garage", "door_bombshop",
|
|
||||||
"door_col_compnd_01", "door_col_compnd_02",
|
|
||||||
"door_col_compnd_03", "door_col_compnd_04",
|
|
||||||
"door_col_compnd_05", "door_jmsgrage",
|
|
||||||
"door_sfehousegrge", "double_garage_dr",
|
|
||||||
"impex_door", "impexpsubgrgdoor",
|
|
||||||
"ind_plyrwoor", "ind_slidedoor",
|
|
||||||
"jamesgrge_kb", "leveldoor2",
|
|
||||||
"oddjgaragdoor", "plysve_gragedoor",
|
|
||||||
"SalvGarage", "shedgaragedoor",
|
|
||||||
"Sub_sprayshopdoor", "towergaragedoor1",
|
|
||||||
"towergaragedoor2", "towergaragedoor3",
|
|
||||||
"vheistlocdoor"}};
|
|
||||||
|
|
||||||
auto gw = game->getWorld();
|
const std::vector<std::tuple<const char*, glm::vec3>> kInterestingPlaces{
|
||||||
for (auto& [id, instancePtr] : gw->instancePool.objects) {
|
{"Docks", {1390.f, -837.f, 100.f}},
|
||||||
auto obj = static_cast<InstanceObject*>(instancePtr.get());
|
{"Garage", {270.f, -605.f, 40.f}},
|
||||||
if (std::find(garageDoorModels.begin(),
|
{"Airport", {-950.f, -980.f, 12.f}},
|
||||||
garageDoorModels.end(),
|
{"Hideout", {875.0, -309.0, 100.0}},
|
||||||
obj->getModelInfo<BaseModelInfo>()->name) !=
|
{"Luigi's", {902.75, -425.56, 100.0}},
|
||||||
garageDoorModels.end()) {
|
{"Hospital", {1123.77, -569.15, 100.0}},
|
||||||
obj->setSolid(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}},
|
|
||||||
kDebugMenuOffset,
|
|
||||||
kDebugFont,
|
|
||||||
kDebugEntryHeight};
|
|
||||||
|
|
||||||
return menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
Menu DebugState::createVehicleMenu() {
|
|
||||||
Menu menu{
|
|
||||||
{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
|
|
||||||
kDebugMenuOffset,
|
|
||||||
kDebugFont,
|
|
||||||
kDebugEntryHeight,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for (const auto& [name, pos] : kInterestingPlaces) {
|
||||||
|
if (ImGui::MenuItem((std::string("Jump to ") + name).c_str())) {
|
||||||
|
jumpCharacter(game, player, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::MenuItem("Unsolid Garage Doors")) {
|
||||||
|
static constexpr std::array<char const*, 33> garageDoorModels{
|
||||||
|
{"8ballsuburbandoor", "amcogaragedoor", "bankjobdoor",
|
||||||
|
"bombdoor", "crushercrush", "crushertop",
|
||||||
|
"door2_garage", "door3_garage", "door4_garage",
|
||||||
|
"door_bombshop", "door_col_compnd_01", "door_col_compnd_02",
|
||||||
|
"door_col_compnd_03", "door_col_compnd_04", "door_col_compnd_05",
|
||||||
|
"door_jmsgrage", "door_sfehousegrge", "double_garage_dr",
|
||||||
|
"impex_door", "impexpsubgrgdoor", "ind_plyrwoor",
|
||||||
|
"ind_slidedoor", "jamesgrge_kb", "leveldoor2",
|
||||||
|
"oddjgaragdoor", "plysve_gragedoor", "SalvGarage",
|
||||||
|
"shedgaragedoor", "Sub_sprayshopdoor", "towergaragedoor1",
|
||||||
|
"towergaragedoor2", "towergaragedoor3", "vheistlocdoor"}};
|
||||||
|
|
||||||
|
auto gw = game->getWorld();
|
||||||
|
for (auto& [id, instancePtr] : gw->instancePool.objects) {
|
||||||
|
auto obj = static_cast<InstanceObject*>(instancePtr.get());
|
||||||
|
if (std::find(garageDoorModels.begin(), garageDoorModels.end(),
|
||||||
|
obj->getModelInfo<BaseModelInfo>()->name) !=
|
||||||
|
garageDoorModels.end()) {
|
||||||
|
obj->setSolid(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugState::drawVehicleMenu() {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -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 = {},
|
||||||
|
Loading…
Reference in New Issue
Block a user