Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move rwviewer into rwgame with imgui #719

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@ add_subdirectory(rwcore)
add_subdirectory(rwengine)
add_subdirectory(rwgame)

if(BUILD_VIEWER)
add_subdirectory(rwviewer)
endif()
if(BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
Expand Down
10 changes: 1 addition & 9 deletions cmake/ctest/build.ctest
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ set(_ARGS_BOOL
BUILD_TYPE
CHECK_IWYU
BUILD_TOOLS
BUILD_VIEWER

RUN_TESTS
SEPARATE_TEST_SUITES
Expand Down Expand Up @@ -121,17 +120,11 @@ if(USE_CONAN)
set(CONAN_CONFIGURATION "Release")
endif()

if(BUILD_VIEWER)
set(_BUILD_VIEWER True)
else()
set(_BUILD_VIEWER False)
endif()

execute_process(
COMMAND
"${CONAN_BIN}" install "${CTEST_SOURCE_DIRECTORY}"
-s arch=${CONAN_ARCH} -s build_type=${CONAN_CONFIGURATION}
-o viewer=${_BUILD_VIEWER} --build missing
--build missing
WORKING_DIRECTORY "${CTEST_BINARY_DIRECTORY}"
RESULT_VARIABLE RES
)
Expand Down Expand Up @@ -161,7 +154,6 @@ set(CTEST_CONFIGURATION_TYPE "${BUILD_TYPE}")

set(_CONFIGURE_OPTIONS
"-DBUILD_TOOLS=${BUILD_TOOLS}"
"-DBUILD_VIEWER=${BUILD_VIEWER}"
"-DBUILD_TESTS=TRUE"
"-DTEST_COVERAGE=${TEST_COVERAGE}"
"-DSEPARATE_TEST_SUITES=${SEPARATE_TEST_SUITES}"
Expand Down
1 change: 0 additions & 1 deletion cmake/ctest/configure_darwin.ctest
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ endif()
set(CONFIGURE_EXTRA_OPTIONS ";")
set(BUILD_EXTRA_FLAGS "")
set(BUILD_TOOLS TRUE)
set(BUILD_VIEWER TRUE)
set(CHECK_IWYU FALSE)
set(ENABLE_SANITIZERS "")

Expand Down
1 change: 0 additions & 1 deletion cmake/ctest/configure_linux.ctest
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ set(CONFIGURE_EXTRA_OPTIONS ";")
set(BUILD_EXTRA_FLAGS "")

set(BUILD_TOOLS TRUE)
set(BUILD_VIEWER TRUE)
set(CHECK_IWYU FALSE)
set(ENABLE_SANITIZERS "address")

Expand Down
1 change: 0 additions & 1 deletion cmake/ctest/configure_windows.ctest
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,5 @@ set(BUILD_TYPE "${CONFIGURATION}")
set(CONAN_ARCH "x86_64")

set(BUILD_TOOLS TRUE)
set(BUILD_VIEWER TRUE)
set(CHECK_IWYU FALSE) #FIXME: ENABLE
set(ENABLE_SANITIZERS "")
1 change: 0 additions & 1 deletion cmake_options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ option(RW_VERBOSE_DEBUG_MESSAGES "Print verbose debugging messages" ON)

option(BUILD_TOOLS "Build tools")
option(BUILD_TESTS "Build test suite")
option(BUILD_VIEWER "Build GUI data viewer")

option(ENABLE_SCRIPT_DEBUG "Enable verbose script execution")
option(ENABLE_PROFILING "Enable detailed profiling metrics")
Expand Down
19 changes: 2 additions & 17 deletions conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ class OpenrwConan(ConanFile):
description = "OpenRW 'Open ReWrite' is an un-official open source recreation of the classic Grand Theft Auto III game executable"
settings = 'os', 'compiler', 'build_type', 'arch'
options = {
'viewer': [True, False],
'tools': [True, False],
'profiling': [True, False],
}

default_options = {
'viewer': True,
'tools': True,
'profiling': True,
'bullet3:shared': False,
Expand All @@ -24,7 +22,7 @@ class OpenrwConan(ConanFile):

generators = 'cmake',
exports_sources = 'CMakeLists.txt', 'cmake_configure.cmake', 'cmake_options.cmake', 'CMakeCPack.cmake', 'COPYING', \
'cmake/modules/*', 'benchmarks', 'rwcore/*', 'rwengine/*', 'rwgame/*', 'rwviewer/*', \
'cmake/modules/*', 'benchmarks', 'rwcore/*', 'rwengine/*', 'rwgame/*', \
'rwtools/*', 'tests/*', 'external/*'

_rw_dependencies = {
Expand All @@ -37,24 +35,15 @@ class OpenrwConan(ConanFile):
'boost/1.68.0@conan/stable',
'bzip2/1.0.8@conan/stable',
),
'viewer': (
'qt/5.12.0@bincrafters/stable',
),
'tools': (
'freetype/2.9.0@bincrafters/stable',
'qt/5.12.0@bincrafters/stable',
),
}

def configure(self):
if self.options.viewer:
self.options['qt'].opengl = 'desktop'

def requirements(self):
for dep in self._rw_dependencies['game']:
self.requires(dep)
if self.options.viewer:
for dep in self._rw_dependencies['viewer']:
self.requires(dep)
if self.options.tools:
for dep in self._rw_dependencies['tools']:
self.requires(dep)
Expand All @@ -65,7 +54,6 @@ def _configure_cmake(self):
'BUILD_SHARED_LIBS': False,
'CMAKE_BUILD_TYPE': self.settings.build_type,
'BUILD_TESTS': True,
'BUILD_VIEWER': self.options.viewer,
'BUILD_TOOLS': self.options.tools,
'ENABLE_PROFILING': self.options.profiling,
'USE_CONAN': True,
Expand All @@ -80,9 +68,6 @@ def build(self):
cmake.build()

def package(self):
if self.options.viewer:
# FIXME: https://github.com/osechet/conan-qt/issues/6 and https://github.com/conan-io/conan/issues/2619
self.copy('qt.conf', dst='bin', src='rwviewer')
cmake = self._configure_cmake()
cmake.install()

Expand Down
5 changes: 5 additions & 0 deletions rwgame/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ add_library(librwgame STATIC
states/DebugState.cpp
states/BenchmarkState.hpp
states/BenchmarkState.cpp

viewer/RWViewer.hpp
viewer/RWViewer.cpp
viewer/RWViewerWindows.hpp
viewer/RWViewerWindows.cpp
)

openrw_target_apply_options(
Expand Down
2 changes: 2 additions & 0 deletions rwgame/RWConfig.inc
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ RWARG_OPT( std::string, loadGamePath,
RWCONFIGARG(std::string, gameLanguage, "american", "game.language", GAME, "language", "LANGUAGE", "Language")

RWARG( bool, help, GENERAL, "help", nullptr, "Show this help message")

RWARG( bool, viewer, GENERAL, "viewer", nullptr, "Data Viewer")
138 changes: 129 additions & 9 deletions rwgame/RWGame.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "RWGame.hpp"

#include <glm/gtx/norm.hpp>

#include "RWImGui.hpp"
#include "GameInput.hpp"
#include "State.hpp"
Expand All @@ -12,20 +10,21 @@
#include "states/MenuState.hpp"

#include <core/Profiler.hpp>

#include <engine/Payphone.hpp>
#include <engine/SaveGame.hpp>
#include <objects/GameObject.hpp>

#include <script/SCMFile.hpp>

#include <ai/AIGraphNode.hpp>
#include <ai/PlayerController.hpp>
#include <core/Logger.hpp>
#include <objects/CharacterObject.hpp>
#include <objects/VehicleObject.hpp>

#include <imgui.h>

#include <glm/gtx/norm.hpp>

#include <boost/algorithm/string/predicate.hpp>

#include <functional>
#include <iomanip>
#include <iostream>
Expand All @@ -47,6 +46,121 @@ static constexpr std::array<
{GameRenderer::Arrow, "arrow.dff", ""}}};

constexpr float kMaxPhysicsSubSteps = 2;

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 float 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<float>::max();
time_max = std::numeric_limits<float>::lowest();

for (auto 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),
static_cast<double>(time_average),
static_cast<double>(time_min),
static_cast<double>(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& [id, obj] : world->vehiclePool.objects) {
if (!isnearby(obj.get())) continue;
auto v = static_cast<VehicleObject*>(obj.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& [id, obj] : world->pedestrianPool.objects) {
if (!isnearby(obj.get())) continue;
auto c = static_cast<CharacterObject*>(obj.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

#define MOUSE_SENSITIVITY_SCALE 2.5f
Expand Down Expand Up @@ -669,7 +783,7 @@ void RWGame::render(float alpha, float time) {

renderer.getRenderer().popDebugGroup();

renderDebugView();
renderDebugView(viewCam);

if (!world->isPaused()) hudDrawer.drawOnScreenText(world.get(), renderer);

Expand All @@ -678,10 +792,10 @@ void RWGame::render(float alpha, float time) {
stateManager.draw(renderer);
}

imgui.endFrame(viewCam);
imgui.endFrame();
}

void RWGame::renderDebugView() {
void RWGame::renderDebugView(const ViewCamera& viewCam) {
RW_PROFILE_SCOPE(__func__);
switch (debugview_) {
case DebugViewMode::Physics:
Expand All @@ -691,6 +805,12 @@ void RWGame::renderDebugView() {
case DebugViewMode::Navigation:
renderDebugPaths();
break;
case RWGame::DebugViewMode::General:
WindowDebugStats(*this);
break;
case RWGame::DebugViewMode::Objects:
WindowDebugObjects(*this, viewCam);
break;
default:
break;
}
Expand Down
Loading