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)]