Skip to content

Commit

Permalink
Plugins: Add way to get/set mod values, reload configs, save configs
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Jun 8, 2024
1 parent ef97ac2 commit d51b4c9
Show file tree
Hide file tree
Showing 9 changed files with 297 additions and 90 deletions.
45 changes: 45 additions & 0 deletions examples/example_plugin/Plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,21 @@ class ExamplePlugin : public uevr::Plugin {
}
}

void reset_height() {
auto& api = API::get();
auto vr = api->param()->vr;
UEVR_Vector3f origin{};
vr->get_standing_origin(&origin);

UEVR_Vector3f hmd_pos{};
UEVR_Quaternionf hmd_rot{};
vr->get_pose(vr->get_hmd_index(), &hmd_pos, &hmd_rot);

origin.y = hmd_pos.y;

vr->set_standing_origin(&origin);
}

void on_device_reset() override {
PLUGIN_LOG_ONCE("Example Device Reset");

Expand Down Expand Up @@ -507,6 +522,36 @@ class ExamplePlugin : public uevr::Plugin {
if (ImGui::Button("Toggle decoupled pitch")) {
API::get()->param()->vr->set_decoupled_pitch_enabled(!API::get()->param()->vr->is_decoupled_pitch_enabled());
}

if (ImGui::Button("Screw up world scale")) {
API::get()->param()->vr->set_mod_value("VR_WorldScale", "1.337");
}

if (ImGui::Button("Toggle GUI")) {
char buffer[256]{};
API::get()->param()->vr->get_mod_value("VR_EnableGUI", buffer, sizeof(buffer));

const auto enabled = std::string_view{buffer} == "true";

API::get()->param()->vr->set_mod_value("VR_EnableGUI", enabled ? "false" : "true");
}

static char input[256]{};
if (ImGui::InputText("Get mod value", input, sizeof(input))) {

}

char buffer[256]{};
API::get()->param()->vr->get_mod_value(input, buffer, sizeof(buffer));
ImGui::Text("Mod value: %s", buffer);

if (ImGui::Button("Save Config")) {
API::get()->param()->vr->save_config();
}

if (ImGui::Button("Reload Config")) {
API::get()->param()->vr->reload_config();
}
#if defined(__clang__)
ImGui::Text("Plugin Compiler: Clang");
#elif defined(_MSC_VER)
Expand Down
7 changes: 6 additions & 1 deletion include/uevr/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ SOFTWARE.
#define UEVR_OUT

#define UEVR_PLUGIN_VERSION_MAJOR 2
#define UEVR_PLUGIN_VERSION_MINOR 18
#define UEVR_PLUGIN_VERSION_MINOR 19
#define UEVR_PLUGIN_VERSION_PATCH 0

#define UEVR_RENDERER_D3D11 0
Expand Down Expand Up @@ -521,6 +521,11 @@ typedef struct {
bool (*is_snap_turn_enabled)();
void (*set_snap_turn_enabled)(bool enabled);
void (*set_decoupled_pitch_enabled)(bool enabled);

void (*set_mod_value)(const char* key, const char* value);
void (*get_mod_value)(const char* key, char* value, unsigned int value_size);
void (*save_config)();
void (*reload_config)();
} UEVR_VRData;

typedef struct {
Expand Down
10 changes: 10 additions & 0 deletions src/Framework.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,16 @@ void Framework::reset_config() try {
spdlog::error("Failed to reset config: {}", e.what());
}

void Framework::reload_config() try {
std::scoped_lock _{m_config_mtx};

m_mods->reload_config(false);

spdlog::info("Reloaded config");
} catch (const std::exception& e) {
spdlog::error("Failed to reload config: {}", e.what());
}

bool Framework::is_drawing_anything() const {
return m_draw_ui || FrameworkConfig::get()->is_always_show_cursor();
}
Expand Down
13 changes: 13 additions & 0 deletions src/Framework.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,21 @@ class Framework {
return get_persistent_dir() / dir;
}

void deferred_save_config() {
m_frame_worker->enqueue([this]() {
save_config();
});
}

void deferred_reload_config() {
m_frame_worker->enqueue([this]() {
reload_config();
});
}

void save_config();
void reset_config();
void reload_config();

enum class RendererType : uint8_t {
D3D11,
Expand Down
77 changes: 73 additions & 4 deletions src/Mod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class IModValue {
virtual void draw_value(std::string_view name) = 0;
virtual void config_load(const utility::Config& cfg, bool set_defaults) = 0;
virtual void config_save(utility::Config& cfg) = 0;
virtual void set(const std::string& value) = 0;
virtual std::string get() = 0;
virtual std::string get_config_name() = 0;
virtual std::string_view get_config_name_view() = 0;
};

// Convenience classes for imgui
Expand Down Expand Up @@ -76,6 +80,44 @@ class ModValue : public IModValue {
}
};

virtual std::string get() override {
if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>) {
return m_value;
} else if constexpr (std::is_same_v<T, bool>) {
return m_value ? "true" : "false";
} else {
return std::to_string(m_value);
}
}

virtual void set(const std::string& value) override {
if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>) {
m_value = value;
return;
}

else if constexpr (std::is_same_v<T, bool>) {
m_value = value == "true" || value == "1";
return;
}

// Use the correct conversion function based on the type.
else if constexpr (std::is_integral_v<T>) {
if constexpr (std::is_unsigned_v<T>) {
m_value = (T)std::stoul(value);
return;
}

m_value = (T)std::stol(value);
return;
} else if constexpr (std::is_floating_point_v<T>) {
m_value = (T)std::stod(value);
return;
}

static_assert(std::is_same_v<T, void> == false, "Unsupported type for ModValue::set");
}

operator T&() {
return m_value;
}
Expand All @@ -88,7 +130,11 @@ class ModValue : public IModValue {
return m_default_value;
}

const auto& get_config_name() const {
std::string get_config_name() override {
return m_config_name;
}

std::string_view get_config_name_view() override {
return m_config_name;
}

Expand Down Expand Up @@ -575,10 +621,18 @@ class Mod {

virtual void on_post_render_vr_framework_dx11(ID3D11DeviceContext* context, ID3D11Texture2D* tex, ID3D11RenderTargetView* rtv) {};
virtual void on_post_render_vr_framework_dx12(ID3D12GraphicsCommandList* command_list, ID3D12Resource* tex, D3D12_CPU_DESCRIPTOR_HANDLE* rtv) {};

virtual void on_config_load(const utility::Config& cfg, bool set_defaults) {
for (auto& value : m_options) {
value.get().config_load(cfg, set_defaults);
}
}

virtual void on_config_load(const utility::Config& cfg, bool set_defaults) {};
virtual void on_config_save(utility::Config& cfg) {};

virtual void on_config_save(utility::Config& cfg) {
for (const auto& value : m_options) {
value.get().config_save(cfg);
}
}
// game specific
virtual void on_pre_engine_tick(sdk::UGameEngine* engine, float delta) {};
virtual void on_post_engine_tick(sdk::UGameEngine* engine, float delta) {};
Expand All @@ -590,6 +644,21 @@ class Mod {
const float world_to_meters, Vector3f* view_location, bool is_double) {};
virtual void on_pre_viewport_client_draw(void* viewport_client, void* viewport, void* canvas) {};
virtual void on_post_viewport_client_draw(void* viewport_client, void* viewport, void* canvas) {};

IModValue* get_value(std::string_view name) {
auto it = std::find_if(m_options.begin(), m_options.end(), [&name](const auto& v) {
return v.get().get_config_name_view() == name;
});

if (it == m_options.end()) {
return nullptr;
}

return &it->get();
}

protected:
ValueList m_options{};
};

class ModComponent : public Mod {
Expand Down
30 changes: 16 additions & 14 deletions src/mods/FrameworkConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,22 @@ class FrameworkConfig : public Mod {
static std::shared_ptr<FrameworkConfig>& get();

public:
FrameworkConfig() {
m_options = {
*m_menu_key,
*m_show_cursor_key,
*m_menu_open,
*m_remember_menu_state,
*m_enable_l3_r3_toggle,
*m_l3_r3_long_press,
*m_advanced_mode,
*m_imgui_theme,
*m_log_level,
*m_always_show_cursor,
*m_font_size,
};
}

std::string_view get_name() const {
return "FrameworkConfig";
}
Expand Down Expand Up @@ -111,18 +127,4 @@ class FrameworkConfig : public Mod {

ModKey::Ptr m_show_cursor_key{ ModKey::create(generate_name("ShowCursorKey")) };
ModInt32::Ptr m_font_size{ModInt32::create(generate_name("FontSize"), 16)};

ValueList m_options {
*m_menu_key,
*m_show_cursor_key,
*m_menu_open,
*m_remember_menu_state,
*m_enable_l3_r3_toggle,
*m_l3_r3_long_press,
*m_advanced_mode,
*m_imgui_theme,
*m_log_level,
*m_always_show_cursor,
*m_font_size,
};
};
54 changes: 54 additions & 0 deletions src/mods/PluginLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "UObjectHook.hpp"
#include "VR.hpp"

#include "Mods.hpp"
#include "PluginLoader.hpp"

UEVR_PluginVersion g_plugin_version{
Expand Down Expand Up @@ -1025,8 +1026,56 @@ void set_snap_turn_enabled(bool enabled) {
void set_decoupled_pitch_enabled(bool enabled) {
VR::get()->set_decoupled_pitch(enabled);
}

// TODO: Optimize this with a map
void set_mod_value(const char* key, const char* value) {
if (key == nullptr || value == nullptr) {
return;
}

auto& mods = g_framework->get_mods()->get_mods();

for (auto& mod : mods) {
auto value_entry = mod->get_value(key);

if (value_entry != nullptr) {
value_entry->set(value);
break;
}
}
}

void get_mod_value(const char* key, char* out_value, unsigned int max_size) {
if (key == nullptr || out_value == nullptr || max_size == 0) {
return;
}

auto& mods = g_framework->get_mods()->get_mods();

for (auto& mod : mods) {
auto value_entry = mod->get_value(key);

if (value_entry != nullptr) {
const auto value = value_entry->get();

const auto size = std::min<size_t>(value.size(), (size_t)max_size - 1);
memcpy(out_value, value.c_str(), size * sizeof(char));
out_value[size] = '\0';
break;
}
}
}

void save_config() {
g_framework->deferred_save_config();
}

void reload_config() {
g_framework->deferred_reload_config();
}
}

} // namespace uevr::vr

UEVR_VRData g_vr_data {
.is_runtime_ready = uevr::vr::is_runtime_ready,
Expand Down Expand Up @@ -1073,6 +1122,11 @@ UEVR_VRData g_vr_data {
.is_snap_turn_enabled = uevr::vr::is_snap_turn_enabled,
.set_snap_turn_enabled = uevr::vr::set_snap_turn_enabled,
.set_decoupled_pitch_enabled = uevr::vr::set_decoupled_pitch_enabled,

.set_mod_value = uevr::vr::set_mod_value,
.get_mod_value = uevr::vr::get_mod_value,
.save_config = uevr::vr::save_config,
.reload_config = uevr::vr::reload_config,
};


Expand Down
18 changes: 12 additions & 6 deletions src/mods/UObjectHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class FArrayProperty;
class UObjectHook : public Mod {
public:
static std::shared_ptr<UObjectHook>& get();

std::unordered_set<sdk::UObjectBase*> get_objects_by_class(sdk::UClass* uclass) const {
std::shared_lock _{m_mutex};
if (auto it = m_objects_by_class.find(uclass); it != m_objects_by_class.end()) {
Expand Down Expand Up @@ -458,10 +459,15 @@ class UObjectHook : public Mod {
bool m_uobject_hook_disabled{false};
bool m_fixed_visibilities{false};

ValueList m_options{
*m_enabled_at_startup,
*m_attach_lerp_enabled,
*m_attach_lerp_speed,
*m_keybind_toggle_uobject_hook
};
public:
UObjectHook() {
m_options = {
*m_enabled_at_startup,
*m_attach_lerp_enabled,
*m_attach_lerp_speed,
*m_keybind_toggle_uobject_hook
};
}

private:
};
Loading

0 comments on commit d51b4c9

Please sign in to comment.