Skip to content

Commit 2247757

Browse files
committed
Map IPL Viewer
1 parent c2d56c1 commit 2247757

File tree

4 files changed

+149
-22
lines changed

4 files changed

+149
-22
lines changed

rwgame/viewer/RWViewer.cpp

+54-19
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ static constexpr std::array<
2626
{GameRenderer::ZoneCylinderB, "zonecylb.dff", "particle"},
2727
{GameRenderer::Arrow, "arrow.dff", ""}}};
2828
const auto kViewerFov = glm::radians(90.f);
29+
30+
auto viewAnglesToQuat(float yaw, float pitch) {
31+
return glm::angleAxis(glm::radians(yaw), glm::vec3(0.f, 0.f, -1.f)) *
32+
glm::angleAxis(glm::radians(pitch), glm::vec3(0.f, 1.f, 0.f));
33+
}
2934
} // namespace
3035

3136
RWViewer::RWViewer(Logger& log, const std::optional<RWArgConfigLayer>& args)
@@ -47,6 +52,7 @@ RWViewer::RWViewer(Logger& log, const std::optional<RWArgConfigLayer>& args)
4752

4853
data_.load();
4954
textViewer_.emplace(data_);
55+
iplViewer_.emplace(log, data_);
5056

5157
for (const auto& [specialModel, fileName, name] : kSpecialModels) {
5258
auto model = data_.loadClump(fileName, name);
@@ -133,15 +139,15 @@ bool RWViewer::updateInput() {
133139
break;
134140

135141
case SDL_MOUSEWHEEL:
136-
viewParams_.z =
137-
glm::max(1.f, viewParams_.z +
138-
-(event.wheel.y * viewParams_.z * 0.1f));
142+
viewAngles_.z =
143+
glm::max(1.f, viewAngles_.z +
144+
-(event.wheel.y * viewAngles_.z * 0.1f));
139145
break;
140146

141147
case SDL_MOUSEMOTION:
142148
if (mouseMode_ == MouseMode::Dragging) {
143-
viewParams_.x += event.motion.xrel * 0.5f;
144-
viewParams_.y += event.motion.yrel * 0.5f;
149+
viewAngles_.x += event.motion.xrel * 0.5f;
150+
viewAngles_.y += event.motion.yrel * 0.5f;
145151
}
146152
break;
147153
}
@@ -166,26 +172,28 @@ void RWViewer::render(float alpha, float time) {
166172

167173
ViewCamera viewCam{};
168174
viewCam.frustum.fov = kViewerFov;
169-
170-
if (viewedObject_) {
171-
auto rotation = glm::angleAxis(glm::radians(viewParams_.x),
172-
glm::vec3(0.f, 0.f, -1.f)) *
173-
glm::angleAxis(glm::radians(viewParams_.y),
174-
glm::vec3(0.f, 1.f, 0.f));
175-
auto viewDirection = rotation * glm::vec3{-1.f, 0.f, 0.f};
176-
viewCam.position = viewDirection * viewParams_.z;
177-
viewCam.rotation = rotation;
178-
}
179-
180175
viewCam.frustum.aspectRatio =
181176
windowSize.x / static_cast<float>(windowSize.y);
182177

178+
viewCam.rotation = viewAnglesToQuat(viewAngles_.x, viewAngles_.y);
179+
183180
glEnable(GL_DEPTH_TEST);
184181
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
185182

186183
renderer_.getRenderer().pushDebugGroup("World");
187184

188-
renderer_.renderWorld(world_.get(), viewCam, alpha);
185+
switch (viewMode_) {
186+
case ViewMode::Model: {
187+
auto viewDirection = viewCam.rotation * glm::vec3{-1.f, 0.f, 0.f};
188+
viewCam.position = viewDirection * viewAngles_.z;
189+
renderer_.renderWorld(world_.get(), viewCam, alpha);
190+
break;
191+
}
192+
case ViewMode::World:
193+
viewCam.position = viewPosition_;
194+
renderer_.renderWorld(iplViewer_->world(), viewCam, alpha);
195+
break;
196+
}
189197

190198
renderer_.getRenderer().popDebugGroup();
191199

@@ -196,13 +204,32 @@ void RWViewer::render(float alpha, float time) {
196204
}
197205

198206
void RWViewer::globalKeyEvent(const SDL_Event& event) {
207+
auto r = viewAnglesToQuat(viewAngles_.x, viewAngles_.y);
199208
switch (event.key.keysym.sym) {
200209
case SDLK_LEFTBRACKET:
201210
world_->offsetGameTime(-30);
202211
break;
203212
case SDLK_RIGHTBRACKET:
204213
world_->offsetGameTime(30);
205214
break;
215+
216+
case SDLK_w:
217+
case SDLK_UP:
218+
viewPosition_ += r * glm::vec3{1.f, 0.f, 0.f};
219+
break;
220+
case SDLK_s:
221+
case SDLK_DOWN:
222+
viewPosition_ -= r * glm::vec3{1.f, 0.f, 0.f};
223+
break;
224+
case SDLK_a:
225+
case SDLK_LEFT:
226+
viewPosition_ += r * glm::vec3{0.f, 1.f, 0.f};
227+
break;
228+
case SDLK_d:
229+
case SDLK_RIGHT:
230+
viewPosition_ -= r * glm::vec3{0.f, 1.f, 0.f};
231+
break;
232+
206233
default:
207234
break;
208235
}
@@ -220,7 +247,10 @@ void RWViewer::drawMenu() {
220247
}
221248
});
222249
menu("View", [&]() {
223-
ImGui::MenuItem("Model", "", viewedObject_ != nullptr);
250+
if (ImGui::MenuItem("Model", "", viewMode_ == ViewMode::Model))
251+
viewMode_ = ViewMode::Model;
252+
if (ImGui::MenuItem("World", "", viewMode_ == ViewMode::World))
253+
viewMode_ = ViewMode::World;
224254
if (ImGui::MenuItem("Remove Object", "")) {
225255
if (viewedObject_) {
226256
world_->destroyObject(viewedObject_);
@@ -231,6 +261,7 @@ void RWViewer::drawMenu() {
231261
menu("Windows", [&]() {
232262
ImGui::MenuItem("Models", "", &showModelList_);
233263
ImGui::MenuItem("Texts", "", &showTextViewer_);
264+
ImGui::MenuItem("Map", "", &showIplViewer_);
234265
ImGui::Separator();
235266
ImGui::MenuItem("Demo", "", &showImGuiDemo_);
236267
});
@@ -297,6 +328,9 @@ void RWViewer::drawWindows() {
297328
window("Texts", showTextViewer_, {920, 320},
298329
[&]() { textViewer_->draw(renderer_); });
299330

331+
window("Map", showIplViewer_, {320, 320},
332+
[&]() { iplViewer_->draw(renderer_); });
333+
300334
if (showImGuiDemo_) ImGui::ShowDemoWindow(&showImGuiDemo_);
301335
}
302336

@@ -327,6 +361,7 @@ void RWViewer::drawModelWindow(ModelID id) {
327361
}
328362

329363
void RWViewer::viewModel(ModelID model) {
364+
viewMode_ = ViewMode::Model;
330365
if (viewedObject_) {
331366
world_->destroyObject(viewedObject_);
332367
viewedObject_ = nullptr;
@@ -357,5 +392,5 @@ void RWViewer::viewModel(ModelID model) {
357392
radius = glm::length(geo.center) + geo.radius;
358393
}
359394
constexpr auto kViewSlop = 1.f;
360-
viewParams_.z = kViewSlop * ((radius * 2) / (glm::tan(kViewerFov / 2.f)));
395+
viewAngles_.z = kViewSlop * ((radius * 2) / (glm::tan(kViewerFov / 2.f)));
361396
}

rwgame/viewer/RWViewer.hpp

+13-3
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,22 @@ class RWViewer final : public GameBase {
7171
bool showTextViewer_ = false;
7272
std::optional<TextViewer> textViewer_;
7373
bool showImGuiDemo_ = false;
74+
bool showIplViewer_ = false;
75+
std::optional<IPLViewer> iplViewer_;
7476
std::set<ModelID> showModels_;
7577

76-
GameObject* viewedObject_ = nullptr;
77-
glm::vec3 viewParams_{};
78-
enum MouseMode { Hovering, Dragging };
78+
enum class ViewMode {
79+
World,
80+
Model,
81+
};
82+
ViewMode viewMode_ = ViewMode::World;
83+
enum class MouseMode { Hovering, Dragging };
7984
MouseMode mouseMode_ = MouseMode::Hovering;
85+
86+
GameObject* viewedObject_ = nullptr;
87+
glm::vec3 viewAngles_{};
88+
89+
glm::vec3 viewPosition_{};
8090
};
8191

8292
#endif

rwgame/viewer/RWViewerWindows.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
#include <viewer/RWViewerWindows.hpp>
22

3+
#include <engine/GameWorld.hpp>
34
#include <loaders/LoaderGXT.hpp>
5+
#include <objects/InstanceObject.hpp>
46
#include <platform/FileHandle.hpp>
57

68
#include <imgui.h>
79

10+
#include <algorithm>
11+
812
namespace {
913
std::array<int, 3> kFonts{{FONT_PAGER, FONT_PRICEDOWN, FONT_ARIAL}};
1014
std::array<const char*, 3> kFontNames{{"Pager", "Pricedown", "Arial"}};
@@ -158,3 +162,47 @@ void TextViewer::draw(GameRenderer& r) {
158162
}
159163
}
160164
}
165+
166+
IPLViewer::IPLViewer(Logger& log, GameData& data)
167+
: data_(data), world_(std::make_unique<GameWorld>(&log, &data)) {
168+
std::transform(begin(data_.iplLocations), end(data_.iplLocations),
169+
std::back_inserter(ipls_), [](const auto& a) -> IPLFileData {
170+
return {false, a.first, a.second, {}, {}};
171+
});
172+
world_->state = &state_;
173+
}
174+
175+
void IPLViewer::draw(GameRenderer& r) {
176+
for (auto& ipl : ipls_) {
177+
if (ImGui::Checkbox(ipl.name.c_str(), &ipl.enabled)) {
178+
if (ipl.enabled)
179+
showIPL(ipl);
180+
else
181+
hideIPL(ipl);
182+
}
183+
}
184+
}
185+
186+
void IPLViewer::showIPL(IPLViewer::IPLFileData& ipl) {
187+
if (ipl.loader.m_instances.empty()) {
188+
ipl.loader.load(ipl.path);
189+
}
190+
191+
for (const auto& inst : ipl.loader.m_instances) {
192+
auto instance = world_->createInstance(inst.id, inst.pos, inst.rot);
193+
if (!instance) {
194+
world_->logger->error("World", "No object data for instance " +
195+
std::to_string(inst.id) +
196+
" in " + ipl.name);
197+
} else {
198+
ipl.objects.push_back(instance);
199+
}
200+
}
201+
}
202+
203+
void IPLViewer::hideIPL(IPLViewer::IPLFileData& ipl) {
204+
for (auto& object : ipl.objects) {
205+
world_->destroyObject(object);
206+
}
207+
ipl.objects.clear();
208+
}

rwgame/viewer/RWViewerWindows.hpp

+34
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
#define RWGAME_RWVIEWERWINDOWS_HPP
33

44
#include <engine/GameData.hpp>
5+
#include <engine/GameState.hpp>
56
#include <fonts/GameTexts.hpp>
7+
#include <loaders/LoaderIPL.hpp>
8+
#include <objects/GameObject.hpp>
69
#include <render/GameRenderer.hpp>
710

11+
#include <core/Logger.hpp>
12+
813
#include <string>
14+
#include <vector>
915

1016
class TextViewer {
1117
public:
@@ -26,4 +32,32 @@ class TextViewer {
2632
bool drawPreview_ = true;
2733
};
2834

35+
class IPLViewer {
36+
public:
37+
IPLViewer(Logger&, GameData& data);
38+
39+
void draw(GameRenderer& r);
40+
41+
GameWorld* world() const {
42+
return world_.get();
43+
}
44+
45+
private:
46+
struct IPLFileData {
47+
bool enabled;
48+
std::string name;
49+
std::string path;
50+
LoaderIPL loader;
51+
std::vector<GameObject*> objects;
52+
};
53+
54+
void showIPL(IPLFileData&);
55+
void hideIPL(IPLFileData&);
56+
57+
GameData& data_;
58+
GameState state_;
59+
std::unique_ptr<GameWorld> world_;
60+
std::vector<IPLFileData> ipls_;
61+
};
62+
2963
#endif // RWGAME_RWVIEWERWINDOWS_HPP

0 commit comments

Comments
 (0)