mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-25 11:52:40 +01:00
commit
c7d77084c2
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "external/microprofile/microprofile"]
|
||||
path = external/microprofile/microprofile
|
||||
url = https://github.com/jonasmr/microprofile.git
|
||||
[submodule "imgui"]
|
||||
path = external/imgui/imgui
|
||||
url = https://github.com/ocornut/imgui.git
|
||||
|
2
external/CMakeLists.txt
vendored
2
external/CMakeLists.txt
vendored
@ -1,3 +1,5 @@
|
||||
if(ENABLE_PROFILING)
|
||||
add_subdirectory(microprofile)
|
||||
endif()
|
||||
|
||||
add_subdirectory(imgui)
|
||||
|
63
external/imgui/CMakeLists.txt
vendored
Normal file
63
external/imgui/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
add_library(imgui EXCLUDE_FROM_ALL
|
||||
rw_imconfig.h
|
||||
imgui/imgui.h
|
||||
imgui/imgui.cpp
|
||||
imgui/imgui_demo.cpp
|
||||
imgui/imgui_draw.cpp
|
||||
imgui/imgui_internal.h
|
||||
imgui/imgui_widgets.cpp
|
||||
imgui/imstb_rectpack.h
|
||||
imgui/imstb_textedit.h
|
||||
imgui/imstb_truetype.h
|
||||
)
|
||||
|
||||
target_include_directories(imgui SYSTEM
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_LIST_DIR}/imgui"
|
||||
)
|
||||
|
||||
target_compile_definitions(imgui
|
||||
PUBLIC
|
||||
IMGUI_USER_CONFIG="${CMAKE_CURRENT_SOURCE_DIR}/rw_imconfig.h"
|
||||
)
|
||||
|
||||
target_link_libraries(imgui
|
||||
PUBLIC
|
||||
openrw::checks
|
||||
)
|
||||
|
||||
add_library(imgui::core ALIAS imgui)
|
||||
|
||||
openrw_target_apply_options(
|
||||
TARGET imgui
|
||||
)
|
||||
|
||||
add_library(imgui_sdl_gl3 EXCLUDE_FROM_ALL
|
||||
imgui/examples/imgui_impl_opengl3.h
|
||||
imgui/examples/imgui_impl_opengl3.cpp
|
||||
imgui/examples/imgui_impl_sdl.h
|
||||
imgui/examples/imgui_impl_sdl.cpp
|
||||
)
|
||||
|
||||
target_include_directories(imgui_sdl_gl3 SYSTEM
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_LIST_DIR}/imgui/examples"
|
||||
)
|
||||
|
||||
target_link_libraries(imgui_sdl_gl3
|
||||
PUBLIC
|
||||
imgui::core
|
||||
SDL2::SDL2
|
||||
)
|
||||
|
||||
# FIXME: extract gl loader to target + add property to get header
|
||||
target_compile_definitions(imgui_sdl_gl3
|
||||
PRIVATE
|
||||
"IMGUI_IMPL_OPENGL_LOADER_CUSTOM=\"${OpenRW_SOURCE_DIR}/rwcore/gl/gl_core_3_3.h\""
|
||||
)
|
||||
|
||||
add_library(imgui::sdl_gl3 ALIAS imgui_sdl_gl3)
|
||||
|
||||
openrw_target_apply_options(
|
||||
TARGET imgui_sdl_gl3
|
||||
)
|
1
external/imgui/imgui
vendored
Submodule
1
external/imgui/imgui
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 801645d35092c8da0eeabe71d7c1997c47aa3648
|
9
external/imgui/rw_imconfig.h
vendored
Normal file
9
external/imgui/rw_imconfig.h
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef RW_IMCONFIG_H
|
||||
#define RW_IMCONFIG_H
|
||||
|
||||
// Disable imgui assertions when not in debug mode
|
||||
#ifndef RW_DEBUG
|
||||
#define IM_ASSERT(MSG) //FIXME(madebr): remove comment
|
||||
#endif
|
||||
|
||||
#endif // RW_IMCONFIG_H
|
@ -19,7 +19,7 @@ public:
|
||||
, rotation(rot) {
|
||||
}
|
||||
|
||||
glm::mat4 getView() {
|
||||
glm::mat4 getView() const {
|
||||
auto up = rotation * glm::vec3(0.f, 0.f, 1.f);
|
||||
return glm::lookAt(position,
|
||||
position + rotation * glm::vec3(1.f, 0.f, 0.f), up);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
glm::mat4 ViewFrustum::projection() {
|
||||
glm::mat4 ViewFrustum::projection() const {
|
||||
return glm::perspective(fov / aspectRatio, aspectRatio, near, far);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
: near(near), far(far), fov(fov), aspectRatio(aspect) {
|
||||
}
|
||||
|
||||
glm::mat4 projection();
|
||||
glm::mat4 projection() const;
|
||||
|
||||
void update(const glm::mat4& proj);
|
||||
|
||||
|
@ -15,6 +15,9 @@ add_library(librwgame STATIC
|
||||
GameWindow.hpp
|
||||
GameWindow.cpp
|
||||
|
||||
RWImGui.cpp
|
||||
RWImGui.hpp
|
||||
|
||||
HUDDrawer.hpp
|
||||
HUDDrawer.cpp
|
||||
MenuSystem.hpp
|
||||
@ -68,6 +71,16 @@ target_link_libraries(librwgame
|
||||
SDL2::SDL2
|
||||
)
|
||||
|
||||
target_compile_definitions(librwgame
|
||||
PUBLIC
|
||||
RW_IMGUI
|
||||
)
|
||||
|
||||
target_link_libraries(librwgame
|
||||
PUBLIC
|
||||
imgui::sdl_gl3
|
||||
)
|
||||
|
||||
add_executable(rwgame
|
||||
main.cpp
|
||||
)
|
||||
|
@ -20,7 +20,7 @@ GameBase::GameBase(Logger &inlog, const std::optional<RWArgConfigLayer> &args) :
|
||||
bool fullscreen = config.fullscreen();
|
||||
size_t w = config.width(), h = config.height();
|
||||
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
|
||||
throw std::runtime_error("Failed to initialize SDL2!");
|
||||
|
||||
window.create(kWindowTitle + " [" + kBuildStr + "]", w, h, fullscreen);
|
||||
|
@ -5,8 +5,9 @@
|
||||
#include <SDL_video.h>
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <SDL.h>
|
||||
|
||||
class GameWindow {
|
||||
SDL_Window* window = nullptr;
|
||||
@ -30,6 +31,10 @@ public:
|
||||
bool isOpen() const {
|
||||
return !!window;
|
||||
}
|
||||
|
||||
std::tuple<SDL_Window *, SDL_GLContext> getSDLContext() {
|
||||
return std::make_tuple(window, glcontext);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
#include "RWImGui.hpp"
|
||||
#include "GameInput.hpp"
|
||||
#include "State.hpp"
|
||||
#include "StateManager.hpp"
|
||||
@ -28,7 +29,6 @@
|
||||
#include <functional>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4305 5033)
|
||||
@ -54,7 +54,8 @@ constexpr float kMaxPhysicsSubSteps = 2;
|
||||
RWGame::RWGame(Logger& log, const std::optional<RWArgConfigLayer> &args)
|
||||
: GameBase(log, args)
|
||||
, data(&log, config.gamedataPath())
|
||||
, renderer(&log, &data) {
|
||||
, renderer(&log, &data)
|
||||
, imgui(*this) {
|
||||
RW_PROFILE_THREAD("Main");
|
||||
RW_TIMELINE_ENTER("Startup", MP_YELLOW);
|
||||
|
||||
@ -76,6 +77,8 @@ RWGame::RWGame(Logger& log, const std::optional<RWArgConfigLayer> &args)
|
||||
config.gamedataPath());
|
||||
}
|
||||
|
||||
imgui.init();
|
||||
|
||||
data.load();
|
||||
|
||||
for (const auto& [specialModel, fileName, name] : kSpecialModels) {
|
||||
@ -480,6 +483,9 @@ bool RWGame::updateInput() {
|
||||
RW_PROFILE_SCOPE(__func__);
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (imgui.processEvent(event)) {
|
||||
continue;
|
||||
}
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
return false;
|
||||
@ -628,10 +634,12 @@ void RWGame::tickObjects(float dt) const {
|
||||
|
||||
void RWGame::render(float alpha, float time) {
|
||||
RW_PROFILE_SCOPEC(__func__, MP_CORNFLOWERBLUE);
|
||||
RW_UNUSED(time);
|
||||
|
||||
lastDraws = getRenderer().getRenderer().getDrawCount();
|
||||
|
||||
getRenderer().getRenderer().swap();
|
||||
imgui.startFrame();
|
||||
|
||||
// Update the camera
|
||||
if (!stateManager.states.empty()) {
|
||||
@ -661,7 +669,7 @@ void RWGame::render(float alpha, float time) {
|
||||
|
||||
renderer.getRenderer().popDebugGroup();
|
||||
|
||||
renderDebugView(time, viewCam);
|
||||
renderDebugView();
|
||||
|
||||
if (!world->isPaused()) hudDrawer.drawOnScreenText(world.get(), renderer);
|
||||
|
||||
@ -669,98 +677,26 @@ void RWGame::render(float alpha, float time) {
|
||||
RW_PROFILE_SCOPE("state");
|
||||
stateManager.draw(renderer);
|
||||
}
|
||||
|
||||
imgui.endFrame(viewCam);
|
||||
}
|
||||
|
||||
void RWGame::renderDebugView(float time, ViewCamera &viewCam) {
|
||||
void RWGame::renderDebugView() {
|
||||
RW_PROFILE_SCOPE(__func__);
|
||||
switch (debugview_) {
|
||||
case DebugViewMode::General:
|
||||
renderDebugStats(time);
|
||||
break;
|
||||
case DebugViewMode::Physics:
|
||||
world->dynamicsWorld->debugDrawWorld();
|
||||
debug.flush(renderer);
|
||||
break;
|
||||
case DebugViewMode::Navigation:
|
||||
renderDebugPaths(time);
|
||||
break;
|
||||
case DebugViewMode::Objects:
|
||||
renderDebugObjects(time, viewCam);
|
||||
renderDebugPaths();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RWGame::renderDebugStats(float time) {
|
||||
// Turn time into milliseconds
|
||||
float time_ms = time * 1000.f;
|
||||
constexpr size_t average_every_frame = 15;
|
||||
static float times[average_every_frame];
|
||||
static size_t times_index = 0;
|
||||
static float time_average = 0;
|
||||
times[times_index++] = time_ms;
|
||||
if (times_index >= average_every_frame) {
|
||||
times_index = 0;
|
||||
time_average = 0;
|
||||
|
||||
for (size_t i = 0; i < average_every_frame; ++i) {
|
||||
time_average += times[i];
|
||||
}
|
||||
time_average /= average_every_frame;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "FPS: " << (1000.f / time_average) << " (" << time_average << "ms)\n"
|
||||
<< "Frame: " << time_ms << "ms\n"
|
||||
<< "Draws/Culls/Textures/Buffers: " << lastDraws << "/"
|
||||
<< renderer.getCulledCount() << "/"
|
||||
<< renderer.getRenderer().getTextureCount() << "/"
|
||||
<< renderer.getRenderer().getBufferCount() << "\n"
|
||||
<< "Timescale: " << world->state->basic.timeScale;
|
||||
|
||||
TextRenderer::TextInfo ti;
|
||||
ti.font = FONT_ARIAL;
|
||||
ti.text = GameStringUtil::fromString(ss.str(), FONT_ARIAL);
|
||||
ti.screenPosition = glm::vec2(10.f, 10.f);
|
||||
ti.size = 15.f;
|
||||
ti.baseColour = glm::u8vec3(255);
|
||||
renderer.text.renderText(ti);
|
||||
|
||||
/*while( engine->log.size() > 0 && engine->log.front().time + 10.f <
|
||||
engine->gameTime ) {
|
||||
engine->log.pop_front();
|
||||
}
|
||||
|
||||
ti.screenPosition = glm::vec2( 10.f, 500.f );
|
||||
ti.size = 15.f;
|
||||
for(auto it = engine->log.begin(); it != engine->log.end(); ++it) {
|
||||
ti.text = it->message;
|
||||
switch(it->type) {
|
||||
case GameWorld::LogEntry::Error:
|
||||
ti.baseColour = glm::vec3(1.f, 0.f, 0.f);
|
||||
break;
|
||||
case GameWorld::LogEntry::Warning:
|
||||
ti.baseColour = glm::vec3(1.f, 1.f, 0.f);
|
||||
break;
|
||||
default:
|
||||
ti.baseColour = glm::vec3(1.f, 1.f, 1.f);
|
||||
break;
|
||||
}
|
||||
|
||||
// Interpolate the color
|
||||
// c.a = (engine->gameTime - it->time > 5.f) ? 255 - (((engine->gameTime
|
||||
- it->time) - 5.f)/5.f) * 255 : 255;
|
||||
// text.setColor(c);
|
||||
|
||||
engine->renderer.text.renderText(ti);
|
||||
ti.screenPosition.y -= ti.size;
|
||||
}*/
|
||||
}
|
||||
|
||||
void RWGame::renderDebugPaths(float time) {
|
||||
RW_UNUSED(time);
|
||||
|
||||
void RWGame::renderDebugPaths() {
|
||||
btVector3 roadColour(1.f, 0.f, 0.f);
|
||||
btVector3 pedColour(0.f, 0.f, 1.f);
|
||||
|
||||
@ -864,74 +800,6 @@ void RWGame::renderDebugPaths(float time) {
|
||||
debug.flush(renderer);
|
||||
}
|
||||
|
||||
void RWGame::renderDebugObjects(float time, ViewCamera& camera) {
|
||||
RW_UNUSED(time);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Models: " << data.modelinfo.size() << "\n"
|
||||
<< "Dynamic Objects:\n"
|
||||
<< " Vehicles: " << world->vehiclePool.objects.size() << "\n"
|
||||
<< " Peds: " << world->pedestrianPool.objects.size() << "\n";
|
||||
|
||||
TextRenderer::TextInfo ti;
|
||||
ti.font = FONT_ARIAL;
|
||||
ti.text = GameStringUtil::fromString(ss.str(), FONT_ARIAL);
|
||||
ti.screenPosition = glm::vec2(10.f, 10.f);
|
||||
ti.size = 15.f;
|
||||
ti.baseColour = glm::u8vec3(255);
|
||||
renderer.text.renderText(ti);
|
||||
|
||||
// Render worldspace overlay for nearby objects
|
||||
constexpr float kNearbyDistance = 25.f;
|
||||
const auto& view = camera.position;
|
||||
const auto& model = camera.getView();
|
||||
const auto& proj = camera.frustum.projection();
|
||||
const auto& size = getWindow().getSize();
|
||||
glm::vec4 viewport(0.f, 0.f, size.x, size.y);
|
||||
auto isnearby = [&](GameObject* o) {
|
||||
return glm::distance2(o->getPosition(), view) <
|
||||
kNearbyDistance * kNearbyDistance;
|
||||
};
|
||||
auto showdata = [&](GameObject* o, std::stringstream& ss) {
|
||||
auto screen = glm::project(o->getPosition(), model, proj, viewport);
|
||||
if (screen.z >= 1.f) {
|
||||
return;
|
||||
}
|
||||
ti.text = GameStringUtil::fromString(ss.str(), FONT_ARIAL);
|
||||
screen.y = viewport.w - screen.y;
|
||||
ti.screenPosition = glm::vec2(screen);
|
||||
ti.size = 10.f;
|
||||
renderer.text.renderText(ti);
|
||||
};
|
||||
|
||||
for (auto& p : world->vehiclePool.objects) {
|
||||
if (!isnearby(p.second.get())) continue;
|
||||
auto v = static_cast<VehicleObject*>(p.second.get());
|
||||
|
||||
std::stringstream ss;
|
||||
ss << v->getVehicle()->vehiclename_ << "\n"
|
||||
<< (v->isFlipped() ? "Flipped" : "Upright") << "\n"
|
||||
<< (v->isStopped() ? "Stopped" : "Moving") << "\n"
|
||||
<< v->getVelocity() << "m/s\n";
|
||||
|
||||
showdata(v, ss);
|
||||
}
|
||||
for (auto& p : world->pedestrianPool.objects) {
|
||||
if (!isnearby(p.second.get())) continue;
|
||||
auto c = static_cast<CharacterObject*>(p.second.get());
|
||||
const auto& state = c->getCurrentState();
|
||||
auto act = c->controller->getCurrentActivity();
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Health: " << state.health << " (" << state.armour << ")\n"
|
||||
<< (c->isAlive() ? "Alive" : "Dead") << "\n"
|
||||
<< "Activity: " << (act ? act->name() : "Idle") << "\n";
|
||||
|
||||
showdata(c, ss);
|
||||
}
|
||||
}
|
||||
|
||||
void RWGame::globalKeyEvent(const SDL_Event& event) {
|
||||
const auto toggle_debug = [&](DebugViewMode m) {
|
||||
debugview_ = debugview_ == m ? DebugViewMode::Disabled : m;
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "GameBase.hpp"
|
||||
#include "HUDDrawer.hpp"
|
||||
#include "RWConfig.hpp"
|
||||
#include "RWImGui.hpp"
|
||||
#include "StateManager.hpp"
|
||||
#include "game.hpp"
|
||||
|
||||
@ -20,8 +22,19 @@
|
||||
#include <chrono>
|
||||
|
||||
class RWGame final : public GameBase {
|
||||
public:
|
||||
enum class DebugViewMode {
|
||||
Disabled,
|
||||
General,
|
||||
Physics,
|
||||
Navigation,
|
||||
Objects
|
||||
};
|
||||
|
||||
private:
|
||||
GameData data;
|
||||
GameRenderer renderer;
|
||||
RWImGui imgui;
|
||||
DebugDraw debug;
|
||||
GameState state;
|
||||
HUDDrawer hudDrawer{};
|
||||
@ -37,14 +50,6 @@ class RWGame final : public GameBase {
|
||||
bool inFocus = true;
|
||||
ViewCamera currentCam;
|
||||
|
||||
enum class DebugViewMode {
|
||||
Disabled,
|
||||
General,
|
||||
Physics,
|
||||
Navigation,
|
||||
Objects
|
||||
};
|
||||
|
||||
DebugViewMode debugview_ = DebugViewMode::Disabled;
|
||||
int lastDraws{0}; /// Number of draws issued for the last frame.
|
||||
|
||||
@ -89,6 +94,10 @@ public:
|
||||
return hudDrawer;
|
||||
}
|
||||
|
||||
DebugViewMode getDebugViewMode() const {
|
||||
return debugview_;
|
||||
}
|
||||
|
||||
bool hitWorldRay(glm::vec3& hit, glm::vec3& normal,
|
||||
GameObject** object = nullptr);
|
||||
|
||||
@ -109,9 +118,7 @@ private:
|
||||
void tick(float dt);
|
||||
void render(float alpha, float dt);
|
||||
|
||||
void renderDebugStats(float time);
|
||||
void renderDebugPaths(float time);
|
||||
void renderDebugObjects(float time, ViewCamera& camera);
|
||||
void renderDebugPaths();
|
||||
|
||||
void handleCheatInput(char symbol);
|
||||
|
||||
@ -121,7 +128,7 @@ private:
|
||||
|
||||
float tickWorld(const float deltaTime, float accumulatedTime);
|
||||
|
||||
void renderDebugView(float time, ViewCamera &viewCam);
|
||||
void renderDebugView();
|
||||
|
||||
void tickObjects(float dt) const;
|
||||
};
|
||||
|
204
rwgame/RWImGui.cpp
Normal file
204
rwgame/RWImGui.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
#include "RWImGui.hpp"
|
||||
|
||||
#include <ai/CharacterController.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
|
||||
#include "RWGame.hpp"
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_impl_sdl.h>
|
||||
#include <imgui_impl_opengl3.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <gl/gl_core_3_3.h>
|
||||
#include <glm/gtx/norm.hpp>
|
||||
|
||||
namespace {
|
||||
void WindowDebugStats(RWGame& game) {
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
auto time_ms = 1000.0f / io.Framerate;
|
||||
constexpr size_t average_every_frame = 240;
|
||||
static float times[average_every_frame];
|
||||
static size_t times_index = 0;
|
||||
static double time_average = 0, time_min = 0, time_max = 0;
|
||||
times[times_index++] = time_ms;
|
||||
if (times_index >= average_every_frame) {
|
||||
times_index = 0;
|
||||
time_average = 0;
|
||||
time_min = std::numeric_limits<double>::max();
|
||||
time_max = std::numeric_limits<double>::lowest();
|
||||
|
||||
for (double time : times) {
|
||||
time_average += time;
|
||||
time_min = std::min(time, time_min);
|
||||
time_max = std::max(time, time_max);
|
||||
}
|
||||
time_average /= average_every_frame;
|
||||
}
|
||||
|
||||
const auto& world = game.getWorld();
|
||||
auto& renderer = game.getRenderer();
|
||||
|
||||
ImGui::SetNextWindowPos({20.f, 20.f});
|
||||
ImGui::Begin("Engine Information", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoInputs);
|
||||
ImGui::Text("%.3f ms/frame (%.1f FPS)\n%.3f / %.3f / %.3f ms",
|
||||
static_cast<double>(1000.0f / io.Framerate),
|
||||
static_cast<double>(io.Framerate), time_average, time_min,
|
||||
time_max);
|
||||
ImGui::Text("Timescale %.2f",
|
||||
static_cast<double>(world->state->basic.timeScale));
|
||||
ImGui::Text("%i Drawn %lu Culled", renderer.getRenderer().getDrawCount(),
|
||||
renderer.getCulledCount());
|
||||
ImGui::Text("%i Textures %i Buffers",
|
||||
renderer.getRenderer().getTextureCount(),
|
||||
renderer.getRenderer().getBufferCount());
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void WindowDebugObjects(RWGame& game, const ViewCamera& camera) {
|
||||
auto& data = game.getGameData();
|
||||
auto world = game.getWorld();
|
||||
|
||||
ImGui::SetNextWindowPos({20.f, 20.f});
|
||||
ImGui::Begin("Object Information", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoInputs);
|
||||
ImGui::Text("%lu Models", data.modelinfo.size());
|
||||
ImGui::Text("Dynamic Objects\n %lu Vehicles\n %lu Peds",
|
||||
world->vehiclePool.objects.size(),
|
||||
world->pedestrianPool.objects.size());
|
||||
ImGui::End();
|
||||
|
||||
// Render worldspace overlay for nearby objects
|
||||
constexpr float kNearbyDistance = 25.f;
|
||||
const auto& view = camera.position;
|
||||
const auto& model = camera.getView();
|
||||
const auto& proj = camera.frustum.projection();
|
||||
const auto& size = game.getWindow().getSize();
|
||||
glm::vec4 viewport(0.f, 0.f, size.x, size.y);
|
||||
auto isnearby = [&](GameObject* o) {
|
||||
return glm::distance2(o->getPosition(), view) <
|
||||
kNearbyDistance * kNearbyDistance;
|
||||
};
|
||||
auto showdata = [&](GameObject* o, std::stringstream& ss) {
|
||||
auto screen = glm::project(o->getPosition(), model, proj, viewport);
|
||||
if (screen.z >= 1.f) {
|
||||
return;
|
||||
}
|
||||
ImGui::SetNextWindowPos({screen.x, viewport.w - screen.y}, 0,
|
||||
{0.5f, 0.5f});
|
||||
ImGui::Begin(
|
||||
std::to_string(reinterpret_cast<uintptr_t>(o)).c_str(), nullptr,
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoInputs);
|
||||
ImGui::Text("%s", ss.str().c_str());
|
||||
ImGui::End();
|
||||
};
|
||||
|
||||
for (auto& p : world->vehiclePool.objects) {
|
||||
if (!isnearby(p.second.get())) continue;
|
||||
auto v = static_cast<VehicleObject*>(p.second.get());
|
||||
|
||||
std::stringstream ss;
|
||||
ss << v->getVehicle()->vehiclename_ << "\n"
|
||||
<< (v->isFlipped() ? "Flipped" : "Upright") << "\n"
|
||||
<< (v->isStopped() ? "Stopped" : "Moving") << "\n"
|
||||
<< v->getVelocity() << "m/s\n";
|
||||
|
||||
showdata(v, ss);
|
||||
}
|
||||
for (auto& p : world->pedestrianPool.objects) {
|
||||
if (!isnearby(p.second.get())) continue;
|
||||
auto c = static_cast<CharacterObject*>(p.second.get());
|
||||
const auto& state = c->getCurrentState();
|
||||
auto act = c->controller->getCurrentActivity();
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Health: " << state.health << " (" << state.armour << ")\n"
|
||||
<< (c->isAlive() ? "Alive" : "Dead") << "\n"
|
||||
<< "Activity: " << (act ? act->name() : "Idle") << "\n";
|
||||
|
||||
showdata(c, ss);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
RWImGui::RWImGui(RWGame &game)
|
||||
: _game(game) {
|
||||
}
|
||||
|
||||
RWImGui::~RWImGui() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void RWImGui::init() {
|
||||
IMGUI_CHECKVERSION();
|
||||
_context = ImGui::CreateContext();
|
||||
|
||||
auto [window, context] = _game.getWindow().getSDLContext();
|
||||
|
||||
ImGui_ImplSDL2_InitForOpenGL(window, context);
|
||||
ImGui_ImplOpenGL3_Init("#version 150");
|
||||
}
|
||||
|
||||
void RWImGui::destroy() {
|
||||
if (!_context) {
|
||||
return;
|
||||
}
|
||||
ImGui::SetCurrentContext(_context);
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
_context = nullptr;
|
||||
}
|
||||
|
||||
bool RWImGui::processEvent(SDL_Event& event) {
|
||||
if (!_context) {
|
||||
return false;
|
||||
}
|
||||
ImGui::SetCurrentContext(_context);
|
||||
ImGui_ImplSDL2_ProcessEvent(&event);
|
||||
auto& io = ImGui::GetIO();
|
||||
return io.WantCaptureMouse || io.WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
void RWImGui::startFrame() {
|
||||
if (!_context) {
|
||||
return;
|
||||
}
|
||||
ImGui::SetCurrentContext(_context);
|
||||
|
||||
auto [window, sdl_glcontext] = _game.getWindow().getSDLContext();
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame(window);
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void RWImGui::endFrame(const ViewCamera& camera) {
|
||||
switch (_game.getDebugViewMode()) {
|
||||
case RWGame::DebugViewMode::General:
|
||||
WindowDebugStats(_game);
|
||||
break;
|
||||
case RWGame::DebugViewMode::Objects:
|
||||
WindowDebugObjects(_game, camera);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
static bool show_demo_window = false;
|
||||
if (show_demo_window) {
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
23
rwgame/RWImGui.hpp
Normal file
23
rwgame/RWImGui.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef RWGAME_RWIMGUI_HPP
|
||||
#define RWGAME_RWIMGUI_HPP
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
class RWGame;
|
||||
struct ImGuiContext;
|
||||
class ViewCamera;
|
||||
|
||||
class RWImGui {
|
||||
RWGame &_game;
|
||||
ImGuiContext *_context = nullptr;
|
||||
public:
|
||||
RWImGui(RWGame &game);
|
||||
~RWImGui();
|
||||
void init();
|
||||
void destroy();
|
||||
bool processEvent(SDL_Event &event);
|
||||
void startFrame();
|
||||
void endFrame(const ViewCamera &);
|
||||
};
|
||||
|
||||
#endif // RWGAME_RWIMGUI_HPP
|
@ -17,10 +17,7 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
constexpr float kDebugEntryHeight = 14.f;
|
||||
constexpr float kDebugEntryHeightMissions = 12.f;
|
||||
constexpr int kDebugFont = 2;
|
||||
const glm::vec2 kDebugMenuOffset = glm::vec2(10.f, 50.f);
|
||||
#include <imgui.h>
|
||||
|
||||
static void jumpCharacter(RWGame* game, CharacterObject* player,
|
||||
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;
|
||||
if (game->getWorld()->getPlayer()) {
|
||||
player = game->getWorld()->getPlayer()->getCharacter();
|
||||
}
|
||||
|
||||
Menu menu{
|
||||
{{"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};
|
||||
ImGui::Begin("Debug Tools");
|
||||
|
||||
if (player && ImGui::BeginMenu("Game")) {
|
||||
if (ImGui::MenuItem("Set Super Jump")) {
|
||||
player->setJumpSpeed(20.f);
|
||||
}
|
||||
if (ImGui::MenuItem("Set Normal Jump")) {
|
||||
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
|
||||
auto cv = player->getCurrentVehicle();
|
||||
if (cv) {
|
||||
menu.lambda("Flip vehicle", [=] {
|
||||
cv->setRotation(cv->getRotation() *
|
||||
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)));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
if (game->getWorld()->getPlayer()) {
|
||||
player = game->getWorld()->getPlayer()->getCharacter();
|
||||
}
|
||||
|
||||
Menu menu{
|
||||
{{"Back", [=] { setNextMenu(createDebugMenu()); }},
|
||||
{"Jump to Docks",
|
||||
[=] {
|
||||
jumpCharacter(game, player, glm::vec3(1390.f, -837.f, 100.f));
|
||||
}},
|
||||
{"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",
|
||||
[=] {
|
||||
if (ImGui::MenuItem("Jump to Debug Camera")) {
|
||||
jumpCharacter(
|
||||
game, player,
|
||||
_debugCam.position + _debugCam.rotation * glm::vec3(3.f, 0.f, 0.f),
|
||||
false);
|
||||
}
|
||||
|
||||
const std::vector<std::tuple<const char*, glm::vec3>> kInterestingPlaces{
|
||||
{"Docks", {1390.f, -837.f, 100.f}},
|
||||
{"Garage", {270.f, -605.f, 40.f}},
|
||||
{"Airport", {-950.f, -980.f, 12.f}},
|
||||
{"Hideout", {875.0, -309.0, 100.0}},
|
||||
{"Luigi's", {902.75, -425.56, 100.0}},
|
||||
{"Hospital", {1123.77, -569.15, 100.0}},
|
||||
};
|
||||
|
||||
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"}};
|
||||
{"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(),
|
||||
if (std::find(garageDoorModels.begin(), garageDoorModels.end(),
|
||||
obj->getModelInfo<BaseModelInfo>()->name) !=
|
||||
garageDoorModels.end()) {
|
||||
obj->setSolid(false);
|
||||
}
|
||||
}
|
||||
}}},
|
||||
kDebugMenuOffset,
|
||||
kDebugFont,
|
||||
kDebugEntryHeight};
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
Menu DebugState::createVehicleMenu() {
|
||||
Menu menu{
|
||||
{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
|
||||
kDebugMenuOffset,
|
||||
kDebugFont,
|
||||
kDebugEntryHeight,
|
||||
};
|
||||
|
||||
void DebugState::drawVehicleMenu() {
|
||||
static constexpr std::array<std::tuple<char const*, unsigned int>, 19>
|
||||
kVehicleTypes{{{"Landstalker", 90},
|
||||
{"Taxi", 110},
|
||||
@ -180,18 +184,13 @@ Menu DebugState::createVehicleMenu() {
|
||||
{"Infernus", 101}}};
|
||||
|
||||
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() {
|
||||
Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
|
||||
kDebugMenuOffset,
|
||||
kDebugFont,
|
||||
kDebugEntryHeight};
|
||||
|
||||
void DebugState::drawAIMenu() {
|
||||
static constexpr std::array<std::tuple<char const*, unsigned int>, 6>
|
||||
kPedTypes{{
|
||||
{"Triad", 12},
|
||||
@ -203,10 +202,12 @@ Menu DebugState::createAIMenu() {
|
||||
}};
|
||||
|
||||
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] :
|
||||
game->getWorld()->pedestrianPool.objects) {
|
||||
if (pedestrianPtr->getLifetime() == GameObject::PlayerLifetime) {
|
||||
@ -220,47 +221,31 @@ Menu DebugState::createAIMenu() {
|
||||
0.f
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
Menu DebugState::createWeaponMenu() {
|
||||
Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
|
||||
kDebugMenuOffset,
|
||||
kDebugFont,
|
||||
kDebugEntryHeight};
|
||||
|
||||
void DebugState::drawWeaponMenu() {
|
||||
for (int i = 1; i < kMaxInventorySlots; ++i) {
|
||||
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() {
|
||||
Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
|
||||
kDebugMenuOffset,
|
||||
kDebugFont,
|
||||
kDebugEntryHeight};
|
||||
|
||||
static constexpr std::array<char const*, 4> w{{"Sunny", "Cloudy", "Rainy", "Foggy"}};
|
||||
void DebugState::drawWeatherMenu() {
|
||||
static constexpr std::array<char const*, 4> w{
|
||||
{"Sunny", "Cloudy", "Rainy", "Foggy"}};
|
||||
|
||||
for (std::size_t i = 0; i < w.size(); ++i) {
|
||||
menu.lambda(w[i],
|
||||
[=] { game->getWorld()->state->basic.nextWeather = static_cast<std::uint16_t>(i); });
|
||||
if (ImGui::MenuItem(w[i])) {
|
||||
game->getWorld()->state->basic.nextWeather =
|
||||
static_cast<std::uint16_t>(i);
|
||||
}
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
Menu DebugState::createMissionsMenu() {
|
||||
Menu menu{{{"Back", [=] { setNextMenu(createDebugMenu()); }}},
|
||||
kDebugMenuOffset,
|
||||
kDebugFont,
|
||||
kDebugEntryHeightMissions};
|
||||
|
||||
void DebugState::drawMissionsMenu() {
|
||||
static constexpr std::array<char const*, 80> w{{
|
||||
"Intro Movie",
|
||||
"Hospital Info Scene",
|
||||
@ -345,7 +330,7 @@ Menu DebugState::createMissionsMenu() {
|
||||
}};
|
||||
|
||||
for (std::size_t i = 0; i < w.size(); ++i) {
|
||||
menu.lambda(w[i], [=] {
|
||||
if (ImGui::MenuItem(w[i])) {
|
||||
ScriptMachine* vm = game->getScriptVM();
|
||||
|
||||
if (vm) {
|
||||
@ -367,16 +352,12 @@ Menu DebugState::createMissionsMenu() {
|
||||
|
||||
vm->startThread(offsets[i], true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
DebugState::DebugState(RWGame* game, const glm::vec3& vp, const glm::quat& vd)
|
||||
: State(game), _invertedY(game->getConfig().invertY()) {
|
||||
this->setNextMenu(createDebugMenu());
|
||||
|
||||
_debugCam.position = vp;
|
||||
_debugCam.rotation = vd;
|
||||
}
|
||||
@ -400,19 +381,18 @@ void DebugState::tick(float dt) {
|
||||
}
|
||||
|
||||
void DebugState::draw(GameRenderer& r) {
|
||||
// Draw useful information like camera position.
|
||||
std::stringstream ss;
|
||||
ss << "Camera Position: " << glm::to_string(_debugCam.position) << "\n";
|
||||
auto zone = getWorld()->data->findZoneAt(_debugCam.position);
|
||||
ss << (zone ? zone->name : "No Zone") << "\n";
|
||||
ImGui::SetNextWindowPos({20.f, 20.f});
|
||||
ImGui::Begin("Debug Info", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoInputs);
|
||||
|
||||
TextRenderer::TextInfo ti;
|
||||
ti.font = FONT_ARIAL;
|
||||
ti.text = GameStringUtil::fromString(ss.str(), ti.font);
|
||||
ti.screenPosition = glm::vec2(10.f, 10.f);
|
||||
ti.size = 15.f;
|
||||
ti.baseColour = glm::u8vec3(255);
|
||||
r.text.renderText(ti);
|
||||
ImGui::Text("Camera: %s", glm::to_string(_debugCam.position).c_str());
|
||||
auto zone = getWorld()->data->findZoneAt(_debugCam.position);
|
||||
ImGui::Text("Zone: %s", zone ? zone->name.c_str() : "No Zone");
|
||||
ImGui::End();
|
||||
|
||||
drawDebugMenu();
|
||||
|
||||
State::draw(r);
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ class DebugState final : public State {
|
||||
bool _sonicMode = false;
|
||||
bool _invertedY;
|
||||
|
||||
Menu createDebugMenu();
|
||||
Menu createMapMenu();
|
||||
Menu createVehicleMenu();
|
||||
Menu createAIMenu();
|
||||
Menu createWeaponMenu();
|
||||
Menu createWeatherMenu();
|
||||
Menu createMissionsMenu();
|
||||
void drawDebugMenu();
|
||||
void drawMapMenu();
|
||||
void drawVehicleMenu();
|
||||
void drawAIMenu();
|
||||
void drawWeaponMenu();
|
||||
void drawWeatherMenu();
|
||||
void drawMissionsMenu();
|
||||
|
||||
public:
|
||||
DebugState(RWGame* game, const glm::vec3& vp = {},
|
||||
|
@ -28,15 +28,13 @@ void LoadingState::handleEvent(const SDL_Event& e) {
|
||||
}
|
||||
|
||||
void LoadingState::draw(GameRenderer& r) {
|
||||
static auto kLoadingString =
|
||||
GameStringUtil::fromString("Loading...", FONT_ARIAL);
|
||||
// Display some manner of loading screen.
|
||||
TextRenderer::TextInfo ti;
|
||||
ti.text = kLoadingString;
|
||||
ti.text = GameStringUtil::fromString("Loading...", FONT_ARIAL);
|
||||
auto size = r.getRenderer().getViewport();
|
||||
ti.size = 25.f;
|
||||
ti.screenPosition = glm::vec2(50.f, size.y - ti.size - 50.f);
|
||||
ti.font = FONT_PRICEDOWN;
|
||||
ti.font = FONT_ARIAL;
|
||||
ti.baseColour = glm::u8vec3(255);
|
||||
r.text.renderText(ti);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ set(TESTS
|
||||
Text
|
||||
TrafficDirector
|
||||
Vehicle
|
||||
ViewCamera
|
||||
VisualFX
|
||||
Weapon
|
||||
World
|
||||
|
@ -3,6 +3,6 @@
|
||||
#include "test_Globals.hpp"
|
||||
|
||||
std::ostream& operator<<(std::ostream& stream, const glm::vec3& v) {
|
||||
stream << v.x << " " << v.y << " " << v.z;
|
||||
stream << glm::to_string(v);
|
||||
return stream;
|
||||
}
|
||||
|
@ -45,6 +45,12 @@ struct print_log_value<glm::vec3> {
|
||||
s << glm::to_string(v);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct print_log_value<glm::vec4> {
|
||||
void operator()(std::ostream& s, glm::vec4 const& v) {
|
||||
s << glm::to_string(v);
|
||||
}
|
||||
};
|
||||
BOOST_NS_MAGIC_CLOSING
|
||||
}
|
||||
}
|
||||
|
26
tests/test_ViewCamera.cpp
Normal file
26
tests/test_ViewCamera.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "test_Globals.hpp"
|
||||
#include <render/ViewCamera.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
struct CameraFixture {
|
||||
ViewCamera camera_ {
|
||||
{1.f, 2.f, 3.f}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(ViewCameraTests)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_creation, CameraFixture) {
|
||||
BOOST_CHECK_EQUAL(camera_.position, glm::vec3(1.f, 2.f, 3.f));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_view_matrix, CameraFixture) {
|
||||
const auto& view = camera_.getView();
|
||||
BOOST_CHECK_EQUAL(view[3], glm::vec4(2.f, -3.f, 1.f, 1.f));
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue
Block a user