Merge pull request #7609 from aws-lumberyard-dev/math_string_converters
[Impactful Change] Consolidate to_string implementations for math classes and add bool to_stringmonroegm-disable-blank-issue-2
commit
7dccb15fb7
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||||
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AzCore/Math/MathStringConversions.h>
|
||||||
|
#include <AzCore/Math/Aabb.h>
|
||||||
|
#include <AzCore/Math/Color.h>
|
||||||
|
#include <AzCore/Math/Matrix3x3.h>
|
||||||
|
#include <AzCore/Math/Matrix3x4.h>
|
||||||
|
#include <AzCore/Math/Matrix4x4.h>
|
||||||
|
#include <AzCore/Math/Transform.h>
|
||||||
|
#include <AzCore/Math/Quaternion.h>
|
||||||
|
#include <AzCore/Math/Vector2.h>
|
||||||
|
#include <AzCore/Math/Vector3.h>
|
||||||
|
|
||||||
|
namespace AZStd
|
||||||
|
{
|
||||||
|
void to_string(string& str, const AZ::Vector2& value)
|
||||||
|
{
|
||||||
|
str = AZStd::string::format("%.8f,%.8f",
|
||||||
|
static_cast<float>(value.GetX()),
|
||||||
|
static_cast<float>(value.GetY()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_string(string& str, const AZ::Vector3& value)
|
||||||
|
{
|
||||||
|
str = AZStd::string::format("%.8f,%.8f,%.8f",
|
||||||
|
static_cast<float>(value.GetX()),
|
||||||
|
static_cast<float>(value.GetY()),
|
||||||
|
static_cast<float>(value.GetZ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_string(string& str, const AZ::Vector4& value)
|
||||||
|
{
|
||||||
|
str = AZStd::string::format("%.8f,%.8f,%.8f,%.8f",
|
||||||
|
static_cast<float>(value.GetX()),
|
||||||
|
static_cast<float>(value.GetY()),
|
||||||
|
static_cast<float>(value.GetZ()),
|
||||||
|
static_cast<float>(value.GetW()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_string(string& str, const AZ::Quaternion& value)
|
||||||
|
{
|
||||||
|
str = AZStd::string::format("%.8f,%.8f,%.8f,%.8f",
|
||||||
|
static_cast<float>(value.GetX()),
|
||||||
|
static_cast<float>(value.GetY()),
|
||||||
|
static_cast<float>(value.GetZ()),
|
||||||
|
static_cast<float>(value.GetW()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_string(string& str, const AZ::Matrix3x3& value)
|
||||||
|
{
|
||||||
|
str = AZStd::string::format(
|
||||||
|
"%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f",
|
||||||
|
static_cast<float>(value(0, 0)), static_cast<float>(value(1, 0)), static_cast<float>(value(2, 0)),
|
||||||
|
static_cast<float>(value(0, 1)), static_cast<float>(value(1, 1)), static_cast<float>(value(2, 1)),
|
||||||
|
static_cast<float>(value(0, 2)), static_cast<float>(value(1, 2)), static_cast<float>(value(2, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_string(string& str, const AZ::Matrix4x4& value)
|
||||||
|
{
|
||||||
|
str = AZStd::string::format("%.8f,%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f,%.8f",
|
||||||
|
static_cast<float>(value(0, 0)), static_cast<float>(value(1, 0)), static_cast<float>(value(2, 0)), static_cast<float>(value(3, 0)),
|
||||||
|
static_cast<float>(value(0, 1)), static_cast<float>(value(1, 1)), static_cast<float>(value(2, 1)), static_cast<float>(value(3, 1)),
|
||||||
|
static_cast<float>(value(0, 2)), static_cast<float>(value(1, 2)), static_cast<float>(value(2, 2)), static_cast<float>(value(3, 2)),
|
||||||
|
static_cast<float>(value(0, 3)), static_cast<float>(value(1, 3)), static_cast<float>(value(2, 3)), static_cast<float>(value(3, 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_string(string& str, const AZ::Transform& value)
|
||||||
|
{
|
||||||
|
AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(value);
|
||||||
|
|
||||||
|
str = AZStd::string::format("%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f",
|
||||||
|
static_cast<float>(matrix3x4(0, 0)), static_cast<float>(matrix3x4(1, 0)), static_cast<float>(matrix3x4(2, 0)),
|
||||||
|
static_cast<float>(matrix3x4(0, 1)), static_cast<float>(matrix3x4(1, 1)), static_cast<float>(matrix3x4(2, 1)),
|
||||||
|
static_cast<float>(matrix3x4(0, 2)), static_cast<float>(matrix3x4(1, 2)), static_cast<float>(matrix3x4(2, 2)),
|
||||||
|
static_cast<float>(matrix3x4(0, 3)), static_cast<float>(matrix3x4(1, 3)), static_cast<float>(matrix3x4(2, 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_string(string& str, const AZ::Aabb& value)
|
||||||
|
{
|
||||||
|
str = AZStd::string::format(
|
||||||
|
"%.8f,%.8f,%.8f\n%.8f,%.8f,%.8f",
|
||||||
|
static_cast<float>(value.GetMin().GetX()), static_cast<float>(value.GetMin().GetY()),
|
||||||
|
static_cast<float>(value.GetMin().GetZ()), static_cast<float>(value.GetMax().GetX()),
|
||||||
|
static_cast<float>(value.GetMax().GetY()), static_cast<float>(value.GetMax().GetZ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void to_string(string& str, const AZ::Color& color)
|
||||||
|
{
|
||||||
|
str = AZStd::string::format("R:%d, G:%d, B:%d A:%d", color.GetR8(), color.GetG8(), color.GetB8(), color.GetA8());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||||
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AzCore/std/functional.h>
|
||||||
|
#include <AzCore/std/string/conversions.h>
|
||||||
|
#include <AzCore/std/string/string.h>
|
||||||
|
|
||||||
|
namespace AZ
|
||||||
|
{
|
||||||
|
class Aabb;
|
||||||
|
class Color;
|
||||||
|
class Matrix3x3;
|
||||||
|
class Matrix4x4;
|
||||||
|
class Quaternion;
|
||||||
|
class Transform;
|
||||||
|
class Vector2;
|
||||||
|
class Vector3;
|
||||||
|
class Vector4;
|
||||||
|
} // namespace AZ
|
||||||
|
|
||||||
|
namespace AZStd
|
||||||
|
{
|
||||||
|
//! Prints a Vector2 with precision to 8 decimal places.
|
||||||
|
void to_string(string& str, const AZ::Vector2& value);
|
||||||
|
|
||||||
|
//! Prints a Vector3 with precision to 8 decimal places.
|
||||||
|
void to_string(string& str, const AZ::Vector3& value);
|
||||||
|
|
||||||
|
//! Prints a Vector4 with precision to 8 decimal places.
|
||||||
|
void to_string(string& str, const AZ::Vector4& value);
|
||||||
|
|
||||||
|
//! Prints a Quaternion with precision to 8 decimal places.
|
||||||
|
void to_string(string& str, const AZ::Quaternion& value);
|
||||||
|
|
||||||
|
//! Prints a 3x3 matrix in row major order over three lines with precision to 8 decimal places.
|
||||||
|
void to_string(string& str, const AZ::Matrix3x3& value);
|
||||||
|
|
||||||
|
//! Prints a 4x4 matrix in row major order over four lines with precision to 8 decimal places.
|
||||||
|
void to_string(string& str, const AZ::Matrix4x4& value);
|
||||||
|
|
||||||
|
//! Prints a transform as a 3x4 matrix in row major order over four lines with precision to 8 decimal places.
|
||||||
|
void to_string(string& str, const AZ::Transform& value);
|
||||||
|
|
||||||
|
//! Prints an AABB as a pair of Vector3s with precision to 8 decimal places.
|
||||||
|
void to_string(string& str, const AZ::Aabb& value);
|
||||||
|
|
||||||
|
//! Prints a Color as four unsigned ints representing RGBA.
|
||||||
|
void to_string(string& str, const AZ::Color& value);
|
||||||
|
|
||||||
|
inline AZStd::string to_string(const AZ::Vector2& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AZStd::string to_string(const AZ::Vector3& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AZStd::string to_string(const AZ::Vector4& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AZStd::string to_string(const AZ::Quaternion& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AZStd::string to_string(const AZ::Matrix3x3& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AZStd::string to_string(const AZ::Matrix4x4& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
inline AZStd::string to_string(const AZ::Transform& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AZStd::string to_string(const AZ::Aabb& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline AZStd::string to_string(const AZ::Color& val)
|
||||||
|
{
|
||||||
|
AZStd::string str;
|
||||||
|
to_string(str, val);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
} // namespace AZStd
|
||||||
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
||||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ToString.h"
|
|
||||||
|
|
||||||
#include <AzCore/Math/Vector2.h>
|
|
||||||
#include <AzCore/Math/Vector3.h>
|
|
||||||
#include <AzCore/Math/Vector4.h>
|
|
||||||
#include <AzCore/Math/Quaternion.h>
|
|
||||||
#include <AzCore/Math/Transform.h>
|
|
||||||
#include <AzCore/Math/Matrix3x3.h>
|
|
||||||
#include <AzCore/Math/Matrix4x4.h>
|
|
||||||
#include <AzCore/Math/Color.h>
|
|
||||||
|
|
||||||
namespace AZ
|
|
||||||
{
|
|
||||||
AZStd::string ToString(const AZ::Vector2& vector2)
|
|
||||||
{
|
|
||||||
return AZStd::string::format("(X:%f, Y:%f)", static_cast<float>(vector2.GetX()), static_cast<float>(vector2.GetY()));
|
|
||||||
}
|
|
||||||
|
|
||||||
AZStd::string ToString(const AZ::Vector3& vector3)
|
|
||||||
{
|
|
||||||
return AZStd::string::format("(X:%f, Y:%f, Z:%f)", static_cast<float>(vector3.GetX()), static_cast<float>(vector3.GetY()), static_cast<float>(vector3.GetZ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
AZStd::string ToString(const AZ::Vector4& vector4)
|
|
||||||
{
|
|
||||||
return AZStd::string::format("(X:%f, Y:%f, Z:%f W:%f)", static_cast<float>(vector4.GetX()), static_cast<float>(vector4.GetY()), static_cast<float>(vector4.GetZ()), static_cast<float>(vector4.GetW()));
|
|
||||||
}
|
|
||||||
|
|
||||||
AZStd::string ToString(const AZ::Quaternion& quaternion)
|
|
||||||
{
|
|
||||||
return AZStd::string::format("(X:%f, Y:%f, Z:%f W:%f)", static_cast<float>(quaternion.GetX()), static_cast<float>(quaternion.GetY()), static_cast<float>(quaternion.GetZ()), static_cast<float>(quaternion.GetW()));
|
|
||||||
}
|
|
||||||
|
|
||||||
AZStd::string ToString(const AZ::Transform& transform)
|
|
||||||
{
|
|
||||||
AZ::Vector3 cols[4];
|
|
||||||
transform.GetBasisAndTranslation(&cols[0], &cols[1], &cols[2], &cols[3]);
|
|
||||||
|
|
||||||
return AZStd::string::format(
|
|
||||||
"[%f, %f, %f, %f]\n"
|
|
||||||
"[%f, %f, %f, %f]\n"
|
|
||||||
"[%f, %f, %f, %f]",
|
|
||||||
cols[0].GetX(), cols[1].GetX(), cols[2].GetX(), cols[3].GetX(),
|
|
||||||
cols[0].GetY(), cols[1].GetY(), cols[2].GetY(), cols[3].GetY(),
|
|
||||||
cols[0].GetZ(), cols[1].GetZ(), cols[2].GetZ(), cols[3].GetZ()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
AZStd::string ToString(const AZ::Matrix3x3& matrix33)
|
|
||||||
{
|
|
||||||
auto row1 = matrix33.GetRow(0);
|
|
||||||
auto row2 = matrix33.GetRow(1);
|
|
||||||
auto row3 = matrix33.GetRow(2);
|
|
||||||
|
|
||||||
return AZStd::string::format(
|
|
||||||
"[%f, %f, %f]\n"
|
|
||||||
"[%f, %f, %f]\n"
|
|
||||||
"[%f, %f, %f]",
|
|
||||||
static_cast<float>(row1.GetX()), static_cast<float>(row1.GetY()), static_cast<float>(row1.GetZ()),
|
|
||||||
static_cast<float>(row2.GetX()), static_cast<float>(row2.GetY()), static_cast<float>(row2.GetZ()),
|
|
||||||
static_cast<float>(row3.GetX()), static_cast<float>(row3.GetY()), static_cast<float>(row3.GetZ())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
AZStd::string ToString(const AZ::Matrix4x4& matrix44)
|
|
||||||
{
|
|
||||||
auto row1 = matrix44.GetRow(0);
|
|
||||||
auto row2 = matrix44.GetRow(1);
|
|
||||||
auto row3 = matrix44.GetRow(2);
|
|
||||||
auto row4 = matrix44.GetRow(3);
|
|
||||||
|
|
||||||
return AZStd::string::format(
|
|
||||||
"[%f, %f, %f %f]\n"
|
|
||||||
"[%f, %f, %f %f]\n"
|
|
||||||
"[%f, %f, %f %f]\n"
|
|
||||||
"[%f, %f, %f %f]",
|
|
||||||
static_cast<float>(row1.GetX()), static_cast<float>(row1.GetY()), static_cast<float>(row1.GetZ()), static_cast<float>(row1.GetW()),
|
|
||||||
static_cast<float>(row2.GetX()), static_cast<float>(row2.GetY()), static_cast<float>(row2.GetZ()), static_cast<float>(row2.GetW()),
|
|
||||||
static_cast<float>(row3.GetX()), static_cast<float>(row3.GetY()), static_cast<float>(row3.GetZ()), static_cast<float>(row3.GetW()),
|
|
||||||
static_cast<float>(row4.GetX()), static_cast<float>(row4.GetY()), static_cast<float>(row4.GetZ()), static_cast<float>(row4.GetW())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
AZStd::string ToString(const AZ::Color& color)
|
|
||||||
{
|
|
||||||
return AZStd::string::format("(R:%d, G:%d, B:%d A:%d)", color.GetR8(), color.GetG8(), color.GetB8(), color.GetA8());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
||||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <AzCore/std/string/string.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility functions for convertings math types into strings.
|
|
||||||
*/
|
|
||||||
namespace AZ
|
|
||||||
{
|
|
||||||
class Vector2;
|
|
||||||
class Vector3;
|
|
||||||
class Vector4;
|
|
||||||
class Quaternion;
|
|
||||||
class Transform;
|
|
||||||
class Matrix3x3;
|
|
||||||
class Matrix4x4;
|
|
||||||
class Color;
|
|
||||||
|
|
||||||
AZStd::string ToString(const Vector2& vector2);
|
|
||||||
AZStd::string ToString(const Vector3& vector3);
|
|
||||||
AZStd::string ToString(const Vector4& vector4);
|
|
||||||
AZStd::string ToString(const Quaternion& quaternion);
|
|
||||||
AZStd::string ToString(const Transform& transform);
|
|
||||||
AZStd::string ToString(const Matrix3x3& matrix33);
|
|
||||||
AZStd::string ToString(const Matrix4x4& matrix44);
|
|
||||||
AZStd::string ToString(const Color& color);
|
|
||||||
}
|
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||||
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AzCore/UnitTest/TestTypes.h>
|
||||||
|
|
||||||
|
#include <AzCore/Math/MathStringConversions.h>
|
||||||
|
#include <AzCore/Math/Aabb.h>
|
||||||
|
#include <AzCore/Math/Color.h>
|
||||||
|
#include <AzCore/Math/Matrix3x3.h>
|
||||||
|
#include <AzCore/Math/Matrix3x4.h>
|
||||||
|
#include <AzCore/Math/Matrix4x4.h>
|
||||||
|
#include <AzCore/Math/Transform.h>
|
||||||
|
#include <AzCore/Math/Quaternion.h>
|
||||||
|
#include <AzCore/Math/Vector2.h>
|
||||||
|
#include <AzCore/Math/Vector3.h>
|
||||||
|
|
||||||
|
namespace UnitTest
|
||||||
|
{
|
||||||
|
class MathStrings : public AllocatorsTestFixture
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(MathStrings, TestVectorStringConverters)
|
||||||
|
{
|
||||||
|
AZ::Vector2 vec2 = AZ::Vector2::CreateOne();
|
||||||
|
AZ::Vector3 vec3 = AZ::Vector3::CreateOne();
|
||||||
|
AZ::Vector4 vec4 = AZ::Vector4::CreateOne();
|
||||||
|
AZ::Quaternion quat = AZ::Quaternion::CreateIdentity();
|
||||||
|
|
||||||
|
EXPECT_EQ(AZStd::to_string(vec2), "1.00000000,1.00000000");
|
||||||
|
EXPECT_EQ(AZStd::to_string(vec3), "1.00000000,1.00000000,1.00000000");
|
||||||
|
EXPECT_EQ(AZStd::to_string(vec4), "1.00000000,1.00000000,1.00000000,1.00000000");
|
||||||
|
EXPECT_EQ(AZStd::to_string(quat), "0.00000000,0.00000000,0.00000000,1.00000000");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MathStrings, TestMatrixStringConverters)
|
||||||
|
{
|
||||||
|
AZ::Matrix3x3 mat33 = AZ::Matrix3x3::CreateIdentity();
|
||||||
|
AZ::Matrix4x4 mat44 = AZ::Matrix4x4::CreateIdentity();
|
||||||
|
AZ::Transform xform = AZ::Transform::CreateIdentity();
|
||||||
|
|
||||||
|
EXPECT_EQ(AZStd::to_string(mat33), "1.00000000,0.00000000,0.00000000\n0.00000000,1.00000000,0.00000000\n0.00000000,0.00000000,1.00000000");
|
||||||
|
EXPECT_EQ(AZStd::to_string(mat44), "1.00000000,0.00000000,0.00000000,0.00000000\n0.00000000,1.00000000,0.00000000,0.00000000\n0.00000000,0.00000000,1.00000000,0.00000000\n0.00000000,0.00000000,0.00000000,1.00000000");
|
||||||
|
EXPECT_EQ(AZStd::to_string(xform), "1.00000000,0.00000000,0.00000000\n0.00000000,1.00000000,0.00000000\n0.00000000,0.00000000,1.00000000\n0.00000000,0.00000000,0.00000000");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MathStrings, TestAabbStringConverter)
|
||||||
|
{
|
||||||
|
AZ::Aabb aabb = AZ::Aabb::CreateFromMinMaxValues(0.f, 0.f, 0.f, 1.f, 1.f, 1.f);
|
||||||
|
EXPECT_EQ(AZStd::to_string(aabb), "0.00000000,0.00000000,0.00000000\n1.00000000,1.00000000,1.00000000");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(MathStrings, TestColorStringConverter)
|
||||||
|
{
|
||||||
|
EXPECT_EQ(AZStd::to_string(AZ::Colors::Black), "R:0, G:0, B:0 A:255");
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue