Skip to content

Commit

Permalink
Plugins: Add additional UObjectHook functions for attachments
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Feb 20, 2024
1 parent f48ed67 commit c25695a
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 66 deletions.
25 changes: 25 additions & 0 deletions examples/example_plugin/Plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,31 @@ class ExamplePlugin : public uevr::Plugin {
std::string name_narrow{std::wstring_convert<std::codecvt_utf8<wchar_t>>{}.to_bytes(test_name.to_string())};
API::get()->log_info("Test FName: %s", name_narrow.c_str());

// Test attaching skeletal mesh components with UObjectHook.
struct {
API::UClass* c;
API::TArray<API::UObject*> return_value{};
} component_params;

component_params.c = API::get()->find_uobject<API::UClass>(L"Class /Script/Engine.SkeletalMeshComponent");
const auto pawn = API::get()->get_local_pawn(0);

if (component_params.c != nullptr && pawn != nullptr) {
// either or.
pawn->call_function(L"K2_GetComponentsByClass", &component_params);
pawn->call_function(L"GetComponentsByClass", &component_params);

if (component_params.return_value.empty()) {
API::get()->log_error("Failed to find any SkeletalMeshComponents");
}

for (auto mesh : component_params.return_value) {
auto state = API::UObjectHook::get_or_add_motion_controller_state(mesh);
}
} else {
API::get()->log_error("Failed to find SkeletalMeshComponent class or local pawn");
}

// Iterate over all console variables.
const auto console_manager = API::get()->get_console_manager();

Expand Down
16 changes: 15 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 12
#define UEVR_PLUGIN_VERSION_MINOR 13
#define UEVR_PLUGIN_VERSION_PATCH 0

#define UEVR_RENDERER_D3D11 0
Expand Down Expand Up @@ -298,6 +298,15 @@ typedef struct {
UEVR_FNameHandle (*get_fname)(UEVR_UObjectHandle object);
} UEVR_UObjectFunctions;

DECLARE_UEVR_HANDLE(UEVR_UObjectHookMotionControllerStateHandle);

typedef struct {
void (*set_rotation_offset)(UEVR_UObjectHookMotionControllerStateHandle, const UEVR_Quaternionf* rotation);
void (*set_location_offset)(UEVR_UObjectHookMotionControllerStateHandle, const UEVR_Vector3f* location);
void (*set_hand)(UEVR_UObjectHookMotionControllerStateHandle, unsigned int hand);
void (*set_permanent)(UEVR_UObjectHookMotionControllerStateHandle, bool permanent);
} UEVR_UObjectHookMotionControllerStateFunctions;

typedef struct {
void (*activate)();
bool (*exists)(UEVR_UObjectHandle object);
Expand All @@ -309,6 +318,11 @@ typedef struct {

UEVR_UObjectHandle (*get_first_object_by_class)(UEVR_UClassHandle klass, bool allow_default);
UEVR_UObjectHandle (*get_first_object_by_class_name)(const wchar_t* class_name, bool allow_default);

UEVR_UObjectHookMotionControllerStateHandle (*get_or_add_motion_controller_state)(UEVR_UObjectHandle object);
UEVR_UObjectHookMotionControllerStateHandle (*get_motion_controller_state)(UEVR_UObjectHandle object);

UEVR_UObjectHookMotionControllerStateFunctions* mc_state;
} UEVR_UObjectHookFunctions;

typedef struct {
Expand Down
103 changes: 101 additions & 2 deletions include/uevr/API.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ class API {
struct IConsoleVariable;
struct IConsoleCommand;
struct ConsoleObjectElement;
struct UObjectHook;

template<typename T>
struct TArray;
Expand Down Expand Up @@ -677,7 +678,9 @@ class API {

// TODO
struct UEngine : public UObject {

static UEngine* get() {
return API::get()->get_engine();
}
};

struct UGameEngine : public UEngine {
Expand All @@ -689,7 +692,9 @@ class API {
};

struct FUObjectArray {

static FUObjectArray* get() {
return API::get()->get_uobject_array();
}
};

// One of the very few non-opaque structs
Expand Down Expand Up @@ -730,6 +735,100 @@ class API {

return data + count;
}

bool empty() const {
return count == 0 || data == nullptr;
}
};

public:
// UEVR specific stuff
struct UObjectHook {
struct MotionControllerState;

static void activate() {
static const auto fn = initialize()->activate;
fn();
}

static bool exists(UObject* obj) {
static const auto fn = initialize()->exists;
return fn(obj->to_handle());
}

static std::vector<UObject*> get_objects_by_class(UClass* c, bool allow_default = false) {
if (c == nullptr) {
return {};
}

return c->get_objects_matching(allow_default);
}

static UObject* get_first_object_by_class(UClass* c, bool allow_default = false) {
if (c == nullptr) {
return nullptr;
}

return c->get_first_object_matching(allow_default);
}

// Must be a USceneComponent
// Also, do NOT keep the pointer around, it will be invalidated at any time
// Call it every time you need it
static MotionControllerState* get_or_add_motion_controller_state(UObject* obj) {
static const auto fn = initialize()->get_or_add_motion_controller_state;
return (MotionControllerState*)fn(obj->to_handle());
}

static MotionControllerState* get_motion_controller_state(UObject* obj) {
static const auto fn = initialize()->get_motion_controller_state;
return (MotionControllerState*)fn(obj->to_handle());
}

struct MotionControllerState {
inline UEVR_UObjectHookMotionControllerStateHandle to_handle() { return (UEVR_UObjectHookMotionControllerStateHandle)this; }
inline UEVR_UObjectHookMotionControllerStateHandle to_handle() const { return (UEVR_UObjectHookMotionControllerStateHandle)this; }

void set_rotation_offset(const UEVR_Quaternionf* offset) {
static const auto fn = initialize()->set_rotation_offset;
fn(to_handle(), offset);
}

void set_location_offset(const UEVR_Vector3f* offset) {
static const auto fn = initialize()->set_location_offset;
fn(to_handle(), offset);
}

void set_hand(uint32_t hand) {
static const auto fn = initialize()->set_hand;
fn(to_handle(), hand);
}

void set_permanent(bool permanent) {
static const auto fn = initialize()->set_permanent;
fn(to_handle(), permanent);
}

private:
static inline const UEVR_UObjectHookMotionControllerStateFunctions* s_functions{nullptr};
static inline const UEVR_UObjectHookMotionControllerStateFunctions* initialize() {
if (s_functions == nullptr) {
s_functions = API::get()->sdk()->uobject_hook->mc_state;
}

return s_functions;
}
};

private:
static inline const UEVR_UObjectHookFunctions* s_functions{nullptr};
static inline const UEVR_UObjectHookFunctions* initialize() {
if (s_functions == nullptr) {
s_functions = API::get()->sdk()->uobject_hook;
}

return s_functions;
}
};

private:
Expand Down
2 changes: 1 addition & 1 deletion src/CommitHash.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#define UEVR_COMMIT_HASH "89f476243d2ebacea6f941a8458dd571a181b568"
#define UEVR_COMMIT_HASH "f48ed675e2c1f8730b2a7ebfb9a1981c9a6ebf3d"
#define UEVR_BUILD_DATE "20.02.2024"
#define UEVR_BUILD_TIME "00:00"
86 changes: 85 additions & 1 deletion src/mods/PluginLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <sdk/UFunction.hpp>
#include <sdk/UGameplayStatics.hpp>
#include <sdk/APlayerController.hpp>
#include <sdk/USceneComponent.hpp>

#include "UObjectHook.hpp"
#include "VR.hpp"
Expand Down Expand Up @@ -507,16 +508,99 @@ namespace uobjecthook {

return get_first_object_by_class((UEVR_UClassHandle)c, allow_default);
}

UEVR_UObjectHookMotionControllerStateHandle get_or_add_motion_controller_state(UEVR_UObjectHandle obj_handle) {
const auto obj = (sdk::USceneComponent*)obj_handle;
if (obj == nullptr || !obj->is_a(sdk::USceneComponent::static_class())) {
return nullptr;
}

const auto result = UObjectHook::get()->get_or_add_motion_controller_state(obj);

return (UEVR_UObjectHookMotionControllerStateHandle)result.get();
}

UEVR_UObjectHookMotionControllerStateHandle get_motion_controller_state(UEVR_UObjectHandle obj_handle) {
const auto obj = (sdk::USceneComponent*)obj_handle;
if (obj == nullptr || !obj->is_a(sdk::USceneComponent::static_class())) {
return nullptr;
}

const auto result = UObjectHook::get()->get_motion_controller_state(obj);

if (!result.has_value()) {
return nullptr;
}

return (UEVR_UObjectHookMotionControllerStateHandle)result->get();
}

namespace mc_state {
void set_rotation_offset(UEVR_UObjectHookMotionControllerStateHandle state, const UEVR_Quaternionf* rotation) {
if (state == nullptr) {
return;
}

auto& s = *(UObjectHook::MotionControllerState*)state;
s.rotation_offset.x = rotation->x;
s.rotation_offset.y = rotation->y;
s.rotation_offset.z = rotation->z;
s.rotation_offset.w = rotation->w;
}

void set_location_offset(UEVR_UObjectHookMotionControllerStateHandle state, const UEVR_Vector3f* location) {
if (state == nullptr) {
return;
}

auto& s = *(UObjectHook::MotionControllerState*)state;
s.location_offset.x = location->x;
s.location_offset.y = location->y;
s.location_offset.z = location->z;
}

void set_hand(UEVR_UObjectHookMotionControllerStateHandle state, unsigned int hand) {
if (state == nullptr) {
return;
}

if (hand > 1) {
return;
}

auto& s = *(UObjectHook::MotionControllerState*)state;
s.hand = (uint8_t)hand;
}

void set_permanent(UEVR_UObjectHookMotionControllerStateHandle state, bool permanent) {
if (state == nullptr) {
return;
}

auto& s = *(UObjectHook::MotionControllerState*)state;
s.permanent = permanent;
}
}
}
}

UEVR_UObjectHookMotionControllerStateFunctions g_mc_functions {
uevr::uobjecthook::mc_state::set_rotation_offset,
uevr::uobjecthook::mc_state::set_location_offset,
uevr::uobjecthook::mc_state::set_hand,
uevr::uobjecthook::mc_state::set_permanent
};

UEVR_UObjectHookFunctions g_uobjecthook_functions {
uevr::uobjecthook::activate,
uevr::uobjecthook::exists,
uevr::uobjecthook::get_objects_by_class,
uevr::uobjecthook::get_objects_by_class_name,
uevr::uobjecthook::get_first_object_by_class,
uevr::uobjecthook::get_first_object_by_class_name
uevr::uobjecthook::get_first_object_by_class_name,
uevr::uobjecthook::get_or_add_motion_controller_state,
uevr::uobjecthook::get_motion_controller_state,
&g_mc_functions
};

#define FFIELDCLASS(x) ((sdk::FFieldClass*)x)
Expand Down
Loading

0 comments on commit c25695a

Please sign in to comment.