Skip to content

Commit

Permalink
Show waypoint notes in the viewer (#1181)
Browse files Browse the repository at this point in the history
If a waypoint has anything in the notes field show that in the 3D view at the position of the waypoint blob.
Add a view option for this (Notes). `true` by default.
Closes #963
  • Loading branch information
chreden authored Sep 16, 2023
1 parent 4ba1556 commit 4803978
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 2 deletions.
31 changes: 31 additions & 0 deletions trview.app.tests/UI/ViewOptionsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,3 +429,34 @@ TEST(ViewOptions, LightingCheckboxUpdated)
imgui.render();
ASSERT_FALSE(imgui.status_flags(imgui.id("View Options").push(ViewOptions::Names::flags).id(IViewer::Options::lighting)) & ImGuiItemStatusFlags_Checked);
}


TEST(ViewOptions, NotesCheckboxToggle)
{
ViewOptions view_options;

std::optional<std::tuple<std::string, bool>> clicked;
auto token = view_options.on_toggle_changed += [&](const std::string& name, bool value)
{
clicked = { name, value };
};

tests::TestImgui imgui([&]() { view_options.render(); });
imgui.click_element(imgui.id("View Options").push(ViewOptions::Names::flags).id(IViewer::Options::notes));

ASSERT_TRUE(clicked.has_value());
ASSERT_EQ(std::get<0>(clicked.value()), IViewer::Options::notes);
ASSERT_FALSE(std::get<1>(clicked.value()));
}

TEST(ViewOptions, NotesCheckboxUpdated)
{
ViewOptions view_options;

tests::TestImgui imgui([&]() { view_options.render(); });
ASSERT_TRUE(imgui.status_flags(imgui.id("View Options").push(ViewOptions::Names::flags).id(IViewer::Options::notes)) & ImGuiItemStatusFlags_Checked);

view_options.set_toggle(IViewer::Options::notes, false);
imgui.render();
ASSERT_FALSE(imgui.status_flags(imgui.id("View Options").push(ViewOptions::Names::flags).id(IViewer::Options::notes)) & ImGuiItemStatusFlags_Checked);
}
8 changes: 8 additions & 0 deletions trview.app.tests/Windows/ViewerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,3 +1056,11 @@ TEST(Viewer, TriggerSelectedForwarded)
level.on_trigger_selected(trigger);
ASSERT_EQ(raised, nullptr);
}

TEST(Viewer, SetRouteForwarded)
{
auto [ui_ptr, ui] = create_mock<MockViewerUI>();
EXPECT_CALL(ui, set_route).Times(2);
auto viewer = register_test_module().with_ui(std::move(ui_ptr)).build();
viewer->set_route(mock_shared<MockRoute>());
}
1 change: 1 addition & 0 deletions trview.app/Mocks/Routing/IWaypoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace trview
MOCK_METHOD(std::weak_ptr<ITrigger>, trigger, (), (const, override));
MOCK_METHOD(Colour, route_colour, (), (const, override));
MOCK_METHOD(Colour, waypoint_colour, (), (const, override));
MOCK_METHOD(DirectX::SimpleMath::Vector2, screen_position, (), (const, override));
/// <summary>
/// Index used for testing ordering.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions trview.app/Mocks/UI/IViewerUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ namespace trview
MOCK_METHOD(bool, toggle, (const std::string&), (const, override));
MOCK_METHOD(void, set_scalar, (const std::string&, int32_t), (override));
MOCK_METHOD(void, set_triggered_by, (const std::vector<std::weak_ptr<ITrigger>>&), (override));
MOCK_METHOD(void, set_route, (const std::weak_ptr<IRoute>&), (override));
};
}
}
1 change: 1 addition & 0 deletions trview.app/Routing/IWaypoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ namespace trview
virtual Colour waypoint_colour() const = 0;
virtual void set_normal(const DirectX::SimpleMath::Vector3& normal) = 0;
virtual void set_room_number(uint32_t room) = 0;
virtual DirectX::SimpleMath::Vector2 screen_position() const = 0;

Event<> on_changed;
};
Expand Down
8 changes: 8 additions & 0 deletions trview.app/Routing/Waypoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ namespace trview
// The light blob.
auto blob_wvp = Matrix::CreateScale(PoleThickness, PoleThickness, PoleThickness) * Matrix::CreateTranslation(-Vector3(0, PoleLength + PoleThickness * 0.5f, 0)) * rotation * Matrix::CreateTranslation(_position) * camera.view_projection();
_mesh->render(blob_wvp, texture_storage, colour == IRenderable::SelectionFill ? colour : static_cast<Color>(_route_colour));

const auto window_size = camera.view_size();
_screen_position = XMVector3Project(blob_position(), 0, 0, window_size.width, window_size.height, 0, 1.0f, camera.projection(), camera.view(), Matrix::Identity);
}

void Waypoint::render_join(const IWaypoint& next_waypoint, const ICamera& camera, const ILevelTextureStorage& texture_storage, const Color& colour)
Expand Down Expand Up @@ -273,5 +276,10 @@ namespace trview
_room = room;
on_changed();
}

Vector2 Waypoint::screen_position() const
{
return _screen_position;
}
}

3 changes: 3 additions & 0 deletions trview.app/Routing/Waypoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ namespace trview
Colour route_colour() const override;
void set_normal(const DirectX::SimpleMath::Vector3& normal) override;
void set_room_number(uint32_t room) override;
DirectX::SimpleMath::Vector2 screen_position() const override;
private:
DirectX::SimpleMath::Matrix calculate_waypoint_rotation() const;
void set_properties(Type type, uint32_t index, uint32_t room, const DirectX::SimpleMath::Vector3& position);
Expand All @@ -76,5 +77,7 @@ namespace trview

