From 6f4e4a2499d3e8739e7819c6e6c3e50c32e2246a Mon Sep 17 00:00:00 2001 From: joeyhodge <96703964+joeyhodge@users.noreply.github.com> Date: Sun, 16 Nov 2025 16:44:06 -0500 Subject: [PATCH] Refactor UI Invert Alpha to slider and migrate config Changed UI Invert Alpha from a boolean toggle to a float slider (0.01-0.99) for finer control. Added migration logic to handle legacy config values, updated shader and D3D12 blend logic to use the new alpha value, and refactored related code and UI. Also added 2 new options for those without touchpads such as reverbg2 (thanks wdoo2 for this), and improved DPad gesture handling and snapturn logic in VR mod. If needed to split up into two different pull requests I can do that as well --- MakeCommitHash.bat | 8 +- src/Mod.hpp | 2 +- src/Mods.cpp | 142 +++- src/mods/VR.cpp | 101 ++- src/mods/VR.hpp | 16 +- src/mods/vr/D3D12Component.cpp | 24 +- src/mods/vr/OverlayComponent.cpp | 169 ++++- src/mods/vr/OverlayComponent.hpp | 8 +- src/mods/vr/d3d12/DirectXTK.cpp | 72 ++- src/mods/vr/d3d12/DirectXTK.hpp | 23 +- ..._luminance_sprite_ps_SpritePixelShader.inc | 604 ++++++++++++++---- .../vr/shaders/alpha_luminance_sprite_ps.fx | 8 +- 12 files changed, 980 insertions(+), 197 deletions(-) diff --git a/MakeCommitHash.bat b/MakeCommitHash.bat index 9cc4ce4b9..fa77f0d73 100644 --- a/MakeCommitHash.bat +++ b/MakeCommitHash.bat @@ -7,10 +7,10 @@ exit /b 0 FOR /F "tokens=*" %%g IN ('git rev-parse HEAD') DO (SET UEVR_COMMIT_HASH=%%g) -FOR /F "tokens=*" %%t IN ('git describe --tags --abbrev^=0') DO (SET UEVR_TAG=%%t) +FOR /F "tokens=*" %%t IN ('git describe --tags --always --abbrev^=0') DO (SET UEVR_TAG=%%t) IF "%UEVR_TAG%"=="" (SET UEVR_TAG=no_tag) -FOR /F "tokens=*" %%c IN ('git describe --tags --long') DO ( +FOR /F "tokens=*" %%c IN ('git describe --tags --always --long') DO ( FOR /F "tokens=1,2 delims=-" %%a IN ("%%c") DO ( SET UEVR_TAG_LONG=%%a SET UEVR_COMMITS_PAST_TAG=%%b @@ -24,7 +24,7 @@ FOR /F "tokens=*" %%b IN ('git rev-parse --abbrev-ref HEAD') DO (SET UEVR_BRANCH FOR /F "tokens=*" %%n IN ('git rev-list --count HEAD') DO (SET UEVR_TOTAL_COMMITS=%%n) IF "%UEVR_TOTAL_COMMITS%"=="" (SET UEVR_TOTAL_COMMITS=0) -FOR /F "tokens=2 delims==" %%a IN ('wmic OS get localdatetime /value') DO ( +FOR /F "tokens=*" %%a IN ('powershell -NoProfile -Command "Get-Date -Format yyyyMMddHHmmss"') DO ( SET datetime=%%a ) @@ -42,4 +42,4 @@ echo #define UEVR_COMMITS_PAST_TAG %UEVR_COMMITS_PAST_TAG% >> src/CommitHash.aut echo #define UEVR_BRANCH "%UEVR_BRANCH%" >> src/CommitHash.autogenerated echo #define UEVR_TOTAL_COMMITS %UEVR_TOTAL_COMMITS% >> src/CommitHash.autogenerated echo #define UEVR_BUILD_DATE "%day%.%month%.%year%" >> src/CommitHash.autogenerated -echo #define UEVR_BUILD_TIME "%hour%:%minute%" >> src/CommitHash.autogenerated \ No newline at end of file +echo #define UEVR_BUILD_TIME "%hour%:%minute%" >> src/CommitHash.autogenerated diff --git a/src/Mod.hpp b/src/Mod.hpp index d734e08f1..0d56608b0 100644 --- a/src/Mod.hpp +++ b/src/Mod.hpp @@ -126,7 +126,7 @@ class ModValue : public IModValue { return m_value; } - T& default_value() { + const T& default_value() const { return m_default_value; } diff --git a/src/Mods.cpp b/src/Mods.cpp index d5d546a4b..4960b3fcf 100644 --- a/src/Mods.cpp +++ b/src/Mods.cpp @@ -1,3 +1,10 @@ +#include +#include +#include +#include +#include +#include + #include #include "Framework.hpp" @@ -9,6 +16,128 @@ #include "mods/UObjectHook.hpp" #include "Mods.hpp" +namespace { + +constexpr const char* UI_INVERT_ALPHA_KEY = "UI_InvertAlpha"; +const std::string UI_INVERT_ALPHA_KEY_STRING{UI_INVERT_ALPHA_KEY}; +constexpr float UI_INVERT_ALPHA_SLIDER_MIN = 0.01f; +constexpr float UI_INVERT_ALPHA_SLIDER_MAX = 0.99f; + +std::string_view trim(std::string_view value) { + while (!value.empty() && std::isspace(static_cast(value.front()))) { + value.remove_prefix(1); + } + + while (!value.empty() && std::isspace(static_cast(value.back()))) { + value.remove_suffix(1); + } + + return value; +} + +std::optional parse_float(std::string_view value) { + const auto trimmed = trim(value); + + if (trimmed.empty()) { + return std::nullopt; + } + + std::string buffer{trimmed}; + char* end_ptr{}; + const auto parsed_value = std::strtof(buffer.c_str(), &end_ptr); + + if (end_ptr == buffer.c_str()) { + return std::nullopt; + } + + while (*end_ptr != '\0') { + if (!std::isspace(static_cast(*end_ptr))) { + return std::nullopt; + } + + ++end_ptr; + } + + return parsed_value; +} + +bool migrate_ui_invert_alpha(utility::Config& cfg) { + auto apply_value = [&](float new_value) { + const auto clamped = std::clamp(new_value, UI_INVERT_ALPHA_SLIDER_MIN, UI_INVERT_ALPHA_SLIDER_MAX); + cfg.set(UI_INVERT_ALPHA_KEY_STRING, clamped); + return true; + }; + + auto safe_get_bool = [&]() -> std::optional { + try { + if (auto value = cfg.get(UI_INVERT_ALPHA_KEY_STRING)) { + return *value; + } + } catch (...) { + } + + return std::nullopt; + }; + + if (auto legacy_bool = safe_get_bool()) { + return apply_value(*legacy_bool ? UI_INVERT_ALPHA_SLIDER_MAX : UI_INVERT_ALPHA_SLIDER_MIN); + } + + auto safe_get_float = [&]() -> std::optional { + try { + if (auto value = cfg.get(UI_INVERT_ALPHA_KEY_STRING)) { + return *value; + } + } catch (...) { + } + + return std::nullopt; + }; + + if (auto legacy_float = safe_get_float()) { + if (*legacy_float < UI_INVERT_ALPHA_SLIDER_MIN || *legacy_float > UI_INVERT_ALPHA_SLIDER_MAX) { + return apply_value(*legacy_float); + } + + return false; + } + + auto safe_get_string = [&]() -> std::optional { + try { + return cfg.get(UI_INVERT_ALPHA_KEY_STRING); + } catch (...) { + return std::nullopt; + } + }; + + if (auto legacy_string = safe_get_string()) { + const auto trimmed = trim(*legacy_string); + + if (!trimmed.empty()) { + std::string lowered{trimmed}; + std::transform(lowered.begin(), lowered.end(), lowered.begin(), [](unsigned char c) { + return static_cast(std::tolower(c)); + }); + + if (lowered == "true" || lowered == "false") { + return apply_value(lowered == "true" ? UI_INVERT_ALPHA_SLIDER_MAX : UI_INVERT_ALPHA_SLIDER_MIN); + } + + if (lowered == "1" || lowered == "0") { + return apply_value(lowered == "1" ? UI_INVERT_ALPHA_SLIDER_MAX : UI_INVERT_ALPHA_SLIDER_MIN); + } + + if (auto parsed = parse_float(trimmed)) { + return apply_value(*parsed); + } + } + } + + return false; +} + +} // namespace + Mods::Mods() { m_mods.emplace_back(FrameworkConfig::get()); m_mods.emplace_back(VR::get()); @@ -54,12 +183,23 @@ std::optional Mods::on_initialize_d3d_thread() const { } void Mods::reload_config(bool set_defaults) const { - utility::Config cfg{ Framework::get_persistent_dir("config.txt").string() }; + const auto config_path = Framework::get_persistent_dir("config.txt"); + utility::Config cfg{ config_path.string() }; + + const auto migrated_invert_alpha = !set_defaults && migrate_ui_invert_alpha(cfg); for (auto& mod : m_mods) { spdlog::info("{:s}::on_config_load()", mod->get_name().data()); mod->on_config_load(cfg, set_defaults); } + + if (migrated_invert_alpha) { + if (!cfg.save(config_path.string())) { + spdlog::warn("Failed to persist migrated UI_InvertAlpha value"); + } else { + spdlog::info("Persisted migrated UI_InvertAlpha value"); + } + } } void Mods::on_pre_imgui_frame() const { diff --git a/src/mods/VR.cpp b/src/mods/VR.cpp index acdb0e667..7dffa4d64 100644 --- a/src/mods/VR.cpp +++ b/src/mods/VR.cpp @@ -876,6 +876,8 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.sThumbRY = (int16_t)std::clamp(((float)state->Gamepad.sThumbRY + right_joystick_axis.y * 32767.0f), -32767.0f, 32767.0f); bool already_dpad_shifted{false}; + bool true_left_joystick_as_dpad{false}; + bool true_right_joystick_as_dpad{false}; if (m_dpad_gesture_state.direction != DPadGestureState::Direction::NONE) { already_dpad_shifted = true; @@ -896,9 +898,14 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; } - // Zero out the thumbstick values - state->Gamepad.sThumbLX = 0; - state->Gamepad.sThumbLY = 0; + DPadMethod dpad_method = get_dpad_method(); + if (dpad_method == DPadMethod::GESTURE_HEAD){ + true_left_joystick_as_dpad = true; + } + else if (dpad_method == DPadMethod::GESTURE_HEAD_RIGHT) { + true_right_joystick_as_dpad = true; + } + std::scoped_lock _{m_dpad_gesture_state.mtx}; m_dpad_gesture_state.direction = DPadGestureState::Direction::NONE; @@ -919,7 +926,10 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE button_touch_inactive = !is_action_active_any_joystick(m_action_a_button_touch_left) && !is_action_active_any_joystick(m_action_b_button_touch_left); } - const auto dpad_active = (button_touch_inactive && thumbrest_check) || dpad_method == DPadMethod::LEFT_JOYSTICK || dpad_method == DPadMethod::RIGHT_JOYSTICK; + // Toggling UEVR menu using L3 + R3 has higher priority + const auto dpad_active = (is_right_joystick_click_down && (dpad_method == DPadMethod::RIGHT_JOYSTICK_CLICK) && (! is_left_joystick_click_down)) + || (is_left_joystick_click_down && (dpad_method == DPadMethod::LEFT_JOYSTICK_CLICK) && (! is_right_joystick_click_down)) + || (button_touch_inactive && thumbrest_check) || dpad_method == DPadMethod::LEFT_JOYSTICK || dpad_method == DPadMethod::RIGHT_JOYSTICK; if (dpad_active) { float ty{0.0f}; @@ -927,17 +937,19 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE //SHORT ThumbY{0}; //SHORT ThumbX{0}; // If someone is accidentally touching both thumbrests while also moving a joystick, this will default to left joystick. - if (dpad_method == DPadMethod::RIGHT_TOUCH || dpad_method == DPadMethod::LEFT_JOYSTICK) { + if (dpad_method == DPadMethod::RIGHT_TOUCH || dpad_method == DPadMethod::LEFT_JOYSTICK || dpad_method == DPadMethod::RIGHT_JOYSTICK_CLICK) { //ThumbY = state->Gamepad.sThumbLY; //ThumbX = state->Gamepad.sThumbLX; ty = true_left_joystick_axis.y; tx = true_left_joystick_axis.x; + true_left_joystick_as_dpad = true; } - else if (dpad_method == DPadMethod::LEFT_TOUCH || dpad_method == DPadMethod::RIGHT_JOYSTICK) { + else if (dpad_method == DPadMethod::LEFT_TOUCH || dpad_method == DPadMethod::RIGHT_JOYSTICK || dpad_method == DPadMethod::LEFT_JOYSTICK_CLICK) { //ThumbY = state->Gamepad.sThumbRY; //ThumbX = state->Gamepad.sThumbRX; ty = true_right_joystick_axis.y; tx = true_right_joystick_axis.x; + true_right_joystick_as_dpad = true; } if (ty >= 0.5f) { @@ -956,27 +968,40 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE state->Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_LEFT; } - if (dpad_method == DPadMethod::RIGHT_TOUCH || dpad_method == DPadMethod::LEFT_JOYSTICK) { - if (!wants_swap) { - state->Gamepad.sThumbLY = 0; - state->Gamepad.sThumbLX = 0; - } else { - state->Gamepad.sThumbRY = 0; - state->Gamepad.sThumbRX = 0; - } + if(dpad_method == DPadMethod::RIGHT_JOYSTICK_CLICK) + { + state->Gamepad.wButtons &= ~XINPUT_GAMEPAD_RIGHT_THUMB; } - else if (dpad_method == DPadMethod::LEFT_TOUCH || dpad_method == DPadMethod::RIGHT_JOYSTICK) { - if (!wants_swap) { - state->Gamepad.sThumbRY = 0; - state->Gamepad.sThumbRX = 0; - } else { - state->Gamepad.sThumbLY = 0; - state->Gamepad.sThumbLX = 0; - } + else if(dpad_method == DPadMethod::LEFT_JOYSTICK_CLICK) + { + state->Gamepad.wButtons &= ~XINPUT_GAMEPAD_LEFT_THUMB; } + + } + } + + // Zero out the thumbstick values + if (true_left_joystick_as_dpad) { + if (!wants_swap) { + state->Gamepad.sThumbLY = 0; + state->Gamepad.sThumbLX = 0; + } else { + state->Gamepad.sThumbRY = 0; + state->Gamepad.sThumbRX = 0; + } + } + else if (true_right_joystick_as_dpad) { + if (!wants_swap) { + state->Gamepad.sThumbRY = 0; + state->Gamepad.sThumbRX = 0; + } else { + state->Gamepad.sThumbLY = 0; + state->Gamepad.sThumbLX = 0; } } + + // Determine if snapturn should be run on frame if (m_snapturn->value()) { DPadMethod dpad_method = get_dpad_method(); @@ -997,12 +1022,17 @@ void VR::on_xinput_get_state(uint32_t* retval, uint32_t user_index, XINPUT_STATE else { stick_axis = right_joystick_axis.x; const auto& thumbrest_touch_left = !wants_swap ? m_action_thumbrest_touch_left : m_action_thumbrest_touch_right; - if (glm::abs(stick_axis) >= snapturn_deadzone && !(dpad_method == DPadMethod::LEFT_TOUCH && is_action_active_any_joystick(thumbrest_touch_left))) { - if (stick_axis < 0) { - m_snapturn_left = true; + const auto& stick_as_dpad = (!wants_swap) ? true_right_joystick_as_dpad : true_left_joystick_as_dpad; + if (glm::abs(stick_axis) >= snapturn_deadzone){ + if(!stick_as_dpad) { + if (stick_axis < 0) { + m_snapturn_left = true; + } + m_snapturn_on_frame = true; } - m_snapturn_on_frame = true; - m_was_snapturn_run_on_input = true; + // Requiring the joystick returning to its natrual position at least once before another snapturn, + // even if no snapturn is actually run + m_was_snapturn_run_on_input = true; } } } @@ -1928,10 +1958,10 @@ void VR::handle_keybinds() { recenter_view(); } - if (m_keybind_recenter_horizon->is_key_down_once()) { + if (m_keybind_recenter_horizon->is_key_down_once()) { recenter_horizon(); - } - + } + if (m_keybind_load_camera_0->is_key_down_once()) { load_camera(0); } @@ -2589,7 +2619,7 @@ void VR::on_draw_sidebar_entry(std::string_view name) { ImGui::SetNextItemOpen(true, ImGuiCond_::ImGuiCond_Once); if (ImGui::TreeNode("Playspace Keys")) { m_keybind_recenter->draw("Recenter View Key"); - m_keybind_recenter_horizon->draw("Recenter Horizon Key"); + m_keybind_recenter_horizon->draw("Recenter Horizon Key"); m_keybind_set_standing_origin->draw("Set Standing Origin Key"); ImGui::TreePop(); @@ -2760,10 +2790,10 @@ void VR::on_draw_ui() { ImGui::SameLine(); - if (ImGui::Button("Recenter Horizon")) { + if (ImGui::Button("Recenter Horizon")) { recenter_horizon(); } - + if (ImGui::Button("Reinitialize Runtime")) { get_runtime()->wants_reinitialize = true; } @@ -3310,18 +3340,19 @@ void VR::process_snapturn() { } m_snapturn_on_frame = false; + } void VR::update_statistics_overlay(sdk::UGameEngine* engine) { if (engine == nullptr) { return; } - + if (m_show_fps_state != m_show_fps->value()) { engine->exec(L"stat fps"); m_show_fps_state = m_show_fps->value(); } - + if (m_show_statistics_state != m_show_statistics->value()) { engine->exec(L"stat unit"); m_show_statistics_state = m_show_statistics->value(); diff --git a/src/mods/VR.hpp b/src/mods/VR.hpp index f723ee730..8ab900f71 100644 --- a/src/mods/VR.hpp +++ b/src/mods/VR.hpp @@ -52,6 +52,8 @@ class VR : public Mod { RIGHT_JOYSTICK, GESTURE_HEAD, GESTURE_HEAD_RIGHT, + RIGHT_JOYSTICK_CLICK, + LEFT_JOYSTICK_CLICK }; enum HORIZONTAL_PROJECTION_OVERRIDE : int32_t { @@ -242,7 +244,6 @@ class VR : public Mod { void recenter_view(); void recenter_horizon(); - template T* get_runtime() const { return (T*)m_runtime.get(); @@ -850,6 +851,8 @@ class VR : public Mod { "Right Joystick (Disables Standard Joystick Input)", "Gesture (Head) + Left Joystick", "Gesture (Head) + Right Joystick", + "Right Joystick Press + Left Joystick (Disables R3)", + "Left Joystick Press + Right Joystick (Disables L3)" }; static const inline std::vector s_horizontal_projection_override_names{ @@ -1006,8 +1009,8 @@ class VR : public Mod { void load_cameras(); void load_camera(int index); void save_camera(int index); - -public: + + public: VR() { m_options = { *m_rendering_method, @@ -1088,14 +1091,15 @@ class VR : public Mod { bool m_wait_for_present{true}; const ModToggle::Ptr m_controllers_allowed{ ModToggle::create(generate_name("ControllersAllowed"), true) }; bool m_controller_test_mode{false}; - + const ModToggle::Ptr m_show_fps{ ModToggle::create(generate_name("ShowFPSOverlay"), false) }; - bool m_show_fps_state{false}; + bool m_show_fps_state{ false }; const ModToggle::Ptr m_show_statistics{ ModToggle::create(generate_name("ShowStatsOverlay"), false) }; - bool m_show_statistics_state{false}; + bool m_show_statistics_state{ false }; void update_statistics_overlay(sdk::UGameEngine* engine); + int m_game_frame_count{}; int m_frame_count{}; diff --git a/src/mods/vr/D3D12Component.cpp b/src/mods/vr/D3D12Component.cpp index ad339e812..68fa51f6c 100644 --- a/src/mods/vr/D3D12Component.cpp +++ b/src/mods/vr/D3D12Component.cpp @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "Framework.hpp" #include "../VR.hpp" @@ -71,7 +73,7 @@ vr::EVRCompositorError D3D12Component::on_frame(VR* vr) { return vr::VRCompositorError_None; } - const auto ui_should_invert_alpha = vr->get_overlay_component().should_invert_ui_alpha(); + const auto ui_invert_alpha = vr->get_overlay_component().get_ui_invert_alpha(); // Update the UI overlay. auto runtime = vr->get_runtime(); @@ -269,8 +271,18 @@ vr::EVRCompositorError D3D12Component::on_frame(VR* vr) { const auto is_2d_screen = vr->is_using_2d_screen(); auto draw_2d_view = [&](d3d12::CommandContext& commands, ID3D12Resource* render_target) { - if (ui_should_invert_alpha && m_game_ui_tex.texture.Get() != nullptr && m_game_ui_tex.srv_heap != nullptr) { - d3d12::render_srv_to_rtv(m_ui_batch_alpha_invert.get(), commands.cmd_list.Get(), m_game_ui_tex, m_game_ui_tex, std::nullopt, ENGINE_SRC_COLOR, ENGINE_SRC_COLOR); + if (ui_invert_alpha > 0.0f && m_game_ui_tex.texture.Get() != nullptr && m_game_ui_tex.srv_heap != nullptr) { + const std::array blend_factor{ 1.0f, 1.0f, 1.0f, ui_invert_alpha }; + const DirectX::XMFLOAT4 invert_alpha_tint{ 1.0f, 1.0f, 1.0f, ui_invert_alpha }; + d3d12::render_srv_to_rtv( + m_ui_batch_alpha_invert.get(), + commands.cmd_list.Get(), + m_game_ui_tex, + m_game_ui_tex, + ENGINE_SRC_COLOR, + ENGINE_SRC_COLOR, + blend_factor, + invert_alpha_tint); } draw_spectator_view(commands.cmd_list.Get(), is_right_eye_frame); @@ -349,7 +361,7 @@ vr::EVRCompositorError D3D12Component::on_frame(VR* vr) { // Draws the spectator view auto clear_rt = [&](d3d12::CommandContext& commands) { - const float ui_clear_color[] = { 0.0f, 0.0f, 0.0f, ui_should_invert_alpha ? 1.0f : 0.0f }; + const float ui_clear_color[] = { 0.0f, 0.0f, 0.0f, ui_invert_alpha }; commands.clear_rtv(m_game_ui_tex, (float*)&ui_clear_color, ENGINE_SRC_COLOR); }; @@ -1269,8 +1281,8 @@ bool D3D12Component::setup() { bdrt.DestBlend = D3D12_BLEND_ZERO; bdrt.BlendOp = D3D12_BLEND_OP_ADD; - bdrt.SrcBlendAlpha = D3D12_BLEND_ONE; - bdrt.DestBlendAlpha = D3D12_BLEND_ZERO; + bdrt.SrcBlendAlpha = D3D12_BLEND_BLEND_FACTOR; + bdrt.DestBlendAlpha = D3D12_BLEND_INV_BLEND_FACTOR; bdrt.BlendOpAlpha = D3D12_BLEND_OP_ADD; bdrt.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; diff --git a/src/mods/vr/OverlayComponent.cpp b/src/mods/vr/OverlayComponent.cpp index 74b1574ab..e32c142c7 100644 --- a/src/mods/vr/OverlayComponent.cpp +++ b/src/mods/vr/OverlayComponent.cpp @@ -1,3 +1,12 @@ +#include +#include +#include +#include +#include +#include +#include +#include + #include #include @@ -193,12 +202,171 @@ void OverlayComponent::on_config_save(utility::Config& cfg) { for (IModValue& option : m_options) { option.config_save(cfg); } + + if (m_should_reserialize_ui_invert_alpha) { + const auto clamped_value = std::clamp(m_ui_invert_alpha->value(), 0.01f, 0.99f); + cfg.set(m_ui_invert_alpha->get_config_name(), clamped_value); + m_should_reserialize_ui_invert_alpha = false; + } } void OverlayComponent::on_config_load(const utility::Config& cfg, bool set_defaults) { for (IModValue& option : m_options) { + if (&option == m_ui_invert_alpha.get()) { + continue; + } + option.config_load(cfg, set_defaults); } + + if (set_defaults) { + const float default_value = m_ui_invert_alpha->default_value(); + m_ui_invert_alpha->value() = std::clamp(default_value, 0.01f, 0.99f); + m_should_reserialize_ui_invert_alpha = false; + return; + } + + m_should_reserialize_ui_invert_alpha = false; + + const auto config_name = m_ui_invert_alpha->get_config_name(); + + constexpr auto slider_min = 0.01f; + constexpr auto slider_max = 0.99f; + + auto apply_invert_alpha = [&](float new_value, bool mark_for_reserialize) { + const auto clamped_value = std::clamp(new_value, slider_min, slider_max); + if (std::abs(clamped_value - new_value) > std::numeric_limits::epsilon()) { + mark_for_reserialize = true; + } + + m_ui_invert_alpha->value() = clamped_value; + m_should_reserialize_ui_invert_alpha |= mark_for_reserialize; + }; + + auto apply_legacy_toggle = [&](bool enabled) { + apply_invert_alpha(enabled ? slider_max : slider_min, true); + }; + + auto trim = [](std::string_view value) { + while (!value.empty() && std::isspace(static_cast(value.front()))) { + value.remove_prefix(1); + } + + while (!value.empty() && std::isspace(static_cast(value.back()))) { + value.remove_suffix(1); + } + + return value; + }; + + auto parse_float = [&](std::string_view value) -> std::optional { + const auto trimmed = trim(value); + + if (trimmed.empty()) { + return std::nullopt; + } + + std::string buffer{trimmed}; + char* end_ptr{}; + const auto parsed_value = std::strtof(buffer.c_str(), &end_ptr); + + if (end_ptr == buffer.c_str()) { + return std::nullopt; + } + + while (*end_ptr != '\0') { + if (!std::isspace(static_cast(*end_ptr))) { + return std::nullopt; + } + + ++end_ptr; + } + + return parsed_value; + }; + + auto try_apply_from_float = [&](std::optional candidate) { + if (!candidate) { + return false; + } + + const auto value = *candidate; + + if (value <= 0.0f || value >= 1.0f) { + apply_legacy_toggle(value >= 1.0f); + return true; + } + + apply_invert_alpha(value, value < slider_min || value > slider_max); + return true; + }; + + auto safe_get_float = [&]() -> std::optional { + try { + if (auto value = cfg.get(config_name)) { + return *value; + } + } catch (...) { + } + + return std::nullopt; + }; + + if (try_apply_from_float(safe_get_float())) { + return; + } + + auto safe_get_string = [&]() -> std::optional { + try { + return cfg.get(config_name); + } catch (...) { + return std::nullopt; + } + }; + + if (auto raw_value = safe_get_string()) { + const auto trimmed = trim(*raw_value); + + if (!trimmed.empty()) { + std::string lowered{trimmed}; + std::transform(lowered.begin(), lowered.end(), lowered.begin(), [](unsigned char c) { + return static_cast(std::tolower(c)); + }); + + if (lowered == "true" || lowered == "false") { + apply_legacy_toggle(lowered == "true"); + return; + } + + if (lowered == "1" || lowered == "0") { + apply_legacy_toggle(lowered == "1"); + return; + } + + if (auto parsed = parse_float(trimmed)) { + apply_invert_alpha(*parsed, true); + return; + } + } + } + + auto safe_get_bool = [&]() -> std::optional { + try { + if (auto value = cfg.get(config_name)) { + return *value; + } + } catch (...) { + } + + return std::nullopt; + }; + + if (auto legacy_toggle = safe_get_bool()) { + apply_legacy_toggle(*legacy_toggle); + return; + } + + m_ui_invert_alpha->value() = std::clamp(m_ui_invert_alpha->value(), slider_min, slider_max); } void OverlayComponent::on_draw_ui() { @@ -223,7 +391,6 @@ void OverlayComponent::on_draw_ui() { m_slate_distance->draw("UI Distance"); m_slate_size->draw("UI Size"); m_ui_follows_view->draw("UI Follows View"); - ImGui::SameLine(); m_ui_invert_alpha->draw("UI Invert Alpha"); m_framework_distance->draw("Framework Distance"); diff --git a/src/mods/vr/OverlayComponent.hpp b/src/mods/vr/OverlayComponent.hpp index 1fceacff0..398d52dc4 100644 --- a/src/mods/vr/OverlayComponent.hpp +++ b/src/mods/vr/OverlayComponent.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "Mod.hpp" @@ -42,8 +43,8 @@ class OverlayComponent : public ModComponent { return m_intersect_state; } - bool should_invert_ui_alpha() const { - return m_ui_invert_alpha->value(); + float get_ui_invert_alpha() const { + return std::clamp(m_ui_invert_alpha->value(), 0.01f, 0.99f); } private: @@ -80,6 +81,7 @@ class OverlayComponent : public ModComponent { bool m_just_closed_ui{false}; bool m_just_opened_ui{false}; bool m_forced_aim{false}; + bool m_should_reserialize_ui_invert_alpha{false}; glm::vec2 m_last_mouse_pos{}; std::chrono::steady_clock::time_point m_last_mouse_move_time{}; @@ -106,7 +108,7 @@ class OverlayComponent : public ModComponent { const ModSlider::Ptr m_slate_size{ ModSlider::create("UI_Size", 0.5f, 10.0f, 2.0f) }; const ModSlider::Ptr m_slate_cylinder_angle{ ModSlider::create("UI_Cylinder_Angle", 0.0f, 360.0f, 90.0f) }; const ModToggle::Ptr m_ui_follows_view{ ModToggle::create("UI_FollowView", false) }; - const ModToggle::Ptr m_ui_invert_alpha{ ModToggle::create("UI_InvertAlpha", false) }; + const ModSlider::Ptr m_ui_invert_alpha{ ModSlider::create("UI_InvertAlpha", 0.01f, 0.99f, 0.01f) }; const ModSlider::Ptr m_framework_distance{ ModSlider::create("UI_Framework_Distance", 0.5f, 10.0f, 1.75f) }; const ModSlider::Ptr m_framework_size{ ModSlider::create("UI_Framework_Size", 0.5f, 10.0f, 2.0f) }; diff --git a/src/mods/vr/d3d12/DirectXTK.cpp b/src/mods/vr/d3d12/DirectXTK.cpp index 4e2b403d2..5b68dfcda 100644 --- a/src/mods/vr/d3d12/DirectXTK.cpp +++ b/src/mods/vr/d3d12/DirectXTK.cpp @@ -1,13 +1,16 @@ #include "DirectXTK.hpp" +#include namespace d3d12 { void render_srv_to_rtv( DirectX::DX12::SpriteBatch* batch, - ID3D12GraphicsCommandList* command_list, - const d3d12::TextureContext& src, - const d3d12::TextureContext& dst, - D3D12_RESOURCE_STATES src_state, - D3D12_RESOURCE_STATES dst_state) + ID3D12GraphicsCommandList* command_list, + const d3d12::TextureContext& src, + const d3d12::TextureContext& dst, + D3D12_RESOURCE_STATES src_state, + D3D12_RESOURCE_STATES dst_state, + std::optional> blend_factor, + std::optional tint) { if (src.texture == nullptr || dst.texture == nullptr) { return; @@ -55,6 +58,13 @@ void render_srv_to_rtv( command_list->RSSetScissorRects(1, &scissor_rect); batch->Begin(command_list, DirectX::DX12::SpriteSortMode::SpriteSortMode_Immediate); + + float blend_factor_values[4]{ 1.0f, 1.0f, 1.0f, 1.0f }; + if (blend_factor) { + std::copy(blend_factor->begin(), blend_factor->end(), blend_factor_values); + } + + command_list->OMSetBlendFactor(blend_factor_values); RECT dest_rect{ 0, 0, (LONG)dst_desc.Width, (LONG)dst_desc.Height }; @@ -62,10 +72,12 @@ void render_srv_to_rtv( ID3D12DescriptorHeap* game_heaps[] = { src.srv_heap->Heap() }; command_list->SetDescriptorHeaps(1, game_heaps); - batch->Draw(src.get_srv_gpu(), + const auto draw_color = tint ? DirectX::XMLoadFloat4(&tint.value()) : DirectX::Colors::White; + + batch->Draw(src.get_srv_gpu(), DirectX::XMUINT2{ (uint32_t)src_desc.Width, (uint32_t)src_desc.Height }, dest_rect, - DirectX::Colors::White); + draw_color); batch->End(); @@ -83,8 +95,10 @@ void render_srv_to_rtv( const d3d12::TextureContext& src, const d3d12::TextureContext& dst, std::optional src_rect, - D3D12_RESOURCE_STATES src_state, - D3D12_RESOURCE_STATES dst_state) + D3D12_RESOURCE_STATES src_state, + D3D12_RESOURCE_STATES dst_state, + std::optional> blend_factor, + std::optional tint) { if (src.texture == nullptr || dst.texture == nullptr) { return; @@ -132,6 +146,13 @@ void render_srv_to_rtv( command_list->RSSetScissorRects(1, &scissor_rect); batch->Begin(command_list, DirectX::DX12::SpriteSortMode::SpriteSortMode_Immediate); + + float blend_factor_values[4]{ 1.0f, 1.0f, 1.0f, 1.0f }; + if (blend_factor) { + std::copy(blend_factor->begin(), blend_factor->end(), blend_factor_values); + } + + command_list->OMSetBlendFactor(blend_factor_values); RECT dest_rect{ 0, 0, (LONG)dst_desc.Width, (LONG)dst_desc.Height }; @@ -139,17 +160,19 @@ void render_srv_to_rtv( ID3D12DescriptorHeap* game_heaps[] = { src.srv_heap->Heap() }; command_list->SetDescriptorHeaps(1, game_heaps); + const auto draw_color = tint ? DirectX::XMLoadFloat4(&tint.value()) : DirectX::Colors::White; + if (src_rect) { - batch->Draw(src.get_srv_gpu(), + batch->Draw(src.get_srv_gpu(), DirectX::XMUINT2{ (uint32_t)src_desc.Width, (uint32_t)src_desc.Height }, dest_rect, &*src_rect, - DirectX::Colors::White); + draw_color); } else { - batch->Draw(src.get_srv_gpu(), + batch->Draw(src.get_srv_gpu(), DirectX::XMUINT2{ (uint32_t)src_desc.Width, (uint32_t)src_desc.Height }, dest_rect, - DirectX::Colors::White); + draw_color); } batch->End(); @@ -169,8 +192,10 @@ void render_srv_to_rtv( const d3d12::TextureContext& dst, std::optional src_rect, std::optional dest_rect, - D3D12_RESOURCE_STATES src_state, - D3D12_RESOURCE_STATES dst_state) + D3D12_RESOURCE_STATES src_state, + D3D12_RESOURCE_STATES dst_state, + std::optional> blend_factor, + std::optional tint) { if (src.texture == nullptr || dst.texture == nullptr) { return; @@ -218,6 +243,13 @@ void render_srv_to_rtv( command_list->RSSetScissorRects(1, &scissor_rect); batch->Begin(command_list, DirectX::DX12::SpriteSortMode::SpriteSortMode_Immediate); + + float blend_factor_values[4]{ 1.0f, 1.0f, 1.0f, 1.0f }; + if (blend_factor) { + std::copy(blend_factor->begin(), blend_factor->end(), blend_factor_values); + } + + command_list->OMSetBlendFactor(blend_factor_values); if (!dest_rect) { dest_rect = RECT{ 0, 0, (LONG)dst_desc.Width, (LONG)dst_desc.Height }; @@ -231,17 +263,19 @@ void render_srv_to_rtv( ID3D12DescriptorHeap* game_heaps[] = { src.srv_heap->Heap() }; command_list->SetDescriptorHeaps(1, game_heaps); + const auto draw_color = tint ? DirectX::XMLoadFloat4(&tint.value()) : DirectX::Colors::White; + if (src_rect) { - batch->Draw(src.get_srv_gpu(), + batch->Draw(src.get_srv_gpu(), DirectX::XMUINT2{ (uint32_t)src_desc.Width, (uint32_t)src_desc.Height }, *dest_rect, &*src_rect, - DirectX::Colors::White); + draw_color); } else { - batch->Draw(src.get_srv_gpu(), + batch->Draw(src.get_srv_gpu(), DirectX::XMUINT2{ (uint32_t)src_desc.Width, (uint32_t)src_desc.Height }, *dest_rect, - DirectX::Colors::White); + draw_color); } batch->End(); diff --git a/src/mods/vr/d3d12/DirectXTK.hpp b/src/mods/vr/d3d12/DirectXTK.hpp index 9a4cda06c..027ba712e 100644 --- a/src/mods/vr/d3d12/DirectXTK.hpp +++ b/src/mods/vr/d3d12/DirectXTK.hpp @@ -1,6 +1,9 @@ #pragma once #include <../../directxtk12-src/Inc/SpriteBatch.h> +#include +#include +#include #include "TextureContext.hpp" @@ -9,9 +12,11 @@ void render_srv_to_rtv( DirectX::DX12::SpriteBatch* sprite_batch, ID3D12GraphicsCommandList* command_list, const d3d12::TextureContext& src, - const d3d12::TextureContext& dst, - D3D12_RESOURCE_STATES src_state, - D3D12_RESOURCE_STATES dst_state); + const d3d12::TextureContext& dst, + D3D12_RESOURCE_STATES src_state, + D3D12_RESOURCE_STATES dst_state, + std::optional> blend_factor = std::nullopt, + std::optional tint = std::nullopt); void render_srv_to_rtv( DirectX::DX12::SpriteBatch* sprite_batch, @@ -19,8 +24,10 @@ void render_srv_to_rtv( const d3d12::TextureContext& src, const d3d12::TextureContext& dst, std::optional src_rect, - D3D12_RESOURCE_STATES src_state, - D3D12_RESOURCE_STATES dst_state); + D3D12_RESOURCE_STATES src_state, + D3D12_RESOURCE_STATES dst_state, + std::optional> blend_factor = std::nullopt, + std::optional tint = std::nullopt); void render_srv_to_rtv( DirectX::DX12::SpriteBatch* sprite_batch, @@ -29,6 +36,8 @@ void render_srv_to_rtv( const d3d12::TextureContext& dst, std::optional src_rect, std::optional dest_rect, - D3D12_RESOURCE_STATES src_state, - D3D12_RESOURCE_STATES dst_state); + D3D12_RESOURCE_STATES src_state, + D3D12_RESOURCE_STATES dst_state, + std::optional> blend_factor = std::nullopt, + std::optional tint = std::nullopt); } \ No newline at end of file diff --git a/src/mods/vr/shaders/Compiled/alpha_luminance_sprite_ps_SpritePixelShader.inc b/src/mods/vr/shaders/Compiled/alpha_luminance_sprite_ps_SpritePixelShader.inc index d2a322f5b..ad6c4f647 100644 --- a/src/mods/vr/shaders/Compiled/alpha_luminance_sprite_ps_SpritePixelShader.inc +++ b/src/mods/vr/shaders/Compiled/alpha_luminance_sprite_ps_SpritePixelShader.inc @@ -1,6 +1,4 @@ -#if 0 -// -// Generated by Microsoft (R) D3D Shader Disassembler +// Generated by dxc v1.8.2505.1 // // // Input signature: @@ -17,115 +15,499 @@ // -------------------- ----- ------ -------- -------- ------- ------ // SV_Target 0 xyzw 0 TARGET float xyzw // -ps_5_0 -dcl_globalFlags refactoringAllowed -dcl_sampler s0, mode_default -dcl_resource_texture2d (float,float,float,float) t0 -dcl_input_ps linear v0.xyzw -dcl_input_ps linear v1.xy -dcl_output o0.xyzw -dcl_temps 1 -sample_indexable(texture2d)(float,float,float,float) r0.xyzw, v1.xyxx, t0.xyzw, s0 -mad r0.xyzw, r0.xyzw, l(1.000000, 1.000000, 1.000000, -1.000000), l(0.000000, 0.000000, 0.000000, 1.000000) -mul o0.xyzw, r0.xyzw, v0.xyzw -ret -// Approximately 0 instruction slots used -#endif +// shader hash: 26c41ea60b2b0b70712e2d069403a8bb +// +// Pipeline Runtime Information: +// +//PSVRuntimeInfo: +// Pixel Shader +// DepthOutput=0 +// SampleFrequency=0 +// MinimumExpectedWaveLaneCount: 0 +// MaximumExpectedWaveLaneCount: 4294967295 +// UsesViewID: false +// SigInputElements: 2 +// SigOutputElements: 1 +// SigPatchConstOrPrimElements: 0 +// SigInputVectors: 2 +// SigOutputVectors[0]: 1 +// SigOutputVectors[1]: 0 +// SigOutputVectors[2]: 0 +// SigOutputVectors[3]: 0 +// EntryFunctionName: SpritePixelShader +// +// +// Input signature: +// +// Name Index InterpMode DynIdx +// -------------------- ----- ---------------------- ------ +// COLOR 0 linear +// TEXCOORD 0 linear +// +// Output signature: +// +// Name Index InterpMode DynIdx +// -------------------- ----- ---------------------- ------ +// SV_Target 0 +// +// Buffer Definitions: +// +// +// Resource Bindings: +// +// Name Type Format Dim ID HLSL Bind Count +// ------------------------------ ---------- ------- ----------- ------- -------------- ------ +// TextureSampler sampler NA NA S0 s0 1 +// Texture texture f32 2d T0 t0 1 +// +// +// ViewId state: +// +// Number of inputs: 6, outputs: 4 +// Outputs dependent on ViewId: { } +// Inputs contributing to computation of Outputs: +// output 0 depends on inputs: { 0, 4, 5 } +// output 1 depends on inputs: { 1, 4, 5 } +// output 2 depends on inputs: { 2, 4, 5 } +// output 3 depends on inputs: { 3, 4, 5 } +// +// target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64" +// target triple = "dxil-ms-dx" +// +// %dx.types.Handle = type { i8* } +// %dx.types.ResRet.f32 = type { float, float, float, float, i32 } +// %"class.Texture2D >" = type { <4 x float>, %"class.Texture2D >::mips_type" } +// %"class.Texture2D >::mips_type" = type { i32 } +// %struct.SamplerState = type { i32 } +// +// define void @SpritePixelShader() { +// %1 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 0, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) +// %2 = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 3, i32 0, i32 0, i1 false) ; CreateHandle(resourceClass,rangeId,index,nonUniformIndex) +// %3 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) +// %4 = call float @dx.op.loadInput.f32(i32 4, i32 1, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) +// %5 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 0, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) +// %6 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 1, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) +// %7 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 2, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) +// %8 = call float @dx.op.loadInput.f32(i32 4, i32 0, i32 0, i8 3, i32 undef) ; LoadInput(inputSigId,rowIndex,colIndex,gsVertexAxis) +// %9 = call %dx.types.ResRet.f32 @dx.op.sample.f32(i32 60, %dx.types.Handle %1, %dx.types.Handle %2, float %3, float %4, float undef, float undef, i32 0, i32 0, i32 undef, float undef) ; Sample(srv,sampler,coord0,coord1,coord2,coord3,offset0,offset1,offset2,clamp) +// %10 = extractvalue %dx.types.ResRet.f32 %9, 0 +// %11 = extractvalue %dx.types.ResRet.f32 %9, 1 +// %12 = extractvalue %dx.types.ResRet.f32 %9, 2 +// %13 = extractvalue %dx.types.ResRet.f32 %9, 3 +// %14 = call float @dx.op.unary.f32(i32 7, float %8) ; Saturate(value) +// %15 = fmul fast float %13, 2.000000e+00 +// %16 = fsub fast float 1.000000e+00, %15 +// %17 = fmul fast float %16, %14 +// %18 = fadd fast float %17, %13 +// %19 = fmul fast float %10, %5 +// %20 = fmul fast float %11, %6 +// %21 = fmul fast float %12, %7 +// call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 0, float %19) ; StoreOutput(outputSigId,rowIndex,colIndex,value) +// call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 1, float %20) ; StoreOutput(outputSigId,rowIndex,colIndex,value) +// call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 2, float %21) ; StoreOutput(outputSigId,rowIndex,colIndex,value) +// call void @dx.op.storeOutput.f32(i32 5, i32 0, i32 0, i8 3, float %18) ; StoreOutput(outputSigId,rowIndex,colIndex,value) +// ret void +// } +// +// Function Attrs: nounwind readnone +// declare float @dx.op.loadInput.f32(i32, i32, i32, i8, i32) #0 +// +// Function Attrs: nounwind +// declare void @dx.op.storeOutput.f32(i32, i32, i32, i8, float) #1 +// +// Function Attrs: nounwind readonly +// declare %dx.types.ResRet.f32 @dx.op.sample.f32(i32, %dx.types.Handle, %dx.types.Handle, float, float, float, float, i32, i32, i32, float) #2 +// +// Function Attrs: nounwind readnone +// declare float @dx.op.unary.f32(i32, float) #0 +// +// Function Attrs: nounwind readonly +// declare %dx.types.Handle @dx.op.createHandle(i32, i8, i32, i32, i1) #2 +// +// attributes #0 = { nounwind readnone } +// attributes #1 = { nounwind } +// attributes #2 = { nounwind readonly } +// +// !llvm.ident = !{!0} +// !dx.version = !{!1} +// !dx.valver = !{!2} +// !dx.shaderModel = !{!3} +// !dx.resources = !{!4} +// !dx.viewIdState = !{!10} +// !dx.entryPoints = !{!11} +// +// !0 = !{!"dxc(private) 1.8.0.4950 (b106a961d)"} +// !1 = !{i32 1, i32 0} +// !2 = !{i32 1, i32 9} +// !3 = !{!"ps", i32 6, i32 0} +// !4 = !{!5, null, null, !8} +// !5 = !{!6} +// !6 = !{i32 0, %"class.Texture2D >"* undef, !"", i32 0, i32 0, i32 1, i32 2, i32 0, !7} +// !7 = !{i32 0, i32 9} +// !8 = !{!9} +// !9 = !{i32 0, %struct.SamplerState* undef, !"", i32 0, i32 0, i32 1, i32 0, null} +// !10 = !{[8 x i32] [i32 6, i32 4, i32 1, i32 2, i32 4, i32 8, i32 15, i32 15]} +// !11 = !{void ()* @SpritePixelShader, !"SpritePixelShader", !12, !4, null} +// !12 = !{!13, !19, null} +// !13 = !{!14, !17} +// !14 = !{i32 0, !"COLOR", i8 9, i8 0, !15, i8 2, i32 1, i8 4, i32 0, i8 0, !16} +// !15 = !{i32 0} +// !16 = !{i32 3, i32 15} +// !17 = !{i32 1, !"TEXCOORD", i8 9, i8 0, !15, i8 2, i32 1, i8 2, i32 1, i8 0, !18} +// !18 = !{i32 3, i32 3} +// !19 = !{!20} +// !20 = !{i32 0, !"SV_Target", i8 9, i8 16, !15, i8 0, i32 1, i8 4, i32 0, i8 0, !16} const BYTE alpha_luminance_sprite_ps_SpritePixelShader[] = { - 68, 88, 66, 67, 132, 97, - 102, 125, 147, 134, 128, 67, - 189, 46, 21, 225, 135, 134, - 209, 134, 1, 0, 0, 0, - 48, 2, 0, 0, 4, 0, - 0, 0, 48, 0, 0, 0, - 128, 0, 0, 0, 180, 0, - 0, 0, 152, 1, 0, 0, - 73, 83, 71, 78, 72, 0, - 0, 0, 2, 0, 0, 0, - 8, 0, 0, 0, 56, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 15, 15, 0, 0, 62, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 3, 3, 0, 0, 67, 79, - 76, 79, 82, 0, 84, 69, - 88, 67, 79, 79, 82, 68, - 0, 171, 79, 83, 71, 78, - 44, 0, 0, 0, 1, 0, - 0, 0, 8, 0, 0, 0, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, - 83, 86, 95, 84, 97, 114, - 103, 101, 116, 0, 171, 171, - 83, 72, 69, 88, 220, 0, - 0, 0, 80, 0, 0, 0, - 55, 0, 0, 0, 106, 8, - 0, 1, 90, 0, 0, 3, - 0, 96, 16, 0, 0, 0, - 0, 0, 88, 24, 0, 4, - 0, 112, 16, 0, 0, 0, - 0, 0, 85, 85, 0, 0, - 98, 16, 0, 3, 242, 16, - 16, 0, 0, 0, 0, 0, - 98, 16, 0, 3, 50, 16, - 16, 0, 1, 0, 0, 0, - 101, 0, 0, 3, 242, 32, - 16, 0, 0, 0, 0, 0, - 104, 0, 0, 2, 1, 0, - 0, 0, 69, 0, 0, 139, - 194, 0, 0, 128, 67, 85, - 21, 0, 242, 0, 16, 0, - 0, 0, 0, 0, 70, 16, - 16, 0, 1, 0, 0, 0, - 70, 126, 16, 0, 0, 0, - 0, 0, 0, 96, 16, 0, - 0, 0, 0, 0, 50, 0, - 0, 15, 242, 0, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 0, 0, 0, 0, - 2, 64, 0, 0, 0, 0, - 128, 63, 0, 0, 128, 63, - 0, 0, 128, 63, 0, 0, - 128, 191, 2, 64, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 128, 63, 56, 0, - 0, 7, 242, 32, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 0, 0, 0, 0, - 70, 30, 16, 0, 0, 0, - 0, 0, 62, 0, 0, 1, - 82, 84, 83, 48, 144, 0, - 0, 0, 2, 0, 0, 0, - 2, 0, 0, 0, 24, 0, - 0, 0, 1, 0, 0, 0, - 92, 0, 0, 0, 29, 0, - 0, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 48, 0, - 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 80, 0, - 0, 0, 1, 0, 0, 0, - 56, 0, 0, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 255, 255, 255, 255, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 21, 0, - 0, 0, 3, 0, 0, 0, - 3, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 4, 0, - 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 255, 255, - 127, 127, 0, 0, 0, 0, - 0, 0, 0, 0, 5, 0, - 0, 0 + 68, 88, 66, 67, 22, 54, 112, 145, 196, 223, 168, 177, + 217, 213, 154, 29, 153, 4, 154, 131, 1, 0, 0, 0, + 100, 16, 0, 0, 8, 0, 0, 0, 64, 0, 0, 0, + 80, 0, 0, 0, 176, 0, 0, 0, 236, 0, 0, 0, + 232, 1, 0, 0, 128, 2, 0, 0, 36, 9, 0, 0, + 64, 9, 0, 0, 83, 70, 73, 48, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 73, 83, 71, 49, + 88, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, + 0, 0, 0, 0, 67, 79, 76, 79, 82, 0, 84, 69, + 88, 67, 79, 79, 82, 68, 0, 0, 79, 83, 71, 49, + 52, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, + 64, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, 83, 86, 95, 84, + 97, 114, 103, 101, 116, 0, 0, 0, 80, 83, 86, 48, + 244, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, + 2, 1, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 2, 0, 0, 0, 24, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, + 0, 67, 79, 76, 79, 82, 0, 84, 69, 88, 67, 79, + 79, 82, 68, 0, 83, 112, 114, 105, 116, 101, 80, 105, + 120, 101, 108, 83, 104, 97, 100, 101, 114, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 68, 0, + 3, 2, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 66, 0, 3, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 68, 16, 3, 0, 0, 0, + 1, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 15, 0, 0, 0, 15, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 82, 84, 83, 48, + 144, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, + 24, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0, + 29, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, + 48, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 80, 0, 0, 0, 1, 0, 0, 0, 56, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, + 4, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 255, 255, 127, 127, 0, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 83, 84, 65, 84, 156, 6, 0, 0, + 96, 0, 0, 0, 167, 1, 0, 0, 68, 88, 73, 76, + 0, 1, 0, 0, 16, 0, 0, 0, 132, 6, 0, 0, + 66, 67, 192, 222, 33, 12, 0, 0, 158, 1, 0, 0, + 11, 130, 32, 0, 2, 0, 0, 0, 19, 0, 0, 0, + 7, 129, 35, 145, 65, 200, 4, 73, 6, 16, 50, 57, + 146, 1, 132, 12, 37, 5, 8, 25, 30, 4, 139, 98, + 128, 20, 69, 2, 66, 146, 11, 66, 164, 16, 50, 20, + 56, 8, 24, 75, 10, 50, 82, 136, 72, 144, 20, 32, + 67, 70, 136, 165, 0, 25, 50, 66, 228, 72, 14, 144, + 145, 34, 196, 80, 65, 81, 129, 140, 225, 131, 229, 138, + 4, 41, 70, 6, 81, 24, 0, 0, 8, 0, 0, 0, + 27, 140, 224, 255, 255, 255, 255, 7, 64, 2, 168, 13, + 132, 240, 255, 255, 255, 255, 3, 32, 109, 48, 134, 255, + 255, 255, 255, 31, 0, 9, 168, 0, 73, 24, 0, 0, + 3, 0, 0, 0, 19, 130, 96, 66, 32, 76, 8, 6, + 0, 0, 0, 0, 137, 32, 0, 0, 68, 0, 0, 0, + 50, 34, 72, 9, 32, 100, 133, 4, 147, 34, 164, 132, + 4, 147, 34, 227, 132, 161, 144, 20, 18, 76, 138, 140, + 11, 132, 164, 76, 16, 112, 35, 0, 37, 0, 20, 102, + 0, 230, 8, 192, 96, 142, 0, 41, 198, 32, 132, 20, + 66, 166, 24, 128, 16, 82, 6, 161, 155, 134, 203, 159, + 176, 135, 144, 252, 149, 144, 86, 98, 242, 139, 219, 70, + 197, 24, 99, 16, 42, 247, 12, 151, 63, 97, 15, 33, + 249, 33, 208, 12, 11, 129, 130, 85, 24, 69, 24, 27, + 99, 12, 66, 200, 160, 86, 134, 65, 6, 189, 57, 130, + 160, 24, 140, 20, 66, 34, 201, 129, 128, 97, 4, 98, + 152, 169, 13, 198, 129, 29, 194, 97, 30, 230, 193, 13, + 104, 161, 28, 240, 129, 30, 234, 65, 30, 202, 65, 14, + 72, 129, 15, 236, 161, 28, 198, 129, 30, 222, 65, 30, + 248, 192, 28, 216, 225, 29, 194, 129, 30, 216, 0, 12, + 232, 192, 15, 192, 192, 15, 244, 64, 15, 218, 33, 29, + 224, 97, 30, 126, 129, 30, 242, 1, 30, 202, 1, 5, + 100, 38, 49, 24, 7, 118, 8, 135, 121, 152, 7, 55, + 160, 133, 114, 192, 7, 122, 168, 7, 121, 40, 7, 57, + 32, 5, 62, 176, 135, 114, 24, 7, 122, 120, 7, 121, + 224, 3, 115, 96, 135, 119, 8, 7, 122, 96, 3, 48, + 160, 3, 63, 0, 3, 63, 64, 66, 181, 116, 111, 146, + 166, 136, 18, 38, 159, 5, 152, 103, 33, 34, 118, 2, + 38, 2, 5, 132, 114, 34, 16, 0, 19, 20, 114, 192, + 135, 116, 96, 135, 54, 104, 135, 121, 104, 3, 114, 192, + 135, 13, 175, 80, 14, 109, 208, 14, 122, 80, 14, 109, + 0, 15, 122, 48, 7, 114, 160, 7, 115, 32, 7, 109, + 144, 14, 113, 160, 7, 115, 32, 7, 109, 144, 14, 120, + 160, 7, 115, 32, 7, 109, 144, 14, 113, 96, 7, 122, + 48, 7, 114, 208, 6, 233, 48, 7, 114, 160, 7, 115, + 32, 7, 109, 144, 14, 118, 64, 7, 122, 96, 7, 116, + 208, 6, 230, 16, 7, 118, 160, 7, 115, 32, 7, 109, + 96, 14, 115, 32, 7, 122, 48, 7, 114, 208, 6, 230, + 96, 7, 116, 160, 7, 118, 64, 7, 109, 224, 14, 120, + 160, 7, 113, 96, 7, 122, 48, 7, 114, 160, 7, 118, + 64, 7, 67, 158, 0, 8, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 134, 60, 6, 16, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 12, 121, 16, 32, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 24, 242, 52, 64, 0, 12, 0, + 0, 0, 0, 0, 0, 0, 48, 228, 121, 128, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 96, 200, 35, 1, 1, + 48, 0, 0, 0, 0, 0, 0, 0, 64, 22, 8, 0, + 15, 0, 0, 0, 50, 30, 152, 20, 25, 17, 76, 144, + 140, 9, 38, 71, 198, 4, 67, 34, 37, 48, 2, 80, + 12, 69, 80, 18, 101, 80, 30, 5, 81, 52, 133, 64, + 165, 36, 70, 0, 138, 160, 16, 10, 132, 240, 12, 0, + 233, 25, 0, 218, 99, 33, 6, 17, 8, 4, 242, 60, + 0, 0, 0, 0, 121, 24, 0, 0, 129, 0, 0, 0, + 26, 3, 76, 144, 70, 2, 19, 196, 49, 32, 195, 27, + 67, 129, 147, 75, 179, 11, 163, 43, 75, 1, 137, 113, + 193, 113, 129, 113, 161, 201, 169, 129, 1, 65, 17, 139, + 129, 177, 9, 203, 177, 137, 33, 75, 217, 16, 4, 19, + 4, 194, 152, 32, 16, 199, 6, 97, 32, 54, 8, 4, + 65, 1, 110, 110, 130, 64, 32, 27, 134, 3, 33, 38, + 8, 88, 197, 131, 170, 12, 143, 174, 78, 174, 108, 130, + 64, 36, 19, 4, 66, 217, 32, 16, 205, 134, 132, 80, + 22, 130, 24, 24, 194, 217, 16, 60, 19, 4, 205, 162, + 67, 85, 134, 71, 87, 39, 87, 54, 21, 214, 6, 199, + 86, 38, 183, 1, 33, 34, 137, 32, 6, 2, 216, 16, + 76, 27, 8, 8, 0, 168, 9, 130, 0, 108, 0, 54, + 12, 196, 117, 109, 8, 176, 13, 195, 96, 101, 19, 132, + 237, 218, 16, 108, 140, 166, 224, 228, 210, 232, 202, 160, + 210, 240, 202, 216, 166, 208, 194, 200, 202, 228, 88, 12, + 61, 49, 61, 73, 77, 16, 10, 104, 130, 80, 68, 27, + 2, 98, 130, 80, 72, 19, 132, 98, 154, 32, 16, 203, + 4, 129, 96, 54, 8, 100, 80, 6, 27, 22, 194, 251, + 192, 32, 12, 196, 96, 24, 3, 2, 12, 204, 128, 8, + 85, 17, 214, 208, 211, 147, 20, 209, 6, 129, 12, 200, + 96, 195, 50, 160, 193, 7, 6, 97, 32, 6, 131, 24, + 12, 96, 144, 6, 27, 132, 51, 80, 3, 38, 83, 86, + 95, 84, 97, 114, 103, 101, 116, 19, 132, 130, 218, 176, + 16, 108, 240, 181, 65, 24, 128, 193, 48, 6, 4, 24, + 152, 193, 134, 192, 13, 54, 12, 107, 240, 6, 192, 134, + 194, 234, 224, 160, 2, 104, 152, 177, 189, 133, 209, 205, + 77, 16, 136, 134, 69, 154, 219, 28, 221, 220, 4, 129, + 112, 104, 204, 165, 157, 125, 177, 145, 209, 152, 75, 59, + 251, 154, 163, 155, 32, 16, 15, 17, 186, 50, 188, 47, + 183, 55, 185, 182, 13, 138, 28, 204, 1, 29, 212, 129, + 29, 32, 119, 128, 7, 121, 48, 84, 97, 99, 179, 107, + 115, 73, 35, 43, 115, 163, 155, 18, 4, 85, 200, 240, + 92, 236, 202, 228, 230, 210, 222, 220, 166, 4, 68, 19, + 50, 60, 23, 187, 48, 54, 187, 50, 185, 41, 65, 81, + 135, 12, 207, 101, 14, 45, 140, 172, 76, 174, 233, 141, + 172, 140, 109, 74, 128, 148, 33, 195, 115, 145, 43, 155, + 123, 171, 147, 27, 43, 155, 155, 18, 80, 149, 200, 240, + 92, 232, 242, 224, 202, 130, 220, 220, 222, 232, 194, 232, + 210, 222, 220, 230, 166, 4, 89, 29, 50, 60, 23, 187, + 180, 178, 187, 36, 178, 41, 186, 48, 186, 178, 41, 193, + 86, 135, 12, 207, 165, 204, 141, 78, 46, 15, 234, 45, + 205, 141, 110, 110, 74, 0, 7, 93, 200, 240, 92, 198, + 222, 234, 220, 232, 202, 228, 230, 166, 4, 121, 0, 0, + 121, 24, 0, 0, 76, 0, 0, 0, 51, 8, 128, 28, + 196, 225, 28, 102, 20, 1, 61, 136, 67, 56, 132, 195, + 140, 66, 128, 7, 121, 120, 7, 115, 152, 113, 12, 230, + 0, 15, 237, 16, 14, 244, 128, 14, 51, 12, 66, 30, + 194, 193, 29, 206, 161, 28, 102, 48, 5, 61, 136, 67, + 56, 132, 131, 27, 204, 3, 61, 200, 67, 61, 140, 3, + 61, 204, 120, 140, 116, 112, 7, 123, 8, 7, 121, 72, + 135, 112, 112, 7, 122, 112, 3, 118, 120, 135, 112, 32, + 135, 25, 204, 17, 14, 236, 144, 14, 225, 48, 15, 110, + 48, 15, 227, 240, 14, 240, 80, 14, 51, 16, 196, 29, + 222, 33, 28, 216, 33, 29, 194, 97, 30, 102, 48, 137, + 59, 188, 131, 59, 208, 67, 57, 180, 3, 60, 188, 131, + 60, 132, 3, 59, 204, 240, 20, 118, 96, 7, 123, 104, + 7, 55, 104, 135, 114, 104, 7, 55, 128, 135, 112, 144, + 135, 112, 96, 7, 118, 40, 7, 118, 248, 5, 118, 120, + 135, 119, 128, 135, 95, 8, 135, 113, 24, 135, 114, 152, + 135, 121, 152, 129, 44, 238, 240, 14, 238, 224, 14, 245, + 192, 14, 236, 48, 3, 98, 200, 161, 28, 228, 161, 28, + 204, 161, 28, 228, 161, 28, 220, 97, 28, 202, 33, 28, + 196, 129, 29, 202, 97, 6, 214, 144, 67, 57, 200, 67, + 57, 152, 67, 57, 200, 67, 57, 184, 195, 56, 148, 67, + 56, 136, 3, 59, 148, 195, 47, 188, 131, 60, 252, 130, + 59, 212, 3, 59, 176, 195, 12, 196, 33, 7, 124, 112, + 3, 122, 40, 135, 118, 128, 135, 25, 209, 67, 14, 248, + 224, 6, 228, 32, 14, 231, 224, 6, 246, 16, 14, 242, + 192, 14, 225, 144, 15, 239, 80, 15, 244, 0, 0, 0, + 113, 32, 0, 0, 24, 0, 0, 0, 6, 16, 177, 79, + 132, 76, 68, 138, 92, 196, 194, 30, 192, 64, 68, 86, + 32, 13, 151, 239, 60, 190, 16, 17, 192, 68, 132, 64, + 51, 44, 132, 5, 76, 195, 229, 59, 143, 191, 56, 192, + 32, 54, 15, 53, 249, 197, 109, 219, 0, 52, 92, 190, + 243, 248, 18, 192, 60, 11, 225, 23, 183, 109, 2, 213, + 112, 249, 206, 227, 75, 147, 19, 17, 40, 53, 61, 212, + 228, 23, 183, 109, 4, 207, 112, 249, 206, 227, 83, 13, + 16, 97, 126, 113, 219, 0, 0, 0, 0, 0, 0, 0, + 72, 65, 83, 72, 20, 0, 0, 0, 0, 0, 0, 0, + 38, 196, 30, 166, 11, 43, 11, 112, 113, 46, 45, 6, + 148, 3, 168, 187, 68, 88, 73, 76, 28, 7, 0, 0, + 96, 0, 0, 0, 199, 1, 0, 0, 68, 88, 73, 76, + 0, 1, 0, 0, 16, 0, 0, 0, 4, 7, 0, 0, + 66, 67, 192, 222, 33, 12, 0, 0, 190, 1, 0, 0, + 11, 130, 32, 0, 2, 0, 0, 0, 19, 0, 0, 0, + 7, 129, 35, 145, 65, 200, 4, 73, 6, 16, 50, 57, + 146, 1, 132, 12, 37, 5, 8, 25, 30, 4, 139, 98, + 128, 20, 69, 2, 66, 146, 11, 66, 164, 16, 50, 20, + 56, 8, 24, 75, 10, 50, 82, 136, 72, 144, 20, 32, + 67, 70, 136, 165, 0, 25, 50, 66, 228, 72, 14, 144, + 145, 34, 196, 80, 65, 81, 129, 140, 225, 131, 229, 138, + 4, 41, 70, 6, 81, 24, 0, 0, 8, 0, 0, 0, + 27, 140, 224, 255, 255, 255, 255, 7, 64, 2, 168, 13, + 132, 240, 255, 255, 255, 255, 3, 32, 109, 48, 134, 255, + 255, 255, 255, 31, 0, 9, 168, 0, 73, 24, 0, 0, + 3, 0, 0, 0, 19, 130, 96, 66, 32, 76, 8, 6, + 0, 0, 0, 0, 137, 32, 0, 0, 68, 0, 0, 0, + 50, 34, 72, 9, 32, 100, 133, 4, 147, 34, 164, 132, + 4, 147, 34, 227, 132, 161, 144, 20, 18, 76, 138, 140, + 11, 132, 164, 76, 16, 112, 35, 0, 37, 0, 20, 102, + 0, 230, 8, 192, 96, 142, 0, 41, 198, 32, 132, 20, + 66, 166, 24, 128, 16, 82, 6, 161, 155, 134, 203, 159, + 176, 135, 144, 252, 149, 144, 86, 98, 242, 139, 219, 70, + 197, 24, 99, 16, 42, 247, 12, 151, 63, 97, 15, 33, + 249, 33, 208, 12, 11, 129, 130, 85, 24, 69, 24, 27, + 99, 12, 66, 200, 160, 86, 134, 65, 6, 189, 57, 130, + 160, 24, 140, 20, 66, 34, 201, 129, 128, 97, 4, 98, + 152, 169, 13, 198, 129, 29, 194, 97, 30, 230, 193, 13, + 104, 161, 28, 240, 129, 30, 234, 65, 30, 202, 65, 14, + 72, 129, 15, 236, 161, 28, 198, 129, 30, 222, 65, 30, + 248, 192, 28, 216, 225, 29, 194, 129, 30, 216, 0, 12, + 232, 192, 15, 192, 192, 15, 244, 64, 15, 218, 33, 29, + 224, 97, 30, 126, 129, 30, 242, 1, 30, 202, 1, 5, + 100, 38, 49, 24, 7, 118, 8, 135, 121, 152, 7, 55, + 160, 133, 114, 192, 7, 122, 168, 7, 121, 40, 7, 57, + 32, 5, 62, 176, 135, 114, 24, 7, 122, 120, 7, 121, + 224, 3, 115, 96, 135, 119, 8, 7, 122, 96, 3, 48, + 160, 3, 63, 0, 3, 63, 64, 66, 181, 116, 111, 146, + 166, 136, 18, 38, 159, 5, 152, 103, 33, 34, 118, 2, + 38, 2, 5, 132, 114, 34, 16, 0, 19, 20, 114, 192, + 135, 116, 96, 135, 54, 104, 135, 121, 104, 3, 114, 192, + 135, 13, 175, 80, 14, 109, 208, 14, 122, 80, 14, 109, + 0, 15, 122, 48, 7, 114, 160, 7, 115, 32, 7, 109, + 144, 14, 113, 160, 7, 115, 32, 7, 109, 144, 14, 120, + 160, 7, 115, 32, 7, 109, 144, 14, 113, 96, 7, 122, + 48, 7, 114, 208, 6, 233, 48, 7, 114, 160, 7, 115, + 32, 7, 109, 144, 14, 118, 64, 7, 122, 96, 7, 116, + 208, 6, 230, 16, 7, 118, 160, 7, 115, 32, 7, 109, + 96, 14, 115, 32, 7, 122, 48, 7, 114, 208, 6, 230, + 96, 7, 116, 160, 7, 118, 64, 7, 109, 224, 14, 120, + 160, 7, 113, 96, 7, 122, 48, 7, 114, 160, 7, 118, + 64, 7, 67, 158, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 134, 60, 6, 16, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 12, 121, 16, 32, 0, 4, 0, 0, + 0, 0, 0, 0, 0, 24, 242, 52, 64, 0, 12, 0, + 0, 0, 0, 0, 0, 0, 48, 228, 121, 128, 0, 8, + 0, 0, 0, 0, 0, 0, 0, 96, 200, 35, 1, 1, + 48, 0, 0, 0, 0, 0, 0, 0, 64, 22, 8, 0, + 13, 0, 0, 0, 50, 30, 152, 20, 25, 17, 76, 144, + 140, 9, 38, 71, 198, 4, 67, 34, 37, 48, 2, 80, + 18, 197, 80, 4, 101, 80, 30, 84, 74, 98, 4, 160, + 8, 10, 161, 64, 8, 207, 0, 144, 158, 1, 160, 61, + 22, 98, 16, 129, 64, 32, 207, 3, 121, 24, 0, 0, + 92, 0, 0, 0, 26, 3, 76, 144, 70, 2, 19, 196, + 49, 32, 195, 27, 67, 129, 147, 75, 179, 11, 163, 43, + 75, 1, 137, 113, 193, 113, 129, 113, 161, 201, 169, 129, + 1, 65, 17, 139, 129, 177, 9, 203, 177, 137, 33, 75, + 217, 16, 4, 19, 4, 194, 152, 32, 16, 199, 6, 97, + 32, 38, 8, 4, 178, 65, 24, 12, 10, 112, 115, 19, + 4, 34, 217, 48, 32, 9, 49, 65, 192, 36, 2, 19, + 4, 66, 217, 32, 16, 198, 134, 132, 88, 24, 130, 24, + 26, 194, 217, 16, 60, 19, 4, 109, 218, 128, 16, 17, + 67, 16, 3, 1, 108, 8, 164, 13, 4, 4, 0, 211, + 4, 97, 163, 54, 4, 213, 4, 65, 0, 24, 77, 193, + 201, 165, 209, 149, 65, 165, 225, 149, 177, 77, 161, 133, + 145, 149, 201, 177, 24, 122, 98, 122, 146, 154, 32, 20, + 205, 4, 161, 112, 54, 4, 196, 4, 161, 120, 38, 8, + 5, 52, 65, 32, 150, 9, 2, 193, 108, 16, 62, 48, + 216, 176, 16, 153, 182, 113, 221, 224, 17, 91, 24, 16, + 161, 42, 194, 26, 122, 122, 146, 34, 218, 32, 124, 223, + 134, 101, 24, 3, 109, 227, 186, 161, 27, 54, 50, 216, + 32, 136, 65, 25, 48, 153, 178, 250, 162, 10, 147, 59, + 43, 163, 155, 32, 20, 209, 134, 133, 56, 3, 13, 13, + 184, 109, 240, 136, 45, 12, 54, 4, 105, 176, 97, 48, + 3, 53, 0, 54, 20, 23, 182, 6, 20, 80, 133, 141, + 205, 174, 205, 37, 141, 172, 204, 141, 110, 74, 16, 84, + 33, 195, 115, 177, 43, 147, 155, 75, 123, 115, 155, 18, + 16, 77, 200, 240, 92, 236, 194, 216, 236, 202, 228, 166, + 4, 70, 29, 50, 60, 151, 57, 180, 48, 178, 50, 185, + 166, 55, 178, 50, 182, 41, 65, 82, 134, 12, 207, 69, + 174, 108, 238, 173, 78, 110, 172, 108, 110, 74, 48, 213, + 33, 195, 115, 177, 75, 43, 187, 75, 34, 155, 162, 11, + 163, 43, 155, 18, 84, 117, 200, 240, 92, 202, 220, 232, + 228, 242, 160, 222, 210, 220, 232, 230, 166, 4, 107, 0, + 121, 24, 0, 0, 76, 0, 0, 0, 51, 8, 128, 28, + 196, 225, 28, 102, 20, 1, 61, 136, 67, 56, 132, 195, + 140, 66, 128, 7, 121, 120, 7, 115, 152, 113, 12, 230, + 0, 15, 237, 16, 14, 244, 128, 14, 51, 12, 66, 30, + 194, 193, 29, 206, 161, 28, 102, 48, 5, 61, 136, 67, + 56, 132, 131, 27, 204, 3, 61, 200, 67, 61, 140, 3, + 61, 204, 120, 140, 116, 112, 7, 123, 8, 7, 121, 72, + 135, 112, 112, 7, 122, 112, 3, 118, 120, 135, 112, 32, + 135, 25, 204, 17, 14, 236, 144, 14, 225, 48, 15, 110, + 48, 15, 227, 240, 14, 240, 80, 14, 51, 16, 196, 29, + 222, 33, 28, 216, 33, 29, 194, 97, 30, 102, 48, 137, + 59, 188, 131, 59, 208, 67, 57, 180, 3, 60, 188, 131, + 60, 132, 3, 59, 204, 240, 20, 118, 96, 7, 123, 104, + 7, 55, 104, 135, 114, 104, 7, 55, 128, 135, 112, 144, + 135, 112, 96, 7, 118, 40, 7, 118, 248, 5, 118, 120, + 135, 119, 128, 135, 95, 8, 135, 113, 24, 135, 114, 152, + 135, 121, 152, 129, 44, 238, 240, 14, 238, 224, 14, 245, + 192, 14, 236, 48, 3, 98, 200, 161, 28, 228, 161, 28, + 204, 161, 28, 228, 161, 28, 220, 97, 28, 202, 33, 28, + 196, 129, 29, 202, 97, 6, 214, 144, 67, 57, 200, 67, + 57, 152, 67, 57, 200, 67, 57, 184, 195, 56, 148, 67, + 56, 136, 3, 59, 148, 195, 47, 188, 131, 60, 252, 130, + 59, 212, 3, 59, 176, 195, 12, 196, 33, 7, 124, 112, + 3, 122, 40, 135, 118, 128, 135, 25, 209, 67, 14, 248, + 224, 6, 228, 32, 14, 231, 224, 6, 246, 16, 14, 242, + 192, 14, 225, 144, 15, 239, 80, 15, 244, 0, 0, 0, + 113, 32, 0, 0, 24, 0, 0, 0, 6, 16, 177, 79, + 132, 76, 68, 138, 92, 196, 194, 30, 192, 64, 68, 86, + 32, 13, 151, 239, 60, 190, 16, 17, 192, 68, 132, 64, + 51, 44, 132, 5, 76, 195, 229, 59, 143, 191, 56, 192, + 32, 54, 15, 53, 249, 197, 109, 219, 0, 52, 92, 190, + 243, 248, 18, 192, 60, 11, 225, 23, 183, 109, 2, 213, + 112, 249, 206, 227, 75, 147, 19, 17, 40, 53, 61, 212, + 228, 23, 183, 109, 4, 207, 112, 249, 206, 227, 83, 13, + 16, 97, 126, 113, 219, 0, 0, 0, 97, 32, 0, 0, + 69, 0, 0, 0, 19, 4, 65, 44, 16, 0, 0, 0, + 9, 0, 0, 0, 20, 71, 0, 168, 148, 64, 25, 16, + 153, 1, 40, 132, 82, 40, 185, 194, 43, 7, 26, 99, + 4, 32, 8, 130, 248, 55, 70, 0, 130, 32, 8, 130, + 193, 12, 0, 0, 35, 6, 9, 0, 130, 96, 32, 113, + 198, 164, 105, 204, 136, 65, 2, 128, 32, 24, 72, 221, + 177, 108, 91, 51, 98, 144, 0, 32, 8, 6, 134, 24, + 40, 29, 87, 45, 35, 6, 9, 0, 130, 96, 96, 140, + 193, 226, 117, 14, 51, 98, 144, 0, 32, 8, 6, 6, + 25, 48, 158, 119, 53, 35, 6, 9, 0, 130, 96, 96, + 148, 65, 243, 125, 144, 51, 98, 144, 0, 32, 8, 6, + 134, 25, 56, 96, 0, 6, 216, 51, 98, 144, 0, 32, + 8, 6, 198, 25, 60, 97, 16, 6, 17, 52, 98, 240, + 0, 32, 8, 6, 141, 25, 52, 200, 97, 20, 73, 34, + 6, 98, 16, 37, 163, 9, 1, 48, 154, 32, 4, 163, + 9, 131, 48, 154, 64, 12, 35, 6, 6, 0, 130, 96, + 240, 168, 65, 100, 152, 0, 201, 199, 164, 32, 62, 22, + 12, 242, 177, 160, 128, 143, 37, 142, 124, 44, 113, 228, + 99, 137, 35, 159, 17, 131, 4, 0, 65, 48, 64, 232, + 128, 123, 131, 55, 64, 131, 97, 196, 32, 1, 64, 16, + 12, 16, 58, 224, 222, 224, 13, 192, 64, 24, 49, 72, + 0, 16, 4, 3, 132, 14, 184, 55, 120, 131, 51, 8, + 70, 12, 18, 0, 4, 193, 0, 161, 3, 238, 13, 222, + 224, 35, 16, 0, 0, 0, 0, 0 }; diff --git a/src/mods/vr/shaders/alpha_luminance_sprite_ps.fx b/src/mods/vr/shaders/alpha_luminance_sprite_ps.fx index 94c522753..32668939c 100644 --- a/src/mods/vr/shaders/alpha_luminance_sprite_ps.fx +++ b/src/mods/vr/shaders/alpha_luminance_sprite_ps.fx @@ -42,9 +42,11 @@ float4 SpritePixelShaderUnified(float4 color : COLOR0, float2 texCoord : TEXCOORD0) { float4 tex = Texture.Sample(TextureSampler, texCoord); - float finalAlpha = (1.0 - tex.a); - - return float4(tex.rgb, finalAlpha) * color; + float invertAmount = saturate(color.a); + float blendedAlpha = lerp(tex.a, 1.0 - tex.a, invertAmount); + float3 blendedColor = tex.rgb * color.rgb; + + return float4(blendedColor, blendedAlpha); } [RootSignature(SpriteStaticRS)]