Skip to content

Commit

Permalink
Add binding to create Scriptables
Browse files Browse the repository at this point in the history
Scriptable with temporary click function

To be replaced, probably.

Binding to add a scriptable to a level

Update mocks

Add first test callback

Register for scriptable changed events

Make view update automatically

Have a data field on scriptables

Tooltips for scriptables

Show notes

Temporary hack with screen position as rendering not inside scriptable

Move rendering to the scriptable

Update IScriptable.h

Update ILevel.h
  • Loading branch information
chreden committed Aug 9, 2024
1 parent 02ac331 commit f2cf329
Show file tree
Hide file tree
Showing 23 changed files with 491 additions and 9 deletions.
6 changes: 6 additions & 0 deletions trview.app.tests/Lua/Lua_trviewTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <external/lua/src/lauxlib.h>
#include <trview.app/Mocks/Routing/IRoute.h>
#include <trview.app/Mocks/Routing/IRandomizerRoute.h>
#include <trview.app/Mocks/Lua/IScriptable.h>
#include "Lua.h"

using namespace trview;
Expand All @@ -26,6 +27,7 @@ TEST(Lua_trview, Level)
[](auto&&) { return mock_shared<MockRoute>(); },
[](auto&&) { return mock_shared<MockRandomizerRoute>(); },
[](auto&&...) { return mock_shared<MockWaypoint>(); },
[](auto&&...) { return mock_shared<MockScriptable>(); },
mock_shared<MockDialogs>(),
mock_shared<MockFiles>());

Expand All @@ -49,6 +51,7 @@ TEST(Lua_trview, RecentFiles)
[](auto&&) { return mock_shared<MockRoute>(); },
[](auto&&) { return mock_shared<MockRandomizerRoute>(); },
[](auto&&...) { return mock_shared<MockWaypoint>(); },
[](auto&&...) { return mock_shared<MockScriptable>(); },
mock_shared<MockDialogs>(),
mock_shared<MockFiles>());

Expand All @@ -72,6 +75,7 @@ TEST(Lua_trview, SetLevel)
[](auto&&) { return mock_shared<MockRoute>(); },
[](auto&&) { return mock_shared<MockRandomizerRoute>(); },
[](auto&&...) { return mock_shared<MockWaypoint>(); },
[](auto&&...) { return mock_shared<MockScriptable>(); },
mock_shared<MockDialogs>(),
mock_shared<MockFiles>());

Expand All @@ -93,6 +97,7 @@ TEST(Lua_trview, Route)
[](auto&&) { return mock_shared<MockRoute>(); },
[](auto&&) { return mock_shared<MockRandomizerRoute>(); },
[](auto&&...) { return mock_shared<MockWaypoint>(); },
[](auto&&...) { return mock_shared<MockScriptable>(); },
mock_shared<MockDialogs>(),
mock_shared<MockFiles>());

Expand All @@ -110,6 +115,7 @@ TEST(Lua_trview, SetRoute)
[](auto&&) { return mock_shared<MockRoute>(); },
[](auto&&) { return mock_shared<MockRandomizerRoute>(); },
[](auto&&...) { return mock_shared<MockWaypoint>(); },
[](auto&&...) { return mock_shared<MockScriptable>(); },
mock_shared<MockDialogs>(),
mock_shared<MockFiles>());

Expand Down
7 changes: 5 additions & 2 deletions trview.app/ApplicationCreate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "Graphics/MeshStorage.h"
#include "Graphics/SelectionRenderer.h"
#include "Graphics/SectorHighlight.h"
#include "Lua/Scriptable/Scriptable.h"
#include "Menus/FileMenu.h"
#include "Menus/UpdateChecker.h"
#include "Routing/Waypoint.h"
Expand Down Expand Up @@ -281,13 +282,15 @@ namespace trview
return new_level;
};

auto scriptable_source = [=](auto state) { return std::make_shared<Scriptable>(state, create_cube_mesh(mesh_source), texture_storage->coloured(Colour::White)); };

auto dialogs = std::make_shared<Dialogs>(window);
auto shell = std::make_shared<Shell>();