mutable std::weak_ptr<IItem> _item;
mutable std::weak_ptr<ITrigger> _trigger;

DirectX::SimpleMath::Vector2 _screen_position{ -1, -1 };
};
}
2 changes: 2 additions & 0 deletions trview.app/UI/IViewerUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,5 +248,7 @@ namespace trview
/// </summary>
/// <param name="triggers"></param>
virtual void set_triggered_by(const std::vector<std::weak_ptr<ITrigger>>& triggers) = 0;

virtual void set_route(const std::weak_ptr<IRoute>& route) = 0;
};
}
2 changes: 2 additions & 0 deletions trview.app/UI/ViewOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ namespace trview
_toggles[IViewer::Options::rooms] = true;
_toggles[IViewer::Options::camera_sinks] = false;
_toggles[IViewer::Options::lighting] = true;
_toggles[IViewer::Options::notes] = true;
}

void ViewOptions::render()
Expand Down Expand Up @@ -67,6 +68,7 @@ namespace trview
add_toggle(IViewer::Options::geometry);
ImGui::TableNextRow();
add_toggle(IViewer::Options::lighting);
add_toggle(IViewer::Options::notes);
ImGui::TableNextRow();
if (!_use_alternate_groups)
{
Expand Down
57 changes: 55 additions & 2 deletions trview.app/UI/ViewerUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,22 @@
#include <trview.app/UI/ContextMenu.h>
#include <trview.input/WindowTester.h>
#include <trview.common/Windows/Shortcuts.h>
#include "../Routing/IRoute.h"
#include "../Windows/IViewer.h"

using namespace DirectX::SimpleMath;

namespace trview
{
namespace
{
template <typename PointType>
bool is_on_screen(const PointType& point, const ImGuiViewport& viewport)
{
return !(point.x < 0 || point.y < 0 || point.x > viewport.Size.x || point.y > viewport.Size.y);
}
}

IViewerUI::~IViewerUI()
{
}
Expand Down Expand Up @@ -210,16 +223,18 @@ namespace trview
if (_show_measure)
{
const auto vp = ImGui::GetMainViewport();
if (!(_measure_position.x < 0 || _measure_position.y < 0 || _measure_position.x > vp->Size.x || _measure_position.y > vp->Size.y))
if (is_on_screen(_measure_position, *vp))
{
ImGui::SetNextWindowPos(vp->Pos + ImVec2(_measure_position.x, _measure_position.y));
if (ImGui::Begin("##measure", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize))
if (ImGui::Begin("##measure", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoFocusOnAppearing))
{
ImGui::Text(_measure_text.c_str());
}
ImGui::End();
}
}

render_route_notes();
}

void ViewerUI::set_alternate_group(uint32_t value, bool enabled)
Expand Down Expand Up @@ -422,4 +437,42 @@ namespace trview
{
_context_menu->set_triggered_by(triggers);
}

void ViewerUI::set_route(const std::weak_ptr<IRoute>& route)
{
_route = route;
}

void ViewerUI::render_route_notes()
{
const auto route = _route.lock();
if (!route || !toggle(IViewer::Options::notes))
{
return;
}

const auto vp = ImGui::GetMainViewport();
for (auto i = 0u; i < route->waypoints(); ++i)
{
if (const auto waypoint = route->waypoint(i).lock())
{
const auto notes = waypoint->notes();
if (notes.empty())
{
continue;
}

const auto pos = waypoint->screen_position();
if (is_on_screen(pos, *vp))
{
ImGui::SetNextWindowPos(vp->Pos + ImVec2(pos.x, pos.y));
if (ImGui::Begin(std::format("##waypoint{}", i).c_str(), nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoFocusOnAppearing))
{
ImGui::Text(notes.c_str());
}
ImGui::End();
}
}
}
}
}
3 changes: 3 additions & 0 deletions trview.app/UI/ViewerUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ namespace trview
virtual void set_toggle(const std::string& name, bool value) override;
virtual bool toggle(const std::string& name) const override;
virtual void set_triggered_by(const std::vector<std::weak_ptr<ITrigger>>& triggers) override;
void set_route(const std::weak_ptr<IRoute>& route) override;
private:
void generate_tool_window();
void render_route_notes();

TokenStore _token_store;
input::Mouse _mouse;
Expand All @@ -95,5 +97,6 @@ namespace trview
bool _visible{ true };
uint32_t _selected_room{ 0u };
uint32_t _selected_item{ 0u };
std::weak_ptr<IRoute> _route;
};
}
1 change: 1 addition & 0 deletions trview.app/Windows/IViewer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace trview
inline static const std::string rooms = "Rooms";
inline static const std::string camera_sinks = "Camera/Sink";
inline static const std::string lighting = "Lighting";
inline static const std::string notes = "Notes";
};

virtual ~IViewer() = 0;
Expand Down
3 changes: 3 additions & 0 deletions trview.app/Windows/Viewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,8 @@ namespace trview
_timer.reset();
_camera_input.reset();
};

_ui->set_route(_route);
}

void Viewer::initialise_input()
Expand Down Expand Up @@ -865,6 +867,7 @@ namespace trview
void Viewer::set_route(const std::shared_ptr<IRoute>& route)
{
_route = route;
_ui->set_route(route);
_scene_changed = true;
}

Expand Down

0 comments on commit 4803978

Please sign in to comment.