Skip to content

Commit

Permalink
Math first part
Browse files Browse the repository at this point in the history
  • Loading branch information
hardcpp committed Apr 9, 2024
1 parent 11f7aef commit 39f5dd4
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 35 deletions.
105 changes: 105 additions & 0 deletions shared/CP_SDK/Unity/Operators.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#pragma once

#include <UnityEngine/Color.hpp>
#include <UnityEngine/Vector2.hpp>
#include <UnityEngine/Vector3.hpp>
#include <UnityEngine/Quaternion.hpp>

constexpr UnityEngine::Color operator+ (const UnityEngine::Color& p_A, const UnityEngine::Color& p_B)
{
return UnityEngine::Color::op_Addition(p_A, p_B);
}
constexpr UnityEngine::Color operator+= (UnityEngine::Color& p_A, const UnityEngine::Color& p_B)
{
return p_A = UnityEngine::Color::op_Addition(p_A, p_B);
}

constexpr UnityEngine::Color operator- (const UnityEngine::Color& p_A, const UnityEngine::Color& p_B)
{
return UnityEngine::Color::op_Subtraction(p_A, p_B);
}
constexpr UnityEngine::Color operator-= (UnityEngine::Color& p_A, const UnityEngine::Color& p_B)
{
return p_A = UnityEngine::Color::op_Subtraction(p_A, p_B);
}

constexpr UnityEngine::Color operator* (const UnityEngine::Color& p_A, const UnityEngine::Color& p_B)
{
return UnityEngine::Color::op_Multiply(p_A, p_B);
}
constexpr UnityEngine::Color operator* (const UnityEngine::Color& p_A, const float& p_B)
{
return UnityEngine::Color::op_Multiply(p_A, p_B);
}
constexpr UnityEngine::Color operator* (const float& p_A, const UnityEngine::Color& p_B)
{
return UnityEngine::Color::op_Multiply(p_A, p_B);
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

constexpr UnityEngine::Vector2 operator+ (const UnityEngine::Vector2& p_A, const UnityEngine::Vector2& p_B)
{
return UnityEngine::Vector2::op_Addition(p_A, p_B);
}
constexpr UnityEngine::Vector2 operator+= (UnityEngine::Vector2& p_A, const UnityEngine::Vector2& p_B)
{
return p_A = UnityEngine::Vector2::op_Addition(p_A, p_B);
}

constexpr UnityEngine::Vector2 operator- (const UnityEngine::Vector2& p_A, const UnityEngine::Vector2& p_B)
{
return UnityEngine::Vector2::op_Subtraction(p_A, p_B);
}
constexpr UnityEngine::Vector2 operator-= (UnityEngine::Vector2& p_A, const UnityEngine::Vector2& p_B)
{
return p_A = UnityEngine::Vector2::op_Subtraction(p_A, p_B);
}

constexpr UnityEngine::Vector2 operator* (const UnityEngine::Vector2& p_A, const float& p_B)
{
return UnityEngine::Vector2::op_Multiply(p_A, p_B);
}
constexpr UnityEngine::Vector2 operator* (const float& p_A, const UnityEngine::Vector2& p_B)
{
return UnityEngine::Vector2::op_Multiply(p_A, p_B);
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

constexpr UnityEngine::Vector3 operator+ (const UnityEngine::Vector3& p_A, const UnityEngine::Vector3& p_B)
{
return UnityEngine::Vector3::op_Addition(p_A, p_B);
}
constexpr UnityEngine::Vector3 operator+= (UnityEngine::Vector3& p_A, const UnityEngine::Vector3& p_B)
{
return p_A = UnityEngine::Vector3::op_Addition(p_A, p_B);
}

constexpr UnityEngine::Vector3 operator- (const UnityEngine::Vector3& p_A, const UnityEngine::Vector3& p_B)
{
return UnityEngine::Vector3::op_Subtraction(p_A, p_B);
}
constexpr UnityEngine::Vector3 operator-= (UnityEngine::Vector3& p_A, const UnityEngine::Vector3& p_B)
{
return p_A = UnityEngine::Vector3::op_Subtraction(p_A, p_B);
}

constexpr UnityEngine::Vector3 operator* (const UnityEngine::Vector3& p_A, const float& p_B)
{
return UnityEngine::Vector3::op_Multiply(p_A, p_B);
}
constexpr UnityEngine::Vector3 operator* (const float& p_A, const UnityEngine::Vector3& p_B)
{
return UnityEngine::Vector3::op_Multiply(p_A, p_B);
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

constexpr UnityEngine::Quaternion operator* (const UnityEngine::Quaternion& p_A, const UnityEngine::Quaternion& p_B)
{
return UnityEngine::Quaternion::op_Multiply(p_A, p_B);
}
5 changes: 3 additions & 2 deletions src/CP_SDK/UI/DefaultComponents/DefaultCColorInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "CP_SDK/UI/IViewController.hpp"
#include "CP_SDK/UI/UISystem.hpp"
#include "CP_SDK/Unity/Extensions/ColorU.hpp"
#include "CP_SDK/Unity/Operators.hpp"

#include <UnityEngine/GameObject.hpp>
#include <UnityEngine/UI/Button.hpp>
Expand Down Expand Up @@ -65,8 +66,8 @@ namespace CP_SDK::UI::DefaultComponents {
auto l_View = GameObject::New_ctor("View", ArrayW<System::Type*>({ reinterpret_cast<System::Type*>(csTypeOf(RectTransform*).convert()) }))->GetComponent<RectTransform*>();
l_View->get_gameObject()->set_layer(UISystem::UILayer);
l_View->SetParent(get_transform(), false);
l_View->set_anchorMin(Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_View->set_anchorMax(Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_View->set_anchorMin(Vector2::get_one() * 0.5f);
l_View->set_anchorMax(Vector2::get_one() * 0.5f);
l_View->set_sizeDelta(Vector2(15.0f, 5.0f));

m_BG = GameObject::New_ctor("BG", ArrayW<System::Type*>({ UISystem::Override_UnityComponent_Image.ptr() }))->GetComponent(UISystem::Override_UnityComponent_Image.ptr()).try_cast<Image>().value_or(nullptr);
Expand Down
3 changes: 2 additions & 1 deletion src/CP_SDK/UI/DefaultComponents/DefaultCIconButton.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "CP_SDK/UI/UISystem.hpp"
#include "CP_SDK/Unity/Extensions/ColorU.hpp"
#include "CP_SDK/ChatPlexSDK.hpp"
#include "CP_SDK/Unity/Operators.hpp"

#include <UnityEngine/GameObject.hpp>
#include <UnityEngine/Rect.hpp>
Expand Down Expand Up @@ -133,7 +134,7 @@ namespace CP_SDK::UI::DefaultComponents {
return;

StopAllCoroutines();
StartCoroutine(custom_types::Helpers::CoroutineHelper::New(Coroutine_AnimateScale(this, Vector3::op_Multiply(Vector3::get_one(), 1.25f), 0.075f)));
StartCoroutine(custom_types::Helpers::CoroutineHelper::New(Coroutine_AnimateScale(this, Vector3::get_one() * 1.25f, 0.075f)));
}
/// @brief On pointer exit
/// @param p_EventData Event data
Expand Down
3 changes: 2 additions & 1 deletion src/CP_SDK/UI/DefaultComponents/DefaultCSlider.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "CP_SDK/UI/DefaultComponents/DefaultCSlider.hpp"
#include "CP_SDK/UI/UISystem.hpp"
#include "CP_SDK/Unity/Extensions/ColorU.hpp"
#include "CP_SDK/Unity/Operators.hpp"

#include <System/Math.hpp>
#include <UnityEngine/GameObject.hpp>
Expand Down Expand Up @@ -435,7 +436,7 @@ namespace CP_SDK::UI::DefaultComponents {
auto l_HandleRect = l_HandleRectTransform->get_rect();
auto l_SlidingRect = m_SlidingArea->get_rect();

auto l_Point = Vector2::op_Multiply(Vector2::op_Subtraction(Vector2::op_Subtraction(Vector2::op_Subtraction(l_LocalPoint, l_SlidingRect.get_position()), Vector2(l_HandleRect.m_Width * 0.5f, 0.0f)), Vector2::op_Subtraction(l_HandleRect.get_size(), l_HandleRectTransform->get_sizeDelta())), 0.5f);
auto l_Point = l_LocalPoint - l_SlidingRect.get_position() - Vector2(l_HandleRect.m_Width * 0.5f, 0.0f) - (l_HandleRect.get_size() - l_HandleRectTransform->get_sizeDelta()) * 0.5f;
auto l_Value = l_SlidingRect.m_Width * (1.0f - m_HandleSize / l_SlidingRect.m_Width);

m_DragTargetValue = (l_Point.x / l_Value);
Expand Down
9 changes: 5 additions & 4 deletions src/CP_SDK/UI/DefaultComponents/DefaultCToggle.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "CP_SDK/UI/DefaultComponents/DefaultCToggle.hpp"
#include "CP_SDK/UI/UISystem.hpp"
#include "CP_SDK/Unity/Extensions/ColorU.hpp"
#include "CP_SDK/Unity/Operators.hpp"

#include <UnityEngine/GameObject.hpp>
#include <UnityEngine/Mathf.hpp>
Expand Down Expand Up @@ -91,8 +92,8 @@ namespace CP_SDK::UI::DefaultComponents {
auto l_View = GameObject::New_ctor("View", ArrayW<System::Type*>({ reinterpret_cast<System::Type*>(csTypeOf(RectTransform*).convert()) }))->get_transform().try_cast<RectTransform>().value_or(nullptr);
l_View->get_gameObject()->set_layer(UISystem::UILayer);
l_View->SetParent(get_transform(), false);
l_View->set_anchorMin (Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_View->set_anchorMax (Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_View->set_anchorMin (Vector2::get_one() * 0.5f);
l_View->set_anchorMax (Vector2::get_one() * 0.5f);
l_View->set_sizeDelta (Vector2(15.0f, 5.0f));

m_Toggle = l_View->get_gameObject()->AddComponent<Subs::SubToggleWithCallbacks*>();
Expand All @@ -103,8 +104,8 @@ namespace CP_SDK::UI::DefaultComponents {
m_BackgroundImage = GameObject::New_ctor("BG", ArrayW<System::Type*>({ UISystem::Override_UnityComponent_Image.ptr() }))->GetComponent(UISystem::Override_UnityComponent_Image.ptr()).try_cast<Image>().value_or(nullptr);
m_BackgroundImage->get_gameObject()->set_layer(UISystem::UILayer);
m_BackgroundImage->get_rectTransform()->SetParent(l_View, false);
m_BackgroundImage->get_rectTransform()->set_anchorMin(Vector2::op_Multiply(Vector2::get_one(), 0.5f));
m_BackgroundImage->get_rectTransform()->set_anchorMax(Vector2::op_Multiply(Vector2::get_one(), 0.5f));
m_BackgroundImage->get_rectTransform()->set_anchorMin(Vector2::get_one() * 0.5f);
m_BackgroundImage->get_rectTransform()->set_anchorMax(Vector2::get_one() * 0.5f);
m_BackgroundImage->get_rectTransform()->set_sizeDelta(Vector2(15.0f, 5.0f));
m_BackgroundImage->set_sprite (UISystem::GetUIRoundBGSprite().Ptr());
m_BackgroundImage->set_color (Color(0.0f, 0.0f, 0.0f, 0.5f));
Expand Down
3 changes: 2 additions & 1 deletion src/CP_SDK/UI/LoadingProgressBar.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "CP_SDK/UI/LoadingProgressBar.hpp"
#include "CP_SDK/UI/UISystem.hpp"
#include "CP_SDK/Unity/Operators.hpp"

#include "UnityEngine/GameObject.hpp"
#include "UnityEngine/Transform.hpp"
Expand Down Expand Up @@ -76,7 +77,7 @@ namespace CP_SDK::UI {
Sprite::Create(
Texture2D::get_whiteTexture(),
Rect(0, 0, Texture2D::get_whiteTexture()->get_width(), Texture2D::get_whiteTexture()->get_height()),
Vector2::op_Multiply(Vector2::get_one(), 0.5f),
Vector2::get_one() * 0.5f,
100,
1,
SpriteMeshType::FullRect,
Expand Down
35 changes: 18 additions & 17 deletions src/CP_SDK/Unity/TextureRaw.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "CP_SDK/Unity/TextureRaw.hpp"
#include "CP_SDK/Unity/Extensions/ColorU.hpp"
#include "CP_SDK/Unity/Operators.hpp"
#include "CP_SDK/ChatPlexSDK.hpp"

#define STB_IMAGE_IMPLEMENTATION
Expand Down Expand Up @@ -83,7 +84,7 @@ namespace CP_SDK::Unity {
auto& l_ImageB = *(p_ImageB.get());

for (auto l_I = 0; l_I < p_ImageA->size(); ++l_I)
l_ImageA[l_I] = Color::op_Multiply(l_ImageA[l_I], l_ImageB[l_I]);
l_ImageA[l_I] = l_ImageA[l_I] * l_ImageB[l_I];
}
/// @brief Resize an image and crop it
/// @param p_InWidth Source width
Expand Down Expand Up @@ -192,27 +193,27 @@ namespace CP_SDK::Unity {
auto l_RI = l_TI + p_Radius;
auto l_FV = l_InPixels[l_TI];
auto l_LV = l_InPixels[l_TI + p_Width - 1];
auto l_Val = Color::op_Multiply(p_Radius + 1.0f, l_FV);
auto l_Val = (p_Radius + 1.0f) * l_FV;

for (auto l_J = 0; l_J < p_Radius; ++l_J)
l_Val = Color::op_Addition(l_Val, (l_InPixels[l_TI + l_J]));
l_Val += l_InPixels[l_TI + l_J];

for (auto l_J = 0; l_J <= p_Radius; ++l_J)
{
l_Val = Color::op_Addition(l_Val, Color::op_Subtraction(l_InPixels[l_RI++], l_FV));
l_InPixels[l_TI++] = Color::op_Multiply(l_Val, l_Mult);
l_Val += l_InPixels[l_RI++] - l_FV;
l_InPixels[l_TI++] = l_Val * l_Mult;
}

for (auto l_J = p_Radius + 1; l_J < p_Width - p_Radius; ++l_J)
{
l_Val = Color::op_Addition(l_Val, Color::op_Subtraction(l_InPixels[l_RI++], l_InPixels[l_LI++]));
l_InPixels[l_TI++] = Color::op_Multiply(l_Val, l_Mult);
l_Val += l_InPixels[l_RI++] - l_InPixels[l_LI++];
l_InPixels[l_TI++] = l_Val * l_Mult;
}

for (auto l_J = p_Width - p_Radius; l_J < p_Width; ++l_J)
{
l_Val = Color::op_Addition(l_Val, Color::op_Subtraction(l_LV, l_InPixels[l_LI++]));
l_InPixels[l_TI++] = Color::op_Multiply(l_Val, l_Mult);
l_Val += l_LV - l_InPixels[l_LI++];
l_InPixels[l_TI++] = l_Val * l_Mult;
}
};
}
Expand All @@ -227,32 +228,32 @@ namespace CP_SDK::Unity {
auto l_RI = l_TI + p_Radius * p_Width;
auto l_FV = l_InPixels[l_TI];
auto l_LV = l_InPixels[l_TI + p_Width * (p_Height - 1)];
auto l_Val = Color::op_Multiply(p_Radius + 1, l_FV);
auto l_Val = (p_Radius + 1) * l_FV;

for (auto l_J = 0; l_J < p_Radius; ++l_J)
l_Val = Color::op_Addition(l_Val, l_InPixels[l_TI + l_J * p_Width]);
l_Val += l_InPixels[l_TI + l_J * p_Width];

for (auto l_J = 0; l_J <= p_Radius; ++l_J)
{
l_Val = Color::op_Multiply(l_Val, Color::op_Subtraction(l_InPixels[l_RI], l_FV));
l_InPixels[l_TI] = Color::op_Multiply(l_Val, l_Mult);
l_Val += l_InPixels[l_RI] - l_FV;
l_InPixels[l_TI] = l_Val * l_Mult;
l_RI += p_Width;
l_TI += p_Width;
}

for (auto l_J = p_Radius + 1; l_J < p_Height - p_Radius; ++l_J)
{
l_Val = Color::op_Addition(l_Val, Color::op_Subtraction(l_InPixels[l_RI], l_InPixels[l_LI]));
l_InPixels[l_TI] = Color::op_Multiply(l_Val, l_Mult);
l_Val += l_InPixels[l_RI] - l_InPixels[l_LI];
l_InPixels[l_TI] = l_Val * l_Mult;
l_LI += p_Width;
l_RI += p_Width;
l_TI += p_Width;
}

for (auto l_J = p_Height - p_Radius; l_J < p_Height; ++l_J)
{
l_Val = Color::op_Addition(l_Val, Color::op_Subtraction(l_LV, l_InPixels[l_LI]));
l_InPixels[l_TI] = Color::op_Multiply(l_Val, l_Mult);
l_Val += l_LV - l_InPixels[l_LI];
l_InPixels[l_TI] = l_Val * l_Mult;
l_LI += p_Width;
l_TI += p_Width;
}
Expand Down
7 changes: 4 additions & 3 deletions src/CP_SDK_BS/UI/HMUIIconSegmentedControl.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "CP_SDK_BS/UI/HMUIIconSegmentedControl.hpp"
#include "CP_SDK/Unity/Operators.hpp"

#include <HMUI/HoverHint.hpp>
#include <GlobalNamespace/BeatmapCharacteristicSegmentedControlController.hpp>
Expand Down Expand Up @@ -36,10 +37,10 @@ namespace CP_SDK_BS::UI {
l_Control->_hideCellBackground = p_HideCellBackground;

auto l_RectTransform = l_Control->get_transform().try_cast<RectTransform>().value_or(nullptr);
l_RectTransform->set_anchorMin (Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_RectTransform->set_anchorMax (Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_RectTransform->set_anchorMin (Vector2::get_one() * 0.5f);
l_RectTransform->set_anchorMax (Vector2::get_one() * 0.5f);
l_RectTransform->set_anchoredPosition(Vector2::get_zero() );
l_RectTransform->set_pivot (Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_RectTransform->set_pivot (Vector2::get_one() * 0.5f);

auto l_ChildCount = l_Control->get_transform()->get_childCount();
for (auto l_I = 0; l_I < l_ChildCount; ++l_I)
Expand Down
7 changes: 4 additions & 3 deletions src/CP_SDK_BS/UI/HMUITextSegmentedControl.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "CP_SDK_BS/UI/HMUITextSegmentedControl.hpp"
#include "CP_SDK/Unity/Operators.hpp"

#include <HMUI/HoverHint.hpp>
#include <GlobalNamespace/BeatmapDifficultySegmentedControlController.hpp>
Expand Down Expand Up @@ -38,10 +39,10 @@ namespace CP_SDK_BS::UI {
l_Control->_hideCellBackground = p_HideCellBackground;

auto l_RectTransform = l_Control->get_transform().try_cast<RectTransform>().value_or(nullptr);
l_RectTransform->set_anchorMin (Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_RectTransform->set_anchorMax (Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_RectTransform->set_anchorMin (Vector2::get_one() * 0.5f);
l_RectTransform->set_anchorMax (Vector2::get_one() * 0.5f);
l_RectTransform->set_anchoredPosition(Vector2::get_zero() );
l_RectTransform->set_pivot (Vector2::op_Multiply(Vector2::get_one(), 0.5f));
l_RectTransform->set_pivot (Vector2::get_one() * 0.5f);

auto l_ChildCount = l_Control->get_transform()->get_childCount();
for (auto l_I = 0; l_I < l_ChildCount; ++l_I)
Expand Down
7 changes: 4 additions & 3 deletions src/CP_SDK_BS/UI/LevelDetail.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "CP_SDK_BS/Game/Levels.hpp"
#include "CP_SDK/UI/UISystem.hpp"
#include "CP_SDK/Unity/SpriteU.hpp"
#include "CP_SDK/Unity/Operators.hpp"
#include "assets.hpp"

#include <BeatmapSaveDataVersion3/BeatmapSaveData.hpp>
Expand Down Expand Up @@ -279,7 +280,7 @@ namespace CP_SDK_BS::UI {
l_LevelBarBig->Find(u"MultipleLineTextContainer")->get_gameObject()->SetActive(false);

auto l_BeatmapParamsPanel = m_GameObject->get_transform()->Find(u"BeatmapParamsPanel");
l_BeatmapParamsPanel->get_transform()->set_localPosition(Vector3::op_Addition(l_BeatmapParamsPanel->get_transform()->get_localPosition(), Vector3::op_Multiply(2, Vector3::get_up())));
l_BeatmapParamsPanel->get_transform()->set_localPosition(l_BeatmapParamsPanel->get_transform()->get_localPosition() + (2 * Vector3::get_up()));

l_BeatmapParamsPanel->get_gameObject()->AddComponent<HorizontalLayoutGroup*>()->set_childControlHeight(false);
l_BeatmapParamsPanel->get_gameObject()->AddComponent<LayoutElement*>();
Expand Down Expand Up @@ -309,12 +310,12 @@ namespace CP_SDK_BS::UI {
m_SongBombsText->get_transform()->get_parent()->get_transform().try_cast<RectTransform>().value_or(nullptr)->set_sizeDelta(l_SizeDelta);

/// Patch
auto l_OffsetSprite = CP_SDK::Unity::SpriteU::CreateFromRaw(Assets::Offset_png, 100.0f, Vector2::op_Multiply(Vector2::get_one(), 16.0f));
auto l_OffsetSprite = CP_SDK::Unity::SpriteU::CreateFromRaw(Assets::Offset_png, 100.0f, Vector2::get_one() * 16.0f);
m_SongOffsetText = GameObject::Instantiate(m_SongNPSText->get_transform()->get_parent()->get_gameObject(), m_SongNPSText->get_transform()->get_parent()->get_parent())->GetComponentInChildren<TextMeshProUGUI*>();
m_SongOffsetText->get_transform()->get_parent()->SetAsFirstSibling();
m_SongOffsetText->get_transform()->get_parent()->GetComponentInChildren<HMUI::ImageView*>()->set_sprite(l_OffsetSprite);

auto l_NJSSprite = CP_SDK::Unity::SpriteU::CreateFromRaw(Assets::NJS_png, 100.0f, Vector2::op_Multiply(Vector2::get_one(), 16.0f));
auto l_NJSSprite = CP_SDK::Unity::SpriteU::CreateFromRaw(Assets::NJS_png, 100.0f, Vector2::get_one() * 16.0f);
m_SongNJSText = GameObject::Instantiate(m_SongNPSText->get_transform()->get_parent()->get_gameObject(), m_SongNPSText->get_transform()->get_parent()->get_parent())->GetComponentInChildren<TextMeshProUGUI*>();
m_SongNJSText->get_transform()->get_parent()->SetAsFirstSibling();
m_SongNJSText->get_transform()->get_parent()->GetComponentInChildren<HMUI::ImageView*>()->set_sprite(l_NJSSprite);
Expand Down

0 comments on commit 39f5dd4

Please sign in to comment.