auto plugin_source = [=](auto&&... args) { return std::make_shared<Plugin>(files, std::make_unique<Lua>(route_source, randomizer_route_source, waypoint_source, dialogs, files), args...); };
auto plugin_source = [=](auto&&... args) { return std::make_shared<Plugin>(files, std::make_unique<Lua>(route_source, randomizer_route_source, waypoint_source, scriptable_source, dialogs, files), args...); };
auto plugins = std::make_shared<Plugins>(
files,
std::make_shared<Plugin>(std::make_unique<Lua>(route_source, randomizer_route_source, waypoint_source, dialogs, files), "Default", "trview", "Default Lua plugin for trview"),
std::make_shared<Plugin>(std::make_unique<Lua>(route_source, randomizer_route_source, waypoint_source, scriptable_source, dialogs, files), "Default", "trview", "Default Lua plugin for trview"),
plugin_source,
settings_loader->load_user_settings());
auto plugins_window_source = [=]() { return std::make_shared<PluginsWindow>(plugins, shell); };
Expand Down
3 changes: 3 additions & 0 deletions trview.app/Elements/ILevel.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "../Elements/ITrigger.h"
#include "../Elements/IRoom.h"
#include "../Elements/IStaticMesh.h"
#include "../Lua/Scriptable/IScriptable.h"
#include "IItem.h"
#include <trview.app/Elements/ILight.h>
#include "CameraSink/ICameraSink.h"
Expand All @@ -31,6 +32,7 @@ namespace trview
};

virtual ~ILevel() = 0;
virtual void add_scriptable(const std::shared_ptr<IScriptable>& scriptable) = 0;
/// Gets whether the specified alternate group is active.
/// @param group The group to check.
/// @returns True if the group is active.
Expand Down Expand Up @@ -79,6 +81,7 @@ namespace trview
// Returns the room with ID provided
virtual std::weak_ptr<IRoom> room(uint32_t id) const = 0;
virtual std::vector<std::weak_ptr<IRoom>> rooms() const = 0;
virtual std::vector<std::weak_ptr<IScriptable>> scriptables() const = 0;
virtual std::optional<uint32_t> selected_item() const = 0;
virtual std::optional<uint32_t> selected_light() const = 0;
virtual std::optional<uint32_t> selected_camera_sink() const = 0;
Expand Down
37 changes: 37 additions & 0 deletions trview.app/Elements/Level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ namespace trview
return _room_highlight_modes.find(mode) != _room_highlight_modes.end();
}

std::vector<std::weak_ptr<IScriptable>> Level::scriptables() const
{
return _scriptables | std::ranges::to<std::vector<std::weak_ptr<IScriptable>>>();
}

void Level::set_selected_room(const std::weak_ptr<IRoom>& room)
{
const auto room_ptr = room.lock();
Expand Down Expand Up @@ -248,6 +253,11 @@ namespace trview

render_rooms(camera);

for (const auto& scriptable : _scriptables)
{
scriptable->render(camera);
}

graphics::set_data(*_pixel_shader_data, context, PixelShaderData{ false });
}

Expand Down Expand Up @@ -686,6 +696,27 @@ namespace trview
}
}

uint32_t index = 0;
for (const auto& scriptable : _scriptables)
{
PickResult result{};
BoundingBox cube(scriptable->position(), Vector3(0.125f, 0.125f, 0.125f));

float distance = 0;
if (cube.Intersects(position, direction, distance))
{
result.distance = distance;
result.hit = true;
result.index = index;
result.position = position + direction * distance;
result.type = PickResult::Type::Scriptable;
result.scriptable = scriptable;
results.push_back(result);
}

++index;
}

std::sort(results.begin(), results.end(), [](const auto& l, const auto& r) { return l.distance < r.distance; });

std::optional<PickResult> actual_result;
Expand Down Expand Up @@ -1353,6 +1384,12 @@ namespace trview
return _static_meshes[index];
}

void Level::add_scriptable(const std::shared_ptr<IScriptable>& scriptable)
{
_scriptables.push_back(scriptable);
scriptable->on_changed += on_level_changed;
}

bool find_item_by_type_id(const ILevel& level, uint32_t type_id, std::weak_ptr<IItem>& output_item)
{
const auto& items = level.items();
Expand Down
4 changes: 4 additions & 0 deletions trview.app/Elements/Level.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace trview
virtual void render_transparency(const ICamera& camera) override;
virtual void set_highlight_mode(RoomHighlightMode mode, bool enabled) override;
virtual bool highlight_mode_enabled(RoomHighlightMode mode) const override;
std::vector<std::weak_ptr<IScriptable>> scriptables() const override;
void set_selected_room(const std::weak_ptr<IRoom>& room) override;
virtual void set_selected_item(uint32_t index) override;
virtual void set_neighbour_depth(uint32_t depth) override;
Expand Down Expand Up @@ -115,6 +116,7 @@ namespace trview
const trlevel::ILevel::LoadCallbacks callbacks);
std::vector<std::weak_ptr<IStaticMesh>> static_meshes() const override;
std::weak_ptr<IStaticMesh> static_mesh(uint32_t index) const override;
void add_scriptable(const std::shared_ptr<IScriptable>& scriptable) override;
private:
void generate_rooms(const trlevel::ILevel& level, const IRoom::Source& room_source, const IMeshStorage& mesh_storage);
void generate_triggers(const ITrigger::Source& trigger_source);
Expand Down Expand Up @@ -207,6 +209,8 @@ namespace trview
std::set<uint32_t> _models;
TokenStore _token_store;
std::string _name;

std::vector<std::shared_ptr<IScriptable>> _scriptables;
};

/// Find the first item with the type id specified.
Expand Down
8 changes: 8 additions & 0 deletions trview.app/Geometry/PickResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,14 @@ namespace trview
}
break;
}
case PickResult::Type::Scriptable:
{
if (const auto scriptable = result.scriptable.lock())
{
stream << scriptable->tooltip();
}
break;
}
}

return stream.str();
Expand Down
5 changes: 4 additions & 1 deletion trview.app/Geometry/PickResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace trview
struct Colour;
struct ILevel;
struct IRoute;
struct IScriptable;

struct PickResult
{
Expand All @@ -21,7 +22,8 @@ namespace trview
Compass,
StaticMesh,
Light,
CameraSink
CameraSink,
Scriptable
};

bool hit{ false };
Expand All @@ -34,6 +36,7 @@ namespace trview
std::string text;
bool override_centre{ false };
Triangle triangle;
std::weak_ptr<IScriptable> scriptable;
};

/// Convert the pick result to a display string.
Expand Down
18 changes: 16 additions & 2 deletions trview.app/Lua/Elements/Level/Lua_Level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,41 @@
#include "../Trigger/Lua_Trigger.h"
#include "../Light/Lua_Light.h"
#include "../StaticMesh/Lua_StaticMesh.h"
#include "../../Scriptable/IScriptable.h"

namespace trview
{
namespace lua
{
namespace
{
int level_addscriptable(lua_State* L)
{
auto level = lua::get_self<ILevel>(L);
auto scriptable = lua::get_self<IScriptable>(L, -1);
level->add_scriptable(scriptable);
return 0;
}

int level_index(lua_State* L)
{
auto level = lua::get_self<ILevel>(L);

const std::string key = lua_tostring(L, 2);
if (key == "cameras_and_sinks")
if (key == "add_scriptable")
{
return push_list_p(L, level->camera_sinks(), create_camera_sink);
lua_pushcfunction(L, level_addscriptable);
return 1;
}
else if (key == "alternate_mode")
{
lua_pushboolean(L, level->alternate_mode());
return 1;
}
else if (key == "cameras_and_sinks")
{
return push_list_p(L, level->camera_sinks(), create_camera_sink);
}
else if (key == "filename")
{
lua_pushstring(L, level->filename().c_str());
Expand Down
6 changes: 3 additions & 3 deletions trview.app/Lua/Lua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ namespace trview
{
}

Lua::Lua(const IRoute::Source& route_source, const IRandomizerRoute::Source& randomizer_route_source, const IWaypoint::Source& waypoint_source, const std::shared_ptr<IDialogs>& dialogs, const std::shared_ptr<IFiles>& files)
: _route_source(route_source), _randomizer_route_source(randomizer_route_source), _waypoint_source(waypoint_source), _dialogs(dialogs), _files(files)
Lua::Lua(const IRoute::Source& route_source, const IRandomizerRoute::Source& randomizer_route_source, const IWaypoint::Source& waypoint_source, const IScriptable::Source& scriptable_source, const std::shared_ptr<IDialogs>& dialogs, const std::shared_ptr<IFiles>& files)
: _route_source(route_source), _randomizer_route_source(randomizer_route_source), _waypoint_source(waypoint_source), _scriptable_source(scriptable_source), _dialogs(dialogs), _files(files)
{
create_state();
}
Expand Down Expand Up @@ -125,7 +125,7 @@ namespace trview
*userdata = this;
lua_pushcclosure(L, dofile, 1);
lua_setglobal(L, "dofile");
lua::trview_register(L, application, _route_source, _randomizer_route_source, _waypoint_source, _dialogs, _files);
lua::trview_register(L, application, _route_source, _randomizer_route_source, _waypoint_source, _scriptable_source, _dialogs, _files);
lua::imgui_register(L);
}

Expand Down
8 changes: 7 additions & 1 deletion trview.app/Lua/Lua.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../Routing/IRoute.h"
#include "../Routing/IRandomizerRoute.h"
#include "../Settings/UserSettings.h"
#include "Scriptable/IScriptable.h"

#include <trview.common/Windows/IDialogs.h>
#include <trview.common/IFiles.h>
Expand All @@ -22,7 +23,11 @@ namespace trview
class Lua final : public ILua
{
public:
explicit Lua(const IRoute::Source& route_source, const IRandomizerRoute::Source& randomizer_route_source, const IWaypoint::Source& waypoint_source, const std::shared_ptr<IDialogs>& dialogs, const std::shared_ptr<IFiles>& files);
explicit Lua(
const IRoute::Source& route_source,
const IRandomizerRoute::Source& randomizer_route_source,
const IWaypoint::Source& waypoint_source, const IScriptable::Source& scriptable_source,
const std::shared_ptr<IDialogs>& dialogs, const std::shared_ptr<IFiles>& files);
~Lua();
void do_file(const std::string& file) override;
void execute(const std::string& command) override;
Expand All @@ -34,6 +39,7 @@ namespace trview
lua_State* L{ nullptr };
IRoute::Source _route_source;
IRandomizerRoute::Source _randomizer_route_source;
IScriptable::Source _scriptable_source;
IWaypoint::Source _waypoint_source;
std::shared_ptr<IDialogs> _dialogs;
std::shared_ptr<IFiles> _files;
Expand Down
43 changes: 43 additions & 0 deletions trview.app/Lua/Scriptable/IScriptable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once

#include <functional>
#include <memory>

#include <trview.common/Event.h>

#include "../../Geometry/IMesh.h"

struct lua_State;

namespace trview
{
struct ICamera;

struct IScriptable
{
using Source = std::function<std::shared_ptr<IScriptable>(lua_State*)>;
virtual ~IScriptable() = 0;
virtual void click() = 0;
virtual int data() const = 0;
virtual std::shared_ptr<IMesh> mesh() const = 0;
virtual std::string notes() const = 0;
virtual DirectX::SimpleMath::Vector3 position() const = 0;
virtual void render(const ICamera& camera) = 0;
virtual DirectX::SimpleMath::Vector3 screen_position() const = 0;
virtual void set_data(int ref) = 0;
virtual void set_notes(const std::string& notes) = 0;
virtual void set_on_click(int ref) = 0;
virtual void set_position(const DirectX::SimpleMath::Vector3& position) = 0;
virtual void set_on_tooltip(int ref) = 0;
virtual void set_screen_position(const DirectX::SimpleMath::Vector3& position) = 0;
virtual std::string tooltip() const = 0;

Event<> on_changed;
};

namespace lua
{
void scriptable_register(lua_State* L, const IScriptable::Source& source);
std::shared_ptr<IScriptable> to_scriptable(lua_State* L, int index);
}
}
Loading

0 comments on commit f2cf329

Please sign in to comment.