From d7fa6fa539c3ee73807b574c51495f2f20344097 Mon Sep 17 00:00:00 2001 From: praydog Date: Sat, 28 Oct 2023 12:56:08 -0700 Subject: [PATCH] UObjectHook: Add WIP overlapper, list of attached components --- src/mods/UObjectHook.cpp | 159 ++++++++++++++++++++++++++++++++++++++- src/mods/UObjectHook.hpp | 3 + 2 files changed, 159 insertions(+), 3 deletions(-) diff --git a/src/mods/UObjectHook.cpp b/src/mods/UObjectHook.cpp index 4de786d0..e0cf964f 100644 --- a/src/mods/UObjectHook.cpp +++ b/src/mods/UObjectHook.cpp @@ -305,6 +305,11 @@ void UObjectHook::on_pre_calculate_stereo_view_offset(void* stereo_device, const return result; }; + if (m_overlap_detection_actor != nullptr && this->exists(m_overlap_detection_actor)) { + m_overlap_detection_actor->set_actor_location(right_hand_position, false, false); + m_overlap_detection_actor->set_actor_rotation(right_hand_euler, false); + } + const auto objs = with_mutex([this]() { return m_motion_controller_attached_objects; }); for (auto object : objs) { @@ -509,6 +514,67 @@ void UObjectHook::on_post_calculate_stereo_view_offset(void* stereo_device, cons VR::get()->set_aim_allowed(!any_adjusting); } +void UObjectHook::spawn_overlapper() { + GameThreadWorker::get().enqueue([this]() { + if (m_overlap_detection_actor != nullptr && this->exists(m_overlap_detection_actor)) { + return; + } + + auto ugs = sdk::UGameplayStatics::get(); + auto world = sdk::UGameEngine::get()->get_world(); + + if (ugs == nullptr || world == nullptr) { + return; + } + + auto overlapper = ugs->spawn_actor(world, sdk::AActor::static_class(), glm::vec3{0, 0, 0}); + m_overlap_detection_actor = overlapper; + + if (overlapper != nullptr) { + auto add_comp = [&](sdk::UClass* c, std::function fn) -> sdk::UActorComponent* { + if (c == nullptr) { + SPDLOG_ERROR("[UObjectHook] Cannot add component of null class"); + return nullptr; + } + + auto new_comp = overlapper->add_component_by_class(c); + + if (new_comp != nullptr) { + fn(new_comp); + + if (new_comp->is_a(sdk::USceneComponent::static_class())) { + auto scene_comp = (sdk::USceneComponent*)new_comp; + scene_comp->set_hidden_in_game(false); + } + + overlapper->finish_add_component(new_comp); + } else { + SPDLOG_ERROR("[UObjectHook] Failed to add component {} to overlapper", utility::narrow(c->get_full_name())); + } + + return new_comp; + }; + + add_comp(sdk::find_uobject(L"Class /Script/Engine.SphereComponent"), [](sdk::UActorComponent* new_comp) { + struct SphereRadiusParams { + float radius{}; + bool update_overlaps{true}; + } params{}; + + params.radius = 10.0f; + + const auto fn = new_comp->get_class()->find_function(L"SetSphereRadius"); + + if (fn != nullptr) { + new_comp->process_event(fn, ¶ms); + } + }); + } else { + SPDLOG_ERROR("[UObjectHook] Failed to spawn actor for overlapper"); + } + }); +} + std::future> sorting_task{}; void UObjectHook::on_draw_ui() { @@ -523,9 +589,89 @@ void UObjectHook::on_draw_ui() { std::shared_lock _{m_mutex}; if (!m_motion_controller_attached_components.empty()) { + const auto made = ImGui::TreeNode("Attached Components"); + + ImGui::SameLine(); if (ImGui::Button("Detach all")) { m_motion_controller_attached_components.clear(); } + + if (made) { + // make a copy because the user could press the detach button while iterating + auto attached = m_motion_controller_attached_components; + + for (auto& it : attached) { + if (!this->exists_unsafe(it.first) || it.second == nullptr) { + continue; + } + + auto comp = it.first; + std::wstring comp_name = comp->get_class()->get_fname().to_string() + L" " + comp->get_fname().to_string(); + + if (ImGui::TreeNode(utility::narrow(comp_name).data())) { + ui_handle_object(comp); + + ImGui::TreePop(); + } + } + + ImGui::TreePop(); + } + } + + if (m_overlap_detection_actor == nullptr) { + if (ImGui::Button("Spawn Overlapper")) { + spawn_overlapper(); + } + } else if (!this->exists_unsafe(m_overlap_detection_actor)) { + m_overlap_detection_actor = nullptr; + } else { + const auto made = ImGui::TreeNode("Overlapped Objects"); + + ImGui::SameLine(); + if (ImGui::Button("Destroy Overlapper")) { + GameThreadWorker::get().enqueue([this]() { + if (!this->exists(m_overlap_detection_actor)) { + return; + } + + m_overlap_detection_actor->destroy_actor(); + m_overlap_detection_actor = nullptr; + }); + } + + if (made) { + /*auto overlapped = m_overlap_detection_actor->get_overlapping_actors(); + + for (auto& it : overlapped) { + if (!this->exists_unsafe(it)) { + continue; + } + + if (ImGui::TreeNode(utility::narrow(it->get_full_name()).data())) { + ui_handle_object(it); + ImGui::TreePop(); + } + }*/ + + auto overlapped_components = m_overlap_detection_actor->get_overlapping_components(); + + for (auto& it : overlapped_components) { + auto comp = (sdk::USceneComponent*)it; + if (!this->exists_unsafe(comp)) { + continue; + } + + std::wstring comp_name = comp->get_class()->get_fname().to_string() + L" " + comp->get_fname().to_string(); + + if (ImGui::TreeNode(utility::narrow(comp_name).data())) { + ui_handle_object(comp); + ImGui::TreePop(); + } + } + + ImGui::TreePop(); + } } ImGui::Text("Objects: %zu (%zu actual)", m_objects.size(), sdk::FUObjectArray::get()->get_object_count()); @@ -859,10 +1005,12 @@ void UObjectHook::ui_handle_object(sdk::UObject* object) { m_motion_controller_attached_components.erase(comp); } - ImGui::SameLine(); - auto& state = m_motion_controller_attached_components[comp]; + if (m_motion_controller_attached_components.contains(comp)) { + ImGui::SameLine(); + auto& state = m_motion_controller_attached_components[comp]; - ImGui::Checkbox("Adjust", &state->adjusting); + ImGui::Checkbox("Adjust", &state->adjusting); + } } else { if (ImGui::Button("Attach left")) { m_motion_controller_attached_components[comp] = std::make_shared(); @@ -1262,6 +1410,11 @@ void UObjectHook::ui_handle_struct(void* addr, sdk::UStruct* uclass) { return; } + if (addr != nullptr && this->exists_unsafe((sdk::UObject*)addr) && uclass->is_a(sdk::UStruct::static_class())) { + uclass = (sdk::UStruct*)addr; + addr = nullptr; + } + // Display inheritance tree if (ImGui::TreeNode("Inheritance")) { for (auto super = (sdk::UStruct*)uclass; super != nullptr; super = super->get_super_struct()) { diff --git a/src/mods/UObjectHook.hpp b/src/mods/UObjectHook.hpp index 08936524..718d69d2 100644 --- a/src/mods/UObjectHook.hpp +++ b/src/mods/UObjectHook.hpp @@ -66,6 +66,8 @@ class UObjectHook : public Mod { void ui_handle_material_interface(sdk::UObject* object); void ui_handle_actor(sdk::UObject* object); + void spawn_overlapper(); + static void* add_object(void* rcx, void* rdx, void* r8, void* r9); static void* destructor(sdk::UObjectBase* object, void* rdx, void* r8, void* r9); @@ -108,4 +110,5 @@ class UObjectHook : public Mod { }; std::unordered_map> m_motion_controller_attached_components{}; + sdk::AActor* m_overlap_detection_actor{nullptr}; }; \ No newline at end of